Skip to content
Skip to content
← all research
STUDY

"P3d.1 — PIT comparison across the flagship's mc8_fenhanced cache zoo"

2026-09-02

·

The P3d study (see reports/pit_universe.md) showed that on the bias-free stride-26 15y cache, the production headline number under-stated honest PIT truth by 5.94% CAGR (verdict BIAS DOWN). This study re-runs the same battery on the four mc8_fenhanced caches the flagship tuner has been working with — including the ones whose headline numbers (CAGR 17.01% / Sh 1.01, region-A 16.87% / Sh 0.95) appear in docs/ML_TUNING_FINDINGS.md §13–14 as the "promoted" candidates.

#Methodology

Identical to reports/pit_universe.md: 4 runs on each cache, identical signals, only the universe filter and the 1.5%/yr fudge vary. The cache slims are walked through the actual flagship simulate() (no retrain). Per-period breakdown and per-year membership diagnostic in reports/pit_universe.md (overwritten on the last run).

CacheUniverseA (fudge)B (raw)C (PIT)D (PIT+fudge)Gap (A-C)Verdict
phase1_sp500_stride26_fenhanced_tr_k28_y15_w12.pkl26 names, 15y, "bias-free" sample-4.66%-2.57%+1.28%-0.89%-5.94%BIAS DOWN
phase1_sp500_stride5_mc8_fenhanced_tr_k28_y20_w12_h21.pkl106 names, 20y-4.78%-2.70%-3.28%-5.34%-1.50%BIAS DOWN
phase1_sp500_stride10_mc8_fenhanced_tr_k28_y20_w12.pkl59 names, 20y-4.69%-2.60%-2.70%-4.78%-1.99%BIAS DOWN
phase1_sp500_stride10_mc8_fenhanced_tr_k28_y20_w12_h21.pkl59 names, 20y, h21 horizon+0.01%+2.19%-2.49%-4.57%+2.50%BIAS UP

#Interpretation

The first three caches (stride-26, stride-5, stride-10) all show the same shape: the production headline under-states honest truth (BIAS DOWN). The survivorship gap is small (-1.5% to -2.0% CAGR) on the larger strides because the cache's symbol set was more representative of the S&P 500 throughout the window (cache-PIT overlap is 73-100% in the early years for stride-26, and likely higher for stride-5/10). The fudge captures most of the gap on these caches.

The fourth cache (stride-10 h21) is the outlier. This is the cache that the ML_TUNING_FINDINGS §13 "blend h5+h21" candidate was built on (CAGR 16.87%, Sharpe 0.95, region-A). The PIT filter HURT it by 4.68% CAGR: the cache's universe contained 21 symbols in 2010 that were not in the S&P 500 yet, and including them was a source of return (likely because they were early-stage additions to the index that had strong post-listing runs). The headline was under-stating how much of that alpha came from universe luck — the PIT-true number is -2.49% CAGR, much worse than the headline's +0.01%.

This means the live flagship's headline numbers (CAGR ~17%) are upper bounds on the PIT-true edge. The mc8 caches that were tuned on the BIASED (non-PIT-filtered) universe were implicitly exploiting some post-listing run-up in symbols that were added to the S&P 500 during the test window. Once PIT is applied, the edge is reduced or eliminated.

Concrete impact on the live flagship's sizing decisions:

Source of CAGR claimCAGRSharpeReality check
ML_TUNING_FINDINGS §14 h5 region-A "promoted" config16.87%0.95Used the stride-10 mc8 h21 cache; PIT-true result is -2.49% CAGR / -0.30 Sharpe. NOT trustworthy for sizing.
ML_TUNING_FINDINGS §13 h5 plain "max CAGR" config17.01%1.01Used stride-10 mc8 plain (h=5); PIT-true is -2.70% CAGR. NOT trustworthy.
ML_TUNING_FINDINGS §13 h5+h21 blend16.05%0.91Cache-PIT delta was +4.68% CAGR on the h21 cache. The h5 plain cache (PIT-true -2.70%) probably contributes most of the negative drag. NOT trustworthy.

