MathPredictions

How our predictions work

Every number on this site is the output of one pipeline that runs the same way for every fixture. No editor picks the matches, no human overrides a probability, and nothing is quietly withdrawn after it loses.

In outline: recency-weighted attack and defence ratings are fitted from several seasons of results, turned into a full distribution over possible scorelines, cross-checked against what the betting market is pricing, and finally settled against the real result in public. The sections below cover each of those steps.

The data underneath

The engine is fitted on several seasons of completed matches across every competition covered here: full-time and half-time scores, corners won and conceded, and the shots and possession the feed carries, which drive the on-page context panels and the corners fallback chain. Alongside them sits a bookmaker price snapshot taken when a prediction is generated and refreshed while the fixture is still open. Esports, virtual and simulated competitions are excluded through a maintained registry rather than by name-matching, so their scorelines can never contaminate a real team's rating.

Time-decayed attack and defence ratings

Every team carries an attack rating and a defence rating — how much it creates and how much it concedes relative to its own environment. The two are fitted jointly by iterative proportional fitting, a closed-form solver that alternates between attack and defence until the entire pool reproduces the scoring actually observed in it, with each historical match discounted by an exponential recency kernel. Recent form dominates and older seasons fade out smoothly, rather than being cut off at an arbitrary season boundary. Fitting happens inside per-country pools that contain a nation's divisions and its domestic cups together, so cup ties act as bridges between divisions, and a promoted side arrives with a rating earned against real opposition instead of a blank slate.

Handling thin evidence

Raw ratings overreact to small samples, so every one of them is shrunk toward its pool prior in proportion to the evidence behind it — an empirical-Bayes step that stops a club with a handful of matches on record from looking like a juggernaut because two of them finished 4-0. League base rates get the same treatment against the pool mean, which keeps a small competition inside a large pool from drifting on noise. The strength of that pull is set by effective sample size, not by match count, so heavily decayed old fixtures correctly count for less.

From ratings to a scoreline distribution

For each fixture the two teams' ratings and the competition's home and away base rates produce an expected goal count for each side. Those expectations are expanded into a full scoreline probability grid — every plausible result from 0-0 upward — carrying the Dixon-Coles correction for the well-documented dependence between the two scores in low-scoring games, which independent-Poisson models get wrong precisely where football actually lives. Match result, correct score, goals over/under, both teams to score, double chance and Asian handicap are all read off that single normalized grid. No two markets we publish can contradict each other, because the over/under price and the correct-score price are the same distribution viewed twice.

Reading the market properly

Where bookmaker prices exist, they are not taken at face value. Posted odds carry the book's margin, so they are first de-margined into fair probabilities. Handicap and total lines are then solved as a system for the two quantities the market is really expressing — the supremacy between the sides and the expected goal total — which is a far more stable signal than any individual price. Quarter lines are priced through a split-stake kernel that handles the half-win and half-loss branches exactly, instead of being rounded to the nearest whole line the way most published models quietly do.

A dedicated corners model

Corners are not inferred from goals. They get their own attack and defence ratings — corners won and conceded, fitted through the same decayed solver — projected per side and then priced against the exact corner line of the match through a discretized continuous distribution rather than a lookup table. Where a team's corner history is too thin to trust, the model degrades along a defined chain: ratings first, then live match statistics, then the market alone. Where none of those clear the bar, it reports no data instead of inventing a number.

Precision-weighted blending

Model and market are combined by precision weighting on effective sample size: the market carries most of the weight for teams whose history is thin, the model carries most of it in deeply covered leagues, and the crossover is continuous rather than a switch. When a value gap of 5% or more survives that blend, the pick is flagged as value — the model is claiming an edge the price does not reflect, and it says so publicly before kickoff, where anyone can check it afterwards.

Calibration and out-of-sample testing

Nothing ships on the strength of a good-looking backtest. The engine is validated across roughly half a million historical matches under strict out-of-sample separation: ratings are fitted only on what was knowable before each kickoff, and outcomes are scored on log-loss and Brier score — proper scoring rules that punish confident wrongness rather than rewarding it — alongside hit rate against the line and binned calibration curves that check whether a 60% call really does win about 60% of the time. A version that misses its acceptance thresholds does not go live.

No hand-picking

Every eligible real-football match gets a prediction — no cherry-picking the easy ones. Predictions freeze 30 minutes before kickoff, and every frozen pick is settled against the final result and counted in the public accuracy record, wins and losses alike.