Files
PythagorasGoal/Old/docs/diary/2026-06-04-exit-lab.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

9.8 KiB
Raw Permalink Blame History

2026-06-04 — EXIT LAB: ricerca massiva exit dinamiche (34 agenti) → EXIT-16 close-confirm SL PROMOSSO

Obiettivo

Cercare exit migliori per le fade attive: TP dinamici, SL dinamici/protettivi, meccanismi per "cavalcare il prezzo". Mandato: ≥20 agenti con specifiche differenti, guardia anti-overfitting, test su tutto lo storico disponibile.

Esito in una riga: "cavalcare" non esiste (17ª conferma), ma la ricerca ha trovato una cosa più grossa — LO STOP-LOSS INTRABAR FISSO È IL COMPONENTE CHE DISTRUGGE PIÙ VALORE NELLE FADE, e la forma robusta del fix (SL confermato in chiusura, EXIT-16) è PROMOSSA a livello PORT06: OOS Sharpe 8.82→10.06, FULL DD 4.10→2.60.

Infrastruttura (riusabile)

  • scripts/analysis/exit_lab.py — harness CONDIVISO: cache segnali live-params delle 3 fade (data/cache/exit_lab_signals.pkl, 73.6k barre 1h 2018→2026-05, BTC+ETH), engine intrabar identico a fade_base (parità verificata al punto percentuale su tutti e 6 gli sleeve), contratto anti-look-ahead esplicito (levels(j) solo dati ≤ j-1; after_bar(j) sul close = eseguibile al poll), protocollo train/OOS (selezione parametri SOLO su pre-2023-11; OOS letto una volta), fill parziali, ExitPolicy pluggable.
  • scripts/analysis/exit_policies/ — 23 policy + 10 script di verifica.
  • scripts/analysis/exit16_port06_impact.py — replay canonico build_trades/ fade_daily_equity con parità ESATTA (corr 1.00000) + innesto EXIT-16 + ricalcolo PORT06 (cap pairs 0.33, leva 2x).

Fase 1 — Explore: 23 agenti, una famiglia ciascuno

Tally: 3 PROMISING, 5 NEUTRAL, 15 REJECT.

REJECT (la famiglia "cavalca il prezzo" è stata falcidiata): trail_atr_ride, trail_pct, breakeven, sar_trail, tp_decay, tp_extend_momentum, tp_moving_mean, partial_tp_trail, hurst_exit, giveback, loser_timestop, donchian_trail, ema_cross_exit, vol_rescale, sl_tp_ride. Autopsia ricorrente: il TP delle fade sta ALLA MEDIA; lì il movimento è esaurito per costruzione → oltre quel punto non c'è coda da cavalcare (il runner finiva oltre il TP ~3% delle volte). Caso da manuale trail_atr_ride: train 5/6 a favore, OOS 0/6 (MR01 ETH ret 134%→1%) — senza l'embargo train/OOS l'avremmo promosso.

NEUTRAL: ratchet, sl_tighten, z_overshoot, wide_sl_trail, swing_stop (miglioramenti misti, mai 5/6).

PROMISING — tre meccanismi diversi, UNA stessa tesi ("gli stop intrabar da wick sono falsi negativi: l'overshoot che buca lo stop è esattamente ciò che la fade vuole fadare, e rientra"):

  • EXIT-02 trail_atr_keep_tp (chandelier k=1.5 + TP fisso): 6/6 train, 5/6 OOS.
  • EXIT-16 close_confirm_sl (SL solo se la barra CHIUDE oltre sl0±0.5·ATR): 6/6 train E 6/6 OOS, plateau.
  • EXIT-22 no_sl (diagnostica: SL rimosso): 6/6+6/6, plateau monotono perfetto SL stretto < base < SL 2x < niente SL.

