World Cup 2026 Model
A forecasting engine for the 48 team 2026 World Cup, built from the ground up. It runs Elo ratings over 154 years of international results, feeds those into a weighted Poisson goal model, and then simulates the entire tournament in the browser.
The question
Every sportsbook prices a World Cup. I wanted to find out what it actually takes to build that price yourself, going from raw match results all the way to a number you would be willing to defend, without reaching for a library that does the hard part for you.
So the whole model is written using nothing but Python's standard library. No pandas, no scikit-learn, no scipy. If a gradient gets computed somewhere in there, I wrote it.
How it works
Three layers, each feeding the next:
- Elo ratings. Every international match since 1872 gets replayed in order. Ratings update using a K factor that scales by match importance, so a World Cup game moves a rating three times as much as a friendly does, and it also scales by margin of victory so that a 5 goal win counts for more than a 1 goal win. Home advantage comes in as a 65 point rating bonus, which is switched off at neutral venues.
-
A weighted Poisson attack and defence model. Each team gets an attack
coefficient and a defence coefficient, fit by maximum likelihood with ridge regularisation
across 11,003 matches since 2015. Recent games count for more, because match weight decays
with a 2.5 year half life, meaning a 2021 result carries roughly a quarter
of the weight of a 2026 one and a 2016 result about a sixteenth. The fit produces expected goals for any fixture using
log λhome = μ + att[H] − def[A] + homeAdv. - Monte Carlo tournament simulation. Two expected goal numbers give you two Poisson distributions, and crossing them gives a full matrix of scorelines, which is where the win, draw and loss probabilities come from. The dashboard then samples scores from that model across all 104 group games plus the knockout bracket, including strength weighted penalty shootouts, thousands of times over, to produce advancement and title odds.
The dashboard
The output is a single self contained HTML file with the fitted model baked into it. There is no server and no dependencies, so it opens anywhere. It does four things:
- A match predictor for any two of the 48 teams, at any venue.
- Live in game repricing, where you set the current minute and score and the probabilities update the way an in play market would. This is the piece closest to what I was doing at Fanatics.
- A scoreline heat map that shows the full joint distribution rather than just the three way price.
- A full tournament simulation with group tables, advancement odds, and CSV export of every table.
What it gets wrong
I want to state these plainly, because a model you can't criticise isn't really a model:
- Goals are modelled as independent Poisson. Real football has correlated scorelines, and draws and 0 to 0 results happen more often than independence would imply. The Dixon and Coles correction for low scores is the standard fix and the obvious next step.
- No squad information. Injuries, suspensions and retirements are completely invisible to the model, since it only knows what teams have done and not who is actually available to play.
- Confederation imbalance. Teams that mostly play inside their own confederation end up with ratings that are hard to compare across regions, because there are so few games connecting the pools together.
- Nothing is calibrated against market prices yet. The honest test of any forecast is whether it can beat the closing line, and that is exactly the standard my Premier League project was built to measure.