Skip to content
← Research papers

Research paper

Rest is a relative quantity

The NBA schedule differential tracks outcomes, the shared-congestion groups look alike, and the one season with a recorded reference forecast cannot tell us whether either is carried

Abstract

Two claims about NBA rest are usually run together: that a tired team plays worse, and that a team tired relative to its opponent wins less often. The schedule separates them. Over 4,793 regular-season games from 2022-23 through 2025-26 the home win frequency climbs monotonically with the rest differential, from 0.4944 when the visitor is better rested by two or more days (n=180) to 0.6409 when the home side is (n=259). The two symmetric-congestion groups look alike: at an equal differential, both teams on a back-to-back produce 0.5510 (n=245) against 0.5518 (n=2,394) when neither is. Similar shares are not absence of fatigue; the smaller group's interval runs 0.4857 to 0.6136, so a difference of several points would not have been resolved. Only one contrast against equal rest separates from zero under a 2,000-replicate game-cluster bootstrap: home rested by two or more days, 0.0892 with an interval of 0.0257 to 0.1502. The pooled gradient runs 0.0602, 0.1051 and 0.1162 in the first three seasons and 0.0114 in 2025-26, and the 1,103 games carrying a recorded pregame reference forecast are all from that last season, where observed minus forecast contains zero in all five cells. The pricing question is a null.

1 Question

The repo already carries one measurement of NBA fatigue: the schedule_density module reports a per-36 box-composite delta of -0.315 on the second night of a back-to-back against rested games (schedule_density.json, per36_deltas.b2b.composite_per36_delta_vs_rested). That is how a team performs, not how often it wins, and the two need not move together.

A game contains two tired teams, or one, or none. If congestion worked on outcomes the way it works on production, two teams both on the second night of a back-to-back would give a different result from two rested teams. If only the asymmetry matters, a game where both sides are tired should look ordinary, and only the gap between the two rest states should appear in the win frequency.

The split is testable straight from the schedule, with no model, because days since each team's previous game is a calendar fact fixed before tip-off. Three questions follow: does the home win frequency change with the rest differential, does it matter at an equal differential that both sides are tired, and on the games carrying a recorded pregame reference forecast does the observed frequency differ from that forecast.

2 Data and definitions

The schedule spine is data/domains/basketball_nba/games.parquet: one row per game with a date, a season, both team codes, a resolved home_win label, both rest_days columns and back-to-back flags. Rows are excluded for two reasons, counted separately, and the waterfall below is the whole of it.

Coverage waterfall, source table to priced subset
StepGames (n)Artifact field
Games in the source table4,846checks.games_in_source
Dropped for a missing rest day53checks.dropped_games_missing_rest
Dropped for a missing outcome0checks.dropped_games_missing_outcome
Measured population4,793panels.rest_differential.n_games
Priced subset joining a recorded moneyline pair1,103panels.market_residual.n_games

Source: novel_rest_asymmetry.json revision 2, as of 2026-09-16. The artifact does not record why a rest day is missing and no reason is supplied here; the 53 excluded rows are all in 2025-26.

Rest days are capped at 10, recorded in checks.rest_days_capped_at; the cap bites only on openers and long breaks, where both sides are usually capped together into the equal cell. The back-to-back flag is exactly rest_days == 1, with a consequence used later: at an equal differential the flag is symmetric, so a mixed congestion game cannot occur. The artifact confirms it with checks.congestion_mixed_n of 0.

The outcome label was cross-checked against data/domains/basketball_nba/game_finals_corrected.parquet, which carries an independently corrected home_win_true column. On the 3,563 games present in both, the labels agree on 0.9997 of rows, recorded in checks.label_agreement.

