Technical Methodology · v3.0

IMPACT: A TWO-SIGNAL FRAMEWORK WITH A TRACKING OVERLAY

Box-score possession value + team-impact RAPM, blended by per-player inverse variance. Displayed alongside the NBA's optical-tracking metrics as an independent third lens.

Read The Game Research  ·  First published April 2026  ·  Living document — updated as the model evolves.

Abstract

We present Impact, the primary player-evaluation metric on Read The Game. Impact is an inverse-variance blend of two independent signals: a per-game box-score possession-value attribution — which values each event (shot, assist, rebound, turnover, foul, hustle play) by the points of possession value it creates relative to league-average expectation, with shots difficulty-adjusted against a 1,030,404-shot training set — and a season-level Ridge-regularized Adjusted Plus-Minus (RAPM) model, team-demeaned to remove squad-quality confounds. The two signals are normalized to z-score space and combined with per-player weights derived from the relative information in each source. The result is a single per-game number that captures both what a player did (box) and what happened when they were on the floor (RAPM), with each player's weight automatically calibrated by their own data. Alongside Impact we display the NBA's optical-tracking metrics (Gravity, Leverage, Shot Quality) as an independent third view, and the individual PBP Credit components (scoring, creation, shot-making, defense, hustle, turnovers) as a diagnostic decomposition of the box-score signal.

2
Signals blended
1,030,404
Shots in training set
121
Shot types classified
60/40
Median box/RAPM weight
~580
Players rated per season
1

MOTIVATION & RELATED WORK

Evaluating individual NBA contribution from public data has a structural problem: every observable outcome (points, rebounds, team wins) is shared across five players on the floor. Basketball is a deeply cooperative sport, and attributing credit to a single player requires either (a) isolating each on-ball action and valuing it in isolation, or (b) regressing outcomes onto player-presence matrices and letting the regression untangle who causes what.

Box-score-based models (Win Shares, PER, PIE) take the first path. They are interpretable and responsive to current form, but reward volume, under-measure defense, and are blind to off-ball impact. Regression-based models (RAPM, EPM, LEBRON) take the second path. They capture everything that happens when a player is on the floor, but suffer from teammate collinearity, wide small-sample uncertainty, and a lag behind role changes.

These two families fail in opposite ways. Our approach is to treat them as two independent estimators of the same latent quantity, combine them by inverse variance, and let each player's own data determine their weight. The result — what we call Impact — is the number we display in the main Impact column on the leaderboard and player pages.

2

PIPELINE OVERVIEW

Every night, for each game in the NBA schedule, the full pipeline runs in four stages:

STAGE 1
Box-Score Signal. Box score + play-by-play + optical-tracking feeds are combined to compute total_impact — a per-game possession-value attribution with shot-difficulty adjustment. §3.
STAGE 2
RAPM Signal. A Ridge-regularized Adjusted Plus-Minus is fit on the season's full possession matrix (λ cross-validated, Bayesian prior seeded from box-score impact). The resulting coefficient is team-demeaned to remove squad-quality inflation. §4.
STAGE 3
Blend. Per-player inverse-variance weights combine the two signals in z-score space and back-transform to points per game. The output is published_impact — the number shown in the Impact column. §5.
STAGE 4
Component & tracking views. Alongside Impact, the leaderboard displays PBP Credit components as a diagnostic decomposition (§6) and the NBA's Inside-the-Game optical metrics as an independent third lens (§7).

What follows documents each stage in full. Everything is published: equations, coefficients, derivations, sample sizes. No black boxes.

3

SIGNAL A — BOX-SCORE POSSESSION VALUE

Basketball is a zero-sum exchange of possessions. An NBA possession produces, on average, 1.12 points. Every event during a possession either moves the expected outcome up or down. Signal A values each event by its possession-outcome delta, attributes it to the player who caused it, and sums the result into a per-game number: total_impact.

Equation 3.1 · Possession value delta(3.1) Δvevent = E[points | event] 1.12 Every event's contribution is expressed relative to the league-average points-per-possession baseline.

Shot-difficulty adjustment

