Skip to content

Learn

Company Research and Valuation

Track earnings revisions with matched broker forecasts

To track earnings estimate revisions, pair forecasts from the same broker for the same stock and target fiscal year across two retained snapshots. Calculate the matched EPS change, then report new and absent coverage separately. A rising average can reflect a changed broker sample rather than any existing broker raising its forecast. The matched panel makes that distinction computable.

This guide executes a synthetic A-share-style comparison using externally supplied snapshots. It does not retrieve historical broker reports or turn a current consensus value into an old observation. CoTrading’s corresponding revision tracker remains planned or unverified, and reference report tools can have windows or response limits that prevent complete historical coverage.

Fix the forecast object before comparing dates

Our target is one fictional company’s 2027 diluted EPS in CNY. The old accepted snapshot is dated 1 October 2026 and the new one 26 October. Each input needs its original source reference, publication or snapshot timing, broker identifier, forecast year, EPS definition and share assumptions. Those history inputs must be supplied by an appropriate archive or saved when they were actually available.

The script receives them as synthetic accepted tables. It does not independently verify each report’s historical publication timestamp. A real workflow must perform that acceptance before pairing. Missing an old report is a coverage limitation, not permission to populate the old snapshot with today’s forecast.

The IFRS IAS 33 overview illustrates why earnings numerators and share denominators matter. It is not an A-share consensus methodology or a rule that all brokers share one forecast basis. Confirm the actual report definitions, including basic versus diluted and adjusted versus reported earnings, before declaring a pair comparable.

Normalize brokers and deduplicate within each snapshot

Use a confirmed broker identity rather than a loosely matched display name. If a snapshot contains several eligible reports from one broker for the same year, apply a documented latest-report rule and retain the superseded records. The fixture starts after that selection and rejects duplicate broker-year entries instead of choosing by input order.

Keep the target year fixed across both dates. “Next year” can roll from one fiscal period to another, producing a numerical difference that is not a revision of the same forecast. In the example, E appears with a 2026 estimate in the old input and a 2027 estimate in the new input. E therefore enters 2027 coverage; its two numbers are not paired.

The pair key is broker and fiscal year inside the fixed company and measurement contract. For a larger dataset, add company and basis identifiers to the key. Do not compare a stock’s forecast with another listing or a different share-unit basis merely because the broker name matches.

Calculate signed changes and conditional percentages

BrokerOld 2027 EPSNew 2027 EPSSigned changeRelative change policy
A1.001.20+0.20+20%
B2.001.80−0.20−10%
C−0.50−0.20+0.30no percentage
D0.010.02+0.01no percentage

The absolute-unit difference is new minus old EPS. It keeps its sign. The magnitude of that change is a separate absolute-value calculation. Relative change is the difference divided by old EPS only under this fixture’s positive-base policy: old EPS must exceed 0.05. That display threshold is an explicit operational choice, not a universal financial standard.

prior, current = before[broker], after[broker]
change = current-prior
relative = change/prior if prior > D("0.05") else None

Python’s decimal reference supports the explicit arithmetic. It cannot repair a mismatched forecast period or a share-count change. If the report basis changes, resolve comparability or retain the pair as blocked rather than producing a precise but misleading percentage.

Run the matched and coverage outputs

Download the complete example. Use Python 3.12+, the standard library and synthetic forecasts; run python R540.py. The source is docs/growth/research/round-5/examples/R540.py.

Actual output has four matched brokers, A through D. A and B have relative changes 0.2 and −0.1. C and D retain signed EPS differences while the relative field is null with a negative-or-near-zero-base explanation. There are three upward pairs and one downward pair.

The signed mean EPS change is 0.0775 CNY per share, calculated across all four pairs. The mean absolute change magnitude is 0.1775. These summaries answer different questions: net direction versus average size ignoring direction. The script derives both and asserts their values, avoiding the ambiguous label “average absolute change” for a signed calculation.

E and F enter the captured 2027 sample, while G is absent from the new captured sample. They do not enter the matched-change average. Assertions verify these coverage sets and confirm that reversing the old input order does not alter its accepted mapping.

Treat losses and small bases as different mechanisms

C’s forecast loss narrows from −0.50 to −0.20, an improvement of 0.30. Dividing by the negative old value produces a sign that is easy to misread as deterioration. The fixture reports the per-share change without a percentage rather than forcing a conventional growth label onto the loss transition.

D rises from 0.01 to 0.02. A percentage would look large despite the small 0.01 change. The chosen near-zero rule withholds it, preserving both raw values and the signed difference. Readers can inspect the policy instead of assuming that every null percentage means missing source data.

These are not the same problem as unpaired coverage. C and D have valid matched observations under the fixed contract; only their percentage presentation is restricted. E and F lack a comparable old 2027 observation in this dataset and cannot be called matched upgrades at all.

Explain coverage without inventing analyst intent

G’s absence does not prove the broker withdrew coverage. It may reflect a query window, response cap or an incomplete archive. Label it absent from the captured snapshot and preserve the acquisition limits. E’s old 2026 forecast also does not establish a prior 2027 estimate, even though the broker was already present for another year.

If a vendor’s current mean is available, retain it separately with its own time and coverage. Do not substitute it for either saved broker panel. A comparison of differently composed means can be useful, but it is a separate composition-and-value analysis and cannot replace matched revisions.

Maintain a reproducible revision panel

Deliver accepted snapshot references, normalized broker-year tables, paired changes, percentage eligibility reasons, coverage entries and exits, and clearly named summaries. Reconcile matched plus old-only brokers to the old target-year sample, and matched plus new-only brokers to the new one. Count reports and contributing brokers separately.

After a new report, update the corresponding broker-year value in a new snapshot and preserve the old source. After a source correction, label the correction separately from a genuinely new forecast. A fiscal-year rollover requires another target-year panel rather than overwriting the original comparison.

Have a reviewer reconstruct A’s percentage, C’s loss improvement and E’s unpaired status from the retained records. The result is a numerical expectations-change artifact with visible coverage boundaries. It is not an assessment of analyst skill, a historical market-consensus database or a prediction that a stock price will follow the EPS revision.

Review the unit of pairing and the summary denominator

A matched broker is not necessarily the same individual analyst. Teams and authors can change while the institution remains the same. This fixture measures broker-level revisions. An individual-analyst claim would require accepted author identifiers and a separate pairing policy; do not infer that identity from the broker name alone.

Keep the summary denominator alongside every reported statistic. The four matched pairs support the signed mean and magnitude mean, while only two satisfy the chosen percentage-base rule. Entering brokers do not enlarge either matched denominator. The coverage tables explain their presence without assigning them a fictional prior forecast.

Before sharing a new panel, replay a positive-base increase, a negative-base improvement, a near-zero case and a fiscal-year mismatch. These branches test different meanings even when all output fields are numeric strings. Preserve null-reason labels in exports so a later spreadsheet does not turn them into zeros. The result should remain a source-linked revision table after formatting, rather than becoming a simple chart that hides why some percentages were withheld or why coverage changed.

Snapshot acceptance also requires every selected EPS to be finite after Decimal parsing. NaN and either infinity raise nonfinite_forecast_eps before entering the broker map, and the downloadable fixture asserts all three rejections. This guard does not exclude a finite loss forecast or change the near-zero percentage policy; it prevents malformed numeric states from reaching revision differences and summary averages.

FAQ

Is an increase in the average automatically an upgrade?

No. Check matched brokers and coverage composition before describing a forecast revision.

Should loss forecasts receive ordinary percentage growth?

Not automatically. Preserve signed per-share differences and a clear denominator policy.