Files
PythagorasGoal/Old/docs/diary/2026-06-06-improvement-sweep.md
T
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

14 KiB
Raw Blame History

2026-06-06 — Improvement sweep multi-agente (review live PORT06)

Ricerca multi-agente del 2026-06-06 (106 agenti, 196 finding grezzi, 60 verificati avversarialmente, 37 validi / 23 uccisi). Workflow: port06-improvement-sweep (wf_56b7d4de-a06).

1. Quadro d'insieme

Il sistema PORT06 gira correttamente nella struttura (17 sleeve, runner pool/ledger == backtest), ma la review ha trovato due classi sistematiche di problemi, non bug isolati.

(a) Divergenze live-vs-backtest per omissione di protezione. Il pattern documentato del progetto è "il live AGGIUNGE protezione che il backtest canonico non ha" (Hurst, EXIT-16) → il live fa meglio del backtest sul DD. Qui si trova il contrario in più punti: il filtro trend_max=3.0 è ON nel backtest canonico ma OFF in produzione su tutte e 6 le fade (base.py:91 / _defs.py:35-38); il cap SHAPE=0.0588 v1.1.2 è inerte (sovrascritto da portfolios.yml) → SH01 gira a 2x peso senza stop-loss; EXIT-16 non è esteso a DIP01 (l'unico sleeve BTC che esegue davvero); la forming-bar lesson non è portata a TR01 né a PairsWorker. Diversi diari (2026-06-04-partial-tp-ladder.md:15, 2026-06-04-exit-lab.md) documentano config che il codice NON implementa.

(b) Calibrazione/sizing che diverge dal validato. SH01 fa fuoco sul 25% delle barre vs 2.9% validato (th0.58 inerte per train-window troppo corto); i pairs girano a pos=0.5 mentre tutta la validazione PR01 è pos=0.15 (DD ~3.3x); TR01 sotto-carica le fee 2x (manca il fattore leva).

Tema ricorrente onesto: la maggior parte delle "scoperte" sono ripristini di config già validate, non nuovo alpha. I bug di config (cap, trend_max) vanno corretti subito; ogni cambio di strategia deve passare il gate PORT06/OOS (precedente FR01: robusto-individualmente ≠ migliora PORT06).

2. P0 — Protezione capitale / gap live

Titolo Cosa fare Evidenza Effort
Cap SHAPE 0.0588 inerte → SH01 a 2x peso load_active_portfolio deve fare deep-merge dei caps (partire da p.caps e aggiornare con ov["caps"]), oppure ridichiarare il dict completo in portfolios.yml:7 come {PAIRS:0.33, SHAPE:0.0588}. Ri-snapshot pesi, confermare sum=1.0. SH01 non ha SL by-design e ha già subìto un 15.6% live: il cap è l'UNICA protezione coda. src/portfolio/base.py:91-93 setattr sovrascrive caps; portfolios.yml:7 {PAIRS:0.33}; scripts/portfolios/_defs.py:75 {PAIRS:0.33,SHAPE:0.0588}; live data/portfolios/PORT06/status.json SH_BTC=SH_ETH=0.0588 (totale 0.1176 = 2.0x intended). Backtest canonico usa il cap giusto (FULL 6.43/OOS 8.58) → è una rottura di parità. low

Nota: la stessa correzione risolve anche il sotto-peso ~9% di tutti gli altri non-pairs (0.0588 live vs 0.0647 intended); il rischio materiale è solo SHAPE.

3. P1 — Alto valore, testabile subito

Titolo Cosa fare Evidenza Effort
trend_max=3.0 OFF in produzione su tutte le 6 fade Aggiungere "trend_max":3.0, "ema_long":200 alla SleeveSpec FADE _defs.py:36-37. Ripristina la config del backtest canonico (look-ahead-free, EMA200 causale). MR02/MR07 lo onorano (non lo ignorano). Ri-validare a livello PORT06 (template exit16_port06_impact.py) perché Hurst+trend si sovrappongono. _defs.py:35-38 (no trend_max); MR01_bollinger_fade.py:61 get('trend_max')→None; combine_portfolio.py:47 canonico usa trend_max=3.0; risk_management.py:242 lo applica a tutte e 3. Live: MR01_ETH/MR02_ETH hanno fadato il crash ETH 06-05 più volte (long@1658.9 poi long@1592.8 in caduta 1727→1517), tutti stoppati (trades.jsonl). Misurato (live-hurst-on, 3x): MR02_ETH DD 27.3%→16.2%, WR +8pp, Sharpe +1.34 (return ~dimezzato — trade-off DD/return). low
Disaster-bracket on-book durante outage feed Il poll-loop intero è in un try/except: in un outage le posizioni REALI restano senza stop sul book e senza valutazione exit. Piazzare un bracket lontano (~30%) su Deribit per i fade eseguiti [MR01,MR02,MR07,DIP01] via cerbero_client.py:137 set_stop_loss (esiste, non cablato). Non spara mai in operatività normale → 0 costo Sharpe; pura assicurazione. runner.py:246-298 (try/except unico, sleep su errore); ETH gap p99.9=996bps, max=3301bps, peggior 3h 3492bps (data/raw/eth_1h.parquet); REAL_OPEN 06-05 verificati; docs/diary/2026-06-04-exit-lab.md:119-121 lo segnala, mai implementato. Caveat: nei crash il fill è al gap, non al livello → cappa ma non al trigger. low-med
SH01 th0.58 inerte: fa fuoco sul 25% delle barre vs 2.9% validato Ri-validare SH01 OOS con train-window pari al regime live (~8760 barre) invece dell'expanding full-history. La LogReg su train piccolo è over-confident (mean max-proba 0.582 vs 0.536). NON limitarsi ad alzare th (la calibrazione resta sbagliata). Se l'edge non sopravvive nel regime live, riconsiderare SH01. misurato: small-train frac≥0.58 = 44.8% vs full 3.8%; live-window 1197 entry (49.9% long) vs 139 (71.9% long), trade-rate 25.1% vs 2.9%. SH01_shape_ml.py:60 th=0.58; tutta la validazione (shape_ml_validate.py) usa training expanding. È la causa meccanica del WR live 1/9. Blast radius limitato dal cap SHAPE (vedi P0). low (test)
Pairs a pos=0.5 vs validazione pos=0.15 (DD ~3.3x) Introdurre un position_size per-famiglia (plumb SleeveSpec/build_worker_for, runner.py:43-89) e portare i pairs a 0.15-0.25. Ri-eseguire combine alla pos live prima del deploy. I pairs sono la famiglia a DD-grezzo più alto (ETH/BTC 47.6%) e senza stop (exit solo z ≤z_exit o max_bars).
TR01: fee sotto-caricate 2x (manca leva) Moltiplicare il termine fee per self.leverage (basket_trend_worker.py:69) per allinearlo al return leveraged (riga 67) e al reference fee=FEE_RT/2*LEV (honest_improve2.py:150). worker fee/flip 1.5e-05 vs corretto 3.0e-05 (POS0.15/LEV2/N5) = 2.0x. tsmom/rotation_worker sono consistenti → TR01 è l'unico difettoso. Drag assoluto piccolo (low turnover) ma bias ottimistico mono-direzionale che gonfia total_capital nel rebalance. low
PairsWorker agisce sulla barra IN FORMAZIONE Portare la EXIT-16 forming-bar logic ai pairs: calcolare bar_ms da median(diff(ts)) e valutare z sull'ultima barra COMPLETA (entry+exit), come strategy_worker.py:445-447. pairs_worker.py:185 i=len(m)-1, :195 exit, :204-207 entry su barra in formazione; backtest pairs_research.py:69-75 solo close settled; validate_worker_pairs.py non esercita il path → divergenza non testata. low
TR01 valuta crossover EMA sulla barra 4h in formazione In tick scartare la barra in formazione (k=-1 if now_ms≥ts[-1]+bar_ms else -2) e valutare il segnale sull'ultima 4h COMPLETA; correggere ANCHE il booking del return (riga 66 legge la finestra in formazione). basket_trend_worker.py:60-72 legge [-1] (forming); reference honest_improve2.py:152 range(n-1) solo completi. Evidenza: SOL flip 0→1@85.66 poi 1→0@77.72 a 59min, stessa finestra 08-12 UTC (9.3% intra-window glitch). Fix incompleto se si tocca solo il segnale. low
DIP01 senza EXIT-16 (ed è l'unico sleeve BTC che esegue reale) Aggiungere "sl_confirm_atr":0.5 (e valutare hurst_max) ai params DIP01 _defs.py:41-42 (il worker lo legge già, zero codice). Ri-validare sul grid OOS proprio di DIP01 + a livello PORT06 con engine gap-aware prima del deploy (DD standalone sale BTC 23→37%). _defs.py:41-42 DIP01 ha solo {min_tp_frac}; worker gira il branch intrabar wick-sensitive (strategy_worker.py:466) invece del close-confirm (:429). Riproducibile: BTC FULL 299→726/OOS 60→168, ETH FULL 187→898/OOS 221→255. I 3 fade BTC sono flat (0 ordini reali); DIP01_BTC è l'UNICO BTC con round-trip reale → gap non teorico. low (fix) / med (validazione)
TSM01 252d lookback: shortfall su un asset tronca l'inner-join sotto need=253, tick() esce in silenzio Aggiungere un WARN/Telegram quando panel<need (gated su "era già operativo" per evitare falsi positivi al cold-start). Coprire anche RotationWorker (stesso silent return). runner.py:37 1d=440; tsmom_worker.py:53-55 need=253, return muto; rotation_worker._panel how='inner' tronca al più corto; live margine 188 (OK ora) → latente, non attivo. low
Osservabilità: TR01/ROT02/TSM01 invisibili in hourly_report hourly_report.collect() filtra su chiavi (event, in_position) che i worker multi-asset non emettono → 100% delle loro righe scartate. Aggiungere in_position ai _save() dei 3 worker e/o esporre status_summary (long correnti + giorni-dall'ultimo-flip). Distingue "flat in chop" da "wiring rotto". TR01 2 record (entrambi 06-03, lo SOL whipsaw), flat da allora; ROT02/TSM01 0 trade (rispettivamente cash / risk-off da 06-01, by-design). hourly_report.py:105,111; worker _log/_save senza event/in_position. low
MR07 reale: ripristino-fill non esercitato (short-side TP-resting mai testato) Smoke testnet live_shadow_smoke.py con direction=-1 per esercitare il limit reduce-only BUY sotto mercato (può crossare subito → path resting_fills). MR07 (+ tutti i worker) ha 0 TP-resting filled finora → reconciliation completamente non testata in produzione. MR07_ETH 5-6 REAL_OPEN tutti 06-03 PRE-fix (TP-resting 2026-06-04); +257/267/283/333bps slippage legacy (sunk, non ricorrente). Tutti i REAL_TP_RESTING verificati sono side=buy (long); il path short non è mai stato esercitato né in ledger né negli smoke. strategy_worker.py:253 _place_real_tp. low

4. P2 — Filoni di ricerca

  • MR01 ETH k=2.0 vs k=2.5 deployato. k=2.0 è uniformemente meglio OOS su ETH (no-filtro +1238% vs +487%; trend-filtrato +569% vs +196%) e neutro su BTC sotto filtro live. Non è nuovo overfit: è il config per-asset documentato (MR01:15-16) che il k=2.5 universale ha silenziosamente abbandonato. Da confermare a livello PORT06 con i param live (hurst/sl_confirm). risk_management.py:40,44.
  • Limit-order maker entry sui fade — NO-GO confermato. Strutturalmente infattibile: il segnale fade fa fuoco quando il close ha già bucato la banda (mediana 33bps sotto); un buy-limit al livello è marketable→taker; un limit più profondo manca i winner che rimbalzano in 1-4 min. Negativo-EV, non implementare. MR01_bollinger_fade.py:84,93; live MR07_ETH 5 open→TP in ~1.4min.

5. P3 / Scartati in verifica

  • Commento errato in _defs.py:17-18 ("MR02/MR07 ignorano min_tp_frac") — falso (lo leggono e applicano, MR02:46,72), ma il filtro è di fatto inerte su MR02/MR07 nel campione → solo igiene doc, no PnL.
  • TSM01 inerte (0 trade da 06-03) — corretto by-design (BTC sotto SMA100 dal 06-01 + tutti gli asset consensus negativo). Solo diagnostica; NON redistribuire il capitale (riduce la diversificazione quando il regime gira).
  • Time-limit fade NON sono un leak — myth-busting: il bucket max_bars è net-positivo OOS (+118÷+195bps, +154%/+335% totale); il vero loser è lo SL (già gestito). NON accorciare max_bars.
  • Fill max_bars next-open vs close — wash misurato (5/6 sleeve identici); il worker già filla ~next-open. Nessuna azione.
  • SH01 H=12 fuori scope exit_lab.py — routing: usare sh01_exit_lab.py (gap-aware) per qualsiasi studio orizzonte SH01. Clarificazione, non bug.
  • PairsWorker bars_held conta poll-con-nuovo-ts non barre reali — latente (0 time_limit su 9 close), bite solo dopo outage >2h con z ancora oltre soglia; rischio di introdurre exit-anticipato se bar_ms via median-diff su feed testnet flaky → usare bar_ms fisso. Igiene, bassa priorità.

6. Piano consigliato (2 settimane)

Settimana 1 — protezione capitale e parità (config-only, niente cambio di strategia):

  1. Giorno 1 — P0 cap SHAPE. Deep-merge dei caps in base.py:91; ri-snapshot pesi PORT06, confermare SH totale=0.0588, sum=1.0, nessuno sleeve affamato. Verificare contro il backtest canonico (FULL 6.43/OOS 8.58). Questo dimezza l'esposizione SH01-no-SL già colpito dalla coda.
  2. Giorno 1-2 — TR01 fee 2x + forming-bar (TR01 e Pairs). Fix puramente di parità/contabilità, nessun gate OOS necessario (avvicinano il live al backtest validato). Coprire il silent-return TSM01/Rotation con WARN.
  3. Giorno 2-3 — disaster-bracket on-book + osservabilità outage. Cablare set_stop_loss lontano (~30%) sui 4 fade eseguiti; aggiungere alert su N poll falliti consecutivi con real_in_position=True e log del gap% al risveglio. Smoke testnet (€0). Pura assicurazione coda, 0 costo Sharpe.
  4. Giorno 3 — osservabilità report (TR01/ROT02/TSM01 in hourly_report) + smoke MR07 short-side TP-resting.

Settimana 2 — ripristini di config validata, ognuno dietro il gate PORT06/OOS:

  1. Giorno 4-6 — trend_max=3.0 sulle 6 fade. Implementare in _defs.py, poi ri-eseguire il gate PORT06 (template exit16_port06_impact.py) misurando trend-ON+hurst+EXIT-16 vs attuale trend-OFF: deploy SOLO se Sharpe OOS non peggiora e DD scende (sovrapposizione hurst+trend va quantificata).
  2. Giorno 6-8 — pos pairs per-famiglia. Plumbing SleeveSpec.position_size; ri-eseguire combine a pos live (target 0.15-0.25); scegliere il punto sul trade-off DD/ritorno; deploy.
  3. Giorno 8-10 — DIP01 EXIT-16+hurst. Validare sul grid OOS proprio di DIP01 (famiglia honest, meccanismi tarati su fade) con engine gap-aware, poi gate PORT06. Deploy solo se passa entrambi.
  4. Giorno 10-12 — SH01 ri-validazione train-window. Ri-eseguire validazione con train cap ~8760 barre (regime live). Se l'edge sopravvive → tarare th/calibrazione su slice held-out; se non sopravvive → riconsiderare SH01 (NON ri-tunare il th a forza). Mai impostare sl/sl_confirm_atr su SH.

Filoni P2 (MR01 k ETH) e cleanup P3 in coda, opportunistici. Regola trasversale: i punti 1-4 sono fix di bug/parità e vanno per primi; 5-8 toccano il comportamento di trading e nessuno va in produzione senza superare il gate OOS + PORT06 (precedente FR01: robusto individualmente ≠ migliora il portafoglio).