Fase 2 — Verify: 10 avversari (leakage / overfit / stress × 3 + tail-risk)

  • EXIT-02 CONFUTATO (2/3). (a) Overfit: è Pareto-dominato da no_sl a ZERO parametri su tutti i 6 sleeve OOS (Sharpe base→trail→noSL: MR01 BTC 2.77→3.08→5.67; MR02 ETH 12.35→11.41→17.24 — il trail PEGGIORA lo sleeve di punta) → overfit di selezione: la forma parametrizzata sbagliata di una tesi giusta. (b) Leakage: codice pulito MA scoperta di metodo: il 54% degli stop del trail è GAP-THROUGH (l'open del bar è già oltre il livello; gap mediano 62-174 bps): l'engine che filla gli stop "al livello" SOVRASTIMA ogni policy a stop stretti; col fill realistico worse(level, open) il confronto si ribalta. Da oggi ogni ricerca con stop tight deve modellare il gap-through. Lo SL largo della base ne è quasi immune.
  • EXIT-16 SUPERA 4/4. Leakage: contratto pulito, robusto a 1-3 bar di lag e al fill a open[j+1] (esce deliberatamente tardi → il timing fine è irrilevante per costruzione). Overfit: plateau monotono su buffer 0.4→1.0 FUORI griglia, il ponte SL-largo k=1.5→4 converge, 4 finestre temporali ok, e indipendente dal loss-guard Hurst (segnali rigenerati senza guard: la tesi regge anche nel regime trending). Stress: fee 2x 6/6, slippage 20 bps simmetrico 6/6, bear 2021-22 ok.
  • EXIT-22 invalidato SENZA mitigazione (tail-risk). p99 MAE ~raddoppia (MR01 ETH 38.8→−59.7%); finestra FTX 2022-11: MR02 ETH 39% (worst 48%, MAE 70%) dove la base faceva +2.7% uscendo in 2-3 barre. E un fatto di wiring: con sl=0 il worker cade nel ramo elif max_barsil fallback 2% è codice morto: no_sl live girerebbe SENZA ALCUNO stop. Il disaster-SL 4× tiene ~95% del ritorno ma il worst pooled resta 47%.
  • Raccomandazione convergente del tail-auditor: EXIT-16 — neutralizza quasi tutta la coda DA SOLO (p99/worst ≈ base; FTX: +2.4%) mantenendo l'immunità ai wick. Mai usare uno stop stretto 2% come fallback (cappa l'edge insieme alla coda).

Fase 3 — Test decisivo a livello PORT06 (path canonico)

Replay di build_trades/fade_daily_equity con parità ESATTA (corr 1.00000, ritorni identici, PORT06 base == Portfolio.backtest() al centesimo: FULL 6.47/4.10%, OOS 8.82/1.30% — i numeri 6.07/8.19 citati in CLAUDE.md sono pre-refresh-dati). Poi SOLO il ramo SL sostituito col close-confirm 0.5·ATR:

PORT06 FULL Sharpe FULL DD FULL CAGR OOS Sharpe OOS DD OOS CAGR
base 6.47 4.10% 61% 8.82 1.30% 86%
EXIT-16 7.84 2.60% 79% 10.06 1.15% 102%

Gate (lo stesso del loss-guard Hurst): PROMOSSO — migliora OGNI metrica, FULL e OOS. Per-sleeve: ritorni FULL ~4-10x (MR01 BTC 299→1963%) e DD giù su 5/6 (eccezione MR02 ETH +3.4pp, assorbita in aggregato).

Verdetto e piano di deploy (DA FARE, non ancora implementato)

EXIT-16 close_confirm_sl, buffer 0.5·ATR14, SOLO sulle 6 fade.

  1. Param sl_confirm_atr=0.5 nelle fade (default None = comportamento attuale, per non rompere i backtest canonici/regression-lock).
  2. FadeStrategy.backtest + StrategyWorker.tick: disattivare l'uscita intrabar a sl0; aggiungere il ramo sul CLOSE del bar (long: esci se close < sl0 0.5·ATR14; short speculare). TP intrabar e max_bars INVARIATI. ATR14 causale già disponibile.
  3. Shadow reale: nessun nuovo tipo d'ordine (il close-confirm esce al close del worker → market reduce-only come oggi; il limit resting al TP di v1.0.7 resta identico).
  4. DIP01/pairs/rotation/tsmom/shape NON toccati.

