How the models work

Methodologies

NHLe + FlameWire Calc for the prospect pool, plus Team Blueprint process metrics (including DirtyXg v4 vs public xG).

← Dashboard

Jump: Eligibility · NHLe · FlameWire Calc · Team Blueprint · DirtyXg · Data · Limits

NHL draft eligibility (age window)

The lab shows an Eligibility column based on the standard NHL Entry Draft age rules (practical approximation for scouting):

Region (NA vs international) is inferred from leagues / hometown when possible; this universe defaults to North American. After July 1 we evaluate the next calendar draft year (e.g. Aug 2026 → 2027 draft).

NHLe (NHL equivalency)

NHLe translates points-per-game from other leagues into an NHL-scale rate using public league factors (classic NHLe tradition). Headline number is NHLe/82 — expected NHL points over 82 games if the translated rate held.

League factors (v1)

LeagueFactorNotes
NHL1.00Baseline
AHL0.50Pro minors
KHL / SHL / Liiga / NCAA / …0.41–0.80Euro / college pro paths
OHL / WHL / QMJHL0.29–0.34Major junior
USHL0.28U.S. junior
ECHL0.32Pro minors
BCHL / AJHL / Jr A0.16–0.20Directional only — lower confidence

Junior A factors are intentionally conservative. Scoring-leader lists over-sample offense and can inflate rates versus full rosters.

FlameWire Calc

Proprietary upside score on a 0–100 “OVR-style” scale:

FW = 0.40·P + 0.30·D + 0.30·A (+ agreement · defense boost · young-elite · soft tiers; v0.9)

Tiers (score floors): Star ≥96 · Top-6 / Top-4 D ≥74 · Middle-6 / 2nd pair ≥62 · Bottom-6 / 3rd pair ≥41 · Bubble ≥26 · else AHL path. Compared side-by-side with NHLe role ceiling.

Accuracy lab results

Draft-day destiny back-test: drafted skaters, age ≤21 at draft, ≥40 NHL GP later, seasons as-of draft only (n≈365). Metrics: exact tier hit and within-1 tier. Live baseline under v0.6–v0.8 PDA blend: ~37% exact · ~87% within-1 (bootstrap 95% CI roughly exact 32–42%, within-1 83–90%).

Literature-inspired formulas tested with 5-fold CV (pure data-only features — NHLe, pick, age/path, CS rank, relative peers, size, F/D):

Result: nothing beat the current PDA blend by more than noise. Near-misses (agree scale 1.5, light CS blend 10–35%) moved within-1 or exact by ~0.3–0.9pp — well inside bootstrap CI, so hard score weights stay put. Aggressive relative / PCS / ridge / tree variants usually hurt within-1 (collinearity of CS≈pick≈0.91; relative≈NHLe on eventual NHLers).

Practical ceiling for 6 hard destiny tiers on draft day with public box data is about 35–40% exact / 85–88% within-1. Targets of 50% exact / 90% within-1 need either fewer tiers, post-draft development seasons, scouting text features, or a different label (e.g. binary NHLer / star as in public logistic models). Soft probabilities are the honest way to express the residual uncertainty without inventing hard precision.

From-scratch formulas without NHLe

We also rebuilt destiny models that never use league translation factors (no NHLe), following public draft research:

On the same draft-day set (n≈365), none beat FlameWire on within-1 (best non-NHLe ~85% vs FW ~87%). One ridge→P/82 path hit slightly higher exact (~38% vs ~37%) while losing ~4pp within-1 — not a joint win. Pure skill (no pick/CS) collapses (~28–37% exact / ~77–80% within-1). So NHLe is not the bottleneck: capital + multi-league context already do most of the ordinal work; dropping NHLe does not unlock a new accuracy regime on this label.

NHL draft status

Draft status is matched against public NHL draft classes from api-web.nhle.com/v1/draft/picks/{year}/all (default years 2005–current). Matching is by normalized full name, with disambiguation on position, age-at-draft, and amateur league when multiple picks share a name.

