Methodology

The Edgework value model gives every on-ice action a goal-value — by how much it shifts the odds of the next goal — then sums those values per player. It adapts VAEP, an action-value framework from soccer analytics, to hockey, and splits the result by rink zone. The payoff is a defensive metric that repeats year over year better than the expected-goals-against rate every public model uses.

The Headline Result

The only test that matters for a player rating is whether it predicts the future. We measure that with year-over-year persistence: rate every player in season T, again in season T+1, and correlate the two. A metric that repeats is a metric that forecasts.

Our defensive-zone contribution rate (v_in_dz_per_60) repeats at 0.54 and 0.60 across the two season-pairs we can measure. The standard public defensive metric — on-ice expected goals against (xga_per60_on_ice) — repeats at only 0.42 and 0.37 over the same pairs. Our action-credited defense is a stronger predictor of a player’s future defense than the rate everyone else cites.

The full table is in Validation below. The sections in between explain how each metric is built, at an intuition level.

How the Metrics Work

Everything starts from the NHL’s public play-by-play feed — the recorded stream of shots, hits, faceoffs, takeaways, giveaways, blocks, penalties, and goals, with coordinates and game state. Two foundation models read that stream. An expected-goals model scores every unblocked shot by quality alone — location, angle, rebound, rush — deliberately ignoring who took it, so shooter skill is measured later rather than baked in. A pair of state-value models then estimate, from the game state at any moment, the probability the team scores — or concedes — within the next ten events.

Action value is the change in those probabilities across each event, credited to the player who caused it. A dangerous shot that raises scoring odds earns positive value; a turnover that raises the opponent’s odds earns negative value. Goals carry a realized +1 reward split across the scorer and assisters (0.55 / 0.30 / 0.15), so playmaking is credited, not just finishing.

Zone Contribution

v_in_oz_per_60 · v_in_dz_per_60

Each action happens somewhere on the ice, so its goal-value is filed by zone from the acting player’s perspective: offensive, neutral, or defensive. Summed over a season and divided by 5v5 ice time, that yields a per-60 rate for each zone. v_in_oz_per_60 measures offensive-zone contribution — the value a player generates attacking; v_in_dz_per_60 measures defensive-zone contribution — value generated defending, including credit for blocked shots.

The defensive rate is the model’s headline: it lands in the skill-stable 0.40–0.65 persistence band and out-predicts the public xGA rate. The offensive rate persists higher (0.86) but is honestly role-confounded — offensive deployment (who gets the offensive-zone starts and the minutes) is itself extremely sticky season to season, so the offensive number repeats partly through usage rather than isolated skill. Read it as informative, not pure.

v_net_per_60(Net Contribution) is a position-adjusted, weighted z-score index. Its base is a player’s offensive-zone value (60% weight) and defensive-zone value (40% weight); as of 2026-06-12 (v2 — see the changelog) the published number blends that zone composite with a chance-creation-for-others term: net = 0.9 · z(0.6 · z(OZ) + 0.4 · z(DZ)) + 0.1 · z(C1), where C1 is the chance-creation-for-others RAPM described below. Each component is measured as standard deviations above or below the average for that position-and-season cohort, then combined. The asymmetric zone weighting reflects that offensive actions generate more total value per minute in hockey, while still giving defensive performance enough weight to materially affect rankings. Pure offensive stars rank near the top; elite two-way players — defensemen who drive offense, forwards who defend — surface high; pure defensive specialists rank in the middle, because their offensive contributions are below the cohort average. The result is a relative index (it carries a + or − sign), not a count of goals.

One framing matters when reading net against the scoring race: net is a strength-matched 5v5 rate— 5v5 value over 5v5 ice time. That is deliberate: 5v5 rates are what repeat year over year (the validation table below is built on them), while power-play production rides heavily on deployment. The cost is that all-strength value — a power-play playmaker’s specialty — is out of the headline number’s scope by design. So the leaderboard and player pages show v_total_season(“Season impact”, cumulative action value across all strengths) alongside net: a player can lead the league in season impact while sitting mid-pack on the 5v5 rate, and both statements are true at once.

Action-Type Breakouts

v_from_shots · v_from_assists · v_from_blocks

The same per-action value also splits by what the player did. v_from_shots is sniping value — value created by taking shots and scoring. v_from_assists is playmaking value, the assist share of goal credit; because the play-by-play feed records no passes, assists are the only window into setup work, so crediting them separately keeps playmakers from being under-rated. v_from_blocks is pure shot-suppression value: a blocked shot earns the blocker a small fixed credit (about the average quality of the attempt it prevented), defensive value a shot-only model never sees.

RAPM

rapm_net — single & multi-season

