Methodology
Several of the impact metrics here are computed by us, not pulled from a provider. The brand-name advanced metrics (EPM, LEBRON, DARKO) can't be legally re-hosted, so we build our own versions of the same families from the NBA's own box scores and play-by-play. Here's exactly how, including what each one can and can't tell you.
Reproducible
Every metric is computed from public NBA endpoints by an open pipeline · no black box.
Validated
The play-by-play lineup reconstruction matches box-score minutes to <0.5s, every game.
Honest about limits
Each metric ships with its caveat. We'd rather you trust the ones that earn it.
RAPM: Regularized Adjusted Plus-Minus
A per-100-possession estimate of a player's impact on offense and defense that controls for the other nine players on the floor. It answers “how much better is his team when he plays, after accounting for who he plays with and against?”
How we compute it
- We reconstruct the five-man unit on the floor for every stint of every game from play-by-play (playbyplayv3) + box scores. There is no public lineup feed for recent seasons.
- Each offensive possession becomes a row in a sparse design matrix: the five offensive players get +1, the five defenders −1, the target is points scored per 100.
- We solve it as a ridge regression (RidgeCV), which shrinks noisy, low-possession players toward zero, the “regularized” part. Coefficients split into O-RAPM and D-RAPM; total = O + D.
Caveat. Single-season RAPM is noisy. Read it as a descriptive signal, not a verdict. Prefer IPM (next) or the 3-year version (the same fit pooled over three seasons with recency weighting) when they disagree.
Validation. The lineup reconstruction is validated game-by-game: reconstructed per-player minutes match the official box score to within half a second across every game.
IPM: Informed Plus-Minus (prior-informed RAPM)
Our flagship impact metric. It is the same RAPM ridge, but instead of shrinking noisy players toward zero it shrinks them toward what their box-score profile predicts. That single change is most of what makes the brand-name metrics (EPM, LEBRON) stable, and every input here is our own.
How we compute it
- First we train an SPM (statistical plus-minus): per-100 box-score rates regressed onto our own nine seasons of RAPM, so the prior's weights are calibrated to the exact quantity they need to predict. Validated leave-one-season-out (the weights never see the season they score).
- Each player's SPM becomes his prior, after thin samples are regressed toward a below-average floor, because a 50-possession rookie's per-100 rates mean nothing.
- The stint-level ridge then fits deviations from the prior: subtract the prior-implied margin from every stint, fit, add the prior back. Big on/off samples can still move a player far from his box profile; small samples stay anchored to it.
Caveat. IPM inherits the box score's blind spots on defense: the defensive prior explains far less than the offensive one (r-squared roughly 0.10 to 0.25 vs 0.35 to 0.46), so defensive IPM leans more on the on/off evidence. It is also a season-level estimate; it does not yet decay within the season or use tracking data the way EPM does.
Validation. In held-out prediction tests across nine seasons, IPM had the lowest error in 17 of 17 splits: all 9 within-season tests and all 8 predict-the-next-season tests, beating pure RAPM, the SPM prior alone, and a league-average baseline. Single stints are extremely noisy, so the error differences are small; the unbroken 17-for-17 ordering is the signal. Full numbers below.
Held-out stint prediction, mean possession-weighted RMSE (lower is better)
| Model | Within-season (9 splits) | Next-season (8 pairs) |
|---|---|---|
| IPM | 58.48 | 61.24 |
| SPM prior alone | 58.55 | 61.28 |
| Pure RAPM | 58.56 | 61.28 |
| League-average baseline | 58.70 | 61.37 |
SPM prior accuracy by season, leave-one-season-out r² vs our RAPM
| Season | Offense r² | Defense r² |
|---|---|---|
| 2017-18 | 0.43 | 0.16 |
| 2018-19 | 0.39 | 0.17 |
| 2019-20 | 0.39 | 0.16 |
| 2020-21 | 0.40 | 0.13 |
| 2021-22 | 0.35 | 0.10 |
| 2022-23 | 0.40 | 0.13 |
| 2023-24 | 0.44 | 0.25 |
| 2024-25 | 0.46 | 0.17 |
| 2025-26 | 0.40 | 0.20 |
Team power ratings (Team IPM & SRS)
Two independent reads of team strength, shown side by side: Team IPM is what the roster is worth (each player's IPM, weighted by minutes, times the five players on court), and SRS is what actually happened (point margin adjusted for opponent and venue). Schedule strength (SOS) falls out of the same solve.
How we compute it
- SRS is one least squares over every game of the season: margin = home rating minus away rating plus home-court advantage (about 1.7 to 2.7 points depending on the season).
- The offense/defense split re-solves the same system on points scored per game, so O-SRS + D-SRS reconciles with SRS. It is per game, not per possession, so fast teams run slightly warm on both ends.
- SOS is the average opponent rating a team actually faced; oSOS and dSOS are the average opposing defense and offense faced.
- Team IPM is the Dunks & Threes Team-EPM recipe applied to our own metric. Traded players count for their final team, a known simplification.
Caveat. Team IPM leads the sort because it earns it: in held-out tests it predicts future game margins better than SRS does. But single-season team samples are small, and Team IPM inherits IPM's defensive blind spots. Read the two columns together; big gaps between them are the story (a team out- or under-performing its talent).
Validation. Chronological three-way split per season (ratings fit on the first 60% of games, tested on the final 20%). Mean held-out margin RMSE below. A fitted blend of the two predicts best of all but takes a negative SRS weight (the two ratings are collinear), so we publish the two readable columns and keep the blend for the upcoming win-probability work.
Predicting held-out game margins, mean RMSE across 9 seasons (lower is better)
| Model | RMSE |
|---|---|
| Team IPM (roster) | 13.82 |
| SRS (results) | 14.54 |
| Home-court only | 15.90 |
| Fitted blend (research, unpublished) | 13.46 |
Pregame win probability
The chance the home team wins, estimated before tip-off from two team ratings built only from games already completed: the season's venue-adjusted point margin so far, and a roster value built from last season's player IPM weighted by the minutes each player has actually logged this season.
How we compute it
- The results rating is refit before every single game on only the games already played, shrunk toward zero so opening week stays sane.
- The roster rating deliberately lags a season: last year's IPM values, this year's minutes. Trades and rotation changes show up within a couple of weeks, and no result from a later date ever feeds an earlier prediction. On opening day it seeds from last season's Team IPM.
- A logistic model on the two rating gaps produces the probability. A parallel margin model (home court comes out at about 2.0 points) will drive the playoff simulator.
Caveat. No injury or rest information, and every prediction uses only completed games: the roster side cuts off strictly before game day, while the results side can also include games played earlier the same evening (worth about 0.2 points of accuracy). The 2020 bubble and empty-arena 2020-21 games mute home court and ride through as noise. Sportsbooks, armed with injury news and market feedback, still grade slightly better; that gap is the honest cost of using only our own numbers.
Validation. Leave-one-season-out across 2018-19 to 2025-26: 9,509 held-out games, averaged over the eight held-out seasons. The blend posts the lowest Brier score in both windows, and its two ingredients trade places the way they should: the roster prior carries the early season before the results rating has a sample, then hands over. Eight of the ten reliability bins hold 150 games or more, and every one of those lands within 1.1 points of its prediction; the 0-10% and 90-100% tails hold 7 and 56 games and are too thin to read.
Held-out prediction quality (Brier score, lower is better)
| Model | Brier, full season (9,509) | Accuracy, full season | Brier, first quarter (2,374) |
|---|---|---|---|
| Blend (published) | 0.2173 | 65.1% | 0.2188 |
| Season results only (SRS) | 0.2192 | 64.7% | 0.2258 |
| Roster IPM only | 0.2257 | 62.4% | 0.2210 |
| Home court only | 0.2469 | 55.7% | 0.2445 |
Calibration: when we say X%, how often does the home team win?
| Predicted | Games | Predicted avg | Actual |
|---|---|---|---|
| 0–10% | 7 | 8.9% | 0.0% |
| 10–20% | 151 | 16.8% | 17.2% |
| 20–30% | 656 | 25.4% | 25.9% |
| 30–40% | 1,101 | 35.4% | 36.1% |
| 40–50% | 1,494 | 45.2% | 44.5% |
| 50–60% | 2,093 | 55.1% | 55.4% |
| 60–70% | 1,845 | 64.8% | 63.7% |
| 70–80% | 1,419 | 74.8% | 75.8% |
| 80–90% | 687 | 84.2% | 84.1% |
| 90–100% | 56 | 91.9% | 89.3% |
Lineup chemistry
How much a specific five-man unit outperforms the sum of its parts, the part of a lineup's net rating the individual players don't already explain.
How we compute it
- From the same RAPM model, we take each lineup's possession-weighted residual: its actual net rating per 100 minus what the model predicts from the ten players on the floor.
- Because the prediction already accounts for opponent quality, the residual is opponent-adjusted by construction. Positive = the unit gels; negative = it underperforms its talent.
Caveat. Only shown for units with enough shared possessions, for seasons with published lineup data (2017-18 onward).
WPA: Win Probability Added (scoring)
How much each made basket swung its team's chance of winning, summed over the season, a leverage-weighted measure of scoring. A buzzer-beating game-winner is worth ~0.9 wins; a garbage-time bucket ~0.
How we compute it
- We fit a win-probability curve, P(home win) as a function of score margin and time remaining (the classic Brownian-motion model), by maximum likelihood on ~1.8M game states across every cached game, so the parameters come from our own data, not a paper.
- For each made shot or free throw, we credit the shooter with the change in their team's win probability at that moment.
Caveat. This is scoring WPA: misses and turnovers are not debited (that needs a possession-aware model). Read it as leverage-weighted scoring, not all-in-one value.
BPM 2.0 & VORP
Box Plus/Minus estimates a player's per-100 contribution from their box-score line and team context; VORP scales it by playing time against a replacement-level baseline.
How we compute it
- Daniel Myers' BPM 2.0 coefficients, computed offline from the per-game box stats and team pace/ratings we already pull. No extra requests.
Caveat. Our estimate is computed on NBA.com data and tracks Basketball-Reference closely (within ~0.2–0.3) but won't match to the decimal. Different pace/ratings sources, and no position labels in the feed.
Shot-making over expected (xeFG)
Whether a player finishes better or worse than a league-average shooter would on his exact shot diet, pure shot-making, separated from shot selection.
How we compute it
- We compute an expected eFG% by weighting league-average efficiency by where the player actually shoots (his shot-zone mix), then subtract it from his real eFG%.
Caveat. Location-based, so it rewards tough shot-making rather than easy looks. A rim-running big who dunks a lot won't top it just for being efficient.
Box Creation & Offensive Load
Box Creation estimates the open shots a player generates for teammates per 100 possessions, the shot-creation half of offense that assists alone miss. Offensive Load is the total share of the offense he shoulders (creation + scoring load + turnovers).
How we compute it
- Ben Taylor's published box-score formulas, computed from per-game stats converted to per-100 via the player's season possessions.
- Box Creation uses a volume-gated 3-point proficiency term (a sigmoid in 3PA × 3P%, so low-volume shooters are correctly discounted), and is floored at zero.
Caveat. Box-score estimates: they capture creation volume, not pass quality. Ben Taylor's Passer Rating (which would add that) needs layup-assist tracking we don't carry, so we deliberately don't show it rather than approximate it.
Want the short version of every stat? See the glossary.