
June 2026
WC 2026 Prediction Dashboard
The 2026 World Cup was coming and I wanted to do something more interesting than filling out a bracket by gut feeling. So I built two things: a match outcome prediction model that retrains itself after every result, and a corners betting dashboard that learns team tendencies as the tournament unfolds. Both running live, both updating automatically. Neither of them required me to touch anything once the tournament started.
The match outcome side ended up at 72.1% accuracy across all 104 matches, with 75 correct. It called Spain as the eventual champion before the knockouts. Spain beat Argentina 1-0 in the final. I'll take it.
The corners model was the harder and more interesting challenge. Predicting how many corners a match will produce sounds simple until you realise how many things influence it: playing styles, ELO gaps, whether a team is chasing the game, whether there are red cards. None of which a model can see mid-match. I built three stacked layers: a base Poisson model, a style matchup matrix (what happens when a high-press team meets a defensive block), and a walk-forward bias learner that corrects itself after every match using exponential moving averages. By the end of 91 played matches it was sitting at 47% within ±2 corners with a MAE of 3.05. Best on matchday 1 at 85% within ±2. Worst in the knockouts, where trailing teams desperately chase corners and blow any expected-value prediction out of the water.
That pattern taught me something useful: the same model can be excellent at one stage and mediocre at another not because the math is wrong, but because the game situation changes what the math is modelling. Group stage football and knockout football are not the same sport in terms of corner variance. The model does not know a team is 3–0 down in the 80th minute. That is the limit, and it is a real one.
The backend was the part that took the most iteration. I needed it to poll ESPN every 3 seconds, detect completed matches, trigger a retrain, and push the updated page to any open browsers without me doing anything manually. One bug that cost me a few hours: the live updater was marking in-progress matches as played and their corner counts were poisoning the bias learner. Fixed it by filtering on ESPN's "post" state flag only. Another: the bet pick logic was only scanning the nearest line to the expected value, so it was returning an UNDER at 67% when an OVER at 71% existed just a few lines away. Once I widened the scan window and filtered out trivially easy lines, the picks got sharper.
None of this was built for gambling. It was a statistics experiment, a way to see how much you can learn about a live tournament by treating every match as new training data. What I came away with is a better intuition for where machine learning is genuinely useful and where real-world variance just swamps the signal.
Match outcome model:
- —RandomForest classifier - win/draw/loss prediction per match
- —Poisson xG + Dixon-Coles matrix - full scoreline probability distribution
- —Loop-learned ELO (K=60 WC weight) - team strength updates after every result
- —Online xG bias correction - adjusts for teams consistently over or underperforming
Corners model:
- —Base Poisson - corners predicted from ELO gap and style matchup
- —Style matchup matrix - encodes how tactical archetypes interact (tiki-taka vs defensive block, high-press vs counter, etc.)
- —Walk-forward bias learner - per-team EMA correction: new = 0.55×old + 0.45×(actual minus predicted)
Backend:
- —Watcher thread - polls ESPN every 3 seconds
- —Rebuild thread - retrains and re-renders after every completed result
- —Backfill thread - recovers missed results at boot and hourly
- —SSE - live page updates pushed to browsers without a refresh
Hosting:
- —Render - live backend running the full watcher and rebuild loop
- —GitHub Pages + GitHub Actions - static mirror on a cron, always-on fallback
Tools:
- —Python - model, backend, data pipeline, rendering
- —ESPN API - live scores, goalscorers, corner stats
- —Claude AI - architecture partner and debugging throughout
Tech Stack