Core principle
Trade Value Units (TVU)
Every asset — NHL player, prospect, or draft pick — converts to a single number: TVU. A fair trade is where both sides receive equal TVU. The engine shows the gap and translates it into hockey terms GMs reason in: "that gap equals a mid-2nd round pick." Prospect TVU is computed from NHLe-adjusted production, ceiling grade, and years-to-NHL timeline. The historical comp layer anchors all outputs to real trades GMs actually agreed to.
verdict = TVU_received_A vs TVU_received_B
// gap <11 → essentially fair (within noise)
// gap 11–47 → minor (≈ 5th–7th round pick)
// gap 47–155 → meaningful (≈ 3rd–late 2nd round pick)
// gap 155–217 → ≈ mid-to-early 2nd round pick
// gap >217 → significant imbalance (1st round territory)
Layer 1
Peak value baseline
Best 3-season rolling avg of age-adjusted pts/60, xGF%, and TOI%. Position multiplier accounts for structural role differences. Anchors to peak output, not one noisy season.
peak = (pts60×0.45 + xGF%×0.35 + toi%×0.20) × pos_mul
// C=1.00 LW/RW=0.93 D=0.88 G=0.85
Layer 2
Current form ±20%
Trailing 20-game rolling stats vs career baseline. Hot streaks earn +20% max premium; prolonged slumps apply −20% max discount. Capped to prevent one month dominating.
form = clamp(rolling20 / career_avg, 0.80, 1.20)
cur = peak × form
Layer 3
Age curve multiplier
Career trajectory by position and archetype. A 24-yr-old on the rise is worth more than stats show. A 33-yr-old declining is worth less. The most differentiating layer — where armchair analysis most often fails.
arc = expected_peak_remaining(age, pos)
// D peak: 28 F peak: 27 G peak: 30
with_arc = cur × (0.60 + 0.40×arc)
// 0.60 floor: elite 36yr has real present value
Layer 4
Contract modifier
Cap efficiency, years of team control, and clause burden. NTC/NMC reduce flexibility for the receiving team — a real and often ignored cost.
cap_eff = (prod/M$) / league_avg
ctrl = min(yrs_left / 4, 1.0)
clause = ntc×0.05 + nmc×0.03
TVU = with_arc × max(0.3, cap_eff×0.6 + ctrl×0.4 − clause)
Prospect TVU — ceiling-adjusted NHLe model
Prospect valuation
NHLe + ceiling + timeline
Prospects are valued on four dimensions: (1) NHLe production — real stats fetched from NHL landing page, converted to expected NHL pts/82 using league-specific factors (AHL×0.45, OHL×0.30, SHL×0.55, NCAA×0.38, etc.); (2) ceiling grade — Elite/A/B/C derived from draft position and development signals; (3) time-to-NHL discount — 12% per year from expected debut, based on league and age; (4) draft floor — R1 prospects always worth at least their pick slot TVU. Stats load automatically when the prospect is added from the dropdown.
nhle_score = raw_pts × league_factor / gp_factor
// AHL factor: 0.45 · OHL/WHL/QMJHL: 0.30 · SHL: 0.55 · NCAA: 0.38
ceiling_mul = {Elite:1.8, A:1.4, B:1.0, C:0.65}
timeline_disc = 0.88 ^ yrs_to_nhl
// Each year of distance costs ~12% of value
prospect_TVU = nhle_score × ceiling_mul × timeline_disc × pos_mul
Pick TVU — granular value chart
Pick valuation
Individual picks 1–5 · blocks of 5 thereafter
Each of picks 1–5 has its own value reflecting the non-linear surplus value at the top of the draft. Picks 6–32 are grouped in blocks of 5 by observed trade patterns. All values derived from 13+ years of NHL pick-for-pick trades, calibrated against Schuckers (200-game model) and Luszczyszyn (GSVA model). Protected picks and future picks are discounted.
pick_TVU = base × recency_disc × protection_disc
// 2+ yrs out → ×0.85 · 3+ yrs → ×0.72
// Top-10 prot. → ×0.68 · Top-5 prot. → ×0.55 of unprotected
| Pick slot | Round | Context | TVU |
| 1st Round — Individual picks |
| #1 overall | R1 | Franchise cornerstone · generational | 1000 |
| #2 overall | R1 | Near-certain franchise player | 900 |
| #3 overall | R1 | Elite ceiling · high hit rate | 810 |
| #4 overall | R1 | Lottery premium · top-end | 730 |
| #5 overall | R1 | Lottery · premium talent pool | 655 |
| 1st Round — Blocks of 5 |
| #6 overall | R1 | High lottery | 600 |
| #7 overall | R1 | High lottery | 575 |
| #8 overall | R1 | Lottery fringe | 548 |
| #9 overall | R1 | Lottery fringe | 522 |
| #10 overall | R1 | Top-10, elite upside | 498 |
| #11–15 | R1 | Lottery fringe · strong ceiling | 390–460 |
| #16–20 | R1 | Mid-round · playoff team range | 290–350 |
| #21–25 | R1 | Late first · solid NHL upside | 215–265 |
| #26–32 | R1 | Deep playoff team · project range | 155–205 |
| 2nd Round |
| #33–37 (Early 2nd) | R2 | Comp range · strong 2nd | 170–185 |
| #38–47 (Mid 2nd) | R2 | Standard 2nd round | 110–155 |
| #48–64 (Late 2nd) | R2 | Late 2nd · project | 75–105 |
| Rounds 3–7 |
| 3rd round | R3 | Depth/development | 50–65 |
| 4th round | R4 | Depth | 30–40 |
| 5th round | R5 | Lottery ticket | 18–25 |
| 6th–7th round | R6–7 | Minimal value | 8–15 |
Three sources merged on NHL player ID + a salary cache updated nightly. Cap ceiling: $104M (2026–27). None alone is sufficient — all four combined power GM-grade analysis.
NHL Stats API
api-web.nhle.com/v1
· Current roster per team
· Prospect pool per team
· Player stats & game logs
· xGF% via EDGE endpoints
· Injuries & transactions
Roster: every 15 min · Prospects: daily
CapWages API
capwages.com/api/gateway/v1
· Cap hits & AAV
· Contract years remaining
· UFA / RFA status
· NTC / NMC clause flags
· Retained salary & LTIR
Salary (User Input)
Entered directly on each player card
· Cap hit ($/yr) — editable field
· Years remaining — editable field
· NTC / NMC clause toggles
· Pre-filled from CapWages if available
· Retention slider unlocks after entry
Always accurate — you control it
Retention model
How retention affects TVU
NHL rules allow the sending team to retain up to 50% of a player's salary. Max 3 retained salary slots per team simultaneously. Retention transfers value: the receiving team gets a better cap bargain, but the retaining team pays a ghost cap cost that reduces their side of the trade.
ghost_cap_cost_TVU = retained_$/yr × years_left × 22 × time_discount
// time_discount = 0.92^((yrs-1)/2) — rising cap ceiling softens future pain
// $1M/yr retained for 1 year ≈ 22 TVU · for 6 years ≈ 113 TVU
receiving_TVU_boost = base_TVU × 0.25 × retain_pct × 0.80
// cap component ≈ 25% of TVU · retention improves that component
sending_net_TVU = base_player_TVU − ghost_cap_cost
receiving_net_TVU = base_player_TVU + receiving_boost
Salary input: Users enter each player's actual cap hit and years remaining.
If no salary is entered, TVU uses a neutral contract modifier (1.0×) — the performance score
still applies but without a cap efficiency premium or penalty.
Example — Morrissey $6.25M, 6yr, 50% retention:
Sending team pays ghost cap cost: $3.125M × 6yr × 22 × 0.92² = −293 TVU
Receiving team gets Morrissey at $3.125M effective cap hit = ~650 TVU (vs 610 unretained)
Net: retaining team sacrifices ~293 TVU of future cap flexibility to make the deal work.