Tonight · method
How tonight’s odds are made
Every win probability on Tonight comes from five measurements of the two lineups plus home ice. This page follows one game from player numbers to the final percentage, factor by factor, using the exact model and numbers behind the Tuesday, 29 September 2026 slate.
The recipeFive steps from lineup to percentage
The weights come from a logistic regression fitted on every regular-season game of 2010-11 to 2025-26. Every input is something known before puck drop.
The answer first
The chart builds the prediction one factor at a time in logit points, the model’s internal currency, where contributions simply add. Bars right of the centre line push toward the home team, bars left toward the visitors. The running win probability is marked at each step.
Step 01 · the lineupsWho is assumed to play
The model rates lineups, not franchises. Each team’s projected lineup comes from the same file as the lineup panels on /tonight: in season, the players who dressed most in the team’s last ten games; before the season, the depth chart. That is 12 forwards, 6 defencemen and the goalies. Once Daily Faceoff confirms a starting goalie (usually after the morning skate) the page is rebuilt and he carries the team’s whole goalie term, as in the fit. Until then every goalie counts in proportion to his expected share of starts: a 60/40 tandem enters as 60% of one goalie and 40% of the other.
Players on injured reserve are not in the projected lineup; the injuries what-if puts them back. Everything below is summed or averaged over this lineup. A scratch or a surprise starter changes the odds, but only once the lineup file catches up.
Step 02 & 03 · factor by factorWhat each factor measures
Each factor below becomes one number per team; the model only sees the home number minus the away number. The chips give the fitted weight in plain terms: how many percentage points a given gap is worth in an otherwise even game.
Home ice
Worth 53.4% for the home team when all else is evenHome ice is not measured per team: it is the model’s starting point. When every factor gap is zero the fit says the home team wins 53.4% of the time, the advantage of last change, familiar ice and no travel. (Home teams actually won 54.1% of the fitted games; part of that is home teams also being slightly better on the measured factors, which those factors absorb.)
Technically: the intercept, plus the small correction that puts all six factors at an exact zero gap (they are centred on their league averages in the fit).
Player Elo — who wins when they play
100 Elo gap ≈ 8.0 ptsEvery player carries a rating that starts at 1500 and moves after every game he plays, like chess Elo but shared by a whole lineup. It rewards results: wins, and by how much.
After each game, the two lineups’ ratings are compared (with 30 Elo points for home ice) to get the expected result; the surprise, scaled by the goal margin, is the step:
Rh, Ra: the lineups’ ice-time-weighted ratings; W = 1 for a home win, 0 for a loss; damp = 2.2 / (2.2 + 0.001 × the winner’s Elo edge), so favourites can’t pile up rating on blowouts. A one-goal win counts ln 2 = 0.69, a three-goal win ln 4 = 1.39.
The step is shared out by each player’s leverage-weighted ice time (a second in a tied third period counts more than one up four goals) and by that night’s net goals: after a loss the team’s best performer takes none of the hit, after a win the worst performer gets none of the gain.
Before tonight, a team’s Elo is the average of its projected players’ ratings, each weighted by expected ice time (a trailing average of his recent leverage-weighted minutes, decay 0.9 per game). A player with no NHL history rates 1500 at 0.8× the lineup’s average weight; goalies are weighted by start share.
Skaters — net goals, last 60 games
+0.1 goals/game gap ≈ 0.9 ptsElo only knows wins and losses. This factor looks at how each skater has been playing: his net goals in each of his last 60 games (on-ice even-strength offence and defence, power play, penalty kill, finishing above expected, playmaking, penalties drawn minus taken, faceoffs), measured against the league average for that season.
The divisor is always 60: a player with only 20 NHL games has the missing 40 counted as league average (zero), so a hot start from a rookie is heavily discounted. The team value is in goals per game above an average lineup.
Goalies — GSAx, last 60 appearances
+0.1 GSAx/game gap ≈ 0.27 ptsEach goalie’s goals saved above expected (expected goals against minus goals allowed) per game over his last 60 appearances, zero-padded the same way. The team value is the start-share-weighted average of its goalies.
The fitted weight is small. Goalie form over 60 games is noisy, and once the skater windows and the lineup Elo (which includes the goalie, at a large ice-time weight) are in the model, recent GSAx adds little. It is kept because it is known before the game and does no harm, but tonight it rarely moves the needle by more than half a point.
Rest — back-to-backs
Rested vs B2B ≈ 5.7 ptsA simple flag: +1 if the home team had at least a day off and the visitors played last night, −1 the other way round, 0 otherwise (both rested, or both on a back-to-back). Travel distance and time zones were tested and rejected; once team quality is known they add nothing.
Coach trust — recent minutes
+1 unit ≈ 3.8 ptsCoaches see practice, injuries and matchups the box score doesn’t. This factor reads their judgement from ice time: each skater’s average minutes over his last 60 games, as a multiple of the league average for his position (forward or defence), summed over the 18 projected skaters. A lineup of average-minute players scores 18.
Games a player hasn’t played yet (short NHL history) count as zero minutes in the sum, and a second term counts how many of them there are. Fitted together, the pair values each missing game at about 0.84× average minutes, so newcomers are assumed to be close to, but a little below, a typical regular.
Both enter the regression; /tonight shows them as one bar.
Injuries — a what-if, not a weight
Uses the existing weightsThere is no injury term in the regression. An injury matters because it changes who is in the lineup, and the lineup feeds every factor above. So the injury effect is a what-if: rebuild the lineup with the injured player back in, recompute the team’s Elo, skater, goalie and coach-trust numbers, and run the same formula.
Who is injured comes from PuckPedia’s injured-reserve list (IR, LTIR and season-ending LTIR), refreshed every morning. Day-to-day injuries that don’t go on IR are not on it.
Who he replaces. A returning skater takes the spot of the player at his position (forward or defence) with the least expected ice time, the one he would bump. A returning goalie with at least 60 NHL games comes back as the starter: he takes the top share of starts, everyone else moves down a slot and the last goalie drops out. A goalie with fewer games comes back as the backup.
Bringing back a depth player can lower the odds: if he rates below the player he would bump, the lineup gets worse on paper. The model has no way of knowing whether the coach would actually dress him.
On /tonight the Injuries (IR) bar is the odds now minus the odds with both teams healthy, so it points toward the team that is less hurt. Tick the boxes to bring players back one at a time.
Step 04 & 05 · the arithmeticWeight, add, convert
Each gap is divided by its typical spread (its standard deviation across all fitted games) and multiplied by its weight from the regression. That gives logit points, which add. The total goes through the logistic curve:
“Typical spread” and “weight” are the regression’s standardised inputs; their ratio is the per-unit effect. Coach trust is two regression terms, the minutes sum and the missing-history count; the other bars on /tonight are one term each.
Inside the fitWhere the weights come from
The weights in the table above are not chosen by hand. They come from a logistic regression: a curve fitted to real games so that its probabilities match what actually happened as closely as possible. This chapter takes the fit apart one piece at a time.
A · Why a curve: odds and logits
A probability is stuck between 0 and 1, but evidence can keep piling up: a 200-point Elo edge on top of a hot lineup on top of a rested team. Adding effects directly to a probability would eventually push it past 100%. The fix is to add them on a scale with no ceiling, then convert back.
That scale is the logit, the logarithm of the odds. Odds of 3 (to 1) mean 75%: three wins for every loss. The logit of 75% is ln 3 = 1.10. Every logit value, however large or negative, maps back to a probability strictly between 0 and 100%:
A logit of 0 is a coin flip, and the scale is symmetric: +1.10 is 75% for the home team, −1.10 is 75% for the visitors. The model’s “logit points” are steps along this scale.
B · The data: one row per game
Every regular-season game from is one row. The row holds the six pre-game gaps, measured exactly as for tonight’s games (expected ice time, the starting goalie, form up to the day before), and one outcome: 1 if the home team won, in regulation, overtime or a shootout, 0 if it lost. Nothing from the game itself leaks in. Three real rows from the last fitted season:
“Model” uses today’s fitted weights. The first game is its most confident correct call that season, the middle one its closest coin flip, the last its most confident miss.
C · One scale for every factor
The gaps come in different units: Elo points (a typical gap is about 70), goals per game (about 0.5), a ±1 rest flag. Before fitting, each gap is standardised: its average is subtracted and the result divided by its standard deviation, so every factor is measured in “typical gaps”:
This doesn’t change the predictions; it puts all the weights on one comparable scale and keeps the arithmetic well behaved. Dividing a weight by its spread converts it back to a per-unit effect. The averages are close to zero (home and away lineups look alike over thousands of games), and the model folds them into the home-ice starting point.
D · Choosing the weights: maximum likelihood
For any set of weights the model gives every past game a probability. The fit picks the weights that make the results that actually happened as likely as possible. In practice it minimises the log-loss, the average over all games of
A confident right call costs little, a confident miss costs a lot. Calling 80% and being right costs −ln 0.8 = 0.22; calling 80% and being wrong costs −ln 0.2 = 1.61. Saying 50% every game costs ln 2 = 0.693 whatever happens. So the fit can’t win by being bold everywhere; it has to be bold only where the evidence holds up.
There is no closed formula for the answer, so it is found by Newton’s method: start with every weight at zero (every game 50%), measure which way and how steeply the log-loss falls for each weight, jump to where that slope says the bottom is, and repeat. The log-loss is bowl-shaped, so this lands on the single best answer in a handful of steps:
Weights per standardised gap (section C). A tiny ridge penalty (10−6) only keeps the arithmetic stable; it doesn’t change the result.
E · What a weight means: “all else equal”
Each weight answers a narrow question: if this gap grows and every other gap stays the same, how much more often does the home team win? That matters because the factors overlap. Lineups with high Elo also tend to have good recent net goals (correlation ), and coaches give the most ice time to the players who win (trust vs Elo ).
Fitted alone, a factor gets credit for everything it is correlated with. Fitted together, the overlap is shared out and each weight keeps only what that factor adds on top of the others. The chart shows it for the skater factor: the dots are the actual home win rate in ten equal-sized groups of games; the dashed line is the skater gap fitted on its own; the solid line is its all-else-equal weight in the full model.
A second reason the weights look modest: every measurement is noisy. A 60-game average of net goals mixes real skill with luck, and the fit discounts the gap by as much as the luck part fails to predict results.
F · From logit points to percentage points
Every gap becomes logit points in a straight line: gap × (weight ÷ spread). Logit points add. Percentage points don’t, because the curve is steep in the middle and flat at the ends: its slope at probability p is p × (1 − p), 0.25 at 50% but 0.16 at 80% and 0.09 at 90%. The same push in logit points buys fewer percentage points the more lopsided the game already is.
The chips’ rule of thumb, 0.1 logit points ≈ 2.5 percentage points, is the slope at 50%. For lopsided games it overstates.
G · Does the curve fit? Calibration and log-loss
If the model says 65%, the home team should win about 65% of those games. The chart checks that on predictions made walk-forward: each season predicted by a fit on earlier seasons only, as if in real time. The games are sorted into ten equal groups by predicted probability; each dot is a group’s average prediction against how often the home team actually won. Dots on the diagonal mean the probabilities can be taken at face value.
The log-loss by season puts a number on it. For scale: 0.693 is a coin flip every game, and backing the home team at its historical rate scores about 0.690. The model’s gain over that looks small because hockey is close to random.
H · Refitting
The fit is redone every time /tonight is built, on every complete season. The season in progress is never in the fit: its games are predicted, not learned from, until the season ends and joins the training data. With thousands of games behind them the weights barely move from one build to the next; what changes daily are the inputs, the player ratings and recent form that make up the gaps.
Reading /tonight“What moves the odds”
Logit points add, but percentage points don’t: the same push is worth more near 50% than near 80%, because the curve flattens. So the bars on /tonight ask a counterfactual instead: how different would the odds be if this factor were even? (The injuries bar asks the same of the lineup: how different would they be with both teams healthy?) Each bar is the win probability minus the probability with that one gap set to zero. Home ice is the all-even probability minus 50%.
That makes each bar honest on its own, but they need not add up to the total. Below, the /tonight bar next to the running-sum version from the chart above (the order-dependent alternative the page avoids).
Try itMove the gaps yourself
Same coefficients, your inputs. The sliders start at the selected game’s gaps (home minus away); drag one to see how far that factor alone can move the odds.
LimitsHow good it is, and what it leaves out
Track record. Predicting each season only from earlier ones (2012-13 to 2025-26, 16,691 games), the model’s log-loss is 0.6663, against 0.6705 for player Elo alone and 0.6898 for always picking the home team. It picks the winner 59.2% of the time. Hockey is close to a coin flip; see the Scorecard for this season.
Lineups and goalies. The odds are only as good as the projected lineup. A late scratch, a star returning from injury or a backup getting the start moves the true odds, and the page won’t know until the next morning’s build.
Playoff stakes are separate. The playoff-odds swings on /tonight come from the season simulation, which rates teams from full-season projections; they answer “how much does this game matter”, not “who wins”. Overtime and shootouts are not modelled separately here: the odds are for winning the game, however it ends.