Before we value a made or missed shot, we need to know how hard it was. Our shot-difficulty model is empirical: every NBA shot is classified into one of 121 types defined by subtype (dunk, layup, pull-up, step-back, etc.), distance bucket, and shot value (2pt or 3pt). The expected FG% for each type is the observed success rate of all such shots in our training set. No latent variables, no modeling assumptions.

Table 3.1 — Sample of the shot-difficulty lookup. Full table has 121 entries. Built from 1,030,404 shots across four NBA seasons (2021-22 through 2025-26).
Shot type Expected FG% Sample size
Dunk (0–4 ft)89.5%n = 45,885
Layup (0–4 ft)61.2%n = 175,363
Driving Layup (0–4 ft)54.8%n = 15,444
Jump Shot (11–16 ft)44.4%n = 75,180
Catch-and-shoot 3PT (23+ ft)36.0%n = 374,430
Pull-up 3PT (23+ ft)32.3%n = 12,877
Step-back 3PT (23+ ft)34.2%n = 6,952

Event coefficients

Non-scoring events are valued by the empirical change in expected possession outcome they produce. Each coefficient below is measured directly from league-observed outcomes, not calibrated.

Table 3.2 — Event value coefficients (points). Positive = value created, negative = value destroyed.
Event Value Derivation
Offensive rebound+1.264Second-chance PPP from direct PBP measurement.
Defensive rebound+0.300P(opponent OREB if unclaimed) × PPP ≈ 0.27 × 1.12.
Assist+0.500Shot-quality creation credit plus residual playmaking.
Steal+2.300Two-possession swing (opponent loss + team transition).
Block (recovered)+0.900P(possession ends on block) × PPP + deterrent adjustment.
Contested shot+0.045Tracking-based defensive pressure credit per contest.
Deflection+0.225Hustle event from the NBA's tracking feed.
Charge drawn+2.100Full turnover swing plus penalty-offensive-foul bonus.
Loose ball recovered+0.650P(possession conversion) × PPP.
Foul drawn (shooting)+0.900Expected FT value net of possession cost.
Turnover (live-ball)−2.370Opponent fast-break PPP ≈ 1.25 plus own lost possession.
Turnover (dead-ball)−1.120Opponent half-court possession only (no transition bonus).
Shooting foul committed−1.560Expected FTs × league FT% × shot value.
Personal foul−0.750P(bonus) × expected FTs + accumulation risk.

Scoring & shot-making

Equation 3.3 · Made-shot value(3.3) vmade = shot_value + (1 xFG%) × shot_value A contested pull-up 3 at 32% expected earns a larger bonus than an open dunk at 90% expected.
Equation 3.4 · Missed-shot penalty(3.4) vmiss = (1 OREB%) × PPP OREB% is shot-type specific (missed 2pt → ~30%, missed 3pt → ~22%). Shots likely to be rebounded back are penalized less.

Creation credit

Equation 3.5 · Assist creation value(3.5) vcreation = xFG% × shot_value 1.12 An assist to a 65%-expected open layup earns more creation credit than to a 35%-expected contested jumper. Self-created shots (unassisted makes) earn both scoring and creation credit.

Baseline normalization

Raw event-value sums are not interpretable on their own — every player accumulates credit in proportion to minutes played. We subtract a per-game baseline so total_impact measures production above or below what an average rotation player would produce in the same minutes:

Equation 3.6 · Total impact (final box signal)(3.6) total_impact = Σvevents (minutes × game_avg_credit_per_min) The baseline is computed per game, so the box signal is zero-sum: summing the ten players' total_impact in any game yields exactly zero. Implementation: calculate_net_impact() in nightly_nba_summary.py.
4

SIGNAL B — RAPM

Ridge-regularized Adjusted Plus-Minus regresses per-possession point differential onto indicator variables for every player on the floor. The coefficient for player i is the number of points per 100 possessions the team's net rating changes when i is on the court, controlling for every teammate and opponent in the same possession. It captures everything — off-ball spacing, defensive rotations, screen-setting, pace effects — that box-score attribution can't see.

