Log the 21:14 orphan as a snapshot-build race, rewrite the context table to authoritative ICs only, and soften the vol-tilt warning. Add extender completion manifest + breadth refuse guard; strip intermediate/orphaned reports; park the thread (no book sim, no deploy).
11 KiB
Broad-universe fip_id IC research (Phase B)
Status: Parked / closed for now. Unconditional fip not green; mom-conditional lead logged; breadth-momentum thesis challenged. No book sim until reopen.
Production impact: none. Display card remains context-only. No deploy from this work.
Artifacts: research log + compact reports + env-gated harness hooks; tooling stays for a future reopen.
Scope
- Research only — production universe, gate, scanner, schedule unchanged.
- Snapshot:
research.sqlite(~4,650 tickers = prod + nasdaq_all extend). - Liquid mask: top 1,500 by point-in-time 63d median $vol, price ≥ $5/week.
- Completion manifest required: extender writes
<snapshot>.manifest.json; breadth runners refuse without a matching complete manifest (see §Race guard).
Caveats
- Survivorship bias (today’s constituents, history backfilled).
- IEX volume undercount → relative $vol rank only.
- Pool skew: Nasdaq-heavy; missing pure NYSE mid-caps.
- Do not mix multi-signal tables across universe baselines.
- Do not cite orphaned 21:14 numbers (see below).
Fingerprint (505-name prod)
| Expected | Observed | |
|---|---|---|
| mean IC | −0.045 | −0.045 |
| t-stat | −2.9 | −2.91 |
| weeks / N / reliable | ≥12 / ~500 / true | 35 / 497.7 / true |
Pass. Formula + pipeline trustworthy.
Residual momentum on the same fingerprint (what the production book ranks on): IC +0.055 / t +1.98.
The orphan (21:14) — root cause
| Source | fip IC (liquid ~1500) | t |
|---|---|---|
Orphan run 21:14 (removed from tree; was fip-breadth-20260718-211440-breadth.json) |
+0.0575 | +5.12 |
| Single-sourced recompute on complete snapshot (2026-07-19) | −0.0168 | −1.85 |
That is a sign disagreement on the same intended quantity. Method rule: the number you cannot reconcile is the number you cannot use.
Verdict: orphaned — raced the snapshot build
Not “orphaned, unexplained.” The mechanism is derivable from the table itself:
- Code was not the difference. Reconcile shows the old harness path and the new shared filter produce identical results on current data (−0.0168 / −1.85). The implementation fork is closed.
- Data was the difference. On today’s complete snapshot the liquid mask binds in 97.1% of weeks at top-N = 1,500. Dense signals (e.g.
vol_6m) post-mask at exactly 1,500. The orphaned report’svol_6maveraged ~1,475 cross-section — a masked run on complete data cannot do that. At 21:14 the eligible pool was smaller than 1,500 and the mask never bound. - Timeline fits. Extender fixes landed ~20:32 / 20:34; full fetch takes ~30 minutes; breadth run fired 21:14 against a partially built
research.sqlite. Every number in that report was computed on an incomplete universe.
Do not cite +0.0575 / t +5.12. It survived less than six hours of contact with project discipline — that is the system working, not time wasted. The orphan JSON was deleted from the tree (still in Git history) so it cannot be re-imported as evidence.
Kept artifacts
| File | Role |
|---|---|
reports/fip-reconcile-20260719-000520.json |
Authoritative single-sourced ICs (compact; membership dumps stripped) |
reports/fip-breadth-20260718-211440-fingerprint.json |
Prod fingerprint pass |
Race guard (same class as calendar truncation)
| Piece | Behavior |
|---|---|
extend_snapshot_universe.py |
Clears any prior manifest on start; on full completion writes <output>.manifest.json with complete=true, ticker / OHLCV / rank_only counts, finished_at. --limit smoke runs write complete=false. |
run_fip_breadth_research.py / run_fip_breadth_diagnostics.py |
Refuse breadth mode unless a matching complete manifest exists and live counts equal the recorded totals. |
Helper: scripts/research_snapshot_manifest.py.
Authoritative unconditional liquid fip (post-reconciliation)
| metric | value |
|---|---|
| mean_ic | −0.0168 |
| ic_t_stat | −1.85 |
| weeks | 35 |
| avg_cross_section (post-mask IC sample) | 1471.2 |
| avg_raw_pool | 3214.4 |
| avg_eligible_pre_mask | 2338.4 |
| mask_binds_pct | 97.1% |
| reliable | true |
Mask binds hard on complete data (eligible ≫ 1500). Post-mask IC N for fip is ~1471 because not every liquid name has a valid 12-1 fip path — that is signal availability, not a non-binding mask. Contrast orphan vol_6m avg N ~1475 vs complete-data vol_6m avg N 1500.
Harness _signal_evaluation vs manual IC through the same filter: exact match (−0.0168 / −1.85).
Iron rule unconditional: not green (|IC| 0.017 < 0.03), correct mild-negative sign.
Context table (orphaned 21:14 vs authoritative) — kill the myth numbers
The context table died with the orphan. −0.16 must not survive in the log.
| signal (liquid ~1500) | orphaned (21:14) | authoritative (shared filter) | consequence |
|---|---|---|---|
| vol_6m | −0.16 / t −6.1 | −0.048 / t −1.36 | “High-vol tilt harmful on breadth” downgrades from finding to directional hypothesis — not significant |
raw mom (mom_12_1) |
+0.10 / t +4.6 | +0.046 / t +1.91 | Below iron-rule bar on this pool |
resid mom (mom_12_1_resid) |
+0.04 / t +2.3 | +0.029 / t +1.33 | Ditto, and weaker than raw |
Breadth-momentum thesis — challenged
That last pair is the sobering one. Momentum on liquid breadth is marginal. The “more breadth strengthens the momentum t-stat” thesis that motivated Phase B is empirically wrong on this pool: same 35 weeks, triple the names, residual-mom t-stat fell versus the 505-name fingerprint (0.055 / 1.98 → 0.029 / 1.33). The clean momentum edge lives in the large-cap universe already traded.
Meanwhile the strongest reliable signal on liquid breadth is now mom-conditional fip (−0.088 / −4.58) — but a fip tilt presupposes a breadth momentum book worth tilting, and that is no longer free.
Compositional story (supported)
fip_id = sign(PRET)×(%neg−%pos) pools:
- Continuous winners → want negative IC
- Continuous bleeders → want positive IC
| check | IC | t | read |
|---|---|---|---|
| Prod-universe subset inside liquid | −0.044 | −2.88 | Matches fingerprint → compositional, not regime change |
| Tier 1–800 (senior) | −0.035 | −2.99 | Winner leg |
| Tier 801–1500 (junior) | +0.014 | +1.25 | More bleeder / junk weight |
| Lagged membership (prior-week $vol) | −0.010 | −0.93 | Same sign as same-week; not a +5σ leak artifact |
Do not log “on Nasdaq, jumpy paths outperform.” That would mythologize an orphaned +0.06.
Platform-relevant test: momentum-conditional fip
Among liquid top-1500, keep mom_12_1 ≥ P80 (~294 names/week):
| metric | value |
|---|---|
| mean_ic | −0.0879 |
| ic_t_stat | −4.58 |
| ic_positive_pct | 22.9% |
| weeks | 35 |
| reliable | true |
Computed on the same single-sourced path as the authoritative −0.017. This is the paper’s claim and the only version a gate could consume.
| Decision | |
|---|---|
| Unconditional fip | Closed for production |
| Mom-conditional fip | Alive as book-tilt candidate only — and only after a baseline breadth book proves itself |
| Display card | Stays |
| Production change | None |
Vol-tilt warning (softened)
| signal (liquid, single-sourced) | IC | t |
|---|---|---|
| vol_6m | −0.048 | −1.36 |
| mom_12_1 | +0.046 | +1.91 |
| mom_12_1_resid | +0.029 | +1.33 |
High-vol names tend to underperform on this pool relative to a clean S&P-like book — that is a directional hypothesis, not a finding. Production 80/20 high-vol tilt was validated on S&P-like names. If the universe ever broadens in production, re-validate that tilt; do not treat the orphaned −0.16 / t −6.1 as evidence.
What this means for the book experiment
A fip tilt presupposes a breadth momentum book worth tilting — that is no longer free.
Caution against over-reacting the other way: modest cross-sectional IC does not preclude a good book. The 505-name book turns resid-mom IC ~0.055 into Sharpe ~2 because the gate trades the extreme tail, not the linear sort. The breadth book might still work; it just has to prove it before the fip arm means anything. If the baseline cannot clearly beat the existing production book’s territory, fip’s future is a footnote regardless of −4.58.
Parked next step (if reopened): pre-registered two-arm design
Not started — design only, pre-register before any sim:
| Arm | Definition |
|---|---|
| A — baseline | Top-quintile residual (or raw — pick one and lock) momentum book on liquid-1500; no fip; honest costs; next-open or near-close fills; production-like capacity / risk / stops |
| B — +fip tilt | Same book + mom-conditional fip tilt (among mom winners, prefer smoother paths / negative fip_id) |
| Grade on | Spec |
|---|---|
| Split | Entry-date train / validation (BACKTEST_HOLDOUT_SPLIT naming — not pristine holdout) |
| Metrics | Sharpe + Mertens/Lo SE, PSR, DSR; max DD; turnover; cost drag |
| Promote bar | Arm A must be in production-book territory first; Arm B must beat A on validation with DSR-aware multiple-testing honesty |
| Fail-closed | If A fails, fip is a footnote; do not shop tilts on a dead baseline |
How to re-run (research branch only)
# 1) Full extend writes completion manifest (required)
.\.venv\Scripts\python.exe scripts\extend_snapshot_universe.py `
--source backtest_snapshots\prod.sqlite `
--output backtest_snapshots\research.sqlite
# 2) Breadth / diagnostics refuse without matching manifest
.\.venv\Scripts\python.exe scripts\run_fip_breadth_diagnostics.py `
--research-snapshot backtest_snapshots\research.sqlite `
--prod-snapshot backtest_snapshots\prod.sqlite `
--workers 6 --allow-spawn
Bottom line
- Formal iron-rule screen: not green either before or after reconciliation.
- +0.0575 / +5.12 is orphaned: raced the snapshot build — authoritative unconditional liquid fip is −0.017 / −1.9; mask binds (~97%) on complete data.
- Context-table myths die with the orphan: vol −0.16 is not real; authoritative vol is −0.048 / t −1.36 (directional only).
- Compositional tug-of-war is the right story; jumpiness premium is not.
- Breadth does not strengthen residual-mom t-stat on this pool (0.055/1.98 → 0.029/1.33).
- Mom-conditional −0.088 / −4.6 stands on the single-sourced path → optional next step is a pre-registered two-arm breadth book (baseline first), not a gate wire-in.
- Manifest guard is in place so the race cannot recur silently.