The reference forecast comes from data/domains/basketball_nba/odds.parquet, joined on date, home team and away team. The join yields 1,103 games, all from 2025-26, recorded in panels.market_residual.seasons. The table stores an American moneyline for each side and no timestamp, so it is treated throughout as a recorded pregame reference forecast without a quote timestamp, not as the close. Both lines are converted to implied probabilities and normalized to sum to one, as definitions.market_forecast states.

  • Population: 4,793 NBA regular-season games over four seasons with a resolved label and a complete rest state.
  • Unit of observation: one game. Every panel row counts games, never possessions or ticks.
  • Conditioning variable: the rest differential, binned -2 or lower, -1, 0, +1, +2 or higher; and for congestion, whether both, one or neither side played the previous day.
  • Priced subset: the 1,103 games joining a recorded moneyline pair, all 2025-26.

3 Method

Each panel is a conditional frequency table. A cell is a set of games sharing a value of the conditioning variable; the reported quantity is the share the home team won. No model is fitted and nothing is smoothed, so the only estimate is a mean of zeros and ones.

frequency(cell) = mean(home_win | cell); gap(cell) = mean(home_win | cell) - mean(reference_forecast | cell)

Intervals come from a bootstrap that resamples whole game clusters with replacement, 2,000 replicates at seed 20260916, reported as the 2.5 and 97.5 percentiles of the replicate distribution. Unit and cluster are the same object here, one game. The artifact records n_boot, seed and the interval rule in its method block.

Contrasts against the equal-rest cell are differences between two separate groups of games. They are not paired: no game appears on both sides. Each replicate draws one resample, recomputes both group frequencies inside it and differences them there, so the interval is a joint bootstrap of the two groups rather than two independent intervals subtracted. A contrast is masked when either side is below the floor, not only the focal cell, so a thin baseline cannot publish a difference against itself.

On timing: rest days come from the gap to each team's previous game date, which exists before tip-off. The moneyline pair is a recorded pregame reference forecast without a quote timestamp, so its position inside the pregame window is unknown and no claim is made that it is the close. Nothing observed during or after the game enters a cell assignment. The artifact says this in timing_guarantee.

4 Results

The rest differential tracks the home win frequency, monotonically across all five cells.

Home win frequency by rest differential, 4,793 games, four seasons
Rest cellGames (n)Home win frequency95 percent interval
away +2 or more1800.49440.4236 to 0.5668
away +17750.51610.4809 to 0.5519
equal2,6390.55170.5333 to 0.5709
home +19400.57550.5430 to 0.6062
home +2 or more2590.64090.5827 to 0.7016

Source: novel_rest_asymmetry.json, panels.rest_differential.cells, as of 2026-09-16.

The spread between the extreme cells is 0.1465, a trivial difference of the two frequencies above. Adjacent intervals overlap heavily, so the contrast panel is the honest reading.

Each rest cell against the equal-rest cell, differenced inside every replicate
Rest cellGames (n)Difference vs equal95 percent intervalInterval excludes zero
away +2 or more180-0.0573-0.1307 to 0.0165no
away +1775-0.0356-0.0739 to 0.0037no
home +19400.0238-0.0142 to 0.0595no
home +2 or more2590.08920.0257 to 0.1502yes

Source: novel_rest_asymmetry.json, panels.contrast_vs_equal_rest. Each row differences two separate groups of games, not the same games twice.

One contrast separates from zero: home rested by two or more days, 0.0892 with an interval of 0.0257 to 0.1502. The away +1 cell at -0.0356 comes close, upper bound 0.0037, and away +2 or more at -0.0573 does not, on 180 games. The shape across all five cells is the more convincing part; no single contrast carries it.

The congestion groups have similar observed home-win shares; this does not establish absence of fatigue. Restricted to the 2,639 games at an equal rest differential, the frequency barely moves between the ends of the congestion range.

Home win frequency at an equal rest differential, split by shared congestion
Congestion stateGames (n)Home win frequency95 percent interval
both on a back-to-back2450.55100.4857 to 0.6136
mixed0maskedempty by construction
neither on a back-to-back2,3940.55180.5325 to 0.5728