Equation 4.1 · Ridge RAPM(4.1) β̂ = arg minβ y‖² + λβ βprior‖² X is the possession-by-player on-court indicator matrix (+1 offensive, −1 defensive); y is point differential per possession; β is the player-effect vector. The regularization pulls β toward a Bayesian prior seeded from box-score impact per minute (impact_per_min / 2.2), so low-possession players shrink toward their box-score prediction rather than zero.

λ selection. We cross-validate over the grid [100, 300, 1,000, 3,000, 10,000, 30,000, 100,000] and select the λ that minimizes held-out prediction MSE on the season's possession matrix. Typical best-λ values land in the 10,000–30,000 range given ~200,000 possessions and ~500 active players.

Output scale. RAPM coefficients are expressed in points per 100 possessions. In the 2025-26 season the per-player distribution has mean ≈ 0 and standard deviation ≈ 0.5, with extremes around ±2.

Team-demeaning

A naive RAPM coefficient entangles individual quality with team quality. All OKC players, for example, play exclusively with other above-average OKC players, and the regression will inflate every OKC player's coefficient by the team's shared excess. We subtract each team's mean RAPM before blending:

Equation 4.2 · Team-demeaned RAPM(4.2) rapmdemeaned,i = rapmi rapmteam(i) This isolates the player's individual contribution from the quality of their teammates. A genuinely above-average contributor on a top team still ranks above a teammate who's only riding the team's wave. Implementation: lines 203–213 of scripts/compute_published_impact.py.

Team-demeaning strips roughly 0.3–0.5 points per 100 possessions of "team quality" from each coefficient in a typical year. This is the trade-off: we lose a bit of signal for stars on excellent teams (their real contribution partially masquerades as team quality), but we avoid systematically promoting every player on a 60-win squad.

5

THE BLEND

Given two independent noisy estimators of the same latent quantity, the minimum-variance linear combination is inverse-variance weighted: the estimator with lower variance gets more weight. This is the standard Bayesian result for combining measurements. Critically, every player gets their own weight, derived from their own data — there is no global box-vs-RAPM tuning parameter.

Per-player variances

We compute two variances for each player, both expressed in z-score units so they are commensurable:

Equation 5.1 · Box-signal z-variance(5.1) σ²box,i = (σ²game,i / ngames,i) / σ²box,global Standard error of the mean for player i's season-average box impact, normalized by the between-player spread. Players with more consistent game-to-game box values have lower σ²box.
Equation 5.2 · RAPM z-variance(5.2) σ²rapm,i = C / npossessions,i RAPM estimation noise scales as 1/n_possessions. The constant C is self-consistently calibrated so that a player with league-median possessions has σ²rapm = σ²box. This makes the blend weight depend only on each player's own sample size relative to the median, not on any hand-tuned knob.

Inverse-variance weights

Equation 5.3 · Blend weights(5.3) wbox,i = σ²rapm,i / (σ²box,i + σ²rapm,i)      wrapm,i = 1 wbox,i Clipped to [0.05, 0.95] to rule out pure-signal extremes. Stars with high possession counts → lower σ²rapm → more RAPM weight. Rotation players and mid-season additions → higher σ²rapm → more box weight.

In practice the weight distribution spans roughly [0.3, 0.8] on the box side, with median ≈ 0.60 — so the typical player's Impact is ~60% box-score and ~40% RAPM.

Per-game Impact

Equation 5.4 · Published Impact(5.4) zbox = (total_impact μbox) / σbox
zrapm = (rapmdemeaned μrapm) / σrapm
zpub = wbox,i · zbox + wrapm,i · zrapm
published_impact = zpub · σbox + μbox Both signals are normalized to z-score space so the blend is in compatible units. The blended z-score is back-transformed using the box-signal mean and standard deviation, so published Impact lives on the same points-per-game scale as the raw box signal. Implementation: lines 234–242 of scripts/compute_published_impact.py.
6

PBP CREDIT (COMPONENT LENS)

Alongside the main Impact column, the leaderboard displays six PBP Credit components: scoring, creation, shot-making, defense, hustle, turnovers. These are a parallel decomposition of the box-score signal — same shot-difficulty table, same event coefficients, but computed event-by-event from the raw play-by-play stream rather than aggregated from the box. Each component isolates one dimension of contribution.

