NSBA Draft Analyticsembargoed · 2026-06-06

15b_sos_robustness_revised.md

15b — SOS-Adjusted Win% + Factual Fixes (REVISION R4)

15b — SOS-Adjusted Win% + Factual Fixes (REVISION R4)

Date: 2026-05-30. Revision of F15/F16/F17/F13/F19 in response to red-team T6, T8, M3, M2.

Lead caveat (unchanged and load-bearing): everything here rests on 41 team-seasons (nsba1=12, nsba2=13, nsba3=16) and 3 game seasons. Schedules are uneven — nsba3 ranges 1–10 games (median 7); 12 of 41 team-seasons have <8 games. Treat every correlation as directional and every Δ below as "did the magnitude move a little or a lot," not as a precise estimate. Two top nsba3 teams (chonk 8-1, boneca anuragu 3-1) sit in a near-perfect dominance cluster, which drives their Bradley-Terry strength to the numerical ceiling (~3.5e5, both pinned at win-prob ≈1.0); their BT-adjusted win% should be read as "≈1.0, ill-determined," not a point value. The RPI metric is immune to this.

This finding does three things the red-team asked for: - (a) Builds a strength-of-schedule (SOS) adjustment for the 41 team-seasons and re-runs the headline win% correlations from F15 (north-star), F16 (coverage), F17 (CS), reporting how far each magnitude moves (red-team T6). - (b) Runs an nsba3 down-weight / exclude sensitivity on the value-board top-N and the north-star ranking (red-team T8). - (c) Fixes two factual slips: the top-25 nsba4-combine count is 3, not 5 (M3), and states which theta column finding 19's buy-low residual actually uses (it is raw theta_overall, r=0.74, not the de-biked column, r=0.67 — M2).

Reproduce: /home/david/code/nsba/.venv/bin/python scripts/sos_robustness.py (first run scripts/north_star.py so team_north_star_features.csv exists). Writes data/processed/team_sos_adjusted.csv and value_board_nsba3_{full,down,excl}.csv.


SOS method

Teams only play within their season, so SOS is computed per season on the head-to-head results of the clean 180-game set. The clean-game reconstruction of wins/win% reproduces team_season.csv exactly (0 mismatches / 41 team-seasons) using the same team-name canonicalization build_master.py applies, so the raw baseline below is the real F15/F16/F17 baseline, not a re-derivation.

Two SOS metrics (both intra-season):

  1. Bradley-Terry MLE (bt_winprob_vs_avg) — fit log-strengths via MM iteration (Hunter 2004) so P(i beats j)=σ(r_i−r_j); ties split 0.5/0.5. The adjusted score is the BT win-probability vs a median-strength opponent in that season (rescaled to [0,1]). This is the cleaner SOS object but is the one that diverges for undefeated teams.
  2. Iterated opponent-win% (rpi_adj, RPI-style) — start from raw win%, replace each team's score with its average opponent's strength, iterate to a fixed point, then mix 0.5·own_raw + 0.5·opp_strength. Robust to the undefeated-team divergence; a useful check.

How much does SOS move teams at all? Raw win% vs adjusted:

pair pearson r (n=41)
raw win% vs BT-adjusted 0.928
raw win% vs RPI-adjusted 0.994
BT vs RPI 0.94

So SOS reshuffles the margins but not the broad ordering. The biggest movers are all short-schedule nsba3 teams (e.g. boneca 4 games 50%→BT rank −6; big shot 6 games 50%→−5; no like blue 8 games 37.5%→+4 because it played a hard slate). The teams whose standing SOS changes most are exactly the <8-game nsba3 teams the red-team flagged.


(a) Headline correlations: raw vs SOS-adjusted win%

Each row: the F15/F16/F17 metric's pearson correlation with raw win% (reproduces the published finding), then with BT- and RPI-adjusted win%, and the shift ΔBT.

F15 — North-star draftable metrics (all 41 team-seasons)

