Skip to content

Repository files navigation

⚽️ 2026 World Cup · Elo Predictor (case study)

⚠️ This is an EDUCATIONAL EXPERIMENT about predictive models and AI. It is NOT a betting tool. We are against gambling. We accept no responsibility for any use of this material. Read the full DISCLAIMER.

Open project by NoMa Studio AI: how well does a simple statistical model based on national-team Elo ratings predict the 2026 World Cup? We built it, measured it against the real results, and document honestly what works and what doesn't.

The point of the case study isn't "beating the World Cup": it's showing, with data, where the ceiling of a model like this is, and why.

🇦🇷 ¿Preferís leerlo en español? Ver README.es.md.


🔮 Current predictions

Last auto-update: 2026-06-28. Backtest: the model gets the 1X2 right in 61.1% of 72 matches played (random ≈ 33%).

🏆 Projected champion (most-likely bracket): Spain. Projected final: Spain 2-1 Argentina.

Most likely finalists (Monte Carlo): Argentina vs Spain (25.9% of simulations).

TeamReaches finalChampion
Spain57.5%40.0%
Argentina45.1%24.0%
England26.4%12.4%
France18.0%8.1%
Colombia9.1%3.1%
Netherlands6.0%2.0%

Full detail (our group-stage predictions vs the results, the match-by-match bracket) in predicciones/PREDICCIONES.md.


📉 Post-mortem: how well did we do?

Post-mortem generated on 2026-07-18. Every match was predicted with the same model (Elo pre-tournament + momentum, host advantage only). The group figure is the backtest; the knockout figure applies the identical model to each real tie.

🎯 Headline

StageMatchesWe got rightAccuracyReference
Group stage (1X2)724461.1%random ≈ 33% · "higher Elo wins" ≈ 61%
Knockouts (who advances)302480.0%coin-flip = 50%
Whole tournament so far1026866.7%

The two metrics are not the same thing. In the group stage a match has three outcomes (win / draw / loss), so 33% is the random baseline. In the knockouts there are no draws: someone always advances, so the honest baseline is a 50/50 coin-flip. The knockout number is measured as "did we call the team that advanced", running the same Elo model on each real tie.

The model called the final right. Its most-likely projected final was Spain vs Argentina, and that is exactly the real final (19/07). It also had both eventual finalists as the two most likely champions in the Monte Carlo (Spain 32.3%, Argentina 30.9%).

🟦 Group stage: accuracy by group (44/72 = 61.1%)

1X2 pick before kick-off vs the real result. Full match-by-match table (72 games) in predicciones/PREDICCIONES.md.

GroupRightMatchesExact score
A462
B461
C561
D160
E461
F461
G262
H260
I660
J561
K360
L461
Total447210

🟥 Knockouts: accuracy by round (24/30 = 80.0%)

RoundRightMatches
Round of 321316
Round of 1658
Quarter-finals44
Semi-finals22
Total2430

🔁 Knockouts: our prediction vs the real result (match by match)

Our pick = the team the model made favourite. Pred. score = the model's most-likely decisive scoreline. ✓ = we called who advanced, ✗ = miss. (a.e.t.) extra time, (pens) penalties.

RoundMatchReal resultAdvancedOur pickPred. scoreHit
Round of 32South Africa vs Canada0-1CanadaCanada0-2
Round of 32Germany vs Paraguay1-1 (pens 3-4)ParaguayGermany2-1
Round of 32Netherlands vs Morocco1-1 (pens 2-3)MoroccoNetherlands1-0
Round of 32Brazil vs Japan2-1BrazilBrazil2-1
Round of 32France vs Sweden3-0FranceFrance2-0
Round of 32Ivory Coast vs Norway1-2NorwayNorway0-1
Round of 32Mexico vs Ecuador2-0MexicoMexico2-1
Round of 32England vs DR Congo2-1EnglandEngland2-0
Round of 32United States vs Bosnia and Herzegovina2-0United StatesUnited States1-0
Round of 32Belgium vs Senegal3-2 (a.e.t.)BelgiumBelgium2-1
Round of 32Portugal vs Croatia2-1PortugalPortugal2-1
Round of 32Spain vs Austria3-0SpainSpain2-0
Round of 32Switzerland vs Algeria2-0SwitzerlandSwitzerland1-0
Round of 32Argentina vs Cape Verde3-2 (a.e.t.)ArgentinaArgentina2-0
Round of 32Colombia vs Ghana1-0ColombiaColombia2-0
Round of 32Australia vs Egypt1-1 (pens 2-4)EgyptAustralia2-1
Round of 16Paraguay vs France0-1FranceFrance0-1
Round of 16Canada vs Morocco0-3MoroccoCanada2-1
Round of 16Brazil vs Norway1-2NorwayBrazil2-1
Round of 16Mexico vs England2-3EnglandEngland1-2
Round of 16Portugal vs Spain0-1SpainSpain0-1
Round of 16United States vs Belgium1-4BelgiumBelgium0-1
Round of 16Argentina vs Egypt3-2 (a.e.t.)ArgentinaArgentina2-0
Round of 16Switzerland vs Colombia0-0 (pens 4-3)SwitzerlandColombia1-2
Quarter-finalsFrance vs Morocco2-0FranceFrance2-0
Quarter-finalsSpain vs Belgium2-1SpainSpain2-0
Quarter-finalsNorway vs England1-2EnglandEngland1-2
Quarter-finalsArgentina vs Switzerland3-1ArgentinaArgentina1-0
Semi-finalsFrance vs Spain0-2SpainSpain1-2
Semi-finalsEngland vs Argentina1-2ArgentinaArgentina1-2

