Inside the Algo

Every number on the board, start to finish

One player, one number, 0 to 99. This page is how we get there. There is no black box, the rating is arithmetic, and you can redo every step yourself. Where a step is a judgment call rather than a tested result, we say so.

The short version

  1. We work out what a player will do per game next season, not what he already did.
  2. We grade every stat against real rotation players, so rebounds and blocks can be added together.
  3. We add those grades up. That total is his value.
  4. We charge him for the games we expect him to miss, by mixing in the player you'd start instead.
  5. We stretch everyone onto a 0–99 scale. Best player is 99, worst is 0.

The rest of this page is those five steps in detail. If you only read this box, you have the shape of it right.

You're reading the board's default equation:9-cat scoringhead-to-head12-team · 13 slotswindow: projectionsdurability onTurn an Algo Input and the math changes with it. Every section below names the control that moves it. The board always computes the equation for your settings, and a player's dossier shows this same walkthrough with his numbers filled in.
pool who's ranked→line per game→grades vs the pool→charges risk→games expected→aging one year→ALGO 0–99

In the formulas below, the colours just group related terms. You don't need to memorise them. The one colour that carries a meaning is the blue taglike this, yours which marks a control you can change.

Contents

One real player, in five lines

Before the detail, here is the whole thing happening to one player. This is Anthony Edwards, computed live by the engine that ranks the board, not typed in by hand.

Anthony Edwards, the rating in five lines
We expect him to play64 of 81 gamesstage 5
His stats grade out at+3.93stage 3
Minus the scoring-volume charge−1.06stage 4
Mixed with the man you'd start instead+1.02stage 6
Stretched onto the 0–99 scale71.8stage 7

That is an ALGO of 71.8, which puts him at #8 of 346 ranked players. Every intermediate number, including all 9 category grades, is in the full worked example at the bottom.

Try this on the rankings, where the same engine runs for every player and the settings are yours to change.

What actually moves a rating

Everything below is measured in grade points , the unit the next few stages build. This is what one is worth, so the numbers mean something when you meet them.

Rough sizes of each effect, in grade points
One category, from average to best in the leagueabout 3 grade points
The scoring-volume charge1.06 for Anthony Edwards; 0.7 to 2.6 across the board
Missing a quarter of the season (Anthony Edwards)about 1.75 grade points
One ALGO point0.15 grade points

Today the whole board runs from −9.97 to +5.18 grade points. So being elite in one extra category is worth roughly 20 ALGO points.

01

Who gets ranked: the pool

Fantasy value is relative. "Good" means "better than what you could roster instead." So before any math, the board decides who counts as the competition.

Roughly 650–700 players are considered: everyone with a recent NBA line. To be ranked, a player needs 25 games and 15 minutes a night in his most recent full season, which today leaves 346. Those are the players the board lists, and the ones every number on this page is measured against. Both floors are yours to move.min GP · min MPG, yours

A second, smaller group sets the grading curve , the top 156 by minutes per game. That is the roster demand of a standard 12-team league with 13 slots, so it is exactly the set of players somebody in that league would have. Real rotation players, not end-of-bench noise.

Connect a league and the curve resizes to your roster demand instead: more for a deeper league, fewer for a shallower one. The same number sets replacement level in stage 6, so the player you are graded against and the player you'd start instead always come from the same league.

Filtering never changes a rating. Exactly two of the board's filters re-grade anyone. The games and minutes floors do, because they decide who is in the pool everyone is measured against. Turning off a stat column does, because it drops that category out of the scoring entirely. (Punting does the same to one category, stage 3 covers it.)

Everything else only decides which already-graded rows get drawn: the position filter, hiding injured players, the rookie and veteran chips, search, and how many rows you show. A center who reads 92 on the open board still reads 92 with C selected. Filtering does renumber the # column to close the gaps. Searching doesn't even do that.

02

His per-game line

Everything starts from one question. What do we expect him to give you per game? The board opens on Projections, so the answer is not what he already did. It is what he is now, carried forward.window, yours

The default, Projections

We take his last three seasons and count them per minute of floor time, not per game. Recent seasons count more. Then we set that rate at the minutes he plays now.