metric raw r BT r RPI r ΔBT
pptf_team (toss-up rate) +0.624 +0.576 +0.610 −0.048
ppg_total (TU+bonus/game) +0.731 +0.703 +0.748 −0.028
n_subjects (breadth) +0.533 +0.471 +0.526 −0.062
subject_hhi (concentration) −0.473 −0.429 −0.467 +0.045

Read. SOS shaves ~0.03–0.06 off every magnitude — small. The metric ranking is fully preserved: ppg_total > pptf_team > n_subjects > |subject_hhi| under raw, BT, and RPI alike. PPTF (the recommended draftable currency) stays a strong, stable correlate (+0.62 → +0.58). F15's conclusion is unchanged.

F16 — Coverage / "don't punt a subject" (games ≥ 5, n = 37)

metric raw r BT r RPI r ΔBT
coverage (credible answerers) +0.537 +0.512 +0.540 −0.025
punts (uncovered subjects) −0.537 −0.512 −0.540 +0.025
subject_hhi −0.456 −0.433 −0.462 +0.023
deep_subjects (redundancy) +0.298 +0.190 +0.305 −0.107
roster_toss_points (talent) +0.602 +0.466 +0.593 −0.136
top2_toss (star talent) +0.633 +0.530 +0.622 −0.103

Read. The punt/coverage effect barely moves under SOS (−0.537 → −0.512 BT, −0.540 RPI; |Δ|≈0.025). Notably, talent correlations move more than coverage under BT (roster_toss_points −0.14, top2 −0.10) — i.e. some of "talent → wins" is "talent → easier realized schedule," whereas the coverage signal is comparatively SOS-robust. This does not rescue F16 from its real fragility (T2: the punt variation is 5 teams, all nsba3 — see the T8 section and the original F16 caveats); SOS just confirms the coverage magnitude is not a schedule artifact. The redundancy/deep_subjects correlation is the most SOS-sensitive (+0.30 → +0.19 BT), reinforcing F16's "redundancy adds little" conclusion.

F17 — CS value (nsba2/nsba3 only)

metric raw r BT r RPI r ΔBT
cs_ppg (CS pts/game) +0.398 (n=28) +0.301 +0.349 −0.097
share_cs (CS point-share) +0.416 (n=29) +0.364 +0.382 −0.052

Read. The team-level CS→win correlation is the most SOS-sensitive of the three findings: cs_ppg drops +0.40 → +0.30 (BT), share_cs +0.42 → +0.36. This is consistent with the causal red-team's T3 (the team CS premium is partly "we were the better/faster team," which SOS absorbs). It does not zero out — CS still correlates positively with winning after SOS — but it widens the already-wide error bar on the team "CS is worth ~Nx" magnitude and adds to the case (made in red-team H1/T3) that the team CS-leverage number is soft. The confound-robust legs of F17 — the player-level CS-mains-vs-generalists conversion gap and theta_cs r=0.60 to in-game CS — are not team-win regressions and are untouched by SOS; those remain the parts of F17 to lean on.

(cs_ppg n=28 because the 1-game team-only nsba3 team 2yellow4brown has no player rows and thus no CS attribution; share_cs comes from team_season directly, n=29.)

Summary of (a)

finding headline metric raw r BT-SOS r verdict
F15 north-star pptf_team +0.624 +0.576 stable (ranking unchanged)
F16 coverage punts −0.537 −0.512 stable (talent moves more than coverage)
F17 CS value cs_ppg +0.398 +0.301 softens (~25% of the corr is schedule/strength)

SOS does not overturn any of the three conclusions, but it discounts the team-level CS magnitude the most — exactly where the red-team said the most aggressive draft action lives.


(b) nsba3 down-weight / exclude sensitivity (T8)

nsba3 is simultaneously the season with the estimated-TUH proxy, the only season with coverage/punt and playoff variation, and the season most like the nsba4 draft target. So we test how much the draftable conclusions depend on it.

North-star ranking, excluding nsba3 (nsba1+nsba2 only, n=25)