Where the model missed in the knockouts (6): Germany was favoured but Paraguay advanced (Germany vs Paraguay); Netherlands was favoured but Morocco advanced (Netherlands vs Morocco); Australia was favoured but Egypt advanced (Australia vs Egypt); Canada was favoured but Morocco advanced (Canada vs Morocco); Brazil was favoured but Norway advanced (Brazil vs Norway); Colombia was favoured but Switzerland advanced (Switzerland vs Colombia).

⏳ Still to play: the model's prediction

These two matches had not been played when this post-mortem was generated (third place 2026-07-18, final 2026-07-19). No real result yet, here is only the model's forecast, to be checked afterwards. Forecast made the forward way (live eloratings.net Elo, same as the projected bracket), with a 50,000-run Monte Carlo resolving draws by penalties: "1/X/2" is the 90-minute result, "Wins the tie" includes extra time and shoot-outs.

MatchRoundDateFavouritePred. scorep(1/X/2) at 90'Wins the tie (MC)
France vs EnglandThird place play-off2026-07-18England1-230/29/40England 57.5%
Spain vs ArgentinaFinal2026-07-19Spain2-143/28/27Spain 61.8%

🧠 What the post-mortem says about the model

  1. Consistent, not clairvoyant. ~61.1% in groups and 80.0% in knockouts is roughly "the higher-Elo team wins": solid, but it lives or dies with the favourites. It cannot see an upset coming (Paraguay over Germany, Morocco over the Netherlands, Norway over Brazil), which is exactly where a pure-Elo index hits its ceiling.
  2. Penalties are a coin-flip the model doesn't model. Several ties it "lost" were 90-minute draws decided from the spot, and the Elo index has nothing to say about a shootout.
  3. It nailed the big picture. The projected bracket's final (Spain vs Argentina) is the real final, and the two finalists were the model's top-2 title favourites. The signal is strongest exactly where there is the most data (elite teams, large Elo gaps) and weakest in the close, one-off games.

Full detail in predicciones/POSTMORTEM.md.


🧪 What we tried (and what we learned)

We started from a base model (Elo → expected goals → Poisson) and evaluated it with a backtest against the matches already played. Then we tried to improve it on three fronts. Honest result:

Improvement we triedDid accuracy improve?Did probability quality improve?
#1 Model draws (Dixon-Coles)NoYes (exact score and well-calibrated draw prob.)
#2 In-tournament form (fresh match-by-match Elo)NoNo
#3 Reduce overconfidence (temper / shrink)NoNo

Key findings:

  1. The model never predicts a draw, and that CANNOT be "fixed" by forcing it. In the backtest, draws happened when favorites slipped up (Spain 0-0 Cape Verde, England 0-0 Ghana), not in evenly-matched games. Forcing draws lowers accuracy without catching the real draws. What does help (Dixon-Coles) is making the draw probability well-calibrated (~24.5% predicted vs 25% real).

  2. In-tournament form doesn't help. A walk-forward backtest (no data leakage) showed +0.0 pp of accuracy. Even using the "perfectly fresh" live Elo from eloratings (an optimistic, leaky upper bound) the ceiling barely rises to ~66%.

  3. The model is already well-calibrated. Tempering confidence worsens the Brier score: the apparent overconfidence on big favorites was offset by underconfidence on close games.

