-- tb-compound-holdout.sql — TOTAL BASES ONLY, direction-aligned. -- -- TWO guards this query exists to enforce: -- 1. TB ROWS ONLY. Averaging into other stats would hide the effect, since -- total_bases is 49 of 437 settled rows. -- 2. DIRECTION-ALIGNED. p_win is P(GRADED SIDE); proj_p_over_line and -- proj_tb_p_over are P(OVER). 31.4% of rows are under-graded, and comparing -- raw P(over) against an under-side outcome measures the model BACKWARDS — -- that artifact alone accounted for 41% of the ladder's apparent loss. -- -- Promote tb-v1 ONLY if it materially improves TB resolution toward/past the -- champion. If it does NOT, the family-mismatch hypothesis is WRONG and the -- mean-weakness / similarity branch REOPENS. Record which. -- -- CONTAMINATION EXCLUSION (2026-08-02, MANDATORY). Rows whose price/book/takeable -- were stamped from a NON-TAKEABLE book (DFS / offshore / exchange) between -- 2026-08-01 and the write-path fix are tagged `quarantine_reason LIKE -- 'nontakeable_book%'`. They are EXCLUDED here and must never be pooled with -- clean rows: their locked price -- and therefore the `takeable` flag computed -- from it -- describes a market you could not have bet. with tb as ( select game_date, id, lower(side) side, (outcome='hit')::int won, p_win::numeric champ, case when lower(side)='under' then 1 - proj_p_over_line::numeric else proj_p_over_line::numeric end ladder_al, case when lower(side)='under' then 1 - proj_tb_p_over::numeric else proj_tb_p_over::numeric end tbv1_al from public.ledger_entries where sport='mlb' and user_id is null and (quarantine_reason is null or quarantine_reason not like 'nontakeable_book%') and stat = 'total_bases' and outcome in ('hit','miss') and p_win is not null and proj_p_over_line is not null and proj_tb_p_over is not null -- matched rows: all three present ) select count(*) n, count(*) filter (where side='under') under_rows, round(avg(won::numeric),3) base_rate, round(corr(champ, won::numeric)::numeric,4) res_champion, round(corr(ladder_al, won::numeric)::numeric,4) res_ladder_v11, round(corr(tbv1_al, won::numeric)::numeric,4) res_tb_v1, round(stddev(ladder_al)::numeric,4) sd_ladder, round(stddev(tbv1_al)::numeric,4) sd_tb_v1, round(avg(ladder_al)::numeric,4) mean_ladder, round(avg(tbv1_al)::numeric,4) mean_tb_v1 from tb;