Files
PythagorasGoal/Old/docs/diary/2026-06-11-stability-sweep.md
Adriano Dal Pastro 14522262e6 chore(reset): v2.0.0 — storico certificato Deribit mainnet, ripartenza pulita
Reset del progetto su fondamenta verificate dopo la scoperta che l'intera
libreria "validata OOS" era artefatto di feed contaminato (print fantasma del
feed Cerbero TESTNET + storico Binance/USDT).

- Storico ricostruito da Deribit MAINNET (ccxt pubblico, tokenless) e
  CERTIFICATO (certify_feed.py): BTC/ETH puliti su TUTTA la storia
  (mediana 2-6 bps vs Coinbase USD), integrita' OHLC + coerenza resample
  (maxΔ 0.00) + cross-venue OK. Alt esclusi (illiquidi/divergenti: LTC/DOGE
  50-82% barre flat; XRP/BNB non certificabili).
- Verdetto sul feed pulito: FADE / PAIRS / XS01 / TSM01 morti (ogni
  portafoglio Sharpe -2.3..-3.0, DD ~40%); solo SH01 e frammenti HONEST
  con segnale residuo, da ri-validare in isolamento.
- Cleanup "restart pulito": strategie, stack live (src/live, src/portfolio,
  runner/executor, yml, docker), ~100 script ricerca/gate, waste/games/
  portfolios, dati non certificati + cache e 60+ diari -> archiviati in Old/
  (preservati, non cancellati). Diario consolidato in un unico documento.
- Skeleton ricerca tenuto: Strategy ABC + indicatori + src/fractal +
  src/backtest/engine + load_data; tool dati certificati (rebuild_history,
  certify_feed, audit_feed, multi_source_check).
- Universo dati ATTIVO: solo BTC/ETH (5m/15m/1h); guardrail fisico
  (load_data su alt -> FileNotFoundError). Esecuzione DISABILITATA, conto flat.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 15:20:59 +00:00

