NHL Model Methodology
Shot-quality windows, a Poisson goal grid, a market blend, and frozen partner-book picks: the spreadsheet model, run daily
Overview
The NHL model is a Poisson goal model, ported from a spreadsheet I ran by hand for a few seasons. Each team's recent shot quality at home and on the road becomes attack and defense strengths relative to the league; a matchup multiplies them into expected goals for each side; and a Poisson grid turns those into win probabilities and a total. The port exists to run it every day, freeze every decision before puck drop, and grade it in public.
The spreadsheet's method is kept on purpose, with three changes: the shot-quality source, a walk-forward backtest, and, since October 9, 2026, a forecast blended halfway with the betting market for every game the books have priced. None of it is betting advice.
Data
- Shot quality. MoneyPuck's team game-by-game file: shots, goals and ice time by danger level and situation, for and against. The spreadsheet used Natural Stat Trick, which no longer serves automated requests.
- Schedule, scores, teams.The NHL's public API. A shootout win counts one goal for the winner, as the books settle it.
- Prices.The NHL's partner sportsbook feed, read each morning: DraftKings on the US feed and FanDuel on the Canadian feed. A pick records the better of the two.
- Historical lines.Opening and closing moneylines and totals for the backtest seasons, from ESPN's public odds data. They are used to check the model against the market, never to price a pick.
Windows
Every team has two windows, its last 25 home games and its last 25 road games, each summed by situation: even strength, power play, penalty kill, and everything else (4 on 4, 3 on 3, 5 on 3, empty net). Windows end the day before the run and reach into the previous season, so opening night is priced off last spring. A team with under ten games in a window is projected but never priced.
Each situation yields the spreadsheet's ten features: shot and goal rates per 60 and shooting percentages, overall and by high, medium and low danger. Goals against use the mirror set with save percentages.
Goal Map
Goals per 60 minutes is a linear function of the ten features, one fit for goals for and one for goals against, on even-strength team-seasons from 2021-22 through 2024-25 and applied to every situation. Expected goals per game at a venue sums each situation's fitted rate times its ice time per game. The fit is near an identity on observed goals per 60 (R squared 0.999), so it mostly reproduces recent goal rates.
Ratings and Matchup
Attack strength is a team's expected goals for divided by the league average at that venue; defense strength is the same for goals against, so 1.000 is average and a lower defense is better. The overall rating on the ratings page is home attack plus away attack minus home defense minus away defense.
The home team's expected goals equal its home attack times the visitor's road defense times the league average home goals; the visitor's mirror that. Home ice enters through the venue split rather than a constant. Each side's goals are independent Poisson counts on a 0 to 10 grid: a win probability is the mass on that side of the diagonal plus half the tie mass, and the same grid gives over, under and push probabilities for a posted total.
Market Blend
On its own the model does not beat the betting market. Checked against opening and closing lines for the backtest seasons, the market's price predicts winners and totals better than the model does, and once the price is known the model adds nothing to it. So for every game the books have priced, the published forecast is blended halfway with the market.
The market's win probability is the no-vig probability from each book that quotes both sides (the two implied probabilities scaled to sum to one), averaged over DraftKings and FanDuel. The model's home win probability first gets a small home-ice correction of 0.10 in log-odds, because it runs about two points low on home teams, and is then averaged with the market in log-odds. The model total is averaged with the posted total, using the median line when the books disagree.
Each side's expected goals are then reset so the Poisson grid returns exactly that win probability and that total. Everything shown for the game, the expected goals, win probability, fair price, total, any pick, and the opening point of the live win probability, comes from that one blended forecast.
The partner feed only prices the current day's games, so games further out on the schedule show the model alone until the morning they are played. The halfway weight is a choice, not a fitted value: the data would put nearly all of the weight on the market, and the model would then never disagree with a price.
Pricing and Picks
The fair price is one over the published win probability, shown in American odds with the spreadsheet's minimum acceptable price beneath it: the fair decimal marked up by ten percent. The edge is the published probability minus the break-even probability of the partner-book price, vig included. Every pick risks a flat one unit so results compare across sports; Kelly at ten percent of full is published for reference.
One decision per game and market, recorded each morning for that day's slate and frozen at first publication. A moneyline is recommended at an edge of at least 4.5 percentage points with positive expected value; a total when the published total differs from the posted line by at least half a goal, which is the spreadsheet's one-goal rule applied to the model's own total. A game without a two-sided price, or with prices older than 24 hours, produces No Play. A moved, postponed or cancelled game voids its pick, totals push on the line, and the database rejects any change to a published pick or a settled result. The record lives on the performance page.
Picks through October 9, 2026 followed the spreadsheet's original rules: the model alone, 13 percentage points for a moneyline, and one goal for a total. The performance page separates the two policies.
Backtest
A walk-forward replay of the 2022-23 through 2025-26 regular seasons prices every game from windows that end the day before it. Across 5,225 games the home win probability scores a log loss of 0.687 against 0.693 for a coin flip and picks the winner 57 percent of the time; the model total misses by 1.90 goals on average and runs about a tenth of a goal low. It is overconfident: games priced at 74 percent for the home side were won 67 percent of the time.
Against historical lines the market is better. Over the 3,913 games from 2023-24 through 2025-26 the closing moneyline scores a log loss of 0.665, the model alone 0.691, and the halfway blend 0.672. The closing total misses by 1.87 goals on average against 1.92 for the model. Betting the model against those lines lost money at every threshold tried: the spreadsheet's 13-point moneyline rule lost between 8 and 15 percent per unit depending on the season and whether the opening or closing price was used. The backtest gives no reason to expect the picks to profit.
Limits
- The Poisson grid stops at ten goals and is not renormalized.
- Overtime and the shootout are a coin flip on tied regulation scores, not a model.
- Home and away goals are independent, with no Dixon-Coles style correction for low scores.
- Expected goals from shot location would carry more signal than the goal map; that is the first planned improvement.
- A hard 25-game window with no shrinkage overreacts to hot and cold stretches.
- Goalies are not modeled; a backup start changes nothing.
- The puck line is read but not priced.
- Prices are the morning partner-feed quotes, not closing lines.
- The blend weight and the pick thresholds are choices, not fitted values, and the backtest finds no betting edge at any threshold.
- Games beyond the current day have no market price yet, so their forecast changes when the blend is applied on game day.
Tech Stack
Python with pandas, numpy and scipy in the momentumnhl repository, run each morning by GitHub Actions from the day before opening night through April. Outputs land in the nhl Postgres schema, where triggers archive every pregame forecast and enforce the ledger rules; this site reads only that schema.