postforecast
Consensus-relative methods applied to forecasts produced elsewhere
This library does not forecast anything. Give it a forecast, a consensus and, when you have them, actuals: it anchors each value to when it was knowable, measures the forecast against consensus, combines the two, and states what it published and which parameters produced it.
Post means after the forecast, not after the fact. Every parameter is fitted on the training period alone, and no value is read before its known_at.
Why it exists
A revenue forecast sold to investors is judged twice, and the two judgements pull against each other.
- Accuracy. How far is the number from what the company reports? A forecast of $1,300m beside a consensus of $1,000m looks absurd, and the user stops trusting the product.
- Information relative to consensus. When the number is above consensus, does the company tend to beat? A forecast that repeats consensus is perfectly credible and tells the customer nothing.
The customer’s question is never “what will revenue be?” — they already have consensus. It is “where is consensus wrong?” Every method here answers that question, and every one of them is auditable a year later.
What makes it different
The arithmetic is simple. The value is that a published number can be defended. Four properties, each mechanically enforced rather than documented:
- Pure. No file, no network, no process, no clock.
import-linterforbids the modules, so a method that cannot read a clock cannot depend on when it ran. - Point-in-time by construction. Values enter through the anchoring functions, which read strictly before a stated moment. A method sees only the anchored frame.
- Train and apply are different types.
fittakes the training rows and returns a frozen object;applytakes any rows and cannot refit. A look-ahead has to be written deliberately, not reached by accident. - Every result is attributable. A fitted method serialises to a plain dict: its parameters, their version, and what it was fitted through.
The two methods
| Anchored estimate | Bayesian posterior | |
|---|---|---|
| Form | consensus, moved a fraction of the way toward the forecast | precision-weighted mean of prior, model and consensus |
| Space | ratios to consensus | growth, converted back to levels |
| Weights | one shipped set, versioned | per company, from each source’s own error history |
| Anchor | consensus, explicitly | none; consensus is one source of three |
| Interval | none | Student-t, heavy-tailed |
| Adapts as data arrives | no, the weights are frozen constants | yes, the precisions update every period |
They answer different questions. For a published revenue number the Bayesian form is better founded: a per-company weight, an uncertainty band, and it degrades gracefully when a model’s record is too short. For a trading signal the fitted form has one decisive advantage — it is fitted on the quantity actually being predicted.
Both are reached through one protocol, so a caller swaps one for the other without knowing how either works.
Reading order
- The panel — the one input format, and what it refuses.
- Point-in-time — the read itself, and why
fitandapplyare different types. - Anchoring — the first method, end to end.
- Bayesian posterior — the second, and how the two relate.
Every figure and every number on this site is computed by the library as the page renders. If a page is wrong, the build is wrong.
Provenance
Both methods are ports, not inventions. The anchored estimate and the Bayesian posterior come from the buy-side consensus study’s reference implementations, and the Bayesian one follows IndependentBayesianRegularizedPredictionSignal in the Exabel production DSL. Each reference ends in a self-check with real numbers, and those self-checks are golden tests in this repository, so the library and the published research cannot drift apart silently.