A Model, Not a Newsroom
Backcheck measures every NHL game from the league's own play-by-play and explains what the numbers show: a read before every game and a breakdown after every one, for all 32 clubs. Nobody here was at the rink. For what happened in the room, read the people who were there. We lead with the computed result, separate process (, , ) from result (goals, wins) from luck (, , ), and always show the uncertainty.
See the validation studyEvery article, board and team report on this site reads the game through the same three layers — and never lets one impersonate another. A team can win the result and lose the process; the whole publication exists to say so out loud, with the numbers attached.
The repeatable part of hockey — the chances a team creates and allows. Process predicts future wins better than wins do.
Every shot's scoring probability — judged on location, angle, shot type and game state — summed up.
A team's slice of all the expected goals in a game or season: xGF ÷ (xGF + xGA).
Share of all shot attempts — on goal, missed or blocked — while a team is on the ice at 5-on-5.
Shot attempts from the slot and crease — the ice where shots become goals most often.
The scoreboard. It's where every story starts, and it's the least reliable thing on this page over a ten-game stretch.
Actual goals scored. The scoreboard.
Any counting stat scaled to a full 60 minutes of ice time.
The reconciliation layer. When result outruns process, one of these numbers is usually holding the bag — and it mean-reverts.
On-ice shooting % plus save % — the two bounce-driven numbers. The league averages almost exactly 1.000.
Actual goals minus expected goals — how far the results outran (or trailed) the chances.
Expected goals against minus actual goals against, for a goalie.
Gradient-boosted models, trained on the shots, shift charts and results we collect ourselves from the NHL's public feeds — no third-party analytics anywhere in the pipeline. The metrics below are the honest ones — held-out performance, printed next to a naive baseline where it matters. When a model barely beats naive (game outcome does, narrowly), we say so and treat its output as a lean.
Expected Goals (xG)
Scores every unblocked shot 0–1 on its probability of becoming a goal, from location, angle, shot type, rush/rebound state and strength — trained on the 111,149 shots we collected for 2025-26 and tested on the 119,954 from 2024-25 it never saw. The spine of every breakdown.
Game Outcome
Pre-game win probability from each team's rolling goal, xG, Corsi, form and points-percentage profiles. Trained on 2022–2024, held out on 2025-26; beats the naive home-win rate on Brier, narrowly, which is what single-game hockey allows.
Goalie Performance
Projects a starter's save percentage above expected (GSAx) given workload, shot quality faced, rest and recent form.
Player Impact
Estimates whether a skater drove play in a game from shot share, xG, finishing-vs-expected and danger-rate inputs.
Development Curve
Models a young skater's production trajectory from usage, shot generation and finishing-luck signals — the highest-fit model in the suite.
In-Game Win Probability
P(home wins) from the lead and the time left, fitted on minute-by-minute score states of every game we collected. It is what lets a breakdown say how much a goal moved the game.
- The feed comes in.When a game goes final, the NHL play-by-play (every shot, hit, faceoff, penalty and goal, with coordinates) and the shift charts (who was on the ice, second by second) are read from the league's public API.
- Our model scores every shot. Each unblocked attempt gets a chance value from our expected-goals model, trained on the shots we collected ourselves. Goals are joined to the seconds before them and to the skaters on the ice, so a goal can be described as a sequence, not a name.
- Templates draft the prose from the numbers. The verdict, the goals, the goaltending and the takeaways are written by rules that only know what was measured. They cannot say a team looked flat or wanted it more.
- An AI editor rewords it for clarity under a gate that rejects any change to a number, a name or a result. If the edit touches one, the draft ships instead.
- A person presses publish.Nothing goes live on a schedule. Every piece carries the byline “By the model”, the model versions, and the time it was written.
- Quote anyone, or report injuries, lineups, trades or news. The league's transaction log appears as a log, not as reporting.
- Attribute motive or effort. Only what was measured: shots, chances, saves, shifts, results.
- Grade a person. Grades attach to a performance in one game, against a league-average game.
- Print a number a reader cannot trace to the play-by-play, the shift charts or a model described on this page.
- Pretend to have been there. Every breakdown ends with what the numbers can't tell you, and the beat's story is worth reading for exactly that.
- Take a wager, sell a pick, or carry a sportsbook advertisement or affiliate link. A win probability here is how often a matchup ends in a win over many simulated tries, printed so a reader understands the game, not so anyone bets on it. If you gamble, you do so on your own judgement; if it is a problem, 1-800-GAMBLER.
Corrections: when a feed is corrected after the fact or a model is retrained, the affected pages are regenerated and the byline's timestamp moves. Write to privacy@backcheckreport.com about anything that looks wrong.
Some numbers on this site stand in for data that doesn't publicly exist. We build them anyway — carefully — and label every single one model-est. where it appears. A proxy is useful for ordering (who is more valuable, which need is bigger) and unreliable for exact magnitudes. The full set:
Our all-in player value estimate, built from 5-on-5 on-ice impact. A proxy — not official RAPM-style WAR.
A skater's on-ice impact after adjusting for role, minutes and teammates — the input under the WAR proxy.
Six percentile dials per skater, versus the same position: offense, creation, defense, finishing, danger, two-way.
A blend of a U-23 skater's current impact, year-over-year xG growth, and the development model's projection.
Impact percentile minus market visibility: how far a player's on-ice value outruns his profile.
A 0–100 estimate of how visible a player is to the market: counting stats, minutes, team spotlight.
The value board's headline number: the size of the impact-vs-visibility gap, weighted by contract phase.
An estimate of contract stage from age and experience — ELC, bridge, prime, veteran. Not real contract data.
How much better a unit's observed xG share is than the sum of its members' individual baselines.
What a unit "should" produce: the additive xG-share baseline from its members' individual profiles.
A 0–1 similarity between how a candidate plays and how the acquiring club creates its offense.
A 0–1 guess at how gettable a player looks, from the selling club's points pace. Not real availability.
The trade board's blend: on-ice value × positional need × style fit × acquirability.
Fit score crossed with market-gap value: the candidates who plug the hole AND look like bargains.
A flagged assignment where an attacker's xGF/60 outruns the best available checker's xGA/60.
Credibility is mostly a list of things you refuse to pretend. Ours:
- No salary or contract data.
Nothing here reads a cap sheet. “Contract phase” is inferred from age and experience; “market visibility” stands in for price. When we say a player is a bargain, we mean the market's attention — not his AAV.
- WAR* is a proxy, not RAPM.
Public WAR models isolate a player with regression on stint-level data. Ours is built from on-ice impact rates, which share credit with linemates. It ranks players well; it does not measure wins to the decimal.
- On-ice stats flatter good teammates.
Every on-ice number partially describes the line, not the man. We adjust for position, minutes and teammate-relative share, and we still tell you to trust orderings over gaps.
- The matchup optimizer isn't a coach.
It assigns threats to suppressors from season-long 5v5 rates. It doesn't know about last change, line-matching in-game, or special teams.
- Small samples lie.
Line chemistry on 30 minutes, a goalie's month of GSAx, a rookie's hot ten games — we show the minutes and games next to the number so you can discount accordingly.
- The win-probability model is barely clairvoyant.
58.9% accuracy, a hair better than naive. That's real signal in a coin-flip sport — and a terrible reason to bet the house. We publish the Brier score so you can judge.
- 01Pull
NHL play-by-play and shift charts feed the models with every shot, location and on-ice state.
- 02Compute
Five XGBoost models score the game: xG on every shot, win probability, GSAx, player impact, development.
- 03Write
A deterministic engine drafts the full article for free; an optional small language-model pass polishes only the prose — never the numbers.
- 04Commit & serve
Each article is written as self-contained JSON and committed. The site is fully static — no live backend, no per-request model calls.
- Every claim carries a number and a context band. Never “the power play is hot” — always the rate, the rank, and whether it's process or variance.
- Process, result and luck are always separated. The scoreboard is the start of the story, not the end of it.
- Everything is computed, not voted. Three stars, the turning point, the deserved winner — all derived, with the inputs shown.
- The machine authorship is the product, not a secret. Every article is signed “By the Model.”
- Every proxy is labeled at the point of use — in the cell, not in a footnote you'll never find.
Every dotted-underlined term anywhere on this site opens its definition in place; the complete vocabulary lives on the glossary page, and both are rendered from the same file — a definition can't drift from its tooltip.
On the roadmap · league-wide playoff-odds deltas on every recap · nightly regression watch across all 32 teams · a process-vs-result luck index. Data: NHL API only. xG model AUC 0.757, trained on our own shot collection.