Caveat onesti

  • L'uscita al close può essere PEGGIO di sl0 sui veri sfondamenti (già nei numeri del backtest, ma la coda dipende dai gap: campione 1h crypto, stress estremi sottorappresentati).
  • Niente stop fisico sul book → rischio gap/disconnessione fra i poll (mitigazione possibile in futuro: disaster-SL intrabar a 4× come cintura, costa ~5% del guadagno).
  • avg_bars +~18% (esposizione su; già nei numeri via non-overlap).
  • I numeri per-sleeve FULL (ret 4-10x) vanno letti col solito sconto del compounding su 8 anni; la decisione è presa sul gate PORT06, non su quelli.

Scoperte collaterali da NON perdere

  1. Gap-through fill: l'engine intrabar filla gli stop al livello anche quando l'open è già oltre → bias sistematico PRO stop-stretti. Aggiungere il fill worse(level, open) all'harness prima di future ricerche su stop.
  2. Wiring worker: una strategia con sl=0+max_bars gira nel ramo elif max_bars → il fallback 2% non si applica. Oggi nessuna strategia attiva emette sl=0, ma il ramo va reso esplicito se mai si deployasse una policy senza SL.
  3. Il prior ladder di stamattina è confermato e generalizzato: 4 conferme indipendenti che oltre il TP non c'è nulla da cavalcare.

Costi della ricerca

34 agenti (23 explore + 10 verify + 1 PORT06), ~1.65M token subagente, ~70 minuti wall-clock su 2 core. Workflow: exit-policy-explore (wf_4b23e922-f48) + exit-policy-verify (wf_f2bb98df-c43).

IMPLEMENTATO E DEPLOYATO (sera stessa, v1.1.0)

Param sl_confirm_atr (default None = comportamento storico):

  • src/strategies/fade_base.py FadeStrategy.backtest + scripts/strategies/ MR01_bollinger_fade.py (ha un backtest proprio, duplicato storico — patch identica): ramo close-confirm al posto dell'SL intrabar; TP intrabar e max_bars invariati; in modalità confirm il TP ha priorità nel bar (come la policy validata in exit_lab).
  • src/live/strategy_worker.py tick: con sl_confirm_atr nei params dello sleeve, TP intrabar al livello come prima; stop SOLO se close sfonda sl ∓ buf·ATR14(df), uscita al prezzo corrente (reason stop_loss invariata → il monitor stop-rate di hourly_report continua a funzionare).
  • scripts/portfolios/_defs.py: SL_CONFIRM_ATR = 0.5 sulle 6 fade (path live, come hurst_max). Il backtest canonico resta NON filtrato.
  • Test: tests/portfolio/test_close_confirm_sl.py (wick non stoppa; breach sul close stoppa al close; TP intrabar resta; buffer regge; regressione senza param). 59/59 verdi.

Nota onesta dal sanity-check sul path GREZZO (nessun filtro): il ritorno esplode (MR02 ETH cap 366k→3.0M) ma il DD per-sleeve SALE (MR01 BTC 32→52%): senza trend-filter/hurst il close-confirm tiene posizione anche nei trend profondi. La riduzione di DD vive nella config live (trend_max 3.0 + hurst 0.55) e nella diversificazione — esattamente ciò che il test PORT06 canonico ha misurato (DD 4.10→2.60). Le tre protezioni sono COMPLEMENTARI: hurst toglie l'esposizione al regime tossico, il trend-filter gli ingressi sovra-estesi, il close-confirm i falsi stop da wick.

Monitoraggio live: lo stop-rate fade su hourly_report dovrebbe scendere sotto il ~38% atteso post-hurst; gli stop avranno exit leggermente oltre il livello (uscita al close), i TP restano al livello (e nello shadow reale al limit reduce-only di v1.0.7).

Deploy: commit a2579d2 (+ research ad65a0b), release v1.1.0.