Source: novel_rest_asymmetry.json, panels.symmetric_congestion.cells. The mixed cell cannot occur because the back-to-back flag is rest_days == 1.

The difference between the two populated cells is 0.0008, a trivial difference of the two frequencies above, on 245 games against 2,394. The interval on the smaller group runs 0.4857 to 0.6136, wide enough to be compatible with a symmetric-congestion difference of several points either way. None is visible at this sample size; that is not the same as fatigue being absent. The panel excludes only a large symmetric-congestion effect on the home win share.

The season panel is the least comfortable result in the artifact, and the one that most constrains what the rest of it can be used for.

Season stability of the rest gradient
SeasonGames (n)Away rested more: freq (n)Equal: freq (n)Home rested more: freq (n)Home-more minus away-more
2022-231,2300.5550 (209)0.5699 (665)0.6152 (356)0.0602
2023-241,2300.4885 (260)0.5429 (687)0.5936 (283)0.1051
2024-251,2300.4880 (250)0.5390 (692)0.6042 (288)0.1162
2025-261,1030.5254 (236)0.5563 (595)0.5368 (272)0.0114

Source: novel_rest_asymmetry.json, panels.season_stability. The 2025-26 row is short the 53 games dropped for a missing rest day.

In the first three seasons the gradient is present and growing. In 2025-26 it is 0.0114 and the ordering inverts: the home side wins 0.5368 when rested against 0.5563 when level. On 272 and 595 games those are not separable, but they are also not a reproduction of the earlier seasons. The pooled gradient averages three seasons that show it and one that does not, and the 1,103 priced games are all from that one.

Observed frequency minus the recorded pregame reference forecast, 1,103 games, 2025-26 only
Rest cellGames (n)Mean reference forecastHome win frequencyGap95 percent interval
away +2 or more380.47950.4474-0.0321-0.1942 to 0.1186
away +11980.51410.54040.0263-0.0340 to 0.0881
equal5950.54760.55630.0087-0.0268 to 0.0444
home +12210.57850.5294-0.0491-0.1094 to 0.0111
home +2 or more510.58240.5686-0.0137-0.1302 to 0.1008

Source: novel_rest_asymmetry.json, panels.market_residual.cells. The forecast carries no quote timestamp.

Every interval contains zero, and the signs alternate rather than trending with the rest state. The mean reference probability does move across the cells, from 0.4795 at away +2 or more to 0.5824 at home +2 or more, a span of 0.1029 as a trivial difference of those two. Mean reference probability differs across rest groups; this comparison does not identify why. The panel cannot separate a forecast that carries the rest state correctly from a season with no gradient to carry, because both predict this table.

5 Robustness and what would falsify this

Five checks are carried in the artifact rather than asserted in prose. The outcome label agrees with an independently corrected finals table on 0.9997 of the 3,563 overlapping games. The 53 games with a missing rest day are dropped and counted rather than binned, and no game is dropped for a missing outcome, recorded separately as checks.dropped_games_missing_outcome of 0. The odds join is verified to leave one row per game_id, recorded as checks.duplicate_game_ids_after_odds_join of 0, so a fanned-out join cannot double-count a priced game. The mixed congestion cell is published as empty with its own mask reason, not as a zero frequency. And the season panel is published in full, so the instability sits beside the pooled number.

The floor of 30 games never bites in the main panel, whose smallest cell holds 180 games, but it is close in the priced subset, where away +2 or more holds 38 and home +2 or more holds 51. Those rows survive the floor and still carry intervals 0.3128 and 0.2310 wide, from panels.market_residual.cells[0].ci95 of -0.1942 to 0.1186 and cells[4].ci95 of -0.1302 to 0.1008. That is the honest reason they cannot decide anything.

