Make your team on this device?
You opened a personal TableTalk link. Your team is starred in every table and shown first on the home page. Nothing is saved unless you say so.
Replace with as your team on this device?
You opened a personal TableTalk link for a different team.
is already your team on this device.
This link's team isn't one we cover this season.
Nothing was changed. You can pick a team with the Your team button at the top of the page.
Track record
Every night the model's newest prediction for each upcoming match is saved. The last one saved before a match kicks off is its locked prediction. Only locked predictions are scored, so nothing can be adjusted after the result. Backtests (predictions of past seasons) are never mixed in: they are on the methodology page.
So far
96 matches scored. Against base rates: model better (log loss difference −0.120 ± 0.073).
- Locked predictions
- 97
- Scored
- 96
- Awaiting a result
- 0
- Voided (postponed, suspended, cancelled)
- 1
- Not counted: made after the actual kick-off
- 0
- Missed: no prediction before kick-off
- 0
- Awarded (decided off the pitch), not scored
- 0
Recording since . Matches before then have no locked predictions, and never count as missed. Updated .
How the model compares
Each scored match is also forecast by two others, on exactly the same matches: base rates (the league's usual home, draw and away frequencies, i.e. knowing nothing about the teams) and the market (bookmakers' closing odds with their margin removed, which arrive a few days after each match). The score is log loss: lower is better, and it punishes confident mistakes hardest.
The difference is the model's log loss minus the other's (negative = model better), with a 95% interval. If the interval includes zero, the verdict is “no detectable difference”.
Against the market: 96 matches so far, too few to judge: roughly 225 are needed to detect a gap the size the backtest found (0.02 in log loss).
Against base rates
| League | Matches | Model | Base rates | Difference ± 95% interval | First half | Second half | Verdict | Matches needed |
|---|---|---|---|---|---|---|---|---|
| All leagues | 96 | 0.924 | 1.044 | −0.120 ± 0.073 | −0.104 | −0.136 | model better | 80 |
| Premier League | 20 | 0.939 | 1.037 | −0.098 ± 0.155 | +0.034 | −0.230 | no detectable difference | 76 |
| Bundesliga | 18 | 1.010 | 1.042 | −0.032 ± 0.160 | +0.019 | −0.082 | no detectable difference | 72 |
| La Liga | 20 | 0.899 | 1.111 | −0.213 ± 0.118 | −0.188 | −0.238 | model better | 44 |
| Serie A | 20 | 0.963 | 1.016 | −0.054 ± 0.200 | −0.191 | +0.084 | no detectable difference | 126 |
| Ligue 1 | 18 | 0.805 | 1.011 | −0.206 ± 0.169 | −0.163 | −0.249 | model better | 81 |
Against the market
| League | Matches | Model | Market | Difference ± 95% interval | First half | Second half | Verdict | Matches needed |
|---|---|---|---|---|---|---|---|---|
| All leagues | 96 | 0.924 | 0.913 | +0.010 ± 0.031 | +0.002 | +0.019 | no detectable difference | 225 |
| Premier League | 20 | 0.939 | 0.882 | +0.057 ± 0.057 | +0.057 | +0.058 | model worse | 165 |
| Bundesliga | 18 | 1.010 | 1.041 | −0.031 ± 0.068 | −0.034 | −0.028 | no detectable difference | 207 |
| La Liga | 20 | 0.899 | 0.870 | +0.029 ± 0.053 | +0.083 | −0.026 | no detectable difference | 143 |
| Serie A | 20 | 0.963 | 0.942 | +0.021 ± 0.087 | −0.047 | +0.090 | no detectable difference | 376 |
| Ligue 1 | 18 | 0.805 | 0.837 | −0.033 ± 0.070 | −0.040 | −0.025 | no detectable difference | 222 |
“First half” and “second half” split the matches in date order. A difference that holds in only one half is “consistently better (or worse) but modest”. “Matches needed” is roughly how many matches it takes to detect a gap the size the backtest found: 0.08 in log loss against base rates, 0.02 against the market. Below that, “no detectable difference” means “not enough matches yet”, not “no better”.
Calibration
When the model says 60%, does it happen about 60% of the time? Forecasts are grouped by the chance they gave, and each group's average forecast is compared with how often the outcome happened.
Across: the average forecast in each group. Up: how often it happened, with its 95% interval. On the diagonal = honest forecasts.
| Outcome | Forecast range | Forecasts | Average forecast | Happened | 95% interval |
|---|---|---|---|---|---|
| Home win | 0%–20% | 10 | 17% | 20% | 6%–51% |
| Home win | 20%–40% | 39 | 31% | 33% | 21%–49% |
| Home win | 40%–60% | 31 | 50% | 61% | 44%–76% |
| Home win | 60%–80% | 14 | 69% | 86% | 60%–96% |
| Home win | 80%–100% | 2 | 84% | >99% | 34%–>99% |
| Draw | 0%–20% | 11 | 16% | 27% | 10%–57% |
| Draw | 20%–40% | 85 | 25% | 21% | 14%–31% |
| Away win | 0%–20% | 22 | 14% | 5% | 1%–22% |
| Away win | 20%–40% | 44 | 31% | 18% | 10%–32% |
| Away win | 40%–60% | 26 | 49% | 62% | 43%–78% |
| Away win | 60%–80% | 4 | 66% | 50% | 15%–85% |
Scored matches
The 50 most recent of 96, newest first. Times in UTC. Every scored match is in summary.json on the data branch.
| Kick-off | Match | Score | Home | Draw | Away | Log loss | Predicted | Model version |
|---|---|---|---|---|---|---|---|---|
| Levante v Athletic BilbaoLa Liga | 3–1 | 37% | 27% | 36% | 1.000 | e1e4276 | ||
| Getafe v Rayo VallecanoLa Liga | 1–1 | 37% | 35% | 28% | 1.047 | a31da68 | ||
| Tottenham Hotspur v Coventry CityPremier League | 3–1 | 55% | 25% | 20% | 0.602 | a31da68 | ||
| Parma v TorinoSerie A | 0–3 | 33% | 30% | 37% | 0.993 | a31da68 | ||
| Monza v CagliariSerie A | 4–0 | 30% | 27% | 43% | 1.188 | a31da68 | ||
| Real Madrid v SevillaLa Liga | 4–1 | 75% | 16% | 9% | 0.281 | a31da68 | ||
| Lyon v NiceLigue 1 | 2–1 | 56% | 24% | 20% | 0.571 | a31da68 | ||
| Juventus v LazioSerie A | 0–3 | 48% | 28% | 24% | 1.411 | a31da68 | ||
| Málaga v Real SociedadLa Liga | 2–5 | 29% | 27% | 44% | 0.819 | a31da68 | ||
| AC Milan v AtalantaSerie A | 3–2 | 40% | 27% | 33% | 0.915 | a31da68 | ||
| Nottingham Forest v ArsenalPremier League | 0–1 | 18% | 27% | 55% | 0.595 | a31da68 | ||
| Borussia Mönchengladbach v TSG HoffenheimBundesliga | 1–2 | 41% | 23% | 36% | 1.014 | a31da68 | ||
| Lorient v MonacoLigue 1 | 1–0 | 30% | 25% | 45% | 1.193 | a31da68 | ||
| Paris FC v RennesLigue 1 | 4–3 | 42% | 25% | 33% | 0.876 | a31da68 | ||
| Le Havre v AuxerreLigue 1 | 1–3 | 37% | 29% | 34% | 1.091 | a31da68 | ||
| Celta Vigo v AlavésLa Liga | 2–1 | 50% | 27% | 23% | 0.688 | a31da68 | ||
| Bayer Leverkusen v SC FreiburgBundesliga | 2–1 | 62% | 20% | 18% | 0.476 | a31da68 | ||
| Fiorentina v ComoSerie A | 1–3 | 25% | 26% | 49% | 0.716 | a31da68 | ||
| Leeds United v Manchester UnitedPremier League | 1–1 | 36% | 27% | 37% | 1.304 | a31da68 | ||
| Brighton & Hove Albion v Crystal PalacePremier League | 5–0 | 54% | 25% | 21% | 0.615 | a31da68 | ||
| Bournemouth v SunderlandPremier League | 2–0 | 47% | 27% | 26% | 0.761 | a31da68 | ||
| Angers v MarseilleLigue 1 | 2–5 | 20% | 25% | 55% | 0.589 | a31da68 | ||
| Osasuna v Racing SantanderLa Liga | 2–0 | 59% | 21% | 20% | 0.524 | a31da68 | ||
| Udinese v LecceSerie A | 0–3 | 50% | 28% | 22% | 1.527 | a31da68 | ||
| Valencia v Athletic BilbaoLa Liga | 0–0 | 36% | 29% | 35% | 1.229 | de5189c | ||
| Troyes v LensLigue 1 | 1–3 | 16% | 21% | 63% | 0.456 | de5189c | ||
| Roma v GenoaSerie A | 2–0 | 65% | 22% | 13% | 0.433 | de5189c | ||
| Lille v BrestLigue 1 | 1–1 | 57% | 24% | 19% | 1.428 | de5189c | ||
| Real Betis v BarcelonaLa Liga | 2–5 | 24% | 22% | 54% | 0.612 | de5189c | ||
| Newcastle United v Aston VillaPremier League | 0–1 | 44% | 25% | 31% | 1.162 | de5189c | ||
| Bayern Munich v RB LeipzigBundesliga | 6–1 | 70% | 16% | 14% | 0.353 | de5189c | ||
| Bologna v Inter MilanSerie A | 1–3 | 19% | 22% | 59% | 0.530 | de5189c | ||
| Strasbourg v Paris Saint-GermainLigue 1 | 1–3 | 23% | 22% | 55% | 0.589 | de5189c | ||
| Villarreal v ElcheLa Liga | 0–0 | 67% | 18% | 15% | 1.719 | de5189c | ||
| Brentford v LiverpoolPremier League | 1–2 | 35% | 25% | 40% | 0.921 | de5189c | ||
| Manchester City v Ipswich TownPremier League | 3–2 | 86% | 10% | 4% | 0.158 | de5189c | ||
| Fulham v Hull CityPremier League | 1–0 | 48% | 28% | 24% | 0.732 | de5189c | ||
| Union Berlin v Borussia DortmundBundesliga | 0–0 | 17% | 23% | 60% | 1.474 | de5189c | ||
| Hamburger SV v VfB StuttgartBundesliga | 1–0 | 23% | 24% | 53% | 1.458 | de5189c | ||
| Werder Bremen v Paderborn 07Bundesliga | 2–2 | 49% | 28% | 23% | 1.277 | de5189c | ||
| Schalke 04 v Mainz 05Bundesliga | 0–1 | 30% | 29% | 41% | 0.882 | de5189c | ||
| SV Elversberg v FC AugsburgBundesliga | 4–3 | 39% | 28% | 33% | 0.947 | de5189c | ||
| Venezia v NapoliSerie A | 1–0 | 13% | 20% | 67% | 2.087 | de5189c | ||
| Espanyol v Atlético MadridLa Liga | 0–1 | 25% | 25% | 50% | 0.695 | de5189c | ||
| Everton v ChelseaPremier League | 0–2 | 34% | 28% | 38% | 0.976 | de5189c | ||
| Deportivo La Coruña v LevanteLa Liga | 1–1 | 43% | 24% | 33% | 1.420 | de5189c | ||
| Frosinone v SassuoloSerie A | 4–2 | 33% | 25% | 42% | 1.110 | de5189c | ||
| Le Mans v ToulouseLigue 1 | 0–3 | 33% | 26% | 41% | 0.884 | de5189c | ||
| Eintracht Frankfurt v 1. FC KölnBundesliga | 1–0 | 57% | 21% | 22% | 0.571 | de5189c | ||
| Levante v SevillaLa Liga | 3–3 | 45% | 25% | 30% | 1.383 | 3796e2c |
How the record is kept honest
- The lock is the last prediction made before kick-off. “Made” means when it was written to disk, the strictest reading.
- Postponed, suspended or cancelled: the lock is kept but voided, and never scored. A rearranged match gets a new lock before its new kick-off.
- Checked against the real kick-off: a prediction that turns out to be from after the actual kick-off is not counted. A match no update predicted in time is recorded as missed.
- Edits show: each line of the lock log carries a fingerprint (sha256) of the line before it, so changing or deleting an old line breaks the chain. The pipeline checked the chain before writing this summary.
- Timing: every night's files are committed to the public data branch, which is protected against rewriting. That is strong evidence of when each prediction was published, not proof: it rests on GitHub's records.
Notes from the pipeline
- Only predictions locked before kick-off by the daily run are scored. Backtests and any retrospective predictions are never mixed in.
- Differences are model minus the other forecaster in log loss (negative = model better), with a 95% interval. With few matches the intervals are wide;
matches_neededis roughly how many matches it would take to detect a gap the size the backtest found (0.08 against base rates, 0.02 against the market). - Market probabilities come from closing odds with the margin removed proportionally (an assumption). They appear a few days after each match.