Action value only sees the player who touched the puck. RAPM — Regularized Adjusted Plus-Minus — is the complement: a ridge regression over every 5v5 shift that isolates each player’s per-60 impact on expected goals while controlling for the quality of teammates and opponents on the ice with them. rapm_net is their net effect on expected goals for minus against.

Single-season RAPM is noisy — one season is not enough lineup variety to separate players who are almost always on the ice together — so the production metric pools multiple seasons of shifts into one regression. Pooling lifts stars who were collinearity-bound (McDavid climbs roughly 25 spots across two seasons of pooling), but it does not fully resolve players whose linemate pairings barely change year to year. Treat rapm_net as a useful, regression-isolated second opinion, not a final word.

Goalie GSAx

gsax_shrunk · gsax_per_60

Goalies are rated by Goals Saved Above Expected. Sum the expected-goal value of every unblocked shot a goalie faced, subtract the goals they actually allowed, and the residual is performance above (or below) what an average goalie would manage on that shot load. Because the expected-goals model is shooter-agnostic and calibrated over the full shot universe, the league average sits at zero, so positive GSAx is genuinely above-average.

Small samples — backups, call-ups — can post wild rates on a handful of starts, so the production figure (gsax_shrunk) is pulled toward the league average by a Bayesian weight: a goalie’s raw GSAx is scaled by shots / (shots + 200). A goalie with thousands of shots is barely moved; one with a few hundred is regressed hard toward zero.

Validation

Every metric below is a strength-matched 5v5 per-60 rate, correlated between the 2023-24 and 2024-25 seasons across the 602 players with at least 200 minutes of 5v5 in both. We read the result in three bands: below 0.30 is noise; 0.30–0.65 is skill-stable (real signal that persists); above 0.85 is role- and usage-confounded (it measures sticky deployment more than individual skill).

MetricPearsonSpearmanQ4 persistReading
v_score_delta_per_600.9360.9230.90Math component of state-value change — tracks role/usage, not skill
v_concede_delta_per_600.9280.7920.58Math component — role/usage, not skill
vaep_per_600.8760.8760.71Total action rate — role/usage-dominated
v_in_oz_per_600.8550.8520.65Offensive-zone contribution — role-confounded but informative
xgf_per60_on_ice0.6290.5670.55Public on-ice xGF — the cleanest repeatable public skill signal
v_in_dz_per_600.5370.5250.50Defensive-zone contribution — skill-stable, and beats public xGA
v_in_nz_per_600.4590.3590.44Neutral-zone contribution — skill-stable, no public analog
xga_per60_on_ice0.4210.4250.47Public on-ice xGA — the standard benchmark v_in_dz beats
rapm_net0.3130.2690.42Single-season RAPM ≈ the raw control (noise-bound)
goal_share_5v50.3110.3140.42Raw 5v5 on-ice goal share — the control
rapm_off0.2680.2430.36Below 0.30 — noise
rapm_def0.1470.1200.31Individual defense barely repeats year to year

The two all-strength delta components are omitted; the strength-matched 5v5 columns shown are the primary skill-comparison rates.

v_in_dz_per_60 (0.54) clears the public on-ice xGA benchmark (0.42) — and on the second, noisier season-pair (2024-25 → 2025-26, measured on the complete recovered 2025-26 season with real full-season ice-time denominators) the gap widens to 0.60 vs 0.37. Single-season RAPM, by contrast, barely matches the raw goal-share control, which is exactly why the production RAPM pools seasons. The math components near the top of the table (0.93+) repeat because they track role and usage, not because they are the best player ratings — read them with that caveat.

Known Limitations

The model is honest about what it cannot see. The most important constraints:

Play-by-Play Only

The NHL feed records discrete events — shots, hits, faceoffs, takeaways, giveaways, blocks, penalties, goals — but no passes, controlled zone entries, zone exits, or sustained possession. So the model cannot directly credit the cross-ice feeds, carries, and entries that drive much of elite-player value. Assists are the only proxy for playmaking, and the partial divergence between action value and RAPM is one symptom of this blind spot. The same constraint cuts on defense: positioning, gap control, and lane denial that never produce a recorded event are invisible to action data, so defensive-zone value rewards players who defend by doing recordable things (blocks, takeaways) over those who defend by being in the right place. Closing either side would need tracking data (NHL EDGE) or licensed microstats.

Chance-creation credit — tested, not shipped

