Back to simulator

Methodology

How the simulator works, no secrets. Same approach as the original video (ELO + Poisson + Monte Carlo), built from scratch in pure TypeScript.

ELO ratings

We use ratings from eloratings.net, NOT the FIFA ranking. Two different systems: ELO is a recursive (chess-style) system that updates after every international match since 1872 and tracks recent form much more faithfully. Belgium was FIFA #1 for years without major titles; ELO never put them there.

Win probability (logistic ELO model):

We = 1 / (10^(-dr / 400) + 1)

dr = ELO gap + 100 if playing at home (USA, Mexico, Canada during group stage).

Goal model

For each match, each team's goals are drawn from an independent Poisson distribution. The parameter λ (expected goals) depends on the ELO gap:

λ_team = clamp(1.30 + 0.18 × (ELO_team − ELO_opp + home_bonus) / 100, 0.15, 6.0)
goals  ~ Poisson(λ_team)

BASE = 1.30 (avg goals per team in recent World Cups). ALPHA = 0.18 (sensitivity to ELO gap, calibrated against historical scoring). If your team has 200 ELO points over the opponent, you expect ~0.36 more goals. λ is clamped to [0.15, 6.0] to keep the distribution sane.

Recent form

Base ELO updates slowly (K=20). To capture level shifts in the past year (e.g. Argentina +107 ELO between 2021 and 2022 from Copa América + unbeaten run) we add an extra adjustment proportional to the 12-month delta, capped at ±150. α and the lookback window are calibrated via a sweep on World Cups 2014/18/22 (n=192 matches): optimum at α=0.20 with a 1-year lookback (+1.6pp accuracy, no Brier regression).

ELO_effective = ELO + clamp(0.20 × (ELO − ELO_one_year_ago), ±150)

Host bonus

USA, Mexico, and Canada play their group games at home. We add +100 ELO in those matches (order of magnitude consistent with the literature on host advantage). A sweep over 28 host-involving matches in World Cups 2014/18/22 found no clear evidence that +100 helps or hurts (Qatar and Russia were weak hosts; their results underperformed what home advantage alone would predict). We keep it pending more data.

Absences (injuries / suspensions)

Each absent player penalizes the team's effective ELO in proportion to a 'criticality' score. The formula combines transfermarkt market value and a positional multiplier. Calibration on World Cups 2014/18/22 showed that qualifier minutes give NO clean signal (France 2022 reached the final without Benzema/Pogba/Kanté), so that term is zeroed out.

criticality = 0.8 × (value_M€ / 150) + 0.2 × (pos_mult − 1) / 0.5
player_penalty = −5 − 75 × criticality
team_penalty   = Σ absent players, capped at −150 ELO

Positional multipliers: GK 1.5, CB 1.3, FB/DM/CM 1.1, attackers 1.0. Data is updated from transfermarkt's injury flag. Pre-2026 baseline: 39/48 teams affected. Top hits: Uruguay −103 ELO, Spain −90, Ecuador −81 (Pacho out), Argentina −75 (Romero + Nico Paz).

Post-extra-time fatigue

In the knockout stage, a team that wins in extra time or on penalties has played ~30 min more than its opponent who rested. We apply a small λ penalty in that team's NEXT match - most measurable between QF and SF when turnaround is short.

Group stage

12 groups × 6 matches × 4 teams = 72 matches. Points: 3/1/0. Tiebreakers in order: points → goal difference → goals scored → random. Top 2 from each group + 8 best 3rd-placed teams advance (ranked by the same criteria across groups).

Knockout

R32 → R16 → QF → SF → 3rd-place + Final. If regulation ends tied, we decide on penalties: instead of a coin flip we use a Bayesian shrinkage model trained on 103 historical shoot-outs (World Cup, Euro, Copa América, Asian Cup, AFCON since 1972). Penalty goals are NOT added to stats.

rate(team) = (PK_wins + 10 × 0.5) / (n_PK + 10)
P(A wins PK) = rate(A) / (rate(A) + rate(B))

Prior is 50% (k=10), strengthens with each recorded shoot-out. Current rates: Argentina 59%, Germany 65%, Brazil 52%, Netherlands 39%, England 40%. Validated on 13 shoot-outs from WC 2014/18/22 (53.8% accuracy vs 50% baseline - not significant at n=13 but no regression).

3rd-place placement: the 495 combinations from FIFA Annex C are approximated - we rank all 12 third-placed teams, take the 8 best, and place them in the bracket's 8 'best 3rd' slots respecting FIFA's group constraints.

Monte Carlo

We run N full tournaments (1k / 10k / 50k / 100k, your choice). Each tournament is independent. Final stats are relative frequencies: 'Argentina won 14,900 of 100,000 tournaments → 14.90% probability'.

Confidence intervals

Each probability is a Bernoulli estimator over N trials. The 95% interval uses the Wilson score (preferred over Wald because it doesn't collapse at p=0 or p=1). With 100k simulations, a 15% probability has a 95% CI of ±0.22pp; at 10k sims it's ±0.70pp. If two teams fall inside each other's CI, the difference isn't statistically distinguishable - run more sims or accept the tie.

center = (p + z²/2N) / (1 + z²/N)
half   = z · √( p(1-p)/N + z²/4N² ) / (1 + z²/N)
lo, hi = center ∓ half        z = 1.96 for 95%

Performance

Pure-TypeScript engine with xoshiro128** PRNG (faster and better-distributed than Math.random) and Knuth's Poisson sampler. 100k sims run in ~3s in Node and ~5-8s in browser via Web Worker.

Sanity checks

  • Champion probabilities sum to 100.000% (exact)
  • Avg goals per match = 2.6 (consistent with World Cup history: 2.5-2.7)
  • Top-5 contenders match bookmaker consensus (Spain, Argentina, France, Brazil, Portugal)

What it does NOT model

Manager changes. Form of the day. Yellow/red cards accumulated mid-tournament (we model them as a Monte Carlo branch but not yet - Tier 1 #4b). The draw (we take it as given). And deliberately: we DON'T tune the model to 'fix' weird outcomes - if the model says something absurd, that's information, not a bug.

Sources

Source code

All simulator code is open-source.

kmanus88/worldcup2026