Every expected-goals number on Heater Stats is ours. It is not a figure we picked up from somewhere else, and you will not find the same decimals on another site. This page is the whole method: what goes in, what each input is worth, how we check it, and where it stops working.
Start with what the number is for. Goals lead every table on this site, and they always will. A goal is a fact. Expected goals is a model's estimate of how often a chance like that one goes in, and its only job is to explain the goals column. When a player has 48 goals on 44.3 expected, the gap is the interesting part, and the gap is only worth reading if the 44.3 is honest.
What the model reads
Every unblocked shot attempt in the NHL since 2007-08 carries a description of the moment it was taken. The model reads thirty-one of them:
- Where it came from. Distance to the net, angle off center, and the raw position on the ice.
- How it was taken. Wrist, snap, slap, backhand, tip, deflection or wraparound.
- What happened just before. The previous event and its type, how long ago, how far away, and how fast the puck traveled between the two.
- Whether it was a rebound, and the angle the shooter had to cover from the previous shot.
- The situation. Skaters on each side, whether the defending net is empty, period and clock.
- Who is tired. Shift length for the shooter and the average for both benches.
- The shooter's handedness, position and whether he was on his off wing.
It does not read the shooter's name. That is deliberate. If the model knew a shot belonged to McDavid it would quietly price his chances higher, and then goals above expected would only be measuring how well he matched himself.
There are no weights to publish
This is the part people expect to be a formula with coefficients, and it is not one. The model is a gradient-boosted classifier trained on 361,613 shots carrying 25,566 goals, the last three completed seasons. It learns the shape of the relationship from what happened rather than being told it. There is no line that says a rebound is worth 1.4 times a normal shot.
So the honest way to show what an input is worth is to measure it. Start with distance, which does more work than everything else combined.
The red line is the share of real shots from that distance that went in. The dashed line is what our model said about those same shots. Inside five feet more than a quarter of attempts score. By 35 to 40 feet it is one in twenty. Past 65 feet it is under one in a hundred.
What each input is worth, once distance is held still
Distance dominates so completely that any other factor looks impressive until you control for it. The chart below is every shot taken from 10 to 25 feet over the last three seasons, so location cannot do the work. All of them together convert at 10.3%.
Three readings here are worth stopping on.
A rebound is worth much less than it looks. Across all distances rebounds convert at 11.4% against 6.3% for everything else, which sounds enormous. Hold the distance still and it is 11.5% against 10.2%. Almost the whole rebound effect is that rebounds happen close to the net.
The frantic scramble is the worst chance on the board. A shot taken within two seconds of the last event converts at 3.0%, less than a quarter of the rate of shots taken two to five seconds later. These are overwhelmingly follow-ups to a shot or a block, taken with the goalie already square and bodies in the lane.
A tip is not a free goal. From inside 25 feet, snap shots go in 16.0% of the time and slap shots 13.5%, while tips manage 8.4%. Tipping a puck is hard, and the shots that get tipped were often headed nowhere.
How we know it is honest
A model that ranks chances well can still be wrong about all of them at once. The test that catches that is calibration: take every shot of a season, sort by what the model said, cut into ten equal groups, and check whether the shots it called 5% went in 5% of the time.
Across 2025-26 the ten groups land on the line. The model has never seen that season in training. Over the whole season it expected 8,608 goals against the 8,565 that were scored. Across all nineteen seasons the average distance between the two is 0.91%.
Empty nets count, and they count properly
A pulled goalie is a real chance, not a rounding error. In 2025-26 there were 957 attempts at an empty net and 471 of them scored, a 49.2% conversion. Our model prices them at 51.1% apiece. They stay in the all-situations totals because they are real goals, and every empty-net shot is flagged so any 5-on-5 or goalie-in-net view drops them cleanly. Nothing is deleted; the 5-on-5 tables are where you look for a clean read on a skater.
The thing that quietly breaks a model like this
Shots are logged by human scorers, and how they log them drifts. In 2025-26 the median shot was recorded two feet closer to the net than the year before, the share taken inside 20 feet rose from 27.7% to 30.8%, and the conversion rate inside 10 feet fell from 13.8% to 13.0%. A model trained on earlier seasons prices all those extra close shots at the old rate and runs about 11% high for a whole year, which is invisible on a website because every number on the page moves together.
So each season carries a single correction, fitted on that season's own early shots and then frozen for the rest of the year. Frozen matters. A correction that kept refitting every night would force league-wide goals above expected to zero by definition, and the metric would stop saying anything.
Two things it does not know
It cannot see the pass that set the shot up, the screen in front of the goalie, or who was in the crease, because none of that is recorded. And it does not know which goalie is in net, so a shot faced by the league's best and its worst carries the same number.
Goals on this site always come from the official box score, so a goal total is the real one and the gap to expected is measured against it.