Because no passes are recorded, the value of an unconverted scoring chance goes entirely to the shooter; playmakers are credited only when a chance becomes a goal. We built and tested the obvious repair: redistributing part of each chance’s value to teammates whose recorded actions (takeaways, earlier shots) built the possession. Candidate parameters were evaluated blind against a pre-registered two-part test, with bootstrap confidence intervals on every comparison: the adjusted metric had to predict the next season’s on-ice goal differential at least as well as the unadjusted one, and had to improve year-over-year repeatability by a margin set before any results were seen. It passed the first part — the adjustment carried a real but tiny predictive gain, about +0.002 correlation — and failed the second outright: repeatability slightly declined rather than improving. It was rejected under that pre-set bar. The per-event credit asymmetry itself still stands and is not repaired here, pending passing or tracking data. A separately-constructed term — chance-creation RAPM (C1), evaluated the same blind way — cleared its out-of-sample prediction bar and ships in the net definition; see “Chance creation for others (C1)” below. It earns its place by improving prediction, not by repairing per-event shooter credit. One experiment rejected, one shipped, under the same pre-registered standard.

Teammate Collinearity in RAPM

Players who share almost all of their ice time cannot be cleanly separated by the regression. The canonical case is McDavid and Hyman in Edmonton, on the ice together for roughly 85% of their 5v5 minutes year after year; some of McDavid’s credit leaks to his linemate. Pooling seasons reduces this but does not eliminate it.

Goalie Year-over-Year Noise

Goalie GSAx barely repeats season to season (persistence near zero on adjacent seasons with a high shot floor). This is largely real — goaltending is genuinely volatile, the qualifying sample is small, and our shot model has no traffic/screen features — so single-season GSAx is descriptive, not a projection.

2025-26 season status — promoted to stable, one documented deviation

The 2025-26 regular season is complete and was promoted out of provisional status on 2026-06-12. Two facts worth keeping on the record. First, the NHL’s JSON feed remains permanently missing shift charts for 505 of 1,312 games — re-checked at the source after season’s end; those shifts were recovered in full from the league’s legacy HTML time-on-ice reports, validated with an exact per-shift match against the JSON feed on games both sources carry, so every 2025-26 metric is built on complete, real shift data. Second, the season’s expected-goals model failed our strict held-out calibration gate (−5.2% on the final tenth of the season) — we investigated rather than waved it through. Full-season calibration is −0.5%, comfortably inside our ±2% standard; the miss is confined to the temporal tail, where league scoring jumped about 7% relative to the rest of the season, with no concentration by team, arena, or feed era. That is a genuine scoring-environment shift the gate punishes by construction, not a data defect — so the season ships as stable with this deviation documented instead of hidden. The gate design itself is queued for review before the 2026-27 build, since it currently cannot distinguish calibrator failure from real late-season scoring drift.

Chance creation for others (C1)

Our action values are built from NHL play-by-play, which records shots but not passes — every non-goal scoring chance is credited entirely to the shooter, and the pass that created it is invisible. That per-event asymmetry is a structural limitation we keep on the record. C1 is not a proven fix for it: it ships because it improved out-of-sample prediction under a pre-registered blind test — the same standard as the rejected chain-credit experiment — not because a playmaking deficit in Net has been demonstrated.

C1: chance creation for others. Standard RAPM asks: when this player is on the ice, does his team generate more expected goals? C1 asks a sharper question: when this player is on the ice, do his teammates — excluding the player himself— generate more shot quality? Every 5v5 stint (a stretch with both lineups unchanged) is expanded ten ways, once per skater. In the copy where a given skater is the “focal” player, the target is the expected-goal total of shots taken by the other four teammates, and the focal player’s own column is zeroed out. A ridge regression over ~1.35 million such rows then estimates each player’s marginal effect on teammates’ shot quality — chance-creation influence with the player’s own shot volume removed by construction. (Without the focal exclusion, the design collapses algebraically into ordinary offensive RAPM.) C1 is moderately related to offensive RAPM (r ≈ 0.55–0.68 across seasons, far below our pre-registered 0.85 redundancy threshold) and repeats within a season at a split-half reliability of ~0.60 after Spearman-Brown adjustment, in all three seasons tested.

This is distinct from the “Playmaking” figure shown on the leaderboards and player pages: that one is realized assist credit (the share of a player’s goal value coming from his actual primary and secondary assists), whereas chance creation for others is a regression-isolated estimate of how much a skater lifts his on-ice teammates’ shot quality, whether or not it ever shows up as a recorded assist.

The blind test and what shipped. Every decision was registered before any result existed. The candidates: the current net definition (baseline), C1 alone, and small fixed blends (10/20/30% C1, plus two variants adding box-score primary assists). The criterion: cross-prediction of next-season on-ice 5v5 goal differential per 60, over two season pairs, with bootstrap confidence intervals — the same out-of-sample standard everything else on this page is held to. The ship bar: at least +0.010 pooled improvement over the baseline with the confidence interval excluding zero, no degradation on a secondary team-level check, and — among everything that cleared — the smallest admixture wins. No names, no ranks, and no player-level numbers were examined until the choice was frozen from the aggregate table. Every blend cleared the bar; the smallest-weight rule selected the 10% blend now published as net v2 (formula above). C1 alone predicted worse than the existing net — it is a complement, not a replacement, which is exactly what a small admixture is for.