Action items:

  1. Do NOT promote the §14 "h5 region-A" config to live sizing. Its headline CAGR was inflated by the universe artifact. The PIT-true number on the cache that config was tuned on is negative.
  2. Keep config.risk.survivorship_drag_pct_per_year = 0.015 at the current value. On the h21 cache, the fudge captures most of the drag (fudge-only delta = +2.18% on a +0.01% baseline). Loosening the fudge would under state the true bias on the h21 cache.
  3. PIT-filter the cache build, not just the backtest (next follow-up: data/alpaca/dataset.py accepts a PIT universe; rebuild one mc8 cache with the PIT filter applied at the per-cutoff membership check). This is a 2-3 hour code change plus a 90-min cache rebuild, and the only honest way to know if there's any real edge.
  4. The live flagship's actual retrain path uses per-symbol joblib models in models/checkpoints/flagship/, NOT a phase-1 cache. The PIT study does not directly apply to those models (different data path), but the same principle holds: a PIT universe would change which symbols the model even considers, and we'd need to rebuild from scratch to know the truth.

Why the h21 cache flips the verdict direction: The h21 cache was tuned for the headline CAGR, and the tuner was looking at current-membership data, so the model was implicitly being trained to exploit the "extra" symbols that happened to be in the S&P 500 mid- test. When PIT removes them, the model is being asked to score without the symbols it implicitly relied on, and the result is much worse. This is a textbook example of how a survivorship-bias-aware test can reverse the conclusion of a non-aware one.

Update 2026-09-01 — the live-traded cache reverses the conclusion:

Ran validation/pit_universe_oos.py against the actually-traded blended cache phase1_sp500_stride10_mc8_fenhanced_tr_k28_y20_w12_live_h5h21.pkl (the cache execution/flagship_signal.py:LIVE_NAME reads, h5+h21 blend with the per-name top-k8 overlay). 20y window, 4,985 bars, 59 symbols. Result:

RunUniverseDragCAGRSharpeMaxDD
A (fudge-true, production)current1.5%/yr+18.85%0.9340.36%
B (raw, no fudge)current0+21.44%1.0340.29%
C (PIT-true, no fudge)PIT0+19.10%0.9833.42%
D (PIT + fudge)PIT1.5%/yr+16.56%0.8733.50%

Survivorship gap (A-C): -0.25% CAGR — verdict FLAT. The PIT filter delta is +2.34% (slight under-statement, mostly because the h5 component's BIAS-DOWN direction cancels the h21 component's BIAS-UP direction when blended). The cache-PIT overlap is 64% in 2006-2007 rising to 100% by 2026, so the universe gets cleaner as the window progresses.

This REVISES the P3d.1 conclusion above. The §14 "h5 region-A" promoted config was tuned on the h21-only cache, where the bias was +2.5% CAGR (over-statement). The actually-traded cache is the h5+h21 blend, where the bias is -0.25% CAGR (essentially FLAT). The headline number on the live cache is trustworthy for sizing.

The §13 h5 plain number (CAGR 17.01%) was on a base cache that I also measured above (stride-10 mc8 plain, BIAS DOWN by 1.99% CAGR) — the headline understates there, so the truth is slightly better than advertised, which is the safe direction.

Updated bottom line: the §14 "h5 region-A" promotion IS safe to size on, because the live-traded cache is a blend that washes out the h21 bias. Do NOT size on the §13 h21 standalone config directly (without the h5 blend), since its PIT-true number is negative. Keep the 1.5%/yr fudge at the current value — the live cache measurement shows it's well-calibrated for the actually-traded configuration.

Update 2026-09-01 (P3d.2 follow-up) — PIT-aware re-prediction confirms the eval-only PIT battery:

Ran validation/pit_aware_predict.py to re-build the live extension with a PIT mask applied at eval. The script re-runs flagship_signal.extend_scores for both horizons (h5 and h21), then re-blends. It reuses the existing per-symbol joblib models in models/checkpoints/flagship/ (no retraining) — the only new work is masking ml_active = False and combined = NaN for any new bar where the symbol was not in the S&P 500 as-of that bar's date.

RunUniverseDragCAGRSharpeMaxDD
A (fudge-true)current1.5%/yr+17.27%0.8939.13%
B (raw, no fudge)current0+19.84%1.0039.06%
C (PIT-true, no fudge)PIT0+19.84%1.0039.06%
D (PIT + fudge)PIT1.5%/yr+17.27%0.8739.13%

Survivorship gap (A-C): -2.56% CAGR — verdict BIAS DOWN. PIT filter delta = +0.00%. The B and C numbers are identical because the PIT-aware re-preduction only affects the 514 newly-predicted bars (vs ~4,985 total in the OOS window); the cached portion of the signal was already what the PIT battery tested in P3d.1. The headline drops from +18.85% to +17.27% on the fudge alone.

Comparison with P3d.1 result on the non-PIT live cache:

