METHODOLOGY
How every number on this site is computed — published in full, not a black box. Plain language first; the math is available below each section.
Method split-half-v3-2026-08 · stabilization study run August 30, 2026
1 · The problem
A category league scores a player on nine separate numbers — points, rebounds, assists, steals, blocks, turnovers, three-pointers made, and two shooting percentages. Those numbers live on completely different scales, so you can't just add them up: one more block is a much bigger deal, statistically, than one more rebound, and neither is worth the same as one more assist. To rank players, or to answer "who should I draft next," those nine numbers have to become one number.
There is no single correct way to do that, because the right way to combine them depends on what you are actually trying to win — and Rotisserie and head-to-head leagues are mathematically different games. That difference shows up directly in draft strategy, most visibly in whether "punting" a category on purpose is smart or not (§4).
2 · Z-score, G-score, H-scoring
We use three levels of the same idea, each one correcting a blind spot in the last.
2.1 Z-score — the industry standard
For each category, look at every player likely to be drafted and measure how many standard deviations above or below the group average a given player sits. Add that up across all nine categories and you have one number. Turnovers count backwards (fewer is better), and the shooting percentages are weighted by how many shots a player takes — a 90% free-throw shooter on one attempt a game shouldn't outscore an 80% shooter on ten.
Z-score is what Basketball Monster and most public rankings use, and it is a reasonable approximation of the right answer for Rotisserie. Its weakness is that it is static: it has no way of knowing that you already drafted four centers.
One thing we do differently, and it changes what the number means: the score we show is anchored at replacement level, not at the pool average. We subtract the summed z-score of the last player who would go undrafted, so zero means "freely available" — a player you could add off waivers for nothing. A positive score is what he gives you above that; a negative one is what he costs you. Anchoring on the pool average instead would put half of a draftable pool below zero and turn the sign into a statement about the average rather than about your team.
2.2 G-score — what it corrects in Z-score
Z-score implicitly assumes you already know exactly how a player will perform for the rest of the season. In a head-to-head league that assumption is the wrong one to make, because you don't win by accumulating the best season total — you win by winning individual weeks, and a player's week-to-week output bounces around his season average. A streaky player delivers less reliable weekly wins than his average line suggests, even against a steadier player with an identical season average. G-score corrects this by adding a term for that week-to-week swing directly into Z-score's denominator, so a volatile player's score gets pulled toward zero relative to his Z-score. Z-score turns out to be the special case of G-score where that weekly swing is assumed to be zero — i.e. where future performance is known exactly.
G = (player's stat − pool average) / √(pool variance + weeks × week-to-week variance)
This needs one thing Z-score does not: a variance, not just a mean, for every player in every category. Every projection on this site carries both — a mean is not a projection on its own.
2.3 H-scoring — valuing the pick, not the player
Both Z-score and G-score give a player a fixed number, computed once, before the draft starts. H-scoring instead asks a live question every time you're on the clock: "given the roster I've already built, which of the players actually available right now helps me the most?" That "given the roster so far" is the whole point — it's what makes advice like "you're short on assists and the best passers are gone" fall directly out of the math, instead of being a rule we wrote by hand. We evaluate roughly 200 candidate players against your league's objective every time a recommendation is shown.
3 · Why ROTO and H2H differ
Both formats reduce to the same underlying quantity: your expected margin over an opponent, in a given category, for a given week. What differs is what you do with that number once you have it.
In head-to-head, the natural goal is to maximize your expected score each scoring period — essentially, add up your win probability across every category and opponent. This objective actively rewards punting: walking away from a category you were going to lose anyway frees up resources to push the categories you can win further above 50%.
In Rotisserie, the natural goal is the probability of winning the whole league — beating the best of your eleven other opponents, across all nine categories, over an entire season. Computing that probability exactly is not just hard, it is computationally impossible: with 12 teams and 9 categories the number of possible final orderings exceeds 1077. No computer enumerates that. Instead we use a published, well-studied approximation (Rosenof 2025 — eight equations plus an analytic gradient): treat your final point total as roughly bell-curve shaped, and compute the odds it clears the best of your rivals' totals.
The key structural difference: ROTO requires beating the maximum of many opponents, not averaging well against one. That single fact is the reason punting behaves so differently between the two formats — see §4.
4 · Why ROTO should punt less
"Balanced teams win Rotisserie" is common advice, and it is backed by two real arguments, not just tradition.
Arithmetic. A typical league-winning ROTO team finishes around 3rd of 12 in each category on average — which leaves roughly 18 total standings points of room to lose across all nine categories combined. Fully punting a single category costs about 11 of those points by itself, which forces near-domination everywhere else just to break even.
Variance. Winning ROTO requires an unusually good season relative to eleven rivals — an upside outcome, not an average one — and your odds of an extreme result scale with how much variance your team's total has. Punting reduces that variance: it makes it clearer in advance exactly which points you'll win and which you'll lose, narrowing your range of outcomes. A narrower range means a smaller chance of the exceptional result you actually need to win the whole league. This falls directly out of the ROTO approximation in §3 — the per-matchup variance term is largest exactly at a coin-flip 50% odds, so all else equal a ROTO team benefits from more coin-flip matchups, not fewer.
This is a real trade-off, not an absolute rule — punting can raise your expected value enough to outweigh the variance you give up. Our own simulated ROTO drafters do punt occasionally, and when they do it is almost always free-throw percentage, because a cluster of otherwise-elite players are dragged down by unusually bad free-throw shooting and go underpriced as a result, since everyone else's valuation penalizes them for it.
In practice, this means: The Decision never surfaces punt suggestions or a punt-build UI in a Rotisserie league. In most Rotisserie drafts, recommending a punt is simply bad advice, and we don't give it.
5 · Auction dollars: value above replacement
A value score ranks players against each other; an auction adds a hard budget on top of that ranking. The question a price has to answer is not "how good is this player, in absolute terms," but "how much better is this player than the one I could pick up off waivers for free after the draft?" — because that replacement-level player only costs a roster spot, not a bid.
Scaling prices proportionally to raw value is arithmetically simple but implies the 200th-best player in the pool has real, positive value — he doesn't; he's a free-agent pickup. Pricing off value above replacement avoids that.
replacement_level = value of the last player who will be drafted surplus(p) = value(p) − replacement_level spendable_pool = total league budget − one $1 minimum per roster slot price(p) = $1 + surplus(p) × (spendable_pool / total positive surplus in the pool)
Two things always hold, and we test for both: the replacement-level player always prices at exactly $1, and every player's price adds up to exactly the money in the room.
We also separate two numbers that are easy to collapse into one. Par is the price a player's projected value alone would justify — rank the pool by value, rank it by price, and pair the two rankings up. Price is what the market actually charges. The gap between them, shown as its own column rather than folded into either number, is positional scarcity, run-on-a-position bidding, or plain market noise — information a single blended "value" number would hide.
Live, mid-draft prices adjust for inflation: every team's spendable money divided across the value still on the board, recomputed after every sale. Spendable money is budget left minus $1 for every other slot still empty — the slot being bid on is the one the money is being spent on, so it is not held back against itself. Getting that off by one slot per team inflates the whole board. Early overpays on stars push that multiplier down, which is exactly what opens up mid-draft bargains later on. Snake drafts are the degenerate case of this same model — price becomes pick number, and budget becomes roster size.
We do not apply a positional adjustment in v1. It is unresolved across the industry: a full adjustment prices scarce positions as bargains the market never actually pays for, and skipping it entirely undervalues them. Basketball's positional scarcity is milder than, say, baseball's catcher scarcity — we plan to revisit this once we have real market data to fit against.
6 · Limitations
Stated here because we publish this, not in a footnote. Being first to say where the model is weak is the point of this page.
- Projection error is the dominant error term in the entire pipeline. No amount of clever aggregation math rescues a bad minutes estimate. Most of what determines whether a valuation is right or wrong happens upstream of everything on this page, in the projections themselves.
- Every model here assumes every drafted player's production counts, all season. Real leagues have injuries, streaming, bench-and-forget managers, and teams that stop trying in March. Our simulated opponents are more rational than real ones, so treat any simulated win rate as directional, not literal.
- Draft-seat effects are understated. Early picks tend to end up on stronger teams than late ones, because the value gap between consecutive players is widest at the top of the board. The ROTO approximation in §3 treats every opponent as drawn from the same distribution, which understates this real advantage.
- Category correlations are estimated, and assumed stable. They come from player-level averages across the pool, not from actual league outcomes, and the model assumes they hold steady across a season.
7 · The stabilization study
Two questions have to be answered before a projection can be built at all: how much early-season evidence does it take before a player's rate in a category becomes a reliable signal (its stabilization point), and once we trust a player's current skill level, how fast does that level itself drift over a season (its half-life)? Categories that swing wildly from game to game, like blocks, take longer to trust than steadier ones like rebounds — and a category whose underlying skill changes quickly with role (three-point attempt rate, say) should be weighted toward recent games much more than one that's stable for a given player (like free-throw shooting form).
Method, in brief. For every category, we split each qualifying player-season's games (or, for shooting percentages, attempts — a two-attempt game and a twenty-attempt game aren't the same amount of evidence) into two random halves and correlate them, sweeping the sample size up and fitting where that correlation crosses 0.5. We do this two independent ways — a variance decomposition and a direct curve fit — and report both numbers rather than picking the one we like better; when they disagree by more than 30%, that's flagged in the table below, not hidden. Half-life is measured differently: we correlate each player's own deviation from his normal rate against that same deviation some number of games later, after removing both his career average and a shuffled-order noise floor, so what's left reflects genuine week-to-week drift in skill — not just "this is a good player" or a leftover arithmetic artifact. The noise floor is measured rather than assumed: reshuffling a player's own game order destroys real time structure while leaving that artifact intact, so the shuffled correlation at each lag is subtracted from the real one, and a lag enters the fit only when what survives clears its own standard error (z ≥ 1.96).
An honest result the theory didn't predict. We expected steals to need a longer half-life than three-point attempt rate — steals are a noisy stat but the underlying defensive skill should be stable, while three-point attempt rate can jump the moment a player's role changes. This run measured the opposite: steals' fitted half-life came out at 33.0 games, shorter than three-point attempt rate's 43.3 games. We're reporting that as a finding, not quietly fitting around it or dropping the comparison.
| Category | Axis | k (closed form) | k (empirical) | Agree? | k crossing | Half-life (games) | Fit R² | Well fit? | n groups / units |
|---|---|---|---|---|---|---|---|---|---|
| FG% | attempts | 35.0 | 38.8 | yes | 57.3 | 36.7 | 0.95 | yes | 8,302 / 3,292,122 |
| FT% | attempts | 13.1 | 18.0 | yes | 19.7 | 333.5 | 0.19 | no | 7,963 / 869,817 |
| 3PTM | games | 3.1 | 3.6 | yes | 3.3 | 47.4 | 0.98 | yes | 8,214 / 400,626 |
| PTS | games | 3.3 | 3.9 | yes | 3.8 | 41.4 | 0.99 | yes | 8,214 / 400,626 |
| REB | games | 2.0 | 2.3 | yes | 2.4 | 31.8 | 0.96 | yes | 8,214 / 400,626 |
| AST | games | 1.9 | 2.2 | yes | 2.3 | 36.9 | 1.00 | yes | 8,214 / 400,626 |
| STL | games | 16.1 | 19.5 | yes | 15.3 | 33.0 | 0.92 | yes | 8,214 / 400,626 |
| BLK | games | 4.7 | 5.9 | yes | 4.8 | 56.0 | 0.91 | yes | 8,214 / 400,626 |
| TO | games | 9.8 | 13.0 | yes | 9.1 | 33.5 | 0.98 | yes | 8,214 / 400,626 |
| 3P% | attempts | 17.6 | 124.2 | no | n/a | n/a | 0.17 | no | 7,630 / 1,101,181 |
| A/T | attempts | 2.2 | 8.4 | no | 9.4 | n/a | 0.10 | no | 8,062 / 519,484 |
| 3PTA | games | 1.2 | 1.3 | yes | 2.0 | 43.3 | 0.96 | yes | 8,214 / 400,626 |
"Well fit" reports the half-life exponential decay fit. Free-throw percentage, 3P% and assist-to-turnover ratio come back not well fit — for 3P% and A/T that means the swept correlation never reaches 0.5 or shows detectable decay within the range we swept, which we report as "no detectable decay," not as an unusually long half-life. Sample sizes and fit quality, per category, are in the table above.
To reproduce. Split every qualifying player-season in the source game logs in half along the relevant axis and correlate the halves, sweeping sample size from 2 to 41 games for the counting categories and 5 to 200 attempts for the percentage ones.k is where that correlation reaches 0.5, read both off the swept curve and out of a variance decomposition, with a 30% disagreement between the two reported rather than resolved. Half-life sweeps lags from 5 to 800 games in 5-game windows and fits r(L) = r₀·e^(−λL) to the null-corrected, significant lags only. A fit counts as good at R² ≥ 0.7, and a fitted k is only trusted when it lands within 20% of the curve's own observed 0.5 crossing.
8 · References
Everything above is derived from published work. We didn't invent Z-score, G-score or the ROTO objective — we implemented them, and we credit the source.
- Rosenof, Z. “Static Quantification of Player Value for Fantasy Basketball.” arXiv:2307.02188
Z-score vs. G-score — the correction described in §2 below.
- Rosenof, Z. “Dynamic Quantification of Player Value for Fantasy Basketball.” arXiv:2409.09884
H-scoring, the roster-aware objective behind §2.3.
- Rosenof, Z. “Optimizing for Rotisserie Fantasy Basketball.” arXiv:2501.00933
The tractable ROTO objective and its gradient, used verbatim in §3–4.