Conclusion and why we leave the model as-is: the predictor is at the ceiling of what the Elo index can deliver for the group stage (~61-62% 1X2 accuracy, the same as "the higher-Elo team wins"), with already-calibrated probabilities. The only improvement that added real value was Dixon-Coles (probability quality), so that's the one we kept. Genuinely raising accuracy would need data outside the index (squad value, injuries, rest, etc.), which is another project.

📄 Backtest detail: .claude/skills/prediccion-mundial-2026/analisis-backtest.md


📐 The model (specs)

  1. Index: national-team Elo rating (World Football Elo Ratings, eloratings.net), taken from the El Atlas chart.
  2. Result probability: the Elo difference (plus home advantage for the hosts Mexico/Canada/USA) is mapped to an expected goal difference, which feeds a Poisson model per team → 1X2 probabilities and scorelines. With a Dixon-Coles correction for low scores.
  3. Recent form: a bounded adjustment from index momentum or recent results (optional). Tested: does not improve accuracy (see above).
  4. Tournament simulation: Monte Carlo (50,000 runs) combining real results with simulations of the remaining matches, resolving groups, best thirds and the official knockout bracket up to the final.
  5. Projected bracket: a single most-likely path that predicts every knockout tie (score + winner) from the Round of 32 to the final.

Backtest (pre-tournament, no leakage): uses the Elo from before the World Cup. Forward predictions: use the live Elo from eloratings (most current).

All parameters live in model.mjs and are tunable.


🚀 Usage

Requires Node.js (no external dependencies).

cd .claude/skills/prediccion-mundial-2026
node predict.mjs "Spain""Argentina" --neutral # one match
node predict.mjs USA "Mexico" --host A # with host advantage
node backtest.mjs --md # backtest vs reality
node simular.mjs 50000 --json # simulate the tournament
node experiment-forma.mjs # form experiment

🔄 Keeping it up to date

The Elo index and the predictions update themselves with:

bash scripts/actualizar.sh

This pulls the live Elo from eloratings.net, refreshes everything and regenerates the predictions and this README. A GitHub Action (.github/workflows/actualizar.yml) runs it every day during the World Cup and commits the changes.

New match results: add group games to data/grupos-resultados-2026.json (played_matches field), moving them out of remaining_fixtures; add knockout games to data/knockout-resultados-2026.json (move a tie from pending to played with its score and who advanced). That's the only manual step; the rest is automatic.


📊 Data and sources

  • Elo: eloratings.net (via El Atlas). 46 of 48 teams come from the Atlas extract; Scotland and Curacao are filled in with the live Elo from eloratings.
  • Results and fixtures: collected and cross-checked across multiple public sources (FIFA match centre, Wikipedia, ESPN, Sky Sports, Yahoo, FOX, CBS, Al Jazeera). Nothing is invented: results not confirmed by two sources are kept as "pending" (the third-place match and the final had not been played when the post-mortem was written, so they carry only the model's forecast, not a result).
  • Knockout bracket: official FIFA structure; the fine pairings after the Round of 32 are the least certain part (see notes in the data).

🧭 Repo structure

README.md · this case study (English)
README.es.md · Spanish version
DISCLAIMER.md · legal notice (EN/ES)
LICENSE · MIT (code) + data note
scripts/actualizar.sh · automatic update
.github/workflows/ · daily Action
predicciones/PREDICCIONES.md · full predictions (auto-generated)
predicciones/POSTMORTEM.md · tournament post-mortem (auto-generated)
.claude/skills/prediccion-mundial-2026/
├── model.mjs · the model (Elo + Poisson + Dixon-Coles)
├── predict.mjs · predict one match
├── backtest.mjs · validation against real results
├── simular.mjs · tournament Monte Carlo
├── proyeccion.mjs · deterministic bracket projection
├── experiment-forma.mjs · in-tournament form experiment
├── actualizar-elo.mjs · live Elo refresh
├── genera-predicciones.mjs · generates the public documents
├── postmortem.mjs · groups + knockouts prediction vs reality
└── data/ · Elo index, groups, results, bracket

⚖️ Notice

Built by NoMa Studio AI for educational and research purposes about AI and predictive models. We do not promote gambling. The predictions carry a high, documented margin of error. Use at your own sole risk. Read the DISCLAIMER.

About

Prode claude

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages