Running Net Points — the math
Oliver's individual offensive and defensive ratings, modified by Jacobs into a per-possession running series. This page is the derivation.
Credit: Dean Oliver (Basketball on Paper) and Justin Jacobs (Squared2020)
Want the plain version first? The clipboard metaphor is next door →
Orientation
Running Net Points is built on top of Dean Oliver's individual offensive and defensive ratings from Basketball on Paper (2004). Justin Jacobs' contribution, published on Squared Statistics, is two deliberate modifications that convert Oliver's season-aggregated ratings into a per-possession running series: a qAST redefinition and a hardcoded 0.2 defensive share. This page walks through Oliver's framework first, then Jacobs' two changes, then the aggregate identity that anchors the whole construction.
Oliver's framework
Oliver's individual offensive rating allocates a team's points to its five on-court players via a formula called points produced (PProd). The core intuition is that every scoring event can be apportioned — a made field goal to the shooter and, if assisted, a weighted share to the passer; free throws to the shooter; offensive rebounds credited toward extending the team's play percentage. The formula is one expression built out of three main parts:
PProd = (PPFGPart + PPASTPart + FTM) × (1 − TmOREB/TmScPoss × TmOREBWt × TmPlayPct) + PPOREBPart
PPFGPart captures the player's made field goals adjusted by qAST (the share of their scoring that was assisted). PPASTPart credits the player's assists, weighted by the team's points-per-assisted-field-goal context. PPOREBPart distributes offensive-rebound value. The outer factor removes double-counting of points created via offensive rebounds.
qAST in Oliver's formulation is a season proportion: the fraction of the player's made field goals that were assisted. It scales the PPFGPart term — higher qAST reduces the credit a player receives for their own scoring, because more of that scoring was set up by a teammate.
On the defensive side, Oliver builds an individual defensive rating (DRtg) from team defensive rating and a player-specific adjustment:
DRtg = TmDefRtg + 0.2 × (100 × DefPtsPerScPoss × (1 − StopPct) − TmDefRtg)
The 0.2 factor inside DRtg is the weight Oliver places on the player's individual stops contribution relative to the team's overall defensive rating. The individual adjustment pulls DRtg above or below the team number depending on the player's stops (blocks, steals, defensive rebounds, forced misses) relative to opponent field-goal attempts while on the floor.
In Oliver's original, the points allowed by a player is then computed from DRtg scaled to that player's share of team possessions:
PAllowed = (DRtg / 100) × (player_possessions_on_court / team_possessions) × OppPoss
That middle factor is what normalizes Oliver's defensive accounting to the player's usage.
Jacobs' modifications
Jacobs preserves Oliver's PProd and DRtg formulas unchanged, but makes two deliberate changes that reshape the metric into a running per-possession series.
Modification 1: qAST as a running sum. Oliver's qAST is a season proportion — it cannot be computed per-possession until the season is complete, because you need the denominator (total made field goals) to close. Jacobs reinterprets qAST as the raw count of assisted field goals credited to the scorer (not the passer), accumulated live as the game progresses. On each assisted make, q_ast_raw += 1 for the scorer; at evaluation time this running count is normalized by current FGM (qAST = q_ast_raw / FGM) and the normalized ratio — not the raw count — enters the PProd formula.
This means two players with identical FGM and AST totals but different assisted shares will produce different PProd. A self-created-offense player (low qAST) gets more PProd from the same FGM than a player who relies on teammates (high qAST) — which matches Oliver's intent, just computed as a live running tally rather than a season-end ratio.
Modification 2: PAllowed with a hardcoded 0.2. Jacobs replaces Oliver's middle scaling factor with a flat 0.2:
Oliver (season)
PAllowed = (DRtg / 100) × (player_possessions_on_court / team_possessions) × OppPoss
Jacobs (per-possession)
PAllowed = (DRtg / 100) × 0.2 × OppPoss
The 0.2 is the 1/5 defensive share per on-court defender — an explicit statement that responsibility for defensive points is split evenly across the five defenders on the floor. Jacobs' version is equivalent to Oliver's if and only if every defender's player_possessions_on_court / team_possessions is exactly 0.2, which holds in the aggregate when all five defenders are on the floor for every defensive possession.
In combination with the per-player on-court scoping of OppPoss (defined below), this gives a PAllowed that can be computed after each possession without needing a season-end normalization.
The third detail: on-court scoping. Both Oliver and Jacobs require that team and opponent stats entering each formula be scoped to the player's on-court window — only the possessions where the player was on the floor contribute to their personal TmFGM, TmFGA, OppFGM, etc. Oliver implements this implicitly through the season-level player_possessions_on_court / team_possessions scaling; Jacobs implements it explicitly through per-player counters that tick alongside team totals only when the player is in the lineup.
The running series
Running Net Points is the cumulative difference between production and defensive points allowed, evaluated at every possession:
RNP(t) = PProd(t) − PAllowed(t)
Both terms are snapshots computed from the player's on-court-scoped cumulative stats up to possession t. The series is plotted directly, and the final value RNP(N) after the last possession of a game is the player's game-ending net impact.
The aggregate identity
Both Oliver's PProd and Jacobs' PAllowed carry a testable identity: summed across a team's players for a full game, each should equal the team's actual points (on offense) or the opponent's actual points (on defense).
Σ PProd_team ≈ team_PTS Σ PAllowed_team ≈ opp_PTS
The PProd identity comes from Oliver: the formula is constructed so that every scoring event gets allocated in full to the five on-court offensive players, and the sum of allocations equals the possession's points — up to a small slack around offensive-rebound weighting and-1 free-throw edge cases.
The PAllowed identity comes from Jacobs' 0.2 factor: the combined (DRtg/100) × 0.2 × OppPoss contribution summed across the five on-court defenders yields (DRtg/100) × OppPoss. Across a full game this aggregates to Σ PAllowed ≈ opp_PTS — an approximation, not a possession-level equality, with deviation driven by per-player DRtg variance across on-court stretches.
Passing both identities — summing each team's PProd to within a few percent of team points, and summing each team's PAllowed to within a few percent of opponent points — is strong evidence the per-player on-court scoping, the running qAST, and the per-possession attribution are implemented correctly. This is how this site validates its RNP pipeline against NBA.com published boxscores, without needing an external RNP oracle.
What's still approximate
The invariants hold only approximately for two independent reasons:
- Oliver's PProd has known OREB slack. The
PPOREBPart+ outer-factor construction doesn't sum exactly to team points when a possession contains multiple offensive rebounds; Oliver's original paper acknowledges the small discrepancy. - Jacobs' PAllowed depends on DRtg uniformity. The 0.2 split is exact only when all five defenders share the same DRtg. In practice, defenders' DRtg values drift based on their individual on-court stretches, and the sum deviates from
opp_PTSby a few percent — over-counting when the lineup's defensive rating is better than the game-wide team rating, under-counting when it's worse.
Neither is a bug; both are properties of the model. Reported values should be read with the understanding that RNP is a credible attribution, not an exact one.
Limitations
Defensive involvement is inferred from the play-by-play, not camera tracking. The DRtg individual adjustment captures stops via blocks, steals, and defensive rebounds, but cannot see closeout quality or body position at shot release. The defensive component of RNP is directionally useful; small differences between two good defenders should not be read as verdicts.
RNP does not adjust for opponent strength. A single-game RNP against an elite defense deserves a heavier weight than the same number against a poor defense. Season-level aggregates smooth opponent-variance out; single-game numbers do not.
Finally: single-game RNP is noisier than season totals. A hundred possessions contain a lot of randomness. The stat earns its credibility over a full-season arc, not a single night.