Deployment and context
How we forecast tonight's line matchups, and how accurate it is
Line matching is one of the oldest coaching tools in hockey. The home coach changes last, so he can get his shutdown pair out against the visitors' top line. Fantasy players talk about it but rarely measure it. We have shift data for every second of every game, so we can measure it and forecast it.
Updated · Method version matchups-1.0.0
How it's calculated
- Usage slots. In each game, a team's forwards are ranked by 5-on-5 ice time into four slots of three (L1 to L4) and its defence into three slots of two (P1 to P3).
- Random mixing. If coaches ignored matchups, player i and opponent j would share toi_i × toi_j ÷ T seconds, where T is the game's 5-on-5 time. This baseline already gets ice time right; what it lacks is matching.
- Last-Change Fingerprint. For each team, at home and on the road separately, we add up the observed seconds between each of its slots and each opposing slot over its last 30 games at that venue, and divide by the random-mixing seconds. A ratio above 1 is a matchup the coach seeks. Ratios are shrunk toward 1 with 180 minutes of baseline time as the prior.
- Player roles. The same ratio for each skater against each opposing slot, over his last 20 games at that venue, shrunk toward his team's fingerprint row with a 30-minute prior. This catches shutdown roles that slot averages blur.
- Pair memory. Earlier meetings between the same two teams (this season and last) add a shrunk ratio for each exact pair of players.
- Projected lineup. Each team's skaters from its latest game, each with a recency-weighted average of 5-on-5 ice time.
- Balancing. The tilted baseline is rescaled (iterative proportional fitting) until every skater's minutes against the opposition add up to five times his projected 5-on-5 time. Every 5-on-5 second has exactly five opponents on the ice.
E_ij ∝ (toi_i × toi_j ÷ T) × role_home(i, slot_j)^wH × role_away(j, slot_i)^wA × pair(i, j)^wP
- role
- shrunk observed ÷ random-mixing ratio against the opposing slot
- wH, wA, wP
- weights fitted on a tuning window (0.8, 0.6, 0.3); the home side has last change
- ∝
- then balanced so each row and column sums to 5 × projected 5v5 TOI
competition = Σ_j E_ij × xGF%_j ÷ Σ_j E_ij − the same with random-mixing seconds
- xGF%_j
- opponent j's shrunk 5v5 expected-goals share (the QoC rating): this season's, blended toward last season's with 300 minutes of 5v5 as the prior weight, so early-season samples do not swing it
One team's forward lines from a single game
Example data: invented for illustration
Four detected forward lines: the first line took 31% of 5v5 time with confidence 0.82, the fourth 14% with confidence 0.41.
Worked example
A top line walking into last change
Includes example dataA visiting top-line forward plays 15:00 at 5v5. The home team's top pair plays 20:00 of a 48:00 game, so random mixing gives 15 × 20 ÷ 48 = 6:15 together.
- At home, this coach's top pair sees opposing top lines 1.30× as often as random mixing (fingerprint, after shrinkage).
- The visiting forward's own record against top pairs on the road is 1.10× (his role).
- With the fitted weights 0.8 and 0.6, the tilt is 1.30^0.8 × 1.10^0.6 ≈ 1.31, so about 8:10 before balancing.
- Balancing takes some of that back from the other pairs, so his total still adds up to five opponents for all 15:00. The final figure is about 7:45 against the top pair, an extra minute and a half of shutdown time.
About 7:45 against the shutdown pair instead of 6:15: a tougher night than his season line suggests. The numbers are illustrative.
Backtest on held-out games
We tuned the weights and shrinkage on 2025-12-01 to 2026-01-31, froze them, and scored every game from 2026-02-01 to 2026-10-03 (556 games, regular season and playoffs). Each game was forecast only from games before its date. The unit is a pairing: one skater and one opposing skater, about 320 per game.
| Measure | Forecast | Random mixing | Forecast (known lineups) | Random (known lineups) |
|---|---|---|---|---|
| Mean error per pairing (s) | 116 | 119 | 75 | 78 |
| Correlation with actual pairing time | 0.367 | 0.325 | 0.674 | 0.646 |
| Named one of a forward's two most-faced D | 47% | 43% | 52% | 50% |
| Measure | Value |
|---|---|
| Skater-games scored | 18,516 |
| Correlation, forwards (one game) | 0.41 |
| Correlation, defence (one game) | 0.54 |
| Correlation, per player over his test games (642 players, 10+ games) | 0.81 |
| Softest 10% of forecasts: predicted / actual shift (xGF% points) | -0.62 / -0.57 |
| Toughest 10% of forecasts: predicted / actual shift (xGF% points) | +0.45 / +0.40 |
Each ingredient alone, on the same held-out games: home-side fingerprint and roles 2% less error than random mixing, road side 1%, pair memory 0%.
Live scoring
After every game, the forecast published before puck drop is compared with the real head-to-head ice time from the shift charts. The running record is on the Matchup Forecast page and in each game's report.
Reliability
The forecast is judged out of sample against a baseline that already gets ice time right, so any gain is from matching. Who draws tough or soft competition is predictable and calibrated. Exact minutes against each opponent are not much better than random mixing. Fingerprints and roles are shrunk toward random mixing, so a few odd games cannot create a "matchup".
| Measure | Split-half r | Sample | Verdict |
|---|---|---|---|
| Competition shift (per player)One game: 0.41 forwards, 0.54 defence. | 0.81 | 642 players, 10+ held-out games | Stable |
| Pair minutes vs random mixingSmall gain; lineups and line changes dominate. | 2% less error | 556 held-out games | Noise |
| Matching only (known lineups)Real lineups and ice time. | 4% less error | 556 held-out games | Stable |
| Live pregame forecastsPublished on the tool page as games are scored. | — | This season | Not measured yet |
Split-half r: we split each sample in two (for example odd and even games) and correlate the two halves across players or teams. Near 0 means the stat is mostly noise; near 1 means it is a stable trait.
Limitations
- Lineups are projected from the last game. A healthy scratch, injury or call-up announced on game day isn't in the forecast until the next refresh, and a lineup change also reshuffles the slots.
- It is 5-on-5 only. Power play, penalty kill, empty net and three-on-three overtime are excluded.
- Coaches react in-game: a blowout, a penalty-heavy night or an injury mid-game breaks the pattern, and score effects aren't modelled yet.
- Slots come from ice-time ranks, which blur when a coach rolls four even lines. Then the forecast is close to random mixing, which is the right answer.
- Competition uses each opponent's shrunk 5v5 xGF%. It is a measure of quality, not a guarantee; a soft matchup doesn't make points.
FAQ
What does last change mean?
At a stoppage the visiting team must put its players on the ice first, and the home team then picks its players. That lets the home coach choose his matchups, which is why we measure fingerprints separately at home and on the road.
Why compare with random mixing?
Players who play more share more ice with everyone. Random mixing removes that, so a ratio above 1.00 means the coach actually seeks the matchup rather than both players simply being on the ice a lot.
How much should a tough matchup change my fantasy lineup?
A little. Even the toughest draws move a forward's expected competition by only about half a point of xGF%. That is a real, predictable effect, but much smaller than power-play time, shot volume or the opposing goalie. Use it as a tiebreaker.
Do you use practice lines?
No. Lineups come from the most recent game's shift data. If a lineup changes on game day, the next forecast refresh picks it up after the next game; we flag it as a limitation.