That second half is what makes it a projection rather than a history. A bench player who earned a rotation role stops being priced at his eight-minute seasons. A veteran whose minutes have fallen stops being priced at minutes he no longer gets.

Then the line is aged one year forward, one stat at a time. Every stat has its own curve by position and years in the league. A center's blocks and a guard's assists don't decline alike. Aging makes and attempts separately is also the only way a shooting percentage can move at all. This is the only place aging happens. There is no aging multiplier later on.

Show the math
His last three seasons are weighted 3 : 2 : 1 toward the most recent, applied per minute of floor time. The minutes level he is set at is last season's, pulled toward the three-year blend by a prior worth 10 games, so one thin year can't lock in a slump. A season he missed entirely is absent from this window rather than counted as zero, it is charged to expected games in stage 5 instead. Shooting percentages are rebuilt from the aged makes and attempts, so an aged line always stays internally consistent.
Tested: pricing production per minute, at today's minutes, ranked players closer to what actually happened than the old per-game blend.
The numbers
Walk-forward 2010–2025. Points-league rank correlation +1.17% (better in 14 of 16 seasons, sign test p = 0.004); 9-category +1.18% (t = 3.08). Per-game error 5.30 → 5.12 fantasy points. Players moving into bigger roles were misranked by 15.9 board places before and 6.2 after. Losing arms, so they stay lost: per-game lines with minutes weights, per-36 scaled by blended minutes, raw last-season minutes, and last-season-only. The seasons overlap heavily, so treat 14 of 16 as consistency, not as 16 independent trials.
Tested: aging each stat on its own curve, rather than scaling the whole line by one number, cut next-season projection error, and cut it most for long-career veterans.
The numbers
Walk-forward over 1,835 player-seasons, curve rebuilt per test season so it never sees what it is scored on. Error in fantasy points per game: overall 5.573 → 5.172 (−7.2%); ages 0–2 −6.3%; prime 3–6 −1.7%; 7–10 −7.4%; 11+ years −22.5%. The prime band barely moving is the check that matters, a curve fitting noise would "improve" every band alike.
It moves as the season does. Once games are played, this season simply enters the window as its most recent year, at weight 3 against 2 and 1. There is no separate in-season rule. Against two full prior seasons, eight games is worth about a tenth of the line, and it takes most of a season for the current year to become the majority of it. That is what stops a hot start from being mistaken for a new player. One thing that does not move: the control itself. The board opens on Projections in October and in January alike.

If you'd rather look backward

Four other windows are yours to pick: this season on its own, or the last 2, 3, or 5 seasons. Those answer "what did he do" rather than "what is he now." They are allowed to disagree with the projection. That is the point of having both.

How the backward windows are weighted
Most recent season heaviest, stepping down by one: 3 : 2 : 1 over three seasons, 2 : 1 over two, 5 : 4 : 3 : 2 : 1 over five. Two details do the honest work. The weights apply per game, so a 12-game injury year can't count as a third of a three-year window. And a season he missed entirely is dropped from the stat math rather than scored as a zero, it is charged against his expected games instead, so an injury never counts twice. On the single-season window, a player who missed the year is shown on his last healthy one, and his row says so. These weights are a convention, not a measured optimum: 3 : 2 : 1 was chosen, and linear decay is the smallest honest generalisation of it.
Rookies
No NBA games exist, so his line is built from a decade of players picked where he was picked, draft slot, opportunity, and closest comparables. His row says his rating is a projection, not production.
Which games count
Regular-season games that count for fantasy scoring. Playoffs and play-in games are excluded everywhere, from the lines, from games played, from everything.

03

Grading against the pool

Twelve rebounds and two blocks live on different scales. Grading converts every stat into the same unit: how unusual is this, among real rotation players?

z = ( x − μ ) ÷ σ then ẑ = 3 · tanh( z ÷ 3 ) then Z = Σ ± ẑ

In plain words: take his number for a stat, subtract what an average rotation player does, and divide by how spread out players are in that stat. That gives a grade in a shared unit. Squash the very extreme grades so one freak category can't run away with the rating. Then add the nine grades up, subtracting the ones where less is better.

