DashboardHow It Works

Seven models, one rule engine, and a scoreboard that keeps them honest.

The full architecture, for the data-curious: how raw FPL data becomes a predicted eleven, and how every prediction is validated against reality.

01

The pipeline

Ingest → Features → Predict → Score → Optimize → Verify. Player match histories, fixtures, and live results come from the official FPL API. A feature factory turns each player-fixture into roughly forty model-ready signals. Seven gradient-boosted models each predict one scoring event. A rule engine converts events to points using FPL's actual scoring rules. A linear-programming optimizer assembles the legal 15-man squad, and a reconciliation job scores everything once results land.

02

Why seven models instead of one

Predicting "total points" directly buries the reasons inside a black box. Predicting the seven events that generate points keeps every claim inspectable — you can see that the model expects a goal but no clean sheet, not just a mysterious "7.2". Each head uses an objective matched to its statistical shape:

EventObjectiveWhy
GoalsPoissoncount data with a low rate
AssistsPoissoncount data with a low rate
Clean sheetsLogisticbinary outcome per match
SavesPoissonkeeper workload is a count
Bonus pointsPoissondiscrete 0–3 award
Defensive contributionLogisticthreshold event (10+/12+ CBIT)
MinutesSquared errorcontinuous playing time

Blanks outnumber hauls roughly 6:1, so positive outcomes are up-weighted at training time — with weights derived from the actual class frequency of the training set at each retrain, not hardcoded.

03

The features that matter

Everything is computed from match history as it stood before each gameweek — never season totals, which would leak the future into the past. Highlights:

Multi-horizon form — rolling points and expected goal involvement over 3, 5, 7, 10 and 15-game windows, because a hot streak and a season trend are different signals. Venue splits — home and away output tracked separately. Set pieces — penalty and corner duty from FPL's own designations (roughly a third of goals come from set pieces). Opponent context — position-specific fixture difficulty from each team's rolling attacking and defensive form, not the static difficulty badge. Season priors — at the start of a season the rolling windows are empty, so every player carries last season's rates, shrunk toward the positional mean, plus a games-played counter that lets the model learn how quickly to hand trust from history to live form. Team strength carries over the same way, regressed a third toward the league mean; promoted teams and new signings start from cautious flags, never fabricated numbers.

Deliberately absent: price. A player's cost is derived from past output, so using it as a signal is circular — "expensive players score more because they're expensive." Instead, the model uses a within-position percentile of points-per-game: pure on-pitch quality, no market bias.
04

From events to points

The seven event predictions are not fed to another model — they're multiplied by FPL's actual scoring rules, position by position: a defender's clean sheet is worth 4, a midfielder's 1; goals range from 4 to 6 by position; a point per three saves; minus for goals conceded. Transparent arithmetic, not a second black box.

On top of the point estimate, a 2,000-run Monte Carlo simulation turns the event rates into probabilities — the chance of a haul, of any return, of a ceiling week — including the real-world correlation that a goalscorer is likelier to also collect bonus points.

05

Validation: the part most projects skip

Every model change is gated on a walk-forward backtest: train on gameweeks 1 through N, predict week N+1, roll forward through the whole season, and measure. No change ships unless it improves out-of-sample error or calibration.

Current benchmarks across the 2025-26 season: mean absolute error of about 2.6 points per player per week, and the predicted best-eleven captured around 37% of the theoretical perfect eleven — measured on weeks the model had never seen.

The same harness runs ablations: every manual adjustment layer is switched off individually and re-measured. Layers that don't earn their place get deleted — one long-standing "sensible" adjustment was removed precisely because the numbers said it hurt.

06

The ledger: no revisions, no hindsight

Before every deadline, the full prediction set is frozen to an immutable ledger. After the final whistle, one reconciliation job fetches the official results and writes a single canonical record of what happened. The public scoreboard is computed from those two files and nothing else — predictions can't be quietly edited after the fact, ever.

Each season is self-contained. When one ends it's sealed into its own archive and the public record resets to zero for the new campaign — no cherry-picking a good run from two years ago. The models still learn across seasons (every training row is tagged with its season), but the scoreboard you see is always this season's honest, from-scratch record.

07

Honest limitations

Clean-sheet probabilities run hot at the high end — a "60%" clean sheet lands more like one-in-three or one-in-four. Calibration improved sharply this off-season and is the next active workstream. Small samples early in a season make the first few gameweeks noisier. Promoted teams arrive with no top-flight history, so their players start from cautious priors. And no model knows about a bust-up in training.

08

The stack

Python with XGBoost for the seven models, PuLP for the squad-optimization linear program, and pandas/NumPy throughout. The site is a static Next.js build — every JSON it reads is generated by scheduled jobs, so there's no server to fall over on deadline day.

Just want to pick a better team? Read the manager's guide →