Model

Time decay in football prediction models: how much should old results count?

By · Published · 7 min read

A match played two years ago and a match played last month are not equally informative about how good a team is now. Players leave, managers change, systems get rebuilt. Time decay in a football prediction model is the mechanism that encodes this: instead of treating every historical result as one full observation, the model weights each match by how recent it is. The idea is simple. The consequences — for how fast the model reacts, how much it wobbles, and how many matches it is really learning from — are not, and they are almost never disclosed.

What time decay does inside a football prediction model

When a goal model fits attack and defence ratings, it is maximising a likelihood summed over past matches. Without decay, every match contributes equally. With decay, each match k gets a weight w, and the sum becomes a weighted one. Matches with small weights barely move the fitted ratings.

The standard choice is exponential decay:

w = 0.5 ^ (age_in_days / H)

where H is the half-life — the age at which a match counts for exactly half of a fresh one. This is the same device Dixon and Coles introduced alongside their low-score correction, and it is worth reading their model as a whole to see how the pieces fit together. The exponential shape has no cut-off, so nothing drops out of the sample abruptly, and it has exactly one parameter to tune.

Some implementations parameterise it as w = exp(-ξ · age). That is the same function; ξ and H are related by H = ln(2) / ξ. Half-life is the better way to talk about it because it is interpretable. “A half-life of six months” tells you something. “ξ = 0.0039 per day” tells you nothing until you do the arithmetic.

Half-life is the parameter worth quoting

Here is what a handful of half-life choices actually do to a match as it ages:

Match age H = 90 days H = 180 days H = 365 days H = 730 days
Fresh 1.00 1.00 1.00 1.00
3 months 0.50 0.71 0.84 0.92
6 months 0.25 0.50 0.71 0.84
1 year 0.06 0.25 0.50 0.71
2 years 0.004 0.06 0.25 0.50

A 90-day half-life effectively erases anything older than a season: a match from last year contributes 6% of an observation. A two-year half-life keeps that same match at 71%, which means the model is still substantially fitting to a squad that may no longer exist.

Neither column is obviously right. They are different bets about how fast football teams actually change.

The hidden cost: effective sample size

Down-weighting old matches does not come free. You are not adding recency — you are subtracting evidence. The right way to see the cost is effective sample size: the sum of all the weights, which tells you how many full-strength matches the model is really learning from.

For a team playing about 50 competitive matches a year, a continuous history under exponential decay gives an effective sample of roughly H × 1.44 × matches-per-day. Working that through:

Half-life Effective sample Relative standard error
90 days ~18 matches 2.8×
180 days ~36 matches 2.0×
365 days ~72 matches 1.4×
730 days ~144 matches 1.0× (baseline)

Parameter uncertainty scales with the inverse square root of the sample, so moving from a two-year half-life to a three-month one shrinks the effective sample eightfold and widens the error on every team rating by a factor of about 2.8.

That is the entire trade-off in one line. Short half-life: responsive, noisy, prone to chasing variance that looks like change. Long half-life: stable, slow, still carrying a team that was dismantled eighteen months ago. A model that reacts fast to real change also reacts fast to nothing at all, and it cannot tell the two apart at the moment it reacts.

Choosing a half-life without fooling yourself

The half-life is not a matter of taste. It is a parameter, and it should be tuned the way any parameter is tuned — on data the model did not see.

The procedure is a grid search. Pick a range of candidate half-lives, say 60 to 900 days. For each one, refit the model on a training window, generate probabilities for the following period, and score those probabilities with a proper scoring rule such as the Brier score. Then walk the window forward and repeat, so the estimate is not one lucky split. The half-life with the best average out-of-sample score wins. Fitting quality on the training data itself is not evidence of anything here — a shorter half-life will always fit recent matches better, which is exactly the trap.

Two things routinely go wrong.

The curve is flatter than it looks. In most leagues the out-of-sample score barely moves across a wide band of half-lives. If 150 days and 280 days differ by less than the run-to-run variation of your validation procedure, you have not found an optimum — you have found noise with a decimal point on it. The honest output of the search is a range, not a number.

Not every parameter should decay at the same rate. Team attack and defence ratings genuinely move over months. League-level home advantage moves over years, if at all. Applying one aggressive half-life to everything estimates a structural constant from three months of data for no reason. Separating the decay rate for team-level parameters from league-level ones is usually a bigger improvement than fine-tuning a single global value.

There is a third decision most write-ups skip entirely: whether age is measured in calendar days or in matches played. Under calendar decay, a team’s rating quietly erodes across a ten-week summer in which nothing happened. That is defensible — squads turn over between seasons, so evidence really does go stale — but it should be a stated choice, not an accident of using a date column.

Decay is not the same thing as form

Time decay and form are frequently conflated, and they are structurally different.

Form is a feature: a number computed from recent results and fed into the model as an input, sitting alongside everything else. Time decay is a property of the fitting procedure: it changes how much each historical observation influences the parameters, and it adds no new column to the data. The distinction matters because they can cancel out. A model with an aggressive half-life has already concentrated its attention on recent matches; bolting a form variable on top double-counts the same evidence and tends to produce overconfident probabilities on teams in the middle of a streak.

If you want the model to react to recent results, decide whether that reaction lives in the weighting or in the features, and do not build it twice. The question of how much the last five matches should count has a different answer depending on which of the two you have already used.

What disclosure should look like

Half-life is one of the small number of parameters that changes a model’s published probabilities materially, and it is cheap to state. A model that says “team ratings use a 200-day half-life; home advantage is fitted on the full history” has told you something checkable — you can predict that it will move quickly after a managerial change and that it will not have much to say about a newly promoted side. A model that says nothing leaves you unable to distinguish between a rating that shifted because the evidence shifted and one that shifted because the weighting is twitchy.

The check that matters, though, is not the parameter — it is whether the resulting probabilities hold up. A well-chosen half-life should show up as better-calibrated forecasts over a long run of matches, and that is only visible in a record that was published before the results were known. Our own probabilities are logged in advance and scored openly on the track record page, which is where any claim about a modelling choice has to end up if it is going to mean anything.

Tuning a decay parameter is easy. Proving it helped is the hard part, and it takes a few hundred matches and a scoreboard nobody can edit afterwards.