# 2026-07-01 — Book live: verifica gate SKH01 + emersione errori silenziosi ## Contesto Il BOOK DERIBIT armato (TP01 0.75 + SKH01 0.25 nettati) è **flat da quando è stato armato (2026-06-23)**: 193 run orari, tutte HOLD, zero ordini reali. Domanda: il flat è legittimo o il gate di SKH01 è muto per un bug? ## Verifica del gate SKH01 — SANO - **Logica viva:** `skyhook_entries` produce 335 entry (BTC, 222 long/113 short) e 341 (ETH, 226/115) su tutta la storia. Non è degenere. - **Shorta davvero i crash:** ha aperto SHORT sulla gamba di crollo di fine maggio/inizio giugno — BTC 05-28→06-04 ($73k→$64k), ETH 06-02→06-06 ($1865→$1555). - **Flat da 06-23 = legittimo:** ultimo entry 06-06, `max_bars=16 × 230m ≈ 2,5g` → chiuso ~06-08/09, **prima** dell'arming (06-23). Dal grind post-crash nessun setup breakout+regime valido → flat corretto per design ("NON trend-follower"). Contesto prezzo al 01-07: BTC −53% dal picco, ETH −67,5%, momentum negativo su 1/3/6/12 mesi → anche TP01 (long-flat TSMOM) è a 0x. - **Entrambi i feed valutano senza crash:** certificato e live `fresh_5m` → `skh_error=None`. ## Bug scoperto e corretto — pattern "eccezione ingoiata → stato safe silenzioso" `src/live/` aveva più `try/except` che, in errore, producono uno stato safe (flat/fallback) **senza farlo emergere**. Rischio: quando l'errore è transitorio ma reale, l'esecutore opera su dati sbagliati credendoli legittimi. ### (1) `skh_error` — CORRETTO `book_report` scriveva `skh_error` in un dict locale **mai incluso nel return** → `r.get("skh_error")` sempre `None`; e `book_execute` non lo leggeva comunque. Un feed SKH rotto avrebbe forzato SKH→flat in silenzio (entry mancato, nessun alert). Fix: `skh_error` esposto nel return + `book_execute` emette log `⚠️ SKH FEED ERRORE` + alert Telegram. (commit 31369b3) ### (2) Gate fail-safe posizione (Opzione A) — CORRETTO `src/live/shadow.py::_positions`: se la read della posizione reale Deribit lancia, assume flat (0.0) con una `note`, MAI propagata (`pos_src`) a `book_report`/`book_execute`. Severità mitigata a valle da `rebalance_signed` che **rilegge la posizione fresca** (no doppia-posizione), ma resta il caso "target≈0 + posizione aperta + read fallita → close saltato quel run" (transitorio, backstoppato dal disaster-SL −30%). **Scelta A = gate fail-safe:** `_positions` ritorna un `pos_error` esplicito → propagato `shadow_report → book_report → book_execute`; se presente (ONLINE ma posizione IGNOTA) l'esecutore **NON opera a cieco** (return + alert), come già fa per `online`. ### (3) Diagnostica equity (Opzione B) — CORRETTO `src/live/shadow.py::_equity`: se `account_summary('USDC')` e tutte le per-asset falliscono, `real_eq=None` e `shadow_report` ripiega su `paper_cap` (~$2000 dallo state paper) mentre il conto reale è ~$598 → il book dimensionerebbe su $2000 invece di $598 (**sovradimensiona ~33%**). Il danno è limitato dall'**hard-cap $300/asset** in `book_net_target`. **Scelta B = SOLO DIAGNOSTICA** (niente gate/halt, l'hard-cap già protegge il downside): `shadow_report` calcola `eq_fallback` (ONLINE + equity reale non leggibile + no override), propagato `→ book_report → book_execute`, che stampa `⚠️ EQUITY FALLBACK` + alert Telegram **ma prosegue** (a differenza del gate posizione, che blocca). ## Test Suite completa **156/156** (era 148; +4 gate A + 4 diagnostica B). Dry-run reale di `book_execute` invariato (nessuna riga d'errore, nessun ordine, conto $598.06 al target). Path live: `pos_error=None`, `skh_error=None`, `eq_fallback=None`. ## Sintesi finale — i 3 pattern "errore silenzioso" del path live sono ora tutti tracciati | # | Punto | Comportamento | Emersione | |---|-------|---------------|-----------| | 1 | `book_report` feed SKH | SKH → flat | log `⚠️ SKH FEED ERRORE` + alert | | 2 | `_positions` read fallita | posizione → flat | **HALT** (non esegue) + alert (gate A) | | 3 | `_equity` non leggibile | sizing → paper_cap | log `⚠️ EQUITY FALLBACK` + alert (diagnostica B) |