PBP Credit is a diagnostic view, not the Impact number itself. The Impact column is the blended published_impact (§5). The PBP columns are shown because a single summary number doesn't answer questions like "is this player's Impact coming from scoring or creation?" or "which part of the box signal is driving their rating?" The decomposition makes those questions answerable at a glance.

A player's total PBP Credit (sum of the six components) closely tracks their total_impact from the box signal — the two are computed from the same underlying framework — but they are not identical because PBP Credit resolves events at the play level where box-score attribution cannot (e.g. live-ball vs dead-ball turnover classification, assist-to-layup vs assist-to-3 creation value). Implementation: compute_game_pbp_credit() in nightly_nba_summary.py.

7

NBA INSIDE-THE-GAME TRACKING

The leaderboard also displays four columns from the NBA's Inside the Game optical-tracking system, built on the league's partnership with Amazon Web Services. These metrics use 29-body-point skeletal tracking at 60 fps and are computed by the NBA itself, not by Read The Game. We fetch them from the NBA Stats API and show them alongside our Impact number as an independent third view.

Table 7.1 — NBA tracking columns displayed on the leaderboard.
Column What it measures
GravityDefensive attention drawn above expected — how much help-defense a player's on-ball or off-ball position forces the defense to commit.
Leverage (total)Win-probability-weighted impact. Events in high-leverage game states count more than garbage time.
Leverage (creation)Leverage share attributable to shot-creation actions.
Leverage (defense)Leverage share attributable to defensive actions.
FG% Above ExpectedNBA's shot-quality-adjusted FG% differential — actual make rate minus what a league-average shooter would produce on the same shots.
Shot QualityNBA's shot-quality index, averaging the expected value of every shot a player takes.

These columns are especially valuable for dimensions where the box-score signal is systematically blind — primarily off-ball defense, which the NBA's skeletal tracking picks up but public play-by-play does not. A player who anchors great team defense without racking up steals or blocks will look weak in Signal A and often mediocre in RAPM (because team defense is shared across the on-court five), but can still register strong Leverage-defense numbers from the tracking feed. Showing these side-by-side lets a reader triangulate beyond any single lens.

8

READING THE IMPACT NUMBER

Impact is expressed as points per game above or below what a replacement-level rotation player would produce in the same role. The 2025-26 distribution across qualified players (≥20 games, ≥15 minutes per game) has mean +2.22, standard deviation 6.82, max +29.38, min −8.21. The positive mean reflects the qualification filter — by restricting to regular rotation players we exclude the bottom tail of garbage-time minutes.

+23
MVP tierTop ~1% of qualified players. Current season: Nikola Jokić (+29.4), Shai Gilgeous-Alexander (+27.9), Luka Dončić (+23.8), Victor Wembanyama (+23.7), Kawhi Leonard (+23.3).
+15
All-NBA / All-Star levelTop ~5%. Current season: Jalen Johnson (+15.8), Bam Adebayo (+15.5), Jaylen Brown (+15.4), Karl-Anthony Towns (+15.2).
+12
Fringe All-StarTop ~10%. Core starters producing clearly above their role expectation.
+6
Quality starterTop ~25%. Current season anchors: Santi Aldama (+6.5), Nic Claxton (+6.4), Tre Jones (+6.1), Keldon Johnson (+6.0).
+1
Average rotationNear the 50th percentile of qualified players. Examples: Isaiah Joe (+0.9), GG Jackson (+0.9).
−3
Below-rotation contribution25th-percentile and below. Often high-volume inefficient scorers, role mismatches, or developing players with room to grow.
−6
Replacement-level or belowBottom ~5% of the qualified distribution.
9

VALIDATION

Any modeling framework must pass empirical tests. We validate Impact along four dimensions:

Internal consistency of the box signal. Signal A is zero-sum by construction (Equation 3.6): summing total_impact across any game's ten players yields exactly zero. This means the box signal cannot silently inflate or deflate — every overrated player is balanced by an underrated one. The blended published_impact does not preserve this exact property (RAPM is a season-level coefficient applied to every game, not a per-game attribution), but the component that feeds it remains internally balanced.