NHL Central Scouting rankings

Public midterm + final prospect rankings from api-web.nhle.com/v1/draft/rankings/{year}/{category} (NA skaters = 1, international skaters = 2; years ~2008–current). Cached under Data/cache/nhl_cs_rankings.json.

Ages & birthdays

Missing ages are filled without HTML scraping, in this order:

  1. Spreadsheet — Age column when present.
  2. CHL LeagueStat JSON (OHL / WHL / QMJHL) — full Tier-1 skater boards from 2010–11 onward (cached under Data/chl/seasons/). Merged into player bios (DOB, height, weight, shoots, hometown) and multi-year season rows (GP/G/A/P/+/−/PIM) for NHLe. Refresh: POST /api/sync-chl-dump or python -m app.chl_dump --from-year 2010.
  3. NHL API — name search + player landing for official birthDate.
  4. NCAA D1 (College Hockey News) — primary college source: full team rosters (DOB, height, weight, class, hometown, draft note) plus full-season overall scoring (~1.3k–1.6k skaters/year), seasons 2010–11 → current including 2022–23. Cached under Data/chn/. Refresh: POST /api/sync-chn or python -m app.chn_dump --from-year 2010.
  5. NCAA D1 leaders (ncaa.com) — optional gap-fill via ncaa-api.henrygd.me (leaderboards only; no bios). Data/ncaa/; POST /api/sync-ncaa.
  6. NCAA class estimate — Fr/So/Jr/Sr/Gr + season year → approximate age (synthetic July 1 birthday). Marked with ≈. Directional only; CHN DOB preferred.

Cache: Data/cache/birthdays.json. Refresh via POST /api/sync-chl-birthdays or POST /api/sync-birthdays.

Team Blueprint

Team Blueprint diagnoses NHL clubs against historical success ladders (regular-season tiers + playoff depth) using official NHL standings/summary rates, then layers NHL EDGE process metrics from season 2021–22 onward:

EDGE dumps cache under Data/blueprint/edge/. Pre-2021–22 seasons keep counting stats only (no EDGE fields).

DirtyXg (experimental) vs public xG

Expected goals (xG) in full public models (e.g. MoneyPuck, Natural Stat Trick, Evolving-Hockey) score every unblocked shot attempt with many features — distance, angle, shot type, rebound/rush, score effects, etc. — trained on large multi-season samples.

DirtyXg is Hockey Scout’s independent chance-quality estimate (FlameWire Lab lineage). Current Blueprint default is v4: a pure-Python L2 logistic fit on NHL play-by-play, trained on goals (not MoneyPuck coefficients). It is not a MoneyPuck/NST feed — think of it as a lab process metric for Blueprint ladders and finishing residuals. MoneyPuck remains a side-check only.

Formula (v4 preferred)

v4 (current): every unblocked PBP attempt (goal + SOG + miss) gets P(goal) from a logistic model with continuous distance/angle (plus squares and interaction), rebound (≤3s since prior shot event), rush (≤4s after NZ/DZ prior event), 5v5 flag, log time-since-last-event, and shot-type one-hots (wrist baseline). Empty-net and miss flags are not features (EN exploded the intercept; miss is label leakage — misses never score). Coefficients live in Data/blueprint/pbp/dirty_xg_v4_model.json. Train calibration is fit so Σ predicted ≈ Σ goals on the training sample (no constant post-hoc scale).

DirtyXg_for = Σ logistic(xi) · 1.0 · same sum for against · method tag pbp_v4

Lanes: every unblocked attempt is scored once, then rolled up as all-situations and 5v5 only (situationCode = 1551). Blueprint ladders and diagnosis prefer DirtyXg% (5v5) when present — cleaner even-strength process — and still show all-sits for full-game context.

v3 (prior PBP): unblocked attempts mapped to EDGE bands, scored with EDGE league conversion rates + shot-type multipliers + miss discount, then ×0.684 so league Σ DirtyXg ≈ Σ goals.

