How this project works
The end-to-end pipeline behind every number on the site — data in, probabilities out — for a technical reader without a betting background.
Tech stack
Python ETL
Ingestion and modelling jobs: Elo + fixtures + odds ingest, the Dixon–Coles engine, Monte Carlo simulations, and calibration.
Supabase (Postgres)
Single source of truth. All jobs upsert idempotently with provenance; the service key stays server-side only.
Next.js + Tailwind
App Router frontend, bilingual (next-intl). Read-only over a server-side API — the browser never touches the database.
The pipeline, step by step
- 1
Data ingest
World Football Elo ratings and the official fixture list are pulled by fail-loud Python jobs — an unrecognised team name or missing field raises rather than silently guessing. Every write is an idempotent upsert stamped with its as-of date and source.
- 2
Team identity mapping
Each source names teams differently (Elo two-letter codes, football-data names, FIFA three-letter codes). An alias layer reconciles them to one canonical id; anything that can't be matched raises instead of creating a duplicate team.
- 3
Elo → team strengths
The Elo gap between two teams becomes the model's measure of relative strength. Host nations (USA, Canada, Mexico) get a home-advantage boost of ≈85 Elo in their own stadiums, fitted from history; every other match is treated as neutral.
- 4
Dixon–Coles fit + gate
A Poisson-based Dixon–Coles model turns the Elo gap into expected goals, with a low-score correction. Its parameters are backtested on ~1,900 international matches since 2010 (recent games weighted more) and only deployed if they beat the prior version on held-out matches — a strict validation gate.
- 5
Per-match predictions
For each fixture the model builds a full scoreline-probability grid, then sums it into 1X2, over/under and both-teams-to-score. Predictions are frozen before kickoff — the model is not re-run mid-match — so the track record scores genuine pre-match calls.
- 6
Monte Carlo group simulation
The whole group stage is replayed tens of thousands of times, each run ranked by the real FIFA tiebreakers (points, head-to-head, goal difference). Counting outcomes across runs gives each team's probability of finishing 1st, 2nd, or qualifying as a best third.
- 7
Knockout simulation
The eight best third-placed teams are slotted using FIFA's Annex C mapping, then the bracket is played out to a champion. Once real knockout results land they lock the corresponding branches, so projections stay consistent with what actually happened.
- 8
Odds ingest + de-vig
Pinnacle prices (a thin-margin, sharp book) are ingested and only stored when they move. Removing the vig — the bookmaker's built-in margin — recovers a fair market probability that serves as the benchmark the model is measured against.
- 9
EV & fractional Kelly
The EV calculator is deliberately model-free: it compares your odds against the de-vigged market and reports expected value and a quarter-Kelly stake. The arithmetic (web/lib/value.ts) is a parity-tested port of the Python engine, kept in sync by golden-vector tests.
- 10
Calibration & in-tournament refit
After each round the model is scored (Brier) against the market. A mid-tournament refit (dc-v1.2) trains only on completed matches, with an anti-leakage gate that forbids using post-match information — so calibration measures real forecasting skill, not hindsight.
The honest framing
The model is experimental and always shown alongside the market — never as the single correct answer. Closing market odds are usually the most accurate estimate available; the model is a comparison and a learning tool, not betting advice.