External validation against tracked passing — including the miss. We also tested C1 against ground truth it was never trained on: All Three Zones’ manually tracked passes that lead to shots (“shot assists”), a few hundred games per season. We registered one validation variable (primary shot assists per 60 of tracked 5v5 time), one coverage floor, and one bar — pooled Spearman ≥ 0.50 with the confidence interval excluding 0.30 — before computing anything, with no alternative columns permitted regardless of outcome. The result: pooled Spearman +0.479, CI [+0.441, +0.518], across ~1,580 player-seasons (per season: +0.53 / +0.42 / +0.49). The interval excludes 0.30 decisively — C1 genuinely tracks real passing — but the point estimate missed our bar. By the registered rule, C1 therefore does not ship as a standalone chance-creation metric; it ships only inside net v2, where its predictive value was established directly. For context, raw primary assists per 60 correlate at +0.621 with the same tracked-passing variable on the same panel — unsurprising, since both are realized-pass counts, while C1 estimates on-ice influence(pre-pass movement, retrievals, and sequence play that tracking attributes to no one). We report the miss rather than re-litigating it, and we deliberately call C1 chance creation rather than playmaking: the validation shows it tracks real passing only moderately, because it measures the on-ice lift in teammates’ shot quality however it arises, not realized passes. One re-test is registered for when fuller tracking coverage publishes; the spec is frozen.

The entanglement caveat. RAPM-family estimates separate players by seeing them in different lineups. A handful of pairs are nearly inseparable — skaters sharing more than 90% of their 5v5 minutes (permanent lines and defense pairings; roughly 5–10 pairs per season). For those players, C1’s split of chance-creation credit within the pair is statistically under-determined, and the 10% C1 component of net v2 should be read with that grain of salt. The affected pairs move very little under v2 in practice (within about ±4 ranks in almost all cases), but the caveat is structural and we flag it rather than hide it.

Contract Surplus

The contract-surplus board asks a different question: what does the model think a contract is worth? For every signed player on the value panel we fit a within-position regression of actual cap hit (AAV) on the player’s value, his contract status (ELC / RFA / UFA), and his signing age. The fitted value is the expected cost, and surplus = expected cost − AAV — positive is a team-friendly deal, negative is an overpay.

The value input is a recency-weighted (5:4:3) blend of net v2 across the player’s seasons — the same 5v5 even-strength zone-rate value vs position peers used everywhere else on the site. That is the key caveat: surplus is built from 5v5 value and does not credit power-play or penalty-kill production. So a player whose value is genuinely special-teams-driven can read as an “overpay” here while still earning his deal. It is a model estimate, not a verdict — the board and every player card carry that framing prominently.

The PP-heavy flag.To keep the overpay reading honest, each player carries a derived special-teams marker. We measure the share of a player’s pooled all-strength action value that comes from outside 5v5 ((Σ v_total − Σ v_total_5v5) / Σ v_total); the flag fires when that share is ≥ 0.40— roughly the league’s top quintile, i.e. all-strength impact at least about 1.7× the 5v5 value. It is fully derived, never a hand-picked star list: it fires on whoever genuinely fits (Kaprizov, Draisaitl) and, by design, stays off genuine overpays with no special-teams excuse (e.g. Huberdeau), whose deals read as expensive even after accounting for special teams.

The bargain floor.The cost curve is roughly linear, so it over-credits cheap depth contracts — without a floor the “bargains” are dominated by minimum-salary bodies whose surplus is just the model intercept. Headline bargains must therefore clear both an AAV floor ($1.5M) and a value floor (0.25 SD above positional average). The regression still fits on every contract and each player keeps his computed surplus; the floor only governs the headline bargain board. Overpays are unfloored. The snapshot is hand-maintained, refreshed manually rather than nightly.

Changelog

2026-06-29 — Contract surplus board. Added the contract-surplus surface (board + player-page card): expected cost from a within-position fit on 5v5 value vs actual AAV, with a derived PP-heavy flag and a prominent “estimate, not a verdict” caveat. See Contract surplus.

2026-06-12 — Net Contribution definition change (v2). Net is now 0.9 · z(0.6 · z(OZ) + 0.4 · z(DZ)) + 0.1 · z(C1) per position cohort and season, same qualification floor (500 events). Selected blind under a pre-registered bar (+0.010 pooled next-season predictive improvement, CI excluding zero; smallest admissible weight wins). Effect: rank correlation with v1 is 0.995 within season; the median absolute rank change is 3–4 spots; same-season agreement with on-ice goal differential improved in all three seasons. Historical seasons are restated under v2 — every season page and leaderboard reflects the new definition.