metric all-41 r no-nsba3 r Δ
pptf_team +0.624 +0.502 −0.122
ppg_total +0.731 +0.774 +0.042
n_subjects (breadth) +0.533 undefined
subject_hhi −0.473 −0.014 +0.459

Two important structural facts surface here:

  1. All breadth/coverage signal is nsba3-only by construction. In nsba1 and nsba2, every team scores all 6 subjects (n_subjects_scored has zero variance → the correlation is undefined), and subject_hhi → win% collapses to −0.01 without nsba3. So F16's coverage finding and F15's "breadth as secondary tiebreak" are entirely carried by nsba3's 16 teams (and within those, by ~5 punting teams). This is the strongest confirmation of red-team T2/T8: the breadth story is one season of data. PPTF and ppg_total, by contrast, transfer cleanly — ppg_total even strengthens without nsba3.
  2. PPTF still works without nsba3 (+0.62 → +0.50) and is positive every season individually: nsba1 +0.535, nsba2 +0.561, nsba3 +0.752. The production-rate north-star does not depend on nsba3; the breadth secondary signal does.

Value-board top-N stability (nsba3 weight ∈ {1.0, 0.5, 0.0})

We rebuilt a career-PPTF board (TUF-weighted, shrunk toward the pool mean at M=35 per F11) under three nsba3 weightings and compared the top-N sets:

top-N Jaccard(full,down=0.5) Jaccard(full,excl=0.0) spearman(full,down) spearman(full,excl)
top-10 1.00 1.00 1.00 1.00
top-15 1.00 0.88 1.00 1.00
top-25 0.85 0.52 0.98 1.00

The board is highly stable to nsba3 down-weighting at the top and degrades only deeper. Reason: the top of the value board is nsba1/nsba2-dominated. In the actual published outputs/player_value_table.csv, the top-14 all have nsba3-TUF share = 0.00; only 8 of the top-25 have any nsba3 data, 6 of them purely nsba3 (Akhil Batchu, Anurag S, Kaden W, Sohil Rathi, Kian Dhawan, Anish A). So:

Decision-relevant read: the proxy-TUH uncertainty in nsba3 propagates into the value of the 6 purely-nsba3 players, not into the board's top tier. For those 6 (several of whom are nsba4-relevant returners — Akhil, Kian), the VORP/PPTF should be treated as ordinal with a wider band, exactly as F13's TUH-proxy caveat says. For the nsba1/nsba2-anchored top of the board, the nsba3 proxy is irrelevant.


(c) Factual fixes

M3 — top-25 nsba4-combine count is 3, not 5 (finding 13)

outputs/player_value_table.csv top-25 has has_nsba4_combine.sum() == 3: Akhil Batchu (#15), Rohan G (#17), Kian Dhawan (#23). Finding 13 stated "5" twice; both occurrences are now corrected to 3. This strengthens F13's own central caveat ("the board is historical talent, not the nsba4 pool") — the live re-registered pool is even thinner than the finding claimed.

M2 — finding 19's buy-low anchor is raw theta_overall (r=0.74), not de-biked (r=0.67)

Recomputed on the 18 returning nsba4 combine entrants (those with prior NSBA1–3 game history):

price column corr(career PPTF, price)
theta_overall (raw IRT) 0.740 ← the anchor finding 19 cites
debiked_overall 0.669
raw_overall 0.759

The 0.74 in finding 19 is unambiguously theta_overall — so despite the finding's repeated "de-biked IRT" framing, the Track-A residual is measured against the raw theta. Finding 19 has been annotated (text + a new caveat #7) to say so. Impact on the board: raw and de-biked theta correlate 0.81 across these 18, so re-pricing on the de-biked column would drop the anchor to r=0.67 and shift every mispricing modestly without likely flipping the buy-low/fade ordering materially — but the exact mispricing magnitudes are anchor-dependent and should be read as ordinal (as finding 19 already cautions for its n=18, 1–4-game reads).


What changed vs the original findings

Limitations specific to this revision

Artifacts


NSBA Draft Analytics · embargoed until after the SSB draft · ← hub