Falsifying this needs more data, not a new method. If the congestion panel were rerun on a corpus several times this size and both-tired games came back a few points from neither-tired with an interval clear of zero, the absolute-congestion reading would be supported and the no-visible-difference report here would be wrong. If the gradient stayed absent for two more seasons, the pooled number would be a property of a stretch of schedule, not of the sport. Recorded pregame forecasts for 2023-24 and 2024-25 would make the pricing question answerable, by putting a forecast beside the seasons where the gradient exists.

One check was deliberately not run: nothing controls for opponent strength, travel or road-trip position, all correlated with rest. The panels are conditional frequencies, not adjusted estimates.

6 Limitations

  • Rest differential is confounded with travel, opponent strength and road-trip position; none are controlled, so the gradient is an association, not a causal estimate.
  • Every contrast compares separate groups of games rather than the same games under two conditions.
  • The priced subset is one season, 1,103 games, and it is the season without a schedule-only gradient, so the pricing null is a coverage limit rather than evidence about the forecast.
  • The odds table records no quote timestamp, so the moneyline is a pregame reference forecast of unknown vintage.
  • The congestion comparison is 245 games against 2,394 and could not resolve a difference much smaller than a few points: absence of evidence, not evidence of absence.
  • Rest days are capped at 10, which compresses the long-break tail into the equal cell.

7 How to read this on the site

The module page for novel_rest_asymmetry prints all five panels in order. Read panels.rest_differential for the headline frequencies, where every row gives n_games first and a masked row keeps its count; then panels.contrast_vs_equal_rest when the question is whether a difference is separable from noise. Read panels.season_stability before panels.market_residual: the season panel is what tells you how much the priced panel can mean.

panels.symmetric_congestion belongs beside the schedule_density module, which measures the same fatigue at the box-score grain. The two are not in conflict: production can fall on a back-to-back while the observed win share does not visibly move, because both sides carry the same load. The panel does not establish that the load has no effect, only that none is resolvable on 245 games.

Evidence

  1. novel_rest_asymmetry.jsonas_of 2026-09-16Source path: /analytics/m/novel_rest_asymmetry/
    Evidence field inventory (37 paths)
    • revision
    • panels.rest_differential.n_games
    • panels.rest_differential.cells[].cell
    • panels.rest_differential.cells[].n_games
    • panels.rest_differential.cells[].home_win_frequency
    • panels.rest_differential.cells[].ci95
    • panels.contrast_vs_equal_rest[].delta_vs_equal
    • panels.contrast_vs_equal_rest[].ci95
    • panels.contrast_vs_equal_rest[].excludes_zero
    • panels.symmetric_congestion.n_games
    • panels.symmetric_congestion.cells[].home_win_frequency
    • panels.symmetric_congestion.cells[].ci95
    • panels.symmetric_congestion.cells[].mask_reason
    • panels.season_stability[].season
    • panels.season_stability[].n_games
    • panels.season_stability[].cells[].home_win_frequency
    • panels.season_stability[].home_more_minus_away_more
    • panels.market_residual.n_games
    • panels.market_residual.seasons
    • panels.market_residual.cells[].mean_market_forecast
    • panels.market_residual.cells[].home_win_frequency
    • panels.market_residual.cells[].gap_observed_minus_market
    • panels.market_residual.cells[].ci95
    • checks.games_in_source
    • checks.dropped_games_missing_rest
    • checks.dropped_games_missing_outcome
    • checks.duplicate_game_ids_after_odds_join
    • checks.label_agreement
    • checks.label_crosscheck_n
    • checks.congestion_mixed_n
    • checks.rest_days_capped_at
    • method.n_boot
    • method.seed
    • method.floor_games_per_cell
    • definitions.market_forecast
    • timing_guarantee
    • verdict
  2. schedule_density.jsondate not publishedSource path: /analytics/m/schedule_density/
    Evidence field inventory (1 path)
    • per36_deltas.b2b.composite_per36_delta_vs_rested
Back to research papers