Football Forecasts: method notes
The Messi model gives a home-win, draw and away-win probability, plus an expected score, for every upcoming 2026-27 match in the Premier League, La Liga, Serie A, Bundesliga and Ligue 1. It started from Kareem's original Poisson notebook, and every improvement was checked on matches the model had not seen.
In plain terms: the Messi model picked the right result in 52.3% of 2025-26 matches, up from 40.4%
- Forecast: Gives the chance of a home win, a draw and an away win, plus the likeliest score, for every upcoming match.
- Back-test: Forecast all 1,752 matches of 2025-26 using only matches played before each one. The Messi model picked the right result 52.3% of the time, against 40.4% for the original model.
- Benchmark: Trailed bookmakers, who picked the right result 53.4% of the time.
- Error Score: Cut the error score from 1.429 to 0.994, where lower is better (bookmakers: 0.978). The score rewards forecasts that are both right and appropriately confident.
Terms used below, in one line each:
- xG (expected goals): how many goals a side's chances would normally produce, so it measures chance quality rather than luck.
- Elo: a running strength score, as in chess, that moves up or down after every result.
- Dixon-Coles: a correction so low scores and draws (0-0, 1-1) come out at the right frequency.
- Poisson model: the standard way to turn a team's expected goals into the chance of each exact score.
- Log loss and Brier score: two error scores for probabilities. They reward forecasts that are both right and appropriately confident; lower is better.
- Walk-forward back-test: replaying past matches in order, using only what was known before each one.
The technical detail follows.
Where it started: Kareem's original model
The original is the notebook Football.ipynb at the root of the walkofgrit/mentorme.github.io repo, available at walkofgrit.com/Football.ipynb. It covered the EPL, MLS and La Liga, and works like this:
- It looks back over the last 19 matchweeks.
- League baseline: the log of average away goals. The home edge is average home goals minus average away goals.
- Team ratings: each team gets an attack rating from the goals it scores at home and a defence rating from the goals it lets in away, both measured against that baseline.
- Expected goals: each side's expected goals is exp(baseline + home edge + attack + opponent's defence). This is a Poisson model in the style of Maher (1982).
- The pick: whichever side has the higher expected goals is picked to win, and the pick is compared with the bookmaker underdog. Exact scores come from head-to-head averages.
- Sentiment plan: a database layout for manager sentiment lagged by seven days ("lead the outcome, lag the sentiment").
How the Messi model improves on the original
| Step | Why |
|---|---|
| Dixon-Coles correction for 0-0, 1-0, 0-1 and 1-1 scores, with one correlation value fitted per league | Plain Poisson gets low-scoring draws wrong |
| Every match, home and away, fitted jointly by weighted maximum likelihood, with a mild pull toward average (ridge 0.5) | The original used home goals for attack and away goals for defence only |
| Time decay, half-life 240 days | Recent form counts more, and three seasons of history steady the early weeks |
| Expected goals (xG): the target is 50% goals and 50% xG. Match xG is used where football-data.co.uk publishes it (2026-27). For older seasons a shots proxy is fitted on 2023-24 (about 0.34 goals per shot on target) | xG is a steadier signal of team quality than goals |
| Home advantage fitted per league, inside the model (×1.12 in Serie A up to ×1.31 in La Liga) | The original added a raw goal difference in log space |
| Elo blend: 85% Dixon-Coles plus 15% Elo (K 20, home edge 60, 75% carried over each season, promoted sides start 100 below), mapped to win/draw/loss by an ordered logit | Elo reacts to results quickly and covers promoted teams |
| Full probabilities for win, draw and loss, plus the likeliest score | The original only picked a winner and almost never called a draw |
All settings (the half-life, the xG share and the Elo share) were chosen on the 2024-25 season only. The model was then frozen and tested on 2025-26.
Back-test
The back-test is walk-forward. Every match is predicted using only earlier matches, and the model is refitted each week. Lower Brier and log loss are better.
Test season 2025-26 (all five leagues, 1,752 matches)
| Model | Brier | Log loss | Accuracy |
|---|---|---|---|
| Kareem's original Poisson (its own probabilities) | 0.833 | 1.429 | 28.5% |
| Original, as picked (higher expected goals wins) | – | – | 40.4% (6 draws picked) |
| Dixon-Coles, goals only | 0.597 | 1.001 | 51.8% |
| Improved (Dixon-Coles + xG + Elo) | 0.593 | 0.994 | 52.3% |
| Bookmaker average odds (benchmark, not an input) | 0.583 | 0.978 | 53.4% |
2026-27 so far (404 matches to 29 Oct): the original scored 0.917 Brier, 1.774 log loss and 41.8% accuracy as picked. The Messi model scored 0.578 Brier, 0.976 log loss and 52.5% accuracy. The bookmaker average scored 0.569, 0.961 and 55.0%.
The Messi model outperformed the original in every league. Its 2025-26 log loss by league:
| League | Original | Improved |
|---|---|---|
| EPL | 1.43 | 1.02 |
| La Liga | 1.41 | 0.98 |
| Serie A | 1.53 | 1.00 |
| Bundesliga | 1.41 | 0.97 |
| Ligue 1 | 1.34 | 1.00 |
It still trails the bookmakers slightly. Bookmakers price in team news, injuries and line-ups, which this model does not see. Base rates for 2025-26 were 44% home wins, 25% draws and 31% away wins.
Season simulation
The remaining fixtures are played 10,000 times using the model's expected goals. From those runs the site gives each club's projected points and its chances of winning the title, finishing in the top four, and landing in the bottom three. In Germany and France the bottom three includes the relegation play-off place.
Team and player deep dives
Team pages show:
- the table, form and match-by-match xG for and against
- attack and defence ratings, where 1.00 is the league average
- Elo, rescaled so the league average is 1500
- the model's pre-match win chance for every game played
- the next six fixtures
Player pages show the top eight players for each club by goals plus assists, with plain-English "drivers":
- Playing time: share of league minutes, or of starts outside the EPL
- Shot volume: shots per 90 minutes or per appearance, and share of the group's shots
- Chance quality: xG per shot
- Finishing: goals minus xG, flagged as running hot or under-finishing
- Creation: assists and xA
- Role
Minutes, xG and xA come from the Fantasy Premier League API, so per-90 and xG drivers exist for Premier League players only. In the other four leagues the drivers use appearances, starts, shots, shots on target and conversion.
News sentiment
- Source: public posts on X from an allowlist of neutral news and stats accounts: @OptaJoe, @BBCSport, @BBCMOTD, @SkySportsPL, @TheAthleticFC, @ESPNFC, @Squawka, @WhoScored, @footballitalia, @premierleague, @LaLigaEN, @SerieA_EN, @Bundesliga_EN, @Ligue1_ENG and @StatsPerform.
- Left out: club accounts, fan accounts, transfer-rumour accounts and anyone posting opinion for engagement.
- Collection: English posts only, no reposts, from the last seven days, using one query per Premier League club and one combined query per league elsewhere.
- Scoring: each post is scored with VADER plus a small football word list. Words like "unbeaten", "defeat", "injury" and "sacked" are included, and links are stripped first.
- Team score: the average of the posts that name the club.
- Player score: the average of the club's posts that name the player.
- What the site shows: the score and links to the posts. The post text itself is not stored.
Effect on accuracy: The check uses the posts from 16 to 23 October and the matches of 23 to 29 October. On the 14 matches where both sides had at least two posts, tilting the probabilities toward the side with better press made log loss slightly worse at every strength tried (1.184 with no tilt, 1.188 at the smallest tilt). Fourteen matches is far too few to conclude anything. The sentiment score is therefore shown next to each forecast as a separate signal, and it is not used in the probabilities. The rule, fixed in advance, is to switch it on only once at least 150 matches show a log-loss gain of 0.005 or more.
Data sources
All sources are free and public:
- football-data.co.uk: results, shots, 2026-27 match xG, and average odds (used as a benchmark only)
- fixturedownload.com: fixtures and kick-off times
- ESPN's public site API: squads and player goals, assists, shots and appearances
- Fantasy Premier League: Premier League minutes, xG and xA
- X: allowlisted public posts
Downloads are cached and rate-limited. Understat and FBref were not used because Understat's robots.txt disallows crawling and FBref blocks automated requests.
Risks and known gaps
- There is no player xG or minutes outside the Premier League.
- The model sees no team news, injuries or line-ups.
- English-language news coverage of La Liga, Serie A, Bundesliga and Ligue 1 clubs is thin, so many of their sentiment scores rest on a handful of posts.
- No discussion boards such as Reddit are used yet.
- One La Liga match, Rayo Vallecano v Athletic Club from 10 October, is postponed with no new date. It is included in the season simulation.
Prediction ledger
Every forecast is written to the prediction ledger (with a CSV copy) before kick-off. Each row records the home, draw and away probabilities, expected goals, the likeliest score, the original model's probabilities and pick, a made_at time in US Eastern time and the data cut-off.
- Append-only. A build may add new rows and fill in results for matches that have been played. It never edits a row. Before writing, the build compares the new ledger with the old one and stops with an error if any existing row or result has changed.
- Hash chain. Each row stores a sha256 of its own fields plus the previous row's hash, so editing, reordering or deleting a row breaks every hash after it. Each result has its own sha256 too. Anyone can download the prediction ledger and recompute the hashes to confirm nothing was rewritten.
- Sources.
backtest-walkforwardrows are the 404 matches of 2026-27 already played when the ledger began on 30 October 2026. Each was predicted only from data before its match week, and the probabilities are copied unchanged from the walk-forward back-test.liverows were frozen before kick-off, and new rounds are added as they come up. - Benchmarks. The scorecard on each page compares the model with the original Poisson notebook and with average bookmaker odds from football-data.co.uk, using the 3-way Brier score (lower is better), accuracy and a calibration chart.