87 lines
5.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 2026-06-11 — Sweep di stabilità su tutte le strategie (anti-overfit)
Obiettivo: analisi di tutte le 19 sleeve cercando miglioramenti/correzioni/protezioni che
aumentino la STABILITÀ, con disciplina anti-overfit (ipotesi pre-registrate, griglie fissate
prima di guardare i numeri, verdetti su TRAIN E OOS con plateau, gate PORT06; nessun re-test
di idee già bocciate: ADX/vol-target/time-stop/hurst/stop SH01/multi-TF/entry-guard ecc.).
## Audit di drift (nessun fitting)
- `report_families` sui dati correnti: correlazioni cross-famiglia ancora ≈0 (pairs 0.03-0.11,
XS01 0.01, SH 0.03-0.04 vs MASTER-9) → la diversificazione NON è driftata.
- **Regression-lock trend_max** (`trendmax_port06_impact`) rieseguito su dati freschi:
parità 1.00000 su tutte e 6 le fade (engine live-path integro) e **plateau trend_max
2.5/3.0/3.5 confermato** (OOS Sh 11.14/11.24/10.98, DD 1.33 identico).
- **Percentile del rolling-return PORT06** (cap weights, storia 2021+): finestra corrente
60g al 19°, 120g al 21°, 160g al 28° percentile → periodo fiacco ma in variazione normale.
- ⚠️ **FADE in coda storica**: il rolling 120g equal-weight delle 6 fade è a **1.0% =
2° percentile** della propria storia (p5 = +0.4%). È il tratto peggiore mai attraversato
dalla famiglia. Decisione esplicita: NESSUN ritocco ai parametri (sarebbe fit sul regime
corrente, l'errore che il progetto evita da sempre); la protezione è la diversificazione
(già in atto: il portafoglio regge al 19-28° pct) + monitoraggio. Follow-up in TODO:
alert di drift per-famiglia nel hourly_report (distribuzione storica precomputata).
## Correzione: bug contabile TR01 worker (FIXATO)
`BasketTrendWorker.tick` usava `mean(rets)` sui SOLI asset in posizione → con paniere
parziale sovrappesa N/k (con 1 solo long: 0.45 del capitale invece di 0.09). Era l'origine
della divergenza replay 44% vs reference +42% annotata nel TODO. La convenzione canonica
(backtest PORT06 via `_tr_basket_daily`) è equal-weight 1/N sull'universo: fix 1 riga
(`sum(rets)/len(universe)`). Replay post-fix: **TR01 +32% vs reference +42%** (stesso segno
e ordine di grandezza = gate del validatore; il residuo è la differenza dichiarata
capitale-unico vs media-equity). ROT02 +171%==ref, TSM01 +5%==ref invariati. Solo
statistica PAPER: nessun effetto su pool/ordini. NB: il forming-bar su ROT02/TSM01 segnato
nel TODO era GIÀ fixato (v1.1.10, `_panel` scarta la barra in formazione) — TODO aggiornato.
## Protezione 1 (pre-registrata): disaster-cap z sui pairs → **NO-GO**
Ipotesi: exit immediata se |z| ≥ z_stop dopo l'ingresso taglia la coda da structural-break
senza toccare i trade normali. Griglia fissata: z_stop {3.0,3.5,4.0,5.0} × 5 coppie 1h +
{2.5,3.0,3.5,4.0} sul 15m, train <2023-11-01 / OOS, engine con regression-lock ESATTO su
`pairs_sim`/`pairs_sim_flat`. Esito (potere statistico AMPIO, centinaia di trigger):
**bocciata su tutti e 3 i criteri** — il DD peggiora quasi ovunque, il worst-trade OOS
peggiora su 4 coppie su 6 (ETH/BTC 62→−168%!), Sharpe OOS cala oltre il 10% relativo in
TUTTE le celle, e il "plateau" esiste solo per il danno (monotono: più stretto, peggio).
Meccanismi: (i) lo stop realizza la perdita al massimo overshoot — il movimento che la
strategia fada (stessa lezione EXIT-16/SH01, **5ª conferma**); (ii) l'engine non-overlap
rientra subito nello spread ancora divergente → churn di fee a 2 gambe e stop ripetuti.
I pairs restano senza stop by design; la mitigazione resta la taglia
(`position_size_family` PAIRS 0.20). Record: `scripts/analysis/pairs_zstop_research.py`.
## Protezione 2 (pre-registrata): phase-tranching XS01 → **PROMOSSA e LIVE**
Diagnosi: il roll non-sovrapposto di XS01 ha una FASE arbitraria (dipende da quando il
worker parte) e l'esito ne dipende parecchio — sulle 12 fasi possibili: Sharpe daily FULL
1.52-2.33, DD per-trade 13.8-33.1% (`xs01_tranche_research.py`). È timing-luck puro: il
backtest canonico (fase 0) è una delle estrazioni FORTUNATE sul FULL (DD 15.4 vs mediana
~21). Rimedio senza parametri fittati: **ensemble di fase** — K sub-book sfasati di hold/K
barre su capitale comune (PnL/K). Gate onesto su equity daily (`xs01_tranche_gate.py`):
- standalone OOS: Sharpe 3.79→4.27 (K=2) →4.85 (K=3), DD 7.99→7.25→5.56;
- FULL standalone: il DD sale verso la mediana di fase (~21%) — il "peggioramento" è la
RIMOZIONE della fortuna della fase 0, non un costo;
- PORT06 swap-sleeve: FULL invariato (7.33/3.46), OOS Sh 10.07→10.11 (K=2) →10.15 (K=3),
OOS DD 1.48→1.43→1.38. **Plateau: K=2 E K=3 entrambi promossi** (non best-pick).
Implementazione: `CrossSectionalWorker` param `tranches` (default 1 = storico; live K=3 in
`_defs.py`), books indipendenti con sfasamento iniziale `wait`, capitale comune, migrazione
automatica dello status legacy (il vecchio book → tranche 0), `last_bar_ts` solo-avanti
(robustezza ai panel accorciati da feed in ritardo). Solo path LIVE come `disp_min` (il
backtest canonico resta single-phase → il confronto live/backtest va letto con la mediana
di fase in mente). **Validatore esteso e PASSATO**: K=1 replay == `xsec_sim` ESATTO
(1427 trade, cap 4993==4993); K=3 replay == unione fasi 0/4/8 ESATTO (4279 trade,
4512==4512). Osservabilità: `hourly_report` aggrega i sub-book nel book medio.
## Non toccati (per evidenza, non per pigrizia)
- **Fade/DIP01**: exit-lab già esaustivo (23+11 famiglie); plateau e parità riconfermati oggi.
- **SH01**: 11 famiglie di stop già bocciate; cap famiglia + monitor trade-rate in essere.
- **ROT02/TSM01**: replay == reference; forming-bar già fixato.
- **TR01 come sleeve** (3 anni negativi su 6): rimosso? NO — sarebbe una decisione guidata
dal regime recente (recency bias); il suo ruolo è catturare i trend che le fade non
prendono. Resta, con la statistica ora contabilizzata correttamente.
## Esito test
`pytest`: 99 passed. Validatori: honest workers OK, xsec K=1/K=3 OK, trendmax lock OK.