Signal agreement. The two signals agree where they should. Across qualified 2025-26 players, the rank correlation between season-average total_impact and team-demeaned RAPM is strong in the upper and lower tails — stars show up in both, and deep-bench players show up negatively in both. Disagreement concentrates in the middle of the distribution, exactly where inverse-variance weighting is most consequential.

Year-over-year stability. A metric that measures talent rather than noise should be strongly correlated with itself across seasons for stable-role players. We track this correlation and publish it as the model accumulates multi-season career data per player.

Live ↔ final reconciliation. During games we compute a box-score-only approximation (Live Impact) from the NBA's live feeds. After the nightly pipeline runs, the final published_impact is available. The correlation between a player's final in-game Live Impact and their post-game published Impact is a running validity check on the live approximation. As this reconciliation log accumulates over the season it will be published here.

Cross-metric correlation with EPM, LEBRON, and RAPM-based public models is a planned addition once we have sufficient licensed access to their season-aligned data.

10

KNOWN LIMITATIONS

We document limitations openly. These are the cases where Impact will systematically diverge from a player's true contribution:

Captured reliably
  • Per-play scoring with shot-difficulty adjustment
  • Shot-creation value (not flat assists)
  • Self-creation premium (unassisted makes)
  • Live-ball vs dead-ball turnover classification
  • Steal, block, rebound, foul event values
  • Hustle plays from tracking (contests, deflections, charges, loose balls)
  • Team-context independence (via team-demeaning)
  • Sample-size-aware signal blending (low-info players lean box)
Systematically under-measured
  • Off-ball defense beyond what RAPM picks up
  • Screen-setting value (not in PBP)
  • Gravity / spacing contribution (shown as NBA tracking columns instead)
  • Transition defense (context-dependent)
  • Coaching / system fit

What the blend cannot fix:

RAPM is season-level. A player who changes roles mid-season (trade, positional shift, injury-return minutes bump) will lag in RAPM until enough possessions accrue in the new role — for them Impact over-weights the stale Signal B. Team-demeaning strips real star-quality signal along with team-quality inflation, so genuine superstars on elite teams are slightly under-rated by the RAPM half of the blend. Rookies and mid-season additions have low-information RAPM estimates and effectively rely on Signal A until their possession count approaches the league median.

To partially offset the off-ball-defense gap, we display the NBA's optical-tracking metrics (§7) as a third independent lens. A player whose real defensive value shows up in Gravity or Leverage-defense but not in our box signal is flagged for the reader.

11

DATA SOURCES

All inputs come from the NBA's public APIs. No proprietary feeds, no paid data licenses:

  • NBA Stats API · Play-by-play endpoints, box-score aggregations, and the Inside-the-Game tracking series (Gravity, Leverage, Shot Quality, FG% Above Expected).
  • NBA CDN · Live scoreboard, live box scores, live play-by-play (used for the Live Impact surface during in-progress games).
  • Basketball-Reference · Historical foul-drawn and defensive-matchup supplementary data.
  • Training corpus · 1,030,404 shot records across four complete NBA regular seasons (2021-22 through 2025-26) plus three postseasons.
  • Canonical derivations · Signal A: calculate_net_impact() in nightly_nba_summary.py. Signal B: scripts/compute_rapm.py. Blend: scripts/compute_published_impact.py.
12

CITATION & CONTACT

Citation

Read The Game Research. (2026). Impact: A Two-Signal Framework with a Tracking Overlay. Version 3.0.
Retrieved from https://readthegame.com/methodology

For front offices, researchers, media

Impact is a published model, not a black box. If you're building a research pipeline, writing a book, or running scouting analytics inside a team, we're happy to discuss methodology, share derivations, or produce custom extracts. Game-level data in parquet format is available on request.

Open for collaboration

TALK TO US

Front offices, researchers, journalists: we'd love to hear how you're using our metrics and what would make them more useful.

edan@readthegame.com