Build a stock research workflow with explicit dependencies
A one-run stock research workflow should execute a defined data-and-calculation chain, not merely generate a company summary. Start with a stock, valuation date and target fiscal year. Acquire a dated price and a compatible EPS forecast, calculate forward PE, then compare it with a user-supplied peer table. Every step needs an output contract and every dependent calculation needs a rule for missing or invalid inputs.
This article implements that control logic with synthetic A-share-style records. No live market, broker report, AI model or CoTrading service is called. Vibe’s reference tools and agent names do not prove that this complete chain has been run. CoTrading’s corresponding task orchestration remains planned or unverified; the reproducible result here is the independent standard-library example.
Write a request that can reach a numerical result
Our request is fictional stock AAA, valuation date 2026-10-26, forecast year 2027 and currency CNY. The desired output is forward PE and its ratio to a comparable peer median. This scope deliberately excludes a general investment recommendation. The final narrative must refer to completed outputs rather than improvise missing figures.
Retain a market-qualified stock identifier in actual use. Declare price type, session convention, forecast source, EPS basis and peer selection before running. A report’s publication date is not its forecast fiscal year. A current forecast for the wrong year cannot fill the requested column simply because it is recent.
The IFRS Foundation’s EPS overview illustrates the importance of per-share numerator and denominator conventions. It does not establish the methodology of a particular A-share forecast source. Confirm that source’s definition and use peer estimates with compatible periods and bases. “Same currency” is necessary for the price-to-EPS ratio but does not alone establish full comparability.
Describe dependencies before choosing an agent layout
The chain has four numerical stages: price, EPS, PE and peers. Price and report acquisition could be performed separately, but PE requires both validated outputs. Peer comparison requires valid PE and a compatible peer table. Writing a final paragraph is a presentation step and cannot change the upstream status.
| Step | Required input | Successful output | Block condition |
|---|---|---|---|
| price | stock and valuation date | dated price, currency, source | unavailable or wrong date |
| EPS | stock, cutoff and fiscal year | forecast, period, basis, source | missing requested year |
| PE | compatible price and EPS | price divided by positive EPS | missing dependency or nonpositive EPS |
| peers | PE and supplied comparable ratios | median and relative ratio | incompatible or absent peers |
Keep the accepted input identifiers on each derived output. A calculation must not reach backward into an unrelated previous run to find a convenient value. If cached data are permitted, define their validity in the request and record the reused version. A tool returning text that contains a number is not the same as a validated numeric output.
Execute the complete synthetic case
The price fixture returns CNY 24 on the valuation date, with source price-1. The eligible report is published on 2026-10-20, forecasts 2027 EPS of CNY 1.2 and has source report-1. The user-supplied peers have comparable forward PE values 16, 20 and 24, so their median is 20.
match = [row for row in forecasts
if row["year"] == request["year"]
and row["date"] <= request["as_of"]]
if not match:
return {"status": "partial", "pe": None,
"steps": {"eps": "blocked_missing_year",
"pe": "blocked_dependency",
"peers": "blocked_dependency"}}
report = max(match, key=lambda row: row["date"])
pe = price["value"] / report["eps"]
The complete fixture adds currency and positive-EPS checks before the division and retains successful price status on blocked runs. It is saved as docs/growth/research/round-5/examples/R552.py. Actual successful output is PE 2E+1, meaning 20, peer median 20 and relative ratio 0. The formula is PE / peer_median − 1, so zero means equal to the supplied median. It does not mean zero investment risk or fair value.
Download the complete example. Use Python 3.12+ with the standard library only; all inputs are synthetic. After downloading, run python R552.py.
The source list on that output is exactly price-1 and report-1. The fixture asserts repeat execution produces the same object. Python’s decimal reference supports the explicit decimal calculation. The scientific notation is an output-format choice; a user-facing table may display 20.00 without changing the retained value.
Inject failures into the dependency chain
For the first failure, change the only report’s forecast year to 2028 while keeping the request at 2027. Price still succeeds, EPS is blocked_missing_year, and PE and peers become blocked_dependency. Final status is partial and PE is null. The script asserts those values instead of checking whether the final text sounds plausible.
For the second failure, keep the correct year but set EPS to −1. The EPS acquisition step succeeds because it has returned a defined observation. The PE step is blocked as blocked_nonpositive_eps under this workflow’s policy, and peer comparison is blocked downstream. This differs from missing EPS: the input is present but the selected PE interpretation is not accepted.
Do not turn null into zero. A zero PE would be a numerical result, whereas null says the calculation did not run. Do not substitute 2028 EPS or last run’s 2027 EPS unless the request explicitly permits that policy. Such substitution could make every step appear successful while answering a different question.
Validate source boundaries beyond the small fixture
The runnable example fixes the symbol and price response, so it does not test wrong-symbol responses, stale prices or transport errors. Add those branches when implementing a real acquisition layer. Reject records whose symbol, currency or date violates the request, and preserve the precise reason. The fixture’s currency assertion is a compatibility stop, not a complete structured provider-error taxonomy.
Use explicit timestamps and market sessions for real feeds. Python’s datetime documentation explains date and timezone objects, but it does not supply the market’s calendar or decide when a broker report became available. Historical work requires actual publication and availability evidence; a current retrieval cannot automatically reconstruct past expectations.
The peer table is externally supplied and assumed comparable here. A production workflow must preserve its fiscal year, source, observation date and selection basis. An empty or zero peer denominator should block relative comparison while leaving an independently valid company PE available. That is partial success at a different point in the chain.
Deliver statuses with the calculation table
The final handoff contains the request, step contracts, successful source records, numerical outputs and blocked dependencies. Summarize completion from required steps, not from whether the last writing step produced a paragraph. In the successful fixture all four stages pass; in the missing-year case only price produces a usable observation.
Reconcile every requested stock to a final state when expanding to batches, and retain partial successes instead of discarding the whole run or hiding failed symbols. Rerun only after the missing input arrives, the source defect is resolved or the request is deliberately revised. Preserve the previous run and identify which downstream calculations changed. This turns “one run” into an inspectable research operation with a clear stopping rule rather than an unsupported promise that an AI answer completed the research.
Retain an event sequence for the actual run: request accepted, price returned, report checked, calculation executed or blocked, final state assembled. Connect each event to input and output identifiers. In the missing-year case, the absence of a PE execution event is stronger control evidence than a fluent final paragraph. For a rerun, decide which observations remain valid before reusing them; a changed valuation date may require a fresh price even when only the report step originally failed.
Preserve all three acceptance cases when adding tools: complete output at PE 20, missing-year dependency blockage and nonpositive-EPS interpretation blockage. Replaying these cases checks that a more elaborate orchestrator still respects its original numerical and evidence boundaries.
FAQ
Does the workflow need several AI agents?
No. Dependencies and validation can be implemented in one script. Several agent names do not establish independent checking.
Can the final summary mark the task complete if EPS is missing?
No. It can explain the partial result, but dependent valuation remains blocked.