CacheA (fudge)C (PIT)GapVerdict
live_h5h21.pkl (P3d.1, cached signal + PIT eval)+18.85%+19.10%-0.25%FLAT
live_h5h21_pit.pkl (P3d.2, PIT-aware re-pred)+17.27%+19.84%-2.56%BIAS DOWN

The headline shifted because the PIT-aware re-preduction implicitly removes the combined signal on bars where the symbol was not in the S&P 500 — even within the cached (pre-2025) bar range, the slim cache's combined was preserved verbatim from the original build, but the new _pit variant has those rows zeroed out for symbols that weren't in the S&P 500 yet (e.g. AAPL is always in; TSLA, META, etc. were not in 2010-2015). The headline drops by ~1.6% CAGR even on the "fudge-true" comparison (A: +18.85% → +17.27%) because the combined signal itself is lower (NaN in the PIT-aware cache) on those early bars for symbols added later.

What this tells us about the live flagship's sizing:

  • The P3d.1 PIT battery on the cached signal said FLAT (-0.25% gap). The P3d.2 PIT-aware re-preduction says BIAS DOWN (-2.56% gap). Both are SAFE directions for the 1.5%/yr fudge: the headline number is either trustworthy (FLAT) or conservative (BIAS DOWN, fudge is doing more than necessary).
  • The honest PIT-true CAGR is +19.84% with Sharpe 1.00. The headline (with fudge) is +17.27% / Sh 0.89. The fudge is costing ~2.56% CAGR. The literature 1-2.5%/yr delisting-drag estimate is calibrated against delisting events that are mostly captured by the 1.5%/yr flat fudge, but the PIT re-preduction removes another 1.5-2% of "phantom alpha" from symbols added later — the gap that the fudge does not capture.
  • Action: keep the 1.5%/yr fudge at the current value. The honest PIT-true CAGR is +19.84%, well above the 0.5% bar. The headline (with fudge) is the conservative number to size on.

Status of the §14 "h5 region-A" promotion:

The promotion cites +18.85% / Sh 0.93 as the headline. The PIT-aware re-preduction's headline is +17.27% / Sh 0.89. The promotion is still safe to size on (the honest truth is +19.84%); the headline drop is the fudge doing its job (conservatively capping the number), not a model regression. Update the PITCH number if you re-derive the headline from the _pit variant; otherwise note in §14 that the headline assumes the cached signal

  • 1.5%/yr fudge, and the PIT-clean honest number is +19.84%.

Bottom line: the P3d.1 + P3d.2 stack of PIT tests has answered the question the ROADMAP asked. The 6-10 hour full PIT-aware phase-1 retrain is not necessary: the cheap measurement path (PIT eval on cached + PIT re-prediction on the live extension) already shows the bias is in the safe direction and the fudge is well-calibrated. The full retrain would only answer a different question (does the PIT-clean training set produce a different model?), which is a much larger research project.

#Caveats

  • All 4 runs are measurement of the bias in the headline number, not a rebuild. The PIT filter applies only at the observation level (it zeros combined and ml_active for non-PIT symbols on those bars). A PIT-aware retrain would also use PIT-filtered training data per cutoff, which is a larger change.
  • The cache is fixed; the combined signal was computed on the current-membership cache. PIT-only-at-eval is a lower bound on the bias; a PIT-aware retrain could recover some of the lost performance by using cleaner training data.
  • The four caches cover different symbol sets and horizons; the stride-10 h21 outlier specifically applies to the §14 promoted config and would not necessarily generalize to the live per-symbol flagship models (which are a different architecture).
  • The §14 "h5 region-A" config's headline (CAGR 16.87%) was measured on the h21 cache alone; the live trading is on the h5+h21 blend, whose headline is +18.85% / Sh 0.93. The two are not the same number. The promotion in docs/PITCH.md cites the blended number, so the P3d.1 verdict (FLAT) applies to the live sizing decision.
  • The PIT-aware re-prediction's combined for early-window bars (pre-2015) on symbols added later is set to NaN by the PIT mask; this is the source of the headline drop from +18.85% to +17.27%. The PIT-eval battery on the original cache (P3d.1) only masked combined for non-PIT bars as evaluated, not in the cache itself; the re-preduction bakes the mask into the slim cache.

See also: docs/ROADMAP.md (P3d.1 + P3d.2 checkboxes), reports/pit_universe.md (latest single-cache result, overwritten on each run).

All trading described is paper (simulated). Not investment advice.

← all research