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>
This commit is contained in:
Adriano Dal Pastro
2026-06-19 15:16:03 +00:00
parent 8401a280b9
commit 14522262e6
383 changed files with 1971 additions and 779 deletions
@@ -0,0 +1,81 @@
# 2026-06-01 — Bugfix: SH01 usciva a 3 barre invece di H=12 (exit a orizzonte)
> Diagnosi partita da un check sulla debolezza apparente di **SH01_BTC** nel paper
> trading live PORT06 (accuratezza 33,3% su 3 trade). Non era sfortuna statistica:
> era un bug di exit nello `StrategyWorker`.
## Sintomo
Nel live PORT06 (Docker `pythagoras-portfolio`), SH01_BTC mostrava 3 trade tutti
`long`, **tutti chiusi con `reason: "hold_limit"` a `bars_held: 3`**, con `tp: null
sl: null`:
| # | entry | exit | bars | net % | esito |
|---|-------|------|------|------:|:---:|
| 1 | 73529.5 | 73433.0 | 3 | 0,46% | ❌ |
| 2 | 73759.5 | 73839.5 | 3 | +0,02% | ✅ |
| 3 | 73811.5 | 73766.0 | 3 | 0,32% | ❌ |
`oos_signal_precision` nei log di TRAIN scendeva 55,6% → 50,0% → 43,3%.
## Causa
SH01 (`scripts/strategies/SH01_shape_ml.py`, config **W24 H12 th0.58**) è una
strategia **horizon-only**: predice il segno del rendimento a **H=12 barre** ed esce a
H barre. I suoi Signal portano `metadata={"max_bars": H}` (=12) e **nessun TP/SL**.
Nello `StrategyWorker.tick()` la logica di uscita era:
```python
if self.tp and self.sl: # SH01: False (tp=sl=0)
... usa self.max_bars ... # -> max_bars=12 consultato SOLO qui
elif self.bars_held >= self.hold_bars: # fallback legacy hold_bars=3
self._close_position(..., "hold_limit") # SH01 finiva QUI
```
`self.max_bars` (=12, settato correttamente in `_open_position`) era onorato **solo
dentro il ramo `tp and sl`**. Senza TP/SL, SH01 cadeva sul fallback `hold_bars=3` e
chiudeva a 3 barre. L'edge di SH01 — per CLAUDE.md è nell'**asimmetria sull'orizzonte
H, non nella frequenza** (win-rate ~50%) — non aveva tempo di realizzarsi: tagliato a
3/12, degenera in rumore.
Solo SH01 (BTC+ETH) era colpito: tutte le fade (MR01/MR02/MR07, DIP01) portano
tp+sl+max_bars e usano il ramo intrabar corretto.
## Fix
`src/live/strategy_worker.py`: aggiunto un ramo per l'exit a orizzonte puro, prima del
fallback `hold_bars`:
```python
elif self.max_bars:
# Exit puro a orizzonte (strategie senza TP/SL, es. SH01 shape-ML H=12):
# onora max_bars dalla metadata del Signal, non il fallback hold_bars=3.
if self.bars_held >= self.max_bars:
self._close_position(current_price, "time_limit")
```
Le fade restano invariate (entrano nel ramo `tp and sl`).
## Verifica
- Nuovo test `tests/portfolio/test_horizon_exit.py` (2 casi): con `max_bars=12` resta
in posizione a 3 barre; esce a 12 con `reason: "time_limit"` e `bars_held: 12`.
- Suite completa: **43 passed**.
- Container riavviato: **tutti i 17 sleeve RESUME puliti**, inclusa una posizione
SH01_ETH short aperta che ora seguirà l'exit a 12 barre.
## Atteso d'ora in poi
I trade SH01 nei log mostreranno `reason: "time_limit"` con `bars_held: 12` invece di
`hold_limit / 3`. Il 33% di accuratezza era un artefatto dell'exit prematuro; ora la
strategia gira sull'orizzonte su cui è validata (BTC OOS Sharpe 2,72, expanding).
Resta comunque un **diversificatore** del MASTER, non un motore di ritorno standalone.
## Lezione
Il backtest di SH01 (`fade_base`/engine onesto) esce a H barre via `max_bars`; il
worker live deve replicarlo. Quando una strategia non porta TP/SL ma solo un
orizzonte, il fallback `hold_bars` del worker la **falsa silenziosamente**. Verificare
sempre che la convenzione di exit del worker live coincida con quella del backtest
validato — non solo l'ingresso.