Diego Garcia

Back to briefs

> var / storm

The Model That Predicts Best Returns the Least

KairoX Storm, an independent Poisson model for total goals, was evaluated across La Liga, Premier League, and Bundesliga over three validation seasons each. Bundesliga produced the best log-loss of the three leagues and the only consistently negative ROI. A Gamma prior added to fix the model's calibration then made every other metric worse.

Jun 202614 min read

Sports prediction work usually assumes that better probability estimates produce better betting returns: improve the log-loss and the edge follows. The cross-league KairoX Storm evaluation is a clean counterexample.

KairoX Storm is a bivariate independent Poisson model: for each match, home and away expected goals are computed from per-team attack and defence ratings estimated via maximum likelihood, and over/under probabilities for lines 0.5 through 4.5 are derived analytically from the resulting joint distribution. The model was evaluated identically across La Liga, Premier League, and Bundesliga using three-fold walk-forward cross-validation on five seasons of data, which gives nine validation folds from one model and one protocol.

Two additional prediction variants were tested alongside the analytical baseline: MC-pure (10,000 Monte Carlo samples from the same Poisson distributions, replacing the analytical convolution) and MC-Gamma (Gamma-sampled lambda before Poisson sampling, propagating uncertainty in the rate estimates). Comparing the three gives the second finding.

The Inversion

Across nine validation folds on the Over 2.5 line, AUC and ROI are uncorrelated (r = 0.06). The fold with the highest AUC (LA F0, AUC=0.639) returns +6.0%; the second-highest (BU F0, AUC=0.608) returns -6.2%. All three Bundesliga folds lose money, at AUCs from 0.553 to 0.608.

Predictive accuracy has no relationship with betting returns

AUC vs flat-stake ROI, Over 2.5 line, analytical model, 9 validation folds across 3 leagues.

-20%-18%-16%-14%-12%-10%-8%-6%-4%-2%0%2%4%6%8%10%0.5400.5500.5600.5700.5800.5900.6000.6100.6200.6300.6400.650AUC (Over 2.5, analytical)Flat-stake ROI % (Over 2.5)LA F0LA F1LA F2PL F0PL F1PL F2BU F0BU F1BU F2
La LigaPremier LeagueBundesliga
Figure 1: AUC vs flat-stake ROI on the Over 2.5 line across 9 validation folds (3 leagues, 3 folds each). No positive correlation. Every Bundesliga fold (squares) sits below zero ROI, whatever its AUC. Premier League fold 0 (amber diamond, bottom-left) is the exception in the opposite direction: low AUC, deeply negative ROI, driven by a season-level scoring shift the model could not anticipate.

Averaged by league:

LeagueOver 2.5 AUCOver 2.5 log-lossMean ROI (3 folds)
Bundesliga0.5870.661-8.4%
La Liga0.5990.681-1.5%
Premier League0.5590.686-2.1%

Cross-league summary on the Over 2.5 line. Bundesliga has the best log-loss and the worst ROI. Premier League has the worst predictive performance and the most encouraging ROI trajectory (fold-over-fold: -15%, +2%, +6%).

The mechanism is market efficiency. Bundesliga is a high-scoring league: the Over 2.5 rate sits between 60% and 64% across all three validation seasons, well above La Liga (46-50%) and Premier League (55-65%). A consistently tilted market is an easier prediction problem, and a predictable market attracts sharper pricing. The bookmakers have priced the Bundesliga's scoring into their Over 2.5 odds, so the signal the model finds is already in the price.

La Liga sits closest to the 50% over rate, making its 2.5 line the hardest to predict and the most sensitive to small probability errors. It is also the market with the most variance in bookmaker pricing, which is where the model's occasional edges appear. Premier League fold 0 fails badly (-15% ROI, ECE=0.152) because the 23-24 season produced a 64.7% over-2.5 rate after two lower-scoring training seasons, a season-level shift that prior data could not have anticipated.

What MC-Gamma Gets Wrong

The MC-Gamma variant was designed to address a real limitation: the analytical Poisson convolution treats lambda as a known quantity rather than an estimate with uncertainty. The Gamma distribution is the conjugate prior to the Poisson, so sampling lambda from Gamma(alpha, lambda/alpha) before sampling goals is a principled way to propagate parameter uncertainty. The resulting marginal distribution over goals is Negative Binomial, which has heavier tails than Poisson and is empirically a better fit for football goal counts.

The hypothesis was that this would improve tail-line probability estimates and reduce calibration error. On ECE for the 2.5 line in La Liga, it does: ECE drops from 0.053 (analytical) to 0.049 (MC-Gamma). Every other metric gets worse.

MC-Gamma raises log-loss everywhere and roughly doubles ROI losses on Over 0.5

Analytical, MC-pure, and MC-Gamma compared across all three leagues.

Log-loss by approach (Over 2.5)

0.6550.6600.6650.6700.6750.6800.6850.6900.695Log-loss (lower = better)La LigaPremier LeagueBundesliganaive baseline (ln 2)

Mean ROI: analytical vs MC-Gamma (Over 0.5)

-50%-45%-40%-35%-30%-25%-20%-15%-10%-5%0%5%Mean ROI % (Over 0.5)La LigaPremier LeagueBundesliga
AnalyticalMC-PureMC-Gamma
Figure 2: Left: log-loss on the Over 2.5 line for all three approaches across leagues. MC-Gamma raises log-loss in every league, most severely in Premier League where it crosses the naive baseline. Right: mean ROI on the Over 0.5 line for analytical vs MC-Gamma. The Gamma prior roughly doubles the losses on a line where the analytical model was already losing.

