WorldCup26: Tempo: The World Cup Forecasting Engine That Refuses to Be a Black Box

A production-grade Python system for calibrated predictions, live bracket simulation, and explainable soccer odds that only promotes models after they beat Elo.

8-10 min read View on GitHub More from Raj1952

A wide editorial scene shows a World Cup bracket being fed by a calibrated control panel. One side is a simple Elo dial and ledger. The other side is a more intricate machine with factor cards pushing into the bracket board, showing how model discipline turns into forecasts.
Tempo treats forecasting as a system of gates, not a single prediction.
Key Takeaways

The model has to earn its place

Most sports predictors promise smarter numbers. Tempo starts somewhere more useful: it asks whether the smarter model is actually better than a simple Elo-logistic baseline. That gatekeeping logic is the article in miniature. Complexity is optional, but evidence is not.

The core pipeline is a model registry with a gate, not a one-way train-and-ship path.

DimensionBaseline Elo-logisticCandidate XGBoost
ComplexitySmall and interpretableRicher feature interactions
RoleReference pointMust prove incremental value
DeploymentAlways availableOnly promoted if it wins
Trust signalSimplicityMeasured improvement
Failure modeMay miss nuanceCan be overfit or overconfident

That structure matters because it changes the burden of proof. The baseline is not a fallback after things go wrong. It is a standing challenger that keeps the whole system honest.

Calibration is the difference between smart and usable

Raw probabilities are seductive and often wrong. Tempo uses isotonic calibration so that a forecast labeled 70 percent is meant to behave like a 70 percent event over time. In sports, that distinction is everything. A model that is merely sharp but poorly calibrated can still mislead coaches, fans, and analysts.

QuestionUncalibrated scoreCalibrated forecast
What does 70% mean?A model output that may be overconfidentA probability tied to observed frequency
How should it be used?CautiouslyDirectly in decisions and simulations
What does it optimize?Ranking or separationTrust in numeric meaning
What does the UI show?A numberA number that is easier to believe

This is where Tempo stops feeling like a toy. The system does not just rank teams. It tries to make each number defensible.

A close-up editorial illustration shows a probability waterfall being assembled by hand. Individual factor cards push a bar up or down while a faint calibration curve and bracket grid sit behind it, explaining how a prediction is built from contributing signals.
Tempo turns model output into legible causes, not just a score.

Tempo’s pipeline is built like a production system, not a notebook

The repository is organized into three layers: data, intelligence, and presentation. That separation is not cosmetic. It keeps ingestion, modeling, and UI concerns from leaking into one another, which is exactly how a forecasting project avoids becoming a tangled script collection.

LayerJobWhy it matters
Data layerIngests results, fixtures, and overridesKeeps inputs reproducible
Intelligence layerTrains, calibrates, explains, simulatesHolds the forecasting logic
Presentation layerRenders the dashboard and routingKeeps the model visible without exposing internals

The daily refresh flow is the heartbeat: ingest, feature build, train, calibrate, promote, predict. That sequence is what makes the repo feel durable. It is not asking a human to remember what to rerun.

The simulator turns a 48-team tournament into 50,000 plausible futures

Tempo does not stop at match probabilities. It pushes them through a Monte Carlo engine that simulates a tournament shape, including messy details like best third-place advancement and live-aware state. That means played matches are fixed, and only the remaining fixtures are allowed to fan out into thousands of futures.

This is the right way to think about a World Cup model. A bracket is not a prediction table. It is a branching system where one result changes the path of several later rounds.

Simulation challengeNaive approachTempo approach
Played matchesSimulate everything from scratchTreat completed games as fixed
Third-place advancementHand-wave the edge casesEncode the advancement rules explicitly
TiebreakersIgnore or simplifyModel goals scored and goal difference
Future pathsA single bracketThousands of Monte Carlo futures

The UI behaves like a dashboard, not a Streamlit demo

Tempo’s frontend is still Streamlit, but it does not feel like a default Streamlit app. Custom routing through query parameters gives it bookmarkable navigation. The result is a dashboard that behaves more like a product surface than a quick prototype.

Default StreamlitTempo presentation layer
Sidebar-centric navigationQuery-param routing with page state
Prototype feelBroadcast-console style dashboard
Raw model outputWaterfall charts and explainability artifacts
Loose couplingLayer boundaries that keep ML imports out of the UI

That presentation choice is subtle and important. If the system is trying to earn trust, the interface has to make the reasoning easy to inspect.

Why this repo feels unusually mature

The maturity shows up in the boring places. There are leakage tests, Monte Carlo boundary tests, typed Python, timestamped artifacts, and automation that keeps the refresh cycle moving. None of that is flashy. All of it is what makes the system believable.

Tempo reads like a project built by someone who understands that forecasting is not only about better numbers. It is about model governance, reproducibility, and the willingness to let a simple baseline say no.

Sign of maturityWhat it signals
Leakage testsThe author cares about validity, not just accuracy
Timestamped model artifactsTraining is operational, not ad hoc
Layer boundariesThe codebase can grow without collapsing into a notebook
Daily refresh orchestrationThe system is meant to live, not just demo