DirtyXg_for = Σ xG_band(unblocked) · 0.684

v2.1 (EDGE-only fallback): season SOG counts by EDGE band high / mid / long (+ residual), then ×1.048:

DirtyXg_raw = N_high·r_high + N_mid·r_mid + N_long·r_long + N_other·r_other

DirtyXg = DirtyXg_raw × 1.048

Typical EDGE rates: high ≈ 0.19 · mid ≈ 0.11 · long ≈ 0.03 · other ≈ 0.06. Blueprint prefers PBP v4 when the model + season rollups are present; EDGE rollup remains as dirty_xg_edge for comparison. Pre-EDGE / no-PBP seasons keep counting stats only.

Spot-check vs MoneyPuck (v4)

We compared DirtyXg v4 to MoneyPuck team xGoalsFor / xGoalsAgainst (situation = all) using the official MoneyPuck data downloads (2023–24 and 2024–25 regular season CSVs) — not HTML scraping. Credit: MoneyPuck.com. Non-commercial research use. Goal is accuracy across the board, not cloning MP; MP is a reference for rank/process fidelity.

Check DirtyXg v4
Sample 64 team-seasons (32 × 2 RS)
Pearson r / Spearman ρ vs MP xGF 0.937 / 0.926
Pearson r / Spearman ρ vs MP xGA 0.915 / 0.908
Pearson r / Spearman ρ vs MP xGF% 0.974 / 0.960
MAE vs MP xGF (goals) ~9.9
Level (Σ DirtyXg / Σ MP xGF) 0.966
Goals / DirtyXg (pair sample) 1.013
Finishing residual r (G−DirtyXg vs G−MP xGF) 0.91
Top-10 team overlap by season (xGF) 8/10 (2023–24) · 9/10 (2024–25)

Ladder sanity (DirtyXg%, EDGE-era RS): Presidents Trophy ~53% · playoff teams ~52% · missed playoffs ~49% · Bottom 5 ~45%. Example: CGY 2024–25 ≈ 225 DirtyXg vs 220 goals (slight underperformance residual).

Read: v4 tracks public chance creation closely enough for Blueprint process ladders, share metrics (DirtyXg%), and finishing residuals. Remaining gaps vs full commercial models are mostly score/venue adjustments, flurry effects, and richer sequence context — not basic location.

Lineage — what each version adds

Idea Source Effect Ship?
League band rates (goals/SOG) EDGE high/mid/long Core of v2 Yes (v2)
Constant public-level scale (~1.05) Calibration EDGE-only level fix Yes (v2.1)
Unblocked attempts (SOG + misses) NHL PBP Public xG unit of analysis Yes (v3)
Continuous distance / angle PBP coordinates Main rank lift vs bands Yes (v4)
Rebound / rush / strength / shot type PBP sequences Closes most residual vs MP ranks Yes (v4)
Fit to goals (logistic L2) PBP goals Train cal ≈ 1.0; no MP labels Yes (v4)
OZ% / CF diff as xG correction EDGE Blurs “chance quality” Keep as separate ladder metrics
Score/venue/flurry adjustments — Commercial-model residual Not in DirtyXg (by design)

Inspired by the public expected-goals tradition (MoneyPuck and peers). DirtyXg is an independent lab estimate — not affiliated with or endorsed by those sites. Always credit MoneyPuck.com when citing their downloadable data.

Data source

Universe is built from the full CHL LeagueStat dump (2010+), College Hockey News NCAA D1 (2010+), and Data/Hockey_Scoring_Leaders_Master.xlsx (other leagues / sheet fills). Players are merged by name (and CHN/CHL ids when present) for multi-year NHLe. Team Blueprint uses official NHL APIs (standings, team summary, playoff carousel) plus NHL EDGE team endpoints. Hit POST /api/reload (or restart) after refreshing dumps; Blueprint/EDGE via POST /api/sync-blueprint or Refresh on /blueprint.

Limits