MC-Gamma fails most visibly on the Over 0.5 line. There, analytical mean ROI across the three leagues is -32.6%, -11.3%, and -12.4% for La Liga, Premier League, and Bundesliga respectively. MC-Gamma returns -40.6%, -34.0%, and -39.2%. With uncertainty propagation the model loses about twice as much on average, and three times as much in the Premier League and Bundesliga, on a line where the event occurs 93-97% of the time.

Sampling lambda from a Gamma distribution includes low-lambda draws, where the sampled rate sits well below the point estimate. In a league where teams score approximately 2.5-3.0 goals per game, a low-lambda draw produces a meaningful probability on zero total goals. Poisson(0.8) assigns about 45% probability to a scoreless game. When these low-lambda samples are averaged into the MC-Gamma estimate, P(0 goals) inflates systematically. The model starts betting Under 0.5 in matches where the true probability of a scoreless game is 3-7%, and those bets lose consistently.

Lambda uncertainty is also not what limits KairoX Storm. The MLE fit on 2-4 seasons of match data produces well-determined team ratings: the standard error on a team's attack parameter from 100-150 career matches is small relative to the inter-team variation. Propagating that uncertainty adds noise to estimates that are already stable. What is not captured by the Poisson model is structural: the independence assumption between home and away goals, the inability to model within-match state dependence (scorelines affect subsequent play), and the absence of opponent-adjusted recent form. Widening the lambda distribution fixes none of these.

MC-pure adds nothing either

The pure Monte Carlo variant, which samples from the same Poisson distributions as the analytical convolution, produces results within 0.0002 log-loss of analytical in every league. That is what an exact convolution and negligible sampling noise at 10,000 iterations should produce. MC-pure costs far more compute for no benefit.

Time Decay and What It Reveals About MLE

All three leagues independently select near-zero time decay as optimal. La Liga: xi=0.001. Premier League: xi=0.000. Bundesliga: xi=0.000, with a monotone increase in log-loss at every subsequent decay level tested.

Time decay adds no signal: MLE team ratings are already optimal

Mean CV log-loss on the Over 2.5 line vs the time-decay parameter (xi), per league.

0.65500.66000.66500.67000.67500.68000.68500.69000.69500.70000.70500.0000.0010.0020.0030.005Time decay parameter (ξ)Mean CV log-loss (Over 2.5)best ξ=0.001best ξ=0.000best ξ=0.000
La LigaPremier LeagueBundesliga
Figure 3: Time decay parameter (xi) vs mean CV log-loss on the Over 2.5 line. All three leagues reach their minimum at xi=0 or xi=0.001. Bundesliga's curve is monotone: every step toward recency weighting raises log-loss.

The expected result would be that some decay helps: teams change over time, players move, managers rotate, and last month's performance is more relevant than three seasons ago. The data disagrees. Bundesliga is the clearest case because its curve is monotone instead of a shallow U: any decay at all makes things worse.

The maximum likelihood estimator for each team's attack and defence parameters uses all historical matches simultaneously to find the parameter values that maximise the joint likelihood of the observed scorelines. This is equivalent to a weighted average of all matches, where the weight is determined by the information content of each match rather than its recency. A match from three seasons ago carries less leverage only if the team's true scoring rate has changed since then. If the structural quality hierarchy between teams is stable within the training window, older matches are informative and removing them by decay costs more than it gains.

Bundesliga shows this most clearly because its quality hierarchy is the most stable: Bayern Munich, Borussia Dortmund, and Bayer Leverkusen have consistently been the three strongest attacking teams in the dataset, and the bottom half is mostly the same clubs every season. The MLE estimate from four seasons of data is a better estimate of each team's scoring rate than one weighted toward recent games, because the signal is stable and every historical match contributes information that recency weighting would discard.

Time decay is therefore the wrong way to bring recent form into a Poisson rating model. A form residual would do it directly: how far is a team currently scoring above or below its long-run MLE rate? That is a separate signal, and it needs its own term in the model.

Where This Leaves the Model

The Poisson model beats the naive log-loss baseline on the 2.5 line in all three leagues. Its ECE is well-controlled (0.053 in La Liga, 0.054 in Bundesliga, 0.074 in Premier League on the primary line). Its AUC on the 2.5 line ranges from 0.56 in the Premier League to 0.60 in La Liga. That is respectable for a model with no match-level features, rolling form windows or xG.

The returns show its ceiling. Three folds of La Liga data return +6.0%, -11.2%, +0.7% on the 2.5 line: one strong season, one season that breaks badly, one near-flat. Premier League shows an improving trajectory (-15%, +2%, +6%) that is consistent with a model whose reliability grows as its training window extends, but three folds is not enough to confirm a structural edge. Bundesliga is priced efficiently enough that the model has no market edge on the 2.5 line despite its best log-loss.

Across the three leagues, the constraints that bind are: the Poisson independence assumption (within-match state dependence is unmodelled), the absence of form features (static ratings cannot track within-season team trajectories), and the season-level scoring drift problem (La Liga and Premier League show year-to-year variation in goal rates that a model trained on prior seasons systematically underestimates). MC-Gamma, time decay tuning and more Monte Carlo samples address none of them. They need structural changes to the model: rolling form residuals, season-level intercepts, or a hybrid with ML features that capture what static ratings cannot.

On the PL fold 0 outlier

Premier League fold 0 (val 23-24) produced ECE=0.152 on the 2.5 line, the worst calibration in the experiment. The 23-24 PL season had a 64.7% Over 2.5 rate, while the model was trained on 21-22 and 22-23 with lower scoring, so it under-predicted goals in a season where Haaland-era scoring was at its peak. That is non-stationarity, which any model trained on historical data will meet when scoring shifts between training and deployment. The season-level intercept experiment, which models year-to-year goal rate drift explicitly, is the direct response.