μ σthe pool average and spread. The average of that stat across the grading pool, and how far apart players are in it. The spread is the unit conversion, both 12.8 rebounds and 2.1 blocks become “how far above the pack.”
zhis grade. Zero is exactly an average rotation player. +1 is clearly above the pack, +2 is star territory in that stat, negative is below average.
ẑhis counted grade. Extremes are compressed so one freak category can’t run away with the rating. It’s a curve, not a ceiling, nothing ever quite reaches ±3.
Zhis total grade. The counted grades summed across the nine scored categories. Turnovers subtract. Around zero is an average starter; the very best land near +8.
How raw grades are compressed
raw grade z+1+2+3+4+6
counted ẑ+0.96+1.75+2.28+2.61+2.89
Tested: compressing the extremes is right, but how hard to compress depends on which question you ask, and the two tests we ran disagree. We kept the looser setting, because it is the one that wins the test closer to how leagues are actually decided.
The numbers
Player against player(walk-forward, truth = next season's all-play-all category record): compression beat the uncompressed sum in every season tested, and so did every hard cap we tried. Tighter compression beat ours. One caveat we found later and are correcting here: that run scored nine seasons, not the ten it reported.

Team against team(drafted rosters, truth = roto standings and weekly head-to-head win rate, 10 seasons, 36 leagues per cell): no tighter setting beat ours in any of 72 cells, and several lost outright. Compression against no compression was a wash. The reason the two disagree is that a category monopolist beats almost everyone either way, so player-against-player can't see the value of his excess, but on a real roster that excess turns a likely category win into a certain one.

A league is won team against team, so that test governs, and the setting stayed where it is. It is the best tested value, not a proven optimum.

Punting.punt, yours A punted category isn't zeroed. It's deleted from the market. No average, no spread, no grade, no term. Up to three. The column stays on the board, struck through, so you can see what you're conceding.

FG% and FT% are in the default nine, and neither is graded as a percentage. Each becomes shooting impact, makes above what a pool-average shooter would make on the same attempts. So a 95% free-throw shooter on two attempts a game can't move a rating, and a high-volume shooter slightly above average can. Volume is the point, and it is why a raw percentage never appears in the grade. The worked example prints the impact number rather than the percentage for exactly this reason; his actual percentage is shown beside it.
Two known quirks of adding grades up
Turnovers reward not touching the ball. A low-usage player gets a positive turnover grade for free, without doing anything useful. Everyone who plays these leagues knows this. It is a real artifact of scoring turnovers as a category, and the board does not correct for it.

Adding grades treats categories as separate and equally valuable. In a real matchup they are neither. A category you already win by a mile is worth nothing extra, and what a player is worth depends on the rest of your roster. The compression above is a partial answer to the first half of that. The second half, roster context, is a matchup question, and it lives on the Matchup Engine rather than in this rating.

04

The scoring-volume charge

One charge comes off the total before anything else. It is built from how much his points bounce around, and it lands hardest on the players who score least.matchup, yours

V = Z − 3 · cv

In plain words: take his total grade, and subtract three times a swing number. That number is how much his points bounce around, divided by how many points he scores.

cvhis swing number. His points standard deviation divided by his points, capped at 1. Measured on his most recent full season, not on the projected line, so it stays put when you change the stat window. It reads like a measure of how steady he is. Measured, it is very nearly a measure of how much he scores, which is what the test below is about.
Vhis value. His value so far, still in grade points. Stage 6 spends his expected games against it before the board sorts.

The charge only exists in head-to-head. Switch to roto and it comes off entirely. Where it applies is a choice made in the code rather than a measured one; how much it is worth, below, is measured.

Tested: We tested this charge on 5 September 2026. Taking it off makes the board worse, in every scoring set we tried, so it stays exactly as it is. But it is not measuring what its old name said it was.
The numbers
The question was written down and the pass/fail rule fixed before anything was run. Twenty seasons, 2006-07 through 2025-26. Leagues of 8 to 16 teams, with balanced, punting, adaptive and anchor rosters. The test: does a team's total rating predict the category record that team actually went on to post?

Four versions of the rating were compared. The charge as it ships. The charge deleted. The same charge flattened to one identical number for everybody, which isolates how much of the effect is just the size of the deduction. And a charge predicted from a player's scoring volume alone, never shown how much he actually bounces around.

Deleting it lost, everywhere. −0.014 in rank correlation on the standard nine categories (t = −2.81), −0.020 on a nine-category set with points taken out of the scoring (t = −2.87), and −0.010 on a twelve-category set (t = −2.21). It lost even in the league that does not score points at all, which is where the objection to the charge is sharpest.

The size of it was swept too, from 0 to 5. Three sits on the plateau: one and two are worse, four and five are indistinguishable from three. No re-scaling is supported, so nothing moved.
What it actually charges for. Points bounce around more, relative to the average, the fewer points a player scores. That is arithmetic, not unreliability, it happens to a perfectly steady player too. So the charge lands harder on low-scoring players: the tenth of the pool that scores least pays about 2.3 grade points, the tenth that scores most about 1.0, and the average across everyone ranked is 1.6.

The test settles which of those two things is doing the work, and it is the volume. A version built from scoring volume alone did at least as well as the real charge, and scoring volume explains about 85% of the swing number. So we describe it as what it is, a charge that scales with how little a player scores, and we do not claim it measures how steady he is. It stays because it was measured to help, not because of the story its old name told.
This is not the Volume Discount switch. The rankings board has an optional control by that name, off unless you turn it on. It is a second, smaller charge of the same shape that stacks on top of this one in a category league, and it is the only one of the two that does anything in a points league. Everything above is about the charge that is always there in head-to-head categories, switch or no switch.
Games missed is not charged here. There are three places in the code that could dock a player for games missed, and on the default board all three stand down. The projection already carries his expected games, and the next stage spends them properly. Availability enters this rating exactly once, and it is not here. A rating that charged for missed games in two places would be quietly double-counting the same injury.

05

Expected games

The xGP number on the board is not last season's games played. It is an estimate of how much of a season he'll actually give you, built in three steps.

raw = Σ u·games played ÷ Σ u·team games over 5 seasons, u = 5,4,3,2,1
shrunk = ( raw·N + pool avg·123 ) ÷ ( N + 123 )
a = shrunk + age adj → xGP = 82 · a

In plain words: first, what share of his team's games he actually played over five seasons, counting recent seasons more. Second, pull that toward the average player, hard if we have little history on him and barely at all if we have a lot. Third, nudge it up or down for how far into his career he is. Multiply by a season to get games.

rawhis recent record. Weighted toward now, counted on games. A fully missed season enters as zeros played against a full season of team games, so it counts hard. Seasons before his debut don’t exist and aren’t counted. A player whose injuries are behind him climbs; one whose injuries are recent falls below his career rate.
poolthe reality check. Small samples get pulled toward the ranked pool’s average availability. N is his team games of history; 123 is the strength of the pull, about a season and a half. One season of history lands closer to the pool average than to his own rate; five seasons and his own record carries most of the weight. No history at all? He is the pool average, never assumed healthy.
agethe age adjustment. A small addition or subtraction by years in the league, capped at about ±20 games. Young players get lifted, long-tenured ones marked down. Fitted from history, applied after the pull.
Tested: weighting recent seasons more describes the player you're about to draft, rather than an average of two different players.
The numbers
Paired with the age correction it was the best arm tested in both formats: points rank correlation +0.47% (better in 16 of 16 seasons), category +0.28% (12 of 16). It also all but removed the bias on players returning from a fully missed season, from +7.8 games over-forecast to +0.5, which no explicit "recovery bonus" managed to do. The age correction itself wins on ranking in 16 of 16 seasons but by only +0.37%; we took it because expected games is a number you read, and being eight games wrong on a 34-year-old is visible in a way a rank is not. The 123-game pull strength was chosen, not fitted.
The 82 is a placeholder until the schedule lands. Before the NBA publishes next season's calendar there are no real game dates to count, so expected games is a share of a nominal 82. Once the schedule is out we count his team's real remaining games instead, which is already how expected games works on a connected league's pages. And each past season is measured against the length of that regular season, 2019-20 and 2020-21 were short, and counting them as 82 would invent absences that never happened.

06

Spending the expected games

Now the two halves meet. This is the only place availability touches the rating, and it is not a multiplier.durability, yours

V′ = a · V + ( 1 − a ) · C

In plain words: on the nights he plays, you get him. On the nights he doesn't, you get whatever that roster spot produces instead. His value is those two mixed together, in proportion to how often each happens.

Rreplacement level. The value of roughly the best player nobody has rostered, in a standard 12-team league with 13 slots, the 157th-best player on the board. It is a real number from this same board, and it is usually negative.
Cwhat a missed game is worth. 65% of the way from an empty roster spot to R. You won't always fill the spot: he still holds a bench or IL slot, and the best pickups go fast. In points an empty spot is 0, so C is 0.65 × R. In categories it is the value of a line where nobody played.
ahis share of the season. From stage 5. The fraction of games we expect to get from him.

That is the whole idea. A missed game costs you the gap between the player and what his spot produces without him, not the whole player. You are not left with nothing when a star sits. You are left with the waiver-wire guy most nights, and with nobody on some of them. So an injury-prone star stays a star, and a fringe player's availability barely matters, because he was worth about replacement anyway.

Tested: the obvious version: multiplying value by availability, is much worse. It prices a missed game at zero, as if the roster slot produced nothing.
The numbers
Walk-forward 2010–2025. Multiplying ranked worse than ignoring availability altogether in 16 of 16 seasons (rank correlation 0.709 against 0.745), because a 0.54-to-1.00 multiplier swamped every real difference in skill. The blend scored 0.746, the best of five arms tested. This is the largest single correction on the page: the form of the availability term is worth roughly 5%, where most other results here are worth well under 1%.
Tested: crediting every missed game at a full replacement player overvalued injured players once a roster had to hold them, so a missed game is credited at 65% of the way to replacement instead.
The numbers
A season simulation with real rosters: 13 spots, an IL slot, weekly add limits, rival claims on the wire, and lineup locks. Each stash was paired with a healthy player of equal value. Fitted on 2016–17, 2018–19 and 2021–22, then tested on 2022–23 through 2025–26. In points, choosing by the 65% credit scored 172 more points over a fantasy regular season (95% interval 23 to 321). In 9-category head-to-head it pointed the same way in all 8 league setups tried, +0.49 categories won, but that interval (−0.28 to +1.26) includes zero.
What happens on a dynasty runway
Aging already happened, back in stage 2, inside the stat line where it can move a shooting percentage. Applying an aging multiplier to the value as well would age him twice, so the board doesn't.

Set a dynasty runwayrunway, yours and that changes. The board sums 2 or 5 successively aged seasons into a multi-year total, which is why dynasty numbers run bigger than redraft ones. The year-over-year curve those seasons are aged on is the expectedchange, the average of what happened to comparable players, collapses included, not the typical survivor's. Past nine years in the league it never turns back up, so a thin group of 15-year veterans who happened to hold up can't make a 15-year player age slower than a 12-year one.

On the 5-year runway only, each future season is also weighted by the odds he is still in the league at all by then, measured from twenty years of careers at his experience level. This applies to every player outside the top 40 by current value. The aging curve alone cannot see this, because it is fitted only on players who played both seasons of a pair, so a career ending is invisible to it. The top 40 are exempt on purpose: established stars almost never leave mid-contract, and top-40 players with 14 to 20 years in the league played the next season close to 100% of the time.
Tested: pricing the odds a player is still in the league helps on a five-year runway, for everyone except established stars. Applied to stars as well, it made the top of the board worse, so it isn't.
The numbers
Walk-forward 2010–2020, 11 five-year windows, top-200 pools. Rank correlation with realized five-year production: +0.010 over no survival term, better in 10 of 11 windows, top-50 +0.012. Predicted rank by experience band (0–3, 4–7, 8–11, 12+ years) lands within about 3 board places of what happened. Applied to everyone, the same odds ranked the top 50 worse and under-priced 12+-year veterans by 6.4 spots, so that form was rejected. On the 2-year runway the same term measured +0.003, inside the noise, so that runway doesn't carry it. Refitting the curve as the expected change with a non-rising tail was worth another +0.011 on the same test, and left next-season rankings unchanged within noise.

Two honest caveats.Five-year windows starting in consecutive seasons share four years of data, so 10 of 11 is a consistency check, not 11 independent trials. And the "exempt the top 40" form was chosen after looking at diagnostics on these same seasons, so it rests on that consistency, on the shape across experience bands and on the rank calibration, not on a p-value. An earlier, stronger-looking version of this result was measured on a flawed base and has been withdrawn.

07

The 0–99

The rating you see is the value, stretched across everyone ranked.

ALGO = round( 99 · ( V′ − min ) ÷ ( max − min ) )

In plain words: find where his value sits between the worst ranked player and the best, and put that on a 0 to 99 scale.

Three honest things about that number.

  • It's relative. The best player in the ranked pool is always exactly 99 and the worst exactly 0. The endpoints carry no information about quality.
  • It belongs to the pool, not your view. Filter down to centers and the best one on screen usually won't read 99, because the scale still stretches across everyone ranked.
  • It isn't rank. Spacing is real. The gap from #1 to #2 can be several ALGO points while ten places further down cost you one. Four ALGO points is the same amount of value wherever you read it. Four places is not.

Two boards with different settings are two different equations, and neither is wrong.

A known weakness of this scale
Because both ends are set by one player each, an unusually dominant season compresses everyone else. Today the board's top player is far enough clear that he alone defines a meaningful slice of the scale. Anchoring the scale on replacement level instead would be steadier across seasons. We haven't changed it because the ordering, which is what a draft board is for, is identical either way.

08

Points leagues: the other branch

If your league scores points, stages 3 and 4 are replaced by something genuinely simpler. We don't dress it up.

V = Σ stat · league weight

In plain words: every stat times what your league pays for it, added up. That's fantasy points per game.

No pool, no averages, no spreads, no compression, no punts, and no scoring-volume charge, which belongs to category head-to-head. The one subtlety worth knowing: double-doubles and triple-doubles are per-game rates. A player who double-doubles 40% of the time earns 0.4 of your double-double bonus every game, rather than a whole one some nights.

Stage 2 builds his line the same way, and stages 5, 6 and 7 are identical, the same expected games, the same blend toward replacement, the same 0–99. Only the grading changes.

WORKED EXAMPLE

All of it, on one real player: Anthony Edwards

Everything above, with his actual numbers, computed live by the same engine that ranks the board, not typed in by hand. He is MIN · G, currently #8 of 346 ranked players.

Stage 5 first, how many games we expect

This is the number people doubt most, so here is every step of it. His last five seasons, most recent weighted heaviest:

Availability by season
SeasonHe playedSeason lengthWeight
2022-237982×1
2023-247982×2
2024-257982×3
2025-266182×4
2026-2711×5
raw = 723.0 ÷ 825.0 = 0.876
shrunk = ( 0.876·329 + 0.573·123 ) ÷ ( 329 + 123 ) = 0.794
a = 0.794 − 0.003 = 0.791 → 81 × 0.791 = 64 games

Read across: his own record says 0.876, but with 329 team games of history against a prior worth 123, it is pulled down toward the pool's 0.573 to land at 0.794. The age adjustment for a player 6 years into his career then marks it down to 0.791 , about 64 of 81 games.

Stages 2–3, his line, graded

His projected per-game line, each stat against the 156-player curve. The last column is what actually entered the sum, after the extremes are compressed. FG% and FT% show impact: makes above a pool-average shooter on his attempts, because that, not the percentage, is what gets graded:

Category grades
CategoryHisPool avgSpreadGradeCounted
PTS29.116.05.0+2.60+2.10
3PM3.81.80.8+2.38+1.98
STL1.21.00.3+0.67+0.66
FT% shooting impact · he shoots 81.9%0.130.00.3+0.46+0.46
AST4.13.61.8+0.27+0.27
BLK0.70.60.4+0.24+0.24
REB5.65.42.2+0.09+0.09
FG% shooting impact · he shoots 46.7%-0.210.00.5−0.38−0.38
TO (lower is better)3.01.80.7+1.63−1.49
His total grade+3.93

Stages 4, 6 and 7, the charge, the blend, the rating

V = +3.93 − 3·0.35 = +2.87
V′ = 0.791·+2.87 + 0.209·−4.12 = +1.02
ALGO = 99 · ( +1.02 − −9.97 ) ÷ ( +5.18 − −9.97 ) = 71.8

His scoring-volume charge is 1.06. Then the blend: he is expected for 64 games, so 79% of him is him and the rest is replacement level at −4.12, the 157th-best player, the man you'd start instead. That lands him at +1.02, which against a board running from −9.97 to +5.18 is an ALGO of 71.8.

Check it yourself. Every number here is the engine's own, the grades, the pool averages, the replacement level and the availability trace all come from the same functions that rank the board, not from a second copy written for this page. If the arithmetic above ever stopped adding up to the rating, this section would disappear rather than show you something that doesn't reconcile.

ASIDE

The playoff schedule: beside the rating, on purpose

The board carries a block of playoff columns, and none of them touch the rating. That is a decision, not an oversight. It is also the one place on this page where the honest answer is that we measured the obvious version and it did not earn a place in the math.

PWplayoff-window games. How many games a player’s NBA team plays inside your fantasy playoff rounds. Pure calendar: teammates share the number, and only games that count for fantasy are counted.
xPWexpected playoff-window games. The same games, each weighted by his own chance of actually playing it, recent availability, role, back-to-back second nights, how late the game falls, and what his team is still playing for. A rotation player on a team already out of the race misses about half his scheduled final-weeks games. This is a window number, not the expected games of stage 5.

So why not fold it in? We tested exactly that, weighting a player's value by the games he's expected to give you in the window. At the window most leagues use, the last three weeks of the season, it measured flat. No reliable gain, no loss. A flat result doesn't get to move a number quietly, so the schedule sits in columns where you can see it and weigh it yourself.

Tested: the schedule genuinely helps only for leagues whose finals land well before the season ends, and it ships for exactly those, nowhere else.
The numbers
The expected-games model was fitted and validated walk-forward across twenty seasons. Weighting value by it gained 1–3% for leagues with early finals, and about nothing at the standard window. A placebo window in mid-January won by the same margins, which settles what the effect really is: a better forecast of production inside any window you choose, not a playoff edge. It ships only at three or more weeks of daylight, the position where the win was clearest.
Where the window comes from, and what ships
Connect a league and its bracket is read from the league itself and locked. Otherwise the PLAYOFF SCHEDULE control above the board opens on the common shape, two rounds and a finals, one week each, over the last three weeks of the regular season, tagged EST until you set your real dates. Rounds don't have to be whole weeks or run end to end, a two-week championship is just a finals with a fourteen-day range, and a league that plays no playoffs at all is a real answer that takes the columns off the board entirely.

The one arm that did not measure flat, leagues whose playoff window closes three or more weeks before the regular season ends, ships for exactly those leagues and no others. Connect one, and from four weeks before its window opens until that window closes, value on your league pages is weighted by expected window games. The public board you are reading about is untouched. Sorting by PW or xPW reorders the board and renumbers the # column, but nobody's rating moves.

09

The receipts

We test the main scoring choices against past seasons. Untested assumptions are labelled below. The tested tags on this page are those results. The rule cuts both ways, here is some of what we measured and rejected.

Kept, because it won
The replacement blend, worth about 5% and the biggest single fix here. Per-stat aging, −7.2% error overall and −22.5% for long careers. The per-minute projection basis, +1.2%. Recency-weighted availability, +0.3 to +0.5%. Grade compression, on the player-level test. The head-to-head scoring-volume charge, which costs about 0.014 in rank correlation when you remove it.
Rejected, because it lost
Multiplying value by availability. A role dimension on the aging curve. A "recovery bonus" for injury returners. Playoff-schedule weighting at the standard window. Career-survival odds applied to stars. Deleting the head-to-head scoring-volume charge, and re-scaling it. Six market intuitions have now been measured and refuted here. A rejection is a result too, and it stays rejected.

How to read a win count on this page. Most of these results are small, a fraction of a percent in rank correlation, and the test seasons overlap, because the same players appear year after year. So "better in 14 of 16 seasons" means the improvement was consistent, not that we ran 16 independent experiments. Where a result was shaped after looking at the data, we say that too. The one genuinely large effect on this page is the replacement blend.

And where a number is a convention rather than a measurement, the 3 : 2 : 1 window weights, the 123-game pull, the missed-games coefficients, we say so instead of inventing a test that was never run.

Glossary

Every term on this page that isn't everyday fantasy vocabulary, defined once.

gradegrade point. The shared unit stages 3 to 6 work in. One grade point is one standard deviation of one category, roughly the gap between an average rotation player and a clearly above-average one in a single stat.
poolthe ranked pool. Everyone who clears the games and minutes floors, 346 players today, out of the 650–700 considered. The 0–99 scale is stretched across them.
curvethe grading curve. The smaller group the averages and spreads are computed from: the top 156 by minutes, which is a standard 12-team league's roster demand, or your own league's if you've connected one.
cvthe swing number. His points standard deviation divided by his points, capped at 1. It sets the size of the scoring-volume charge in stage 4. It looks like a measure of how steady a player is; measured, it tracks how much he scores far more closely than how steadily he scores.
replreplacement level. The best player nobody rosters. In a 12-team league with 13 slots, about the 157th player. It is what you actually get on a night your man sits.
xGPexpected games. How many of a season's games we expect from him. Not last season's games played: an estimate built from five seasons, pulled toward the average, and age-adjusted.
wfwalk-forward. How every result here was tested. To score a season, the model may only use data from before it. Nothing is ever fitted on the season it is graded on.
ρrank correlation. How closely a ranking matches what actually happened, from -1 (exactly reversed), through 0 (no rank association), to 1 (perfect agreement). A change of +0.01 is small; the availability fix was worth about +0.037.
runwayrunway. How many future seasons a dynasty rating adds up: 1, 2 or 5. Longer runways produce bigger numbers, because they are sums.

Updates

The algorithm improves by measurement, and this page moves with it, last updated —. Recent changes:

—Stage 6: a missed game is now credited at 65% of a replacement player instead of a full one. An injured player still holds a roster or IL spot, and the pickups that would fill in for him are not always there, so crediting every missed game in full overvalued players expected to miss a third of the season or more. Players with a long expected absence move down, and durable players move up a little; nobody's expected games changed. Tested in a season simulation with real roster limits, fitted on three seasons and checked on four others: clearly better in points, the same direction but too close to call in 9-category head-to-head.
—Stage 4, the charge this page used to call the streakiness charge, has now been tested — it was the last untested number in the default rating. Removing it makes the board worse in every scoring set we tried, so it stays exactly as it is and no rating moved. But the test also showed it is not measuring steadiness: a version built from a player's scoring volume alone, never shown how much he actually bounces around, does at least as well. So it is now called the scoring-volume charge and described as one. Measured 5 September 2026, over the 2006-07 through 2025-26 seasons.
—The board now opens on a standard 12-team, 9-category league: PTS, REB, AST, STL, BLK, 3PM, FG%, FT% and turnovers, graded against the 156 players a 12-team roster actually holds. It used to open on ten counting stats with no percentages, graded against the top 200, which meant the curve described one league while replacement level described another. Both now describe the same one. If you had already changed your columns, your choice is untouched. This moves ratings: shooting volume and efficiency count for the first time, and double-doubles no longer do.
—This page rewritten in plain English: a short version at the top, a real player near it, the arithmetic moved under expanders, and every measured result stated as what it means before what it measured. Three claims were corrected rather than reworded, the grade-compression result now reports the team-level test alongside the player-level one, the compression table had a rounding error, and the streakiness charge is now labelled as what it is, the one untested number in the default rating. The rating itself did not change.
—The 5-year dynasty runway now weighs the measured odds a player is still in the league in each future season, for players outside the top 40 by current value, long-career role players stop being priced as if careers never end, while established stars, who almost never leave mid-contract, are left to the aging curve. Better in 10 of 11 backtested five-year windows; the gain on the 2-year runway was too small to call, so that runway is unchanged. The aging curve behind every horizon is now the expected year-over-year change rather than the typical survivor's, and it never turns back up past nine years in the league; redraft rankings measured unchanged within noise.
—Projections re-based on per-minute production at today's minutes: a player who earned a bigger role stops being priced at his bench seasons. Better in 14 of 16 backtested seasons.
—This walkthrough published.

The knobs are yours. Every blue tag on this page is an Algo Input, a control you can turn on the rankings board or in the Algo Lab, per profile and even per player. Gray steps are part of the algorithm. One control is deliberately neither: the playoff schedule columns are information beside the rating, and this board's rating never sees them.

Player data from the regular season only, play-in excluded. Ratings recompute as the season moves. A player's dossier shows this same walkthrough with his own numbers in every slot.