Batch stock research while preserving partial failures
Batch stock research should apply the same question and output contract to each company, while preserving the cases that cannot be completed. Start with a fixed stock list, target year, valuation date and EPS convention. Process each company independently, return one structured result per input, and aggregate the statuses only after all rows exist. One failed source must not erase the remaining companies or vanish from the denominator.
This guide uses six fictional A-share-style identifiers and an external annual diluted-EPS forecast input. The independent Python file calculates forward PE where the supplied data permit it. Its source functions return synthetic fixtures or raise a deliberate timeout. It does not retrieve real prices, generate forecasts with a model or prove that CoTrading can supply forecast coverage across A-shares, Hong Kong or US markets.
Fix the question before looping over companies
The task is: for each input stock, calculate price divided by positive FY2027 forecast diluted EPS, using the 2026-10-26 data snapshot and CNY conventions. Preserve company identifiers exactly as provided. Decide how duplicates and alternate share classes are handled before submitting a larger list. The same ticker string on different exchanges is not necessarily the same security, so real adapters need qualified identifiers.
The forecast must come from a reviewed external source with its target year, forecast date, currency, dilution basis and source reference. IAS 33’s official description distinguishes EPS numerators and denominators. Here the lesson is to preserve an explicit comparable EPS basis; the standard does not supply broker forecasts or certify the synthetic input values. Keep adjusted versus statutory conventions visible when sourcing real estimates.
Use one output schema for successes and failures. The example includes symbol, target year, snapshot date, currency, basis, status, price, EPS, PE, reasons and sources. Missing numbers use null. A status word explains the stage reached: success means price, compatible positive EPS and PE are available; partial means a valid price survives but valuation is incomplete; failed means the price prerequisite itself did not complete.
Treat each company as an isolated unit of work
The per-company function creates a result row before fetching anything. It attempts the price step first, validates scope and requires a finite positive number. If price retrieval times out, it records the failure and returns that row without asking for EPS. Other companies still execute. This makes the dependency order visible and avoids spending effort on a downstream calculation that cannot currently produce a dated valuation.
Next retrieve and validate the forecast schema. Require the expected fields before reading them. Check the exact requested year before calculating PE; a nearby available year is not a substitute. Check snapshot, currency and dilution convention against the contract. Python JSON documentation describes the interchange format used for output; JSON structure alone does not establish that financial fields have the required meaning.
Parse numeric values through an explicit finite-number gate. Python Decimal can hold NaN and infinities, so successful construction is not enough. Retain an accepted EPS of zero as an observed value, but leave PE unavailable under the positive-EPS rule. Keep an invalid nonfinite value out of the accepted numeric field and put the reason in the result instead.
Inspect all six outcomes in the worked example
AAA has price 24 and compatible FY2027 EPS 1.2, so forward PE is 20. It is the only complete success. The output may serialize Decimal’s value as 2E+1; this is numeric scientific notation for 20, not a different multiple. A display layer can format it as 20.00 while preserving the underlying calculation and source references.
BBB has price 30 but only an FY2028 estimate. Its row is partial with missing_requested_forecast_year, and accepted EPS and PE remain null. The program does not calculate 30 divided by the FY2028 number and label it FY2027. The next action is to obtain a compatible target-year observation or explicitly revise the whole research question, not to fill the missing year automatically.
CCC’s price source raises price_source_timeout. Its row is failed, price and EPS are null, and the EPS function is not needed for that company. DDD has price 20 and a valid observed EPS of zero. Its row is partial with nonpositive_eps_pe_not_applicable; zero remains visible in EPS, while PE is null. These two rows have different data availability even though neither produces a valuation multiple.
EEE has price 18 and an invalid EPS token NaN. Its accepted price survives, EPS stays null and the reason identifies a nonfinite numeric field. FFF has price 15 but the alleged forecast payload contains only a prose summary. It is partial with eps_schema_missing_fields. A fluent sentence about earnings growth cannot stand in for a target year, numeric EPS and source reference.
results = [run_one(symbol) for symbol in SYMBOLS]
assert len(results) == len(SYMBOLS)
assert [row["symbol"] for row in results] == SYMBOLS
Download the complete example. Use Python 3.12+, the standard library and synthetic data, then run python R553.py. The full program implements the sources, guards, arithmetic, uniform result rows and assertions. The printed summary is one success, four partial results and one failure, reconciling to all six input stocks.
Preserve different failure mechanisms in the follow-up list
Turn reasons into explicit follow-up actions. CCC needs a dated price-source retry. BBB needs the missing FY2027 forecast. DDD needs no blind data retry: positive-EPS PE is not applicable to its observed zero. EEE needs correction or confirmation of the numeric source field. FFF needs a structured extraction or external table that supplies the required schema. Repeating the same broad request for all five rows would waste effort and obscure the cause.
Do not replace unavailable values with zero or an average across other companies. Zero is already a meaningful observed EPS in DDD. Using it as the missing marker would make a source failure indistinguishable from a real nonpositive observation. Likewise, dropping failed rows before calculating coverage would turn one out of six successes into a misleading one out of one completed valuations.
If a source returns a contradiction rather than a missing field, preserve both references and block that company’s calculation until a documented selection policy applies. Do not select the more plausible number based on the PE you want. The small fixture shows several local failures; it does not implement every vendor schema or all financial reconciliation policies needed for live research.
Aggregate coverage before interpreting valuation
Produce counts for each status and list the specific companies and reasons. A valuation comparison should use only compatible complete rows, with its restricted coverage stated beside it. With one success in this example, there is no meaningful six-stock ranking. The batch has successfully recorded six outcomes, but only one stock’s requested valuation calculation is complete; those are two different measures of task completion.
Inspect the per-row source list. Accepted partial data retain their sources so a corrected downstream step can reuse them when still valid. Invalid or mismatched fields should be recorded in a separate diagnostic record rather than silently becoming accepted EPS. For a real pipeline, also retain raw source versions and verification timestamps; this example’s compact sources identify synthetic fixture origins only.
Re-run selectively under the same contract
When a missing forecast or corrected field arrives, rerun that company and preserve the earlier attempt. Check that reused prices still meet the valuation-date policy. A new day’s price is a different research version; do not combine it silently with yesterday’s completed table. When the target year, basis or currency changes, invalidate the relevant rows across the batch and label the new contract.
The file processes companies sequentially for clarity. Adding concurrency requires bounded requests, source limits and independent exception handling, while maintaining one output per input. Those engineering extensions do not solve missing historical estimates or unclear EPS definitions. The useful baseline remains a reproducible common question, explicit partial outcomes and a follow-up list that tells the researcher exactly what is still needed.
FAQ
Is a partial row a failed batch?
The batch can complete its reporting contract while some company valuations remain incomplete. Keep both facts visible.
Can prose forecasts be included in numeric comparison?
Only after obtaining and validating the required numeric fields and scope. The summary alone is insufficient.