Risposta a "trova un sistema di protezione da fallimento exchange" SOTTO IL VINCOLO
della decisione appena presa (100% Deribit fino a $20k). Se non si puo' ridurre
l'ESPOSIZIONE, l'unica leva e' il TEMPO: il modello di rischio del mattino assumeva il
salto a zero istantaneo, ma i fallimenti reali non lo sono (Mt.Gox mesi, FTX ~72h, e
misurato qui: Bitfinex 2018-19 dislocato per 2.324 ore consecutive).
SEGNALE: un venue che gata i prelievi rompe l'ARBITRAGGIO -> il prezzo si stacca dal
consenso e ci resta. E' |scarto|, non il segno (Mt.Gox a premio, un venue in fuga a
sconto: stessa cosa). Consenso = venue USD indipendenti (Coinbase, Bitstamp), mai USDT.
Deribit sta a 3 bps dal consenso in mediana su 8 anni (65.043 ore BTC + 64.541 ETH).
TARATURA CONGELATA: 100 bps persistenti 4h a segno costante. Criterio DICHIARATO PRIMA,
perche' i due ovvi sbagliano in versi opposti (provati entrambi): "minimi bps" -> 25/24h
consuma 24 delle ~72h di FTX; "minime ore" -> 500/2h MANCA FTX (margine 0.6x). Regola:
zero falsi allarmi in 8 anni + margine >=3x sul caso storico piu' debole -> soglia
<=100bps -> poi minima latenza. Margine 3x FTX / 5x Quadriga / 10-20x Mt.Gox, zero falsi
allarmi con crash COVID, maggio 2021, LUNA e novembre 2022 inclusi.
CONTROLLO POSITIVO SUPERATO (un rilevatore tarato per non segnalare e' indistinguibile da
uno rotto): puntato su Bitfinex 2018-19 scatta 22 volte, episodio piu' lungo 2.324h a
+447bps. 22 dove il problema c'era, 0 su Deribit. E la durata risponde alla domanda vera:
un venue gated resta dislocato per settimane, quindi 4h di latenza sono trascurabili.
ECONOMIA: falso allarme = 0.248% atteso (flat 3g misurato sul book reale a ogni data
d'inizio); vero positivo = 100% salvato. Break-even p > (falsi/anno) x 0.00248: a 1 ogni
8 anni serve p > 0.031%. Il valore sta nella SPECIFICITA', non nella sensibilita'.
CABLATO: src/live/venue_watch.py (nucleo puro) + scripts/live/venue_watch.py, in
cron_book.sh PRIMA di book_execute (se Deribit e' in stress l'allarme deve partire anche
quando l'esecuzione fallisce per la stessa ragione). Tre stati OK/ALERT/BLIND — "non
vedo" non e' "va bene". ALLERTA, NON BLOCCA: l'azione e' prelevare (manuale; una chiave
con permesso di prelievo sarebbe essa stessa un rischio) e bloccare non protegge un saldo
che e' a rischio anche stando flat. Runbook pre-deciso nel docstring.
NON COPRE, e non e' un argomento per riaprire il 26/07: un fallimento SENZA finestra
(furto chiavi, sequestro, exit-scam) non lo prende nessun tripwire.
ERRORI CATTURATI IN SESSIONE:
- break-even calcolato sul p5 invece che sulla media (8.3x piu' severo, conclusione
ribaltata);
- ipotesi meccanica sbagliata: credevo che i crash dislocassero a segno ALTERNATO. Falso,
sono a segno costante anche loro (perp sotto spot per ore in cascata). A separare sono
ampiezza e durata, non il segno;
- la prima corsa tronco' il campione da 8 anni a 29 GIORNI per un inner-join con Kraken
(che serve solo ~700 candele) e la copertura era gia' stampata a video: una diagnostica
stampata NON e' un controllo. Ora c'e' una guardia che ferma lo script. 2a occorrenza
in un giorno dopo GTAA01;
- il controllo positivo era finito dentro il ramo `else` -> non girava mai, cioe'
esattamente il difetto che doveva prevenire.
Book, pesi, config INVARIATI. 359 test verdi (+23).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
T1 (TP di SKH01 come limit resting on-book) NON e' stato implementato, per misura.
Leggendo il codice di produzione: TP01 e SKH01 tradano lo stesso strumento con una
sola posizione netta Deribit, quindi un ordine on-book al livello di SKH chiuderebbe
anche quota TP01. Misurati i due ostacoli: (A) segno compatibile nel 97% dei trade
che escono in TP = risolvibile; (B) divergenza modello/live apparentemente bloccante.
Ma (B) non esiste: resample_5m NON scarta il bin 230m in corso (21 barre 5m su 46
nell'ultimo bin) e _skyhook_positions ci itera dentro -> il live rileva gia' SL/TP
intra-barra, entro ~1h dal tocco. I docstring che dicevano "usa solo barre chiuse" e
"latenza fino alla chiusura della barra 230m" erano FALSI e hanno guidato tre analisi
(02/07, 24/07, T1). Corretti sul posto.
Conseguenza: la lente `hourly` sottostima il path live di +0.081 Sharpe FULL di book
(23/23 offset, banda appaiata); il live vero sta sopra il canonical sul FULL, e il fix
richiesto sarebbe un declassamento (+0.054 vs +0.081) in cambio di ordini parziali sul
netto in un percorso con soldi veri.
Cablato invece il problema vero trovato per strada: fresh_5m fallisce in SILENZIO
(fallback al certificato, rigenerato 1x/giorno) -> la latenza d'uscita di SKH01 passa
da ~1h a ~1 giorno senza segnalazione, e nessun controllo esistente scatta (il gate di
staleness guarda il feed di TP01). Stesso schema del feed-freeze del 14/07.
* livefeed.feed_age_minutes: pura, eta' dalla CHIUSURA della barra, None = non
misurata, clamp sugli skew d'orologio
* book_report espone skh_feed_age_min (max fra gli asset)
* book_execute stampa lo stato e allerta su Telegram sopra skh_feed_max_age_min (30m)
Scelta dichiarata: ALLERTA, NON blocca. Bloccare fermerebbe anche TP01 (nettato sullo
stesso strumento) per un guasto di rete; forzare SKH flat chiuderebbe posizioni buone
su un glitch.
Follow-up dichiarato: la stessa barra parziale tocca gli INGRESSI (ent[n-1] da breakout
non confermato). Disaccordo in 1 bin su 112, ma con 3 entry nel campione la taglia non
e' stimabile. E' un cambio di strategia, non di strumentazione -> misura dedicata prima.
Strategia, pesi e cadenza del cron INVARIATI. Nessun ordine inviato. Suite 266 verdi.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Il paper trader standalone TP01 (paper_trend.py) era inerte dal 2026-06-19
(n_bars=0), non in cron, e sostituito da paper_portfolio (TP01+XS01, gira ogni
giorno). Archiviato in Old/scripts/live/ e stato congelato rimosso.
Book live INTATTO: shadow.py legge PAPER_STATE con guardia .exists() -> degrada
a FALLBACK_CAPITAL=2000 (identico allo stato congelato) e paper_pos=None. Dry-run
di book_execute identico prima/dopo (conto online, HOLD su BTC/ETH).
- git mv scripts/live/paper_trend.py -> Old/scripts/live/paper_trend.py
- rm data/paper_trend/ (state inerte, gitignored)
- CLAUDE.md: 3 riferimenti -> paper_portfolio + nota di ritiro
- live_trend.py + shadow.py: hint/commento fallback legacy aggiornati
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Il cap notional per-asset non e' piu' fisso a $300: con max_notional_per_asset_frac
in config diventa equity/2, cosi' cresce col capitale e un deposito futuro non resta
strozzato (frontiera 2026-07-03). Guardrail: dinamico SOLO con equity reale fidata;
su fallback/offline si torna al cap fisso (protezione downside quando E e' ignota).
Live dry-run: cap $299 a equity $598 -> inerte oggi. Suite 172 passed (+4 test).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Il dashboard non mostrava nessuno dei tre segnali di health introdotti nei
commit 31369b3 (skh_error) e 5670469 (pos_error/eq_fallback): finivano solo su
Telegram + log cron, invisibili a chi guarda il monitor. pos_error/eq_fallback
erano gia' in shadow_report (usato dal dashboard) ma ignorati dal template;
skh_error non era nemmeno recuperato (il dashboard usa shadow_report, non
book_report).
Fix:
- _alerts_banner(): helper puro (verde "nessun alert" se pulito, rosso con una
riga per errore) che rispecchia i tre alert di book_execute.
- build(): raccoglie pos_error/eq_fallback dallo shadow gia' fetchato + skh_error
da book_report(offline=True) (feed certificato, nessuna rete extra).
- html(): renderizza il banner in cima alla sezione ① LIVE.
- tests/test_dashboard.py: +4 (verde, 3 alert, parziale, chiave-ignota).
Suite 160/160. Render end-to-end verde (conto sano $598.06 flat). Chiude la
copertura: i 3 pattern di errore silenzioso ora visibili su log + Telegram + dashboard.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Terza+quarta chiusura del pattern "eccezione ingoiata -> stato safe silenzioso"
in src/live, dopo skh_error (31369b3). Emerse durante la verifica del gate SKH01.
Opzione A (gate fail-safe posizione):
- shadow._positions: se la read della posizione reale Deribit lancia, assume flat
MA ora ritorna un pos_error esplicito (prima solo una note mai propagata).
- Propagato shadow_report -> book_report -> book_execute: se ONLINE ma posizione
IGNOTA, l'esecutore NON opera a cieco (return + alert), come gia' per 'online'.
Opzione B (diagnostica equity, no halt):
- shadow._equity/shadow_report: se ONLINE ma equity reale non leggibile, il book
ripiega su paper_cap (~$2000) invece del conto reale (~$598) -> sovradimensiona
~33%, ma l'hard-cap $300/asset limita il downside. Nuovo flag eq_fallback ->
book_execute stampa warning + alert Telegram MA prosegue (niente gate: la scelta
e' solo diagnostica, l'hard-cap gia' protegge).
Test: +8 (4 gate A, 4 diagnostica B). Suite 156/156. Path live pulito
(skh_error/pos_error/eq_fallback = None). Diario 2026-07-01-book-live-error-surfacing.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
book_report scriveva skh_error in un dict locale MAI incluso nel return ->
r.get("skh_error") era sempre None. E book_execute non lo leggeva comunque.
Risultato: se il feed SKH (fresh_5m) fallisse, il book forzava SKH a flat in
silenzio, indistinguibile da un flat legittimo -> entry SKH reale mancato,
nessun alert.
Fix:
- src/live/book.py: skh_error come variabile esplicita, esposta nel dict di
ritorno (None normalmente). Il fail-safe (SKH->flat, TP01 indipendente sul
suo feed certificato) resta invariato.
- scripts/live/book_execute.py: emette la riga di log + alert Telegram quando
skh_error e' presente.
- tests: book_report cattura-e-flagga l'errore; book_execute lo fa emergere
(log + notify). Suite 148/148.
Contesto: verifica del gate SKH01 dopo 193 run flat dal 06-23 (gate SANO —
335/341 entry storici, shorta i crash; flat legittimo: ultimo entry 06-06
chiuso ~06-08 pre-arming). Questo chiude il rischio latente scoperto durante
la verifica.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Aggiunge il forward-monitor STATARB-RESID al dashboard accanto a PREVDAY (sezione
③·c FORWARD-MONITOR): carica data/paper_statarb/state.json, mostra doppio libro
MODELED/REAL-$600, ret/maxDD/fill-haircut, posizione spread corrente e giorni forward.
Warn aggiornato: LEAD sotto deflated-Sharpe -> forward per confermare l'edge, non deploy.
Smoke-test html() OK (box presente, dati live). Test 146/146.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Estende l'esecuzione live da TP01-only al book Deribit-only completo. TP01 e SKH01
tradano lo STESSO strumento (una sola posizione netta per conto su Deribit) -> netting
in software: un solo ordine/asset verso il target netto.
- src/live/book.py: target NETTO per asset = clamp(0.5*E*(0.75*tp_frac + 0.25*skh_sign), ±cap).
Riusa current_target (TP01, causale) + _skyhook_positions (segno L/S, book 230m) + conto reale.
- src/live/execution.py: rebalance_signed() — reconcile CON SEGNO (long/short, flip via close+open,
reduce reduce_only). La close resta sempre permessa (si esce da qualunque posizione).
- src/live/livefeed.py: fresh_5m() — feed 5m certificato + coda recente EFFIMERA da Deribit pubblico
(stesso simbolo inverse, in-memory, NON scrive su disco -> dati certificati intatti; fallback al
certificato su errore). Solo SKH01 ne ha bisogno (e' a 230m); TP01 e' giornaliero.
- scripts/live/book_execute.py: executor doppio-gate (config + --execute), disaster-SL on-book sulla
posizione netta, log in data/live/book_executions.jsonl. Feed SKH fresco (live_feed=True).
- scripts/cron_book.sh + crontab ORARIO: book idempotente ogni ora (riconcilia al netto corrente);
rimossa la riga live_execute.py (TP01-only) dal cron daily per non far collidere i due.
- config/live.json: ARMATO (execution_enabled=true). cap/asset $300 split 75/25, disaster-SL -30%.
Tutto flat all'arming -> nessun ordine finche' un segnale non arma.
- tests/test_book_live.py: 20 test (sizing 75/25, cap, flip/close/reduce, parita' pesi backtest,
gate-safety, reconcile con trader fittizio, merge/dedup feed + fallback, loader onorato). 76/76 pass.
CAVEAT: exit SKH SOFTWARE (latenza fino a fine barra 230m; solo disaster-SL on-book); TP01 scende a
peso 0.75 (max $225/asset); SKH01 resta research-grade (equity daily-step, margine DD ETH sottile).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- dashboard riorganizzata in 3 sezioni: ① LIVE (mainnet sola lettura) in
alto, ② TRADES ESEGUITI (reali) + frequenza operativa al centro,
③ STORICO (backtest/forward simulato) in fondo (COMBO/BOOK/FORWARD come ③·a/b/c).
- book_trade_frequency() in sleeves.py: trade/anno CONTATI sui dati certificati
(cache di modulo, una volta per processo). SKH01 round-trip BTC ~37 / ETH ~43
-> ~75/anno combinato; TP01 turnover ~7x/anno. Card "trade/anno" + blocco freq.
- fix: collisione var `pos` nel ramo shadow-online (-> shpos) che avrebbe rotto
la tabella posizioni se il conto fosse leggibile dal container.
- fix: turnover TP01 nan (disallineamento groupby) -> groupby posizionale, 7.2x/anno.
- 56 test pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New section showing the executable Deribit-only book (TP01 75% + SKH01 25%): combined
FULL/HOLD Sharpe+DD, plus the reinvest-winnings accumulation projection (historical &
conservative CAGR, €5k→5y/10y, conservative €/day run-rate). Reuses the already-computed
sleeve daily series (no extra heavy compute). Honest caveats (bull sample, no leverage,
SKH01 not live, ~€177k for €50/day).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
active_sleeves() already feeds the per-sleeve table & combined metrics, so SKH01
appears automatically. Manual touch-ups: title/docstring -> +SKH01; position label
is now sleeve-aware (the None fallback used to mislabel every pos-fn-less sleeve as
XS01's "book 19 gambe" — now XS01/SKH01/VRP01 get correct labels); footer note adds
SKH01 (quasi-orthogonal @25%, FULL Sharpe 1.68->2.13, DD 14->8%, research/forward-monitor).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Nuova sezione "FORWARD-MONITOR — lead paper (non deploy)" nel dashboard, tra PAPER e LIVE:
legge data/paper_prevday/state.json e mostra i due libri (modeled €2k nominale vs real-$600
con min-order $5), ret/maxDD di entrambi, il fill-haircut, le posizioni correnti BTC/ETH e
i giorni/flip forward. Nota esplicita: LEAD in osservazione, NON deployato.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
src/live/notifier.py (stdlib, no-op se non configurato): legge TELEGRAM_BOT_TOKEN/CHAT_ID da env o
.env(.mainnet) gitignored. live_execute.py invia alert su: ordine eseguito (✅), ordine non
verificato (⚠️), disaster-SL piazzato/fallito (🛡️/⚠️), conto offline, e qualsiasi eccezione (🛑).
Nessun alert nei giorni flat/HOLD (no rumore). Config gia' presente in .env -> alert attivi.
Test config: uv run python -m src.live.notifier "msg". Test 28/28.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lo shadow espone i bracket disaster-SL aperti (open_orders filtrati per label DISASTER_LABEL,
centralizzata in deribit.py): asset, stop price, size. La sezione LIVE li mostra
("disaster-SL attivi (-30%): ..." o "nessuno (flat)"). Test 28/28.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ensure_disaster_sl(): garantisce UN solo STOP_MARKET reduce_only a ~-30% coerente con la posizione,
ad ogni run del loop, per asset:
- flat -> cancella i bracket orfani;
- long -> assicura lo stop (size = posizione, prezzo al tick);
- gia' coerente (1 bracket, amount~=, stop entro 5%) -> lascia com'e' (niente churn ne' gap di
protezione fra cancel e place).
- deribit.py: open_orders (merge type all+trigger_all), disaster_stop_price.
- execution.py: cancel_order + ensure_disaster_sl.
- live_execute.py: gestione bracket ogni run, gated come l'esecuzione. Validato armato: flat ->
disaster-SL 'flat' (cleanup), zero ordini. Test 28/28.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
scripts/live/live_execute.py porta il conto reale al target di TP01 (min(0.5*frazione*equity,
cap/asset)): apre/riduce/chiude via DeribitTrader.rebalance_to(). DOPPIO GATE: config/live.json
execution_enabled=true (master, default false) E flag --execute; senza entrambi e' dry-run.
Reconciliation post-ordine + log in data/live/executions.jsonl. TP01 flat -> 0 azioni.
- execution.py: rebalance_to() (open/reduce/close al target); MAX_AMOUNT alzato a tetto hard
anti-fat-finger (~$630/$430 su conto ~$600), il sizing operativo lo decide config max_notional.
- config/live.json: master switch + cap/asset $300 + min ordine $5 + disaster_sl_pct.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Le sezioni erano testo grigio poco visibile e il browser cacheava la pagina ('non vedo differenza').
Ora: header PAPER con barra verde, LIVE con barra rossa + sfondo rosso-tenue (separazione netta);
risposta HTTP con Cache-Control no-cache/no-store -> niente pagina stantia.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Correzione post-micro-test (il conto e' USDC, non BTC/ETH):
- deribit.py: INSTRUMENT -> BTC/ETH_USDC-PERPETUAL (lineari, gli unici eseguibili sul conto USDC);
notional_to_amount gestisce i lineari (amount in base-coin = notional/price); + quantize_price;
trade_history (read-only) per i trade reali. build_rebalance_order passa il prezzo.
- shadow.py: sizing col prezzo; espone live_trades (trade reali eseguiti su Deribit).
Entrata/uscita verificate (logica presa da Old/src/live/execution.py):
- execution.py: open() market verificato (state=='filled' + trade, fill/fee reali, filled_amount
autorevole), close() market reduce_only (le CHIUSURE si tentano SEMPRE, senza cap), disaster-SL
STOP_MARKET reduce_only. Cap di size SOLO sulle aperture. Fill dataclass.
- microtest.py: usa open()/close(); safe-close se l'apertura non e' verificata.
Dashboard: sezione PAPER (backtest+forward) separata da sezione LIVE (conto reale Deribit: shadow
TP01 + Trades REALI eseguiti). Test 27/27.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Primo ordine reale post-reset, a rischio ~0 ($6 notional, leva 0.011x). Scoperto che il conto e'
USDC -> strumento eseguibile = perp LINEARE BTC_USDC-PERPETUAL (l'inverse BTC-PERPETUAL fallisce
'not_enough_funds'). Round-trip BUY/SELL reduce_only verificato: fill reali, fee reali (0.0064 USDC),
posizione tornata a FLAT, costo totale $0.0071.
- src/live/execution.py : DeribitTrader (estende DeribitRead) con market order + verifica posizione,
GUARDRAIL hard (solo BTC_USDC-PERPETUAL, amount <= 0.0002 BTC). Niente leva per-ordine (Deribit non
la accetta: l'esposizione la decide la SIZE).
- scripts/live/microtest.py : runner round-trip, default DRY-RUN, --live per inviare. Pre-flight ABORT
se posizione preesistente; chiusura reduce_only; verifica ritorno a FLAT.
- src/live/deribit.py : aggiunti spec contratto LINEARI USDC (BTC/ETH_USDC-PERPETUAL).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Nuova sezione "Trades TP01" nella dashboard: eventi ENTRY long / EXIT flat dedotti da
target_series sui dati certificati (data, asset, transizione di posizione, prezzo). In
src/live/shadow.tp01_trades(): account-independent (gira anche offline nel container),
ricalcolata a ogni render -> storico + forward. Empty-state se TP01 non ha mai mosso.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Validazione esecuzione di TP01 a RISCHIO ZERO: gira il loop live contro dati/conto/posizioni REALI
del mainnet, costruisce gli ordini di ribilancio esatti e li STAMPA invece di inviarli. Niente
testnet (e' la causa del reset v2.0.0: feed farlocco) -> shadow su mainnet reale + micro-test a
size minima come unica via per il fill (passo successivo).
- src/live/deribit.py : client Deribit mainnet SOLA LETTURA (ticker/conto/posizioni via Cerbero MCP)
+ costruttore ordini deterministico (notional->contratti, step BTC $10/ETH $1, quantizzazione,
delta vs posizione). Nessun metodo di trading, by design.
- src/live/shadow.py : shadow_report() condiviso CLI+dashboard (niente drift); degrada con grazia
se il mainnet non risponde.
- scripts/live/live_trend.py : CLI shadow (--no-net offline, --equity override). Verificato su
mainnet reale: conto $598.07, posizioni flat, TP01 flat -> 0 ordini, parita' col paper OK.
- src/live/dashboard.py : box "Shadow live" + titolo/note al 3-way (TP01+XS01+VRP01).
- tests/test_live_shadow.py : 9 test deterministici (quantizzazione, sizing 50/50, entry/exit/None,
parita' live==backtest). Suite 26/26.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
src/live/dashboard.py: web UI stdlib (:8787) che mostra metriche (FULL/HOLD Sharpe, DD, CAGR),
per-sleeve, posizioni correnti, equity (backtest + paper forward), ultimo dato. Solo MONITOR,
esecuzione REALE disabilitata. scripts/live/paper_portfolio.py: forward-only del portafoglio
(StrategyPortfolio su active_sleeves), stato persistente in data/paper_portfolio (gitignored).
Dockerfile + docker-compose.yml minimali (solo servizio dashboard; runner/esecuzione restano in
Old/). Container pythagoras-dashboard ricostruito col codice nuovo (il vecchio mostrava dati
pre-reset). Mount data/ read-only. .dockerignore esclude Old/data/.venv/.git/.env.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
Wire del Price Ladder come sleeve PAPER (sim-only, fuori dal pool €500, NESSUN ordine reale):
- runner: kind="grid" -> GridWorker in build_worker_for; _spec_assets_tf grid; tick branch
(w.tick(res[asset])); meccanismo PAPER_EXTRA (sleeve paper letti da overrides.paper_extra,
NON da _defs.py -> NON entrano nel backtest canonico/regression-lock: PORT06 resta 19 sleeve).
Parsing difensivo (un errore non crasha il runner mainnet). Loop dati estesi a paper_extra.
- GridWorker: bootstrap storia FULL (start fisso, come SH01) + mappatura capitale forward dal
deploy (capital = initial*eq[-1]/base_norm) -> niente salti da finestra mobile; base_norm
persistito (resume). grid_mtm robusto al df live (timestamp senza datetime; param df).
- portfolios.yml: GRID_BTC in paper_extra (regime range1.5, rd0.20/ru0.06, L6, sl0.10/tp0.03,
position_size 0.15 PINNATO). Gira in data/portfolio_paper_stats/GRID_BTC/.
Validazione (validate_grid_worker.py): [A] logica n_trades==backtest, [B] forward-tracking
esatto, [C] resume esatto. Dry-test integrazione runner: import OK, build OK, tick OK, pos 0.15.
SICUREZZA: kind=grid mai eseguito reale (runner avvia ordini solo per single/ml); €500 intatti.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Stage 1 dello shadow per il Price Ladder (config finale: BTC 1h range1.5 rd0.20 ru0.06 L6
sl0.10 tp0.03). GridWorker (src/live/grid_worker.py) gira sul feed LIVE e contabilizza
l'equity mark-to-market col motore CANONICO grid_mtm (parita' col backtest per costruzione),
SENZA piazzare ordini reali (sim/paper). Stato persistente + resume. grid_mtm esteso con
param df=None (retro-compatibile: il feed live passa il df; None = _load come prima, gate
invariato — BTC ladder 10.8/5.9, PORT06 base 8.18 identici). Validazione
validate_grid_worker.py: [A] full-tick == grid_mtm esatto, [B] replay incrementale converge
esatto, [C] resume entro la persistenza (4 dec) -> VALIDAZIONE OK.
NB SICUREZZA: nessuna modifica a runner/portfolios.yml/_defs -> il sistema mainnet (€500
reali) e' INTATTO; il worker e' inerte finche' non wirato. L'esecuzione REALE (griglia di
LIMIT resting su Deribit, fill parziali/episodi) e' lo stage 2-3, dietro testnet +
autorizzazione esplicita. Il runner avvia ordini reali solo per kind in (single,ml);
kind=grid resta sim per costruzione.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
La KPI "PnL totale" sottraeva un capitale iniziale fisso di 2000 (retaggio
testnet) -> sul micro-test mainnet da 500 mostrava -1499 (-74.95%) invece di
+0.95 (+0.19%). Nuovo helper _ledger_pnl(): legge pnl_total dall'ultima riga
di equity.jsonl (il ledger lo scrive come equity-initial_capital) e ne deriva
l'iniziale -> la dashboard combacia col ledger per costruzione, qualunque sia
il capitale (500 mainnet / 2000 testnet), niente piu' valori fissi da
aggiornare a mano. Fallback: primo punto equity, poi l'equity stessa.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Un wick transitorio fa calcolare un tp dal lato sbagliato dell'entry (donchian: segnale
su barra wickata, entry al prezzo recuperato oltre il proprio tp) -> l'exit intrabar
scatta a bars_held=0 in perdita (16-06: 8 giri MR02_BTC 15m, sim -17.9 / reale -2.3).
TP_PHANTOM non lo prende (niente resting oracle, prezzo oltre il livello). Gate
zero-parametri in StrategyWorker._open_position, solo path live. Test + diario + CLAUDE.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Piano operativo per validare l'edge su mainnet con poco denaro reale (il gate per
scalare). Fasi: smoke -> fade-only €1000 2-4 sett -> verdetto ledger-vs-backtest ->
espansione. Sizing motivato (fades €1000 = rumore arrotondamento 2.6% BTC; pairs
esclusi: 30% a quella taglia). Token ora da env CERBERO_TOKEN (default testnet
invariato) -> switch mainnet = solo .env, niente codice. is_mainnet() helper.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Nuove colonne 'Ingresso (UTC)' (entry_time) e 'In posizione' (durata dall'ingresso,
formattata m/h/g) con flag stantio. Sostituisce la colonna Eta (staleness) col
tempo di holding effettivo.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- entry/mark/unrealized SEMPRE reali (entry di esecuzione vs mark USDC live); il
feed sim/decisione (testnet inverse dislocato) non e' piu' mostrato come prezzo
- pairs: valore di mercato reale di ENTRAMBE le gambe + PnL non realizzato reale a
2 gambe (prima 'pairs (z)' senza valore)
- tabella attivi spostata subito sotto il grafico equity
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Le posizioni eseguite mostravano l'entry SIM (feed decisione testnet inverse,
dislocato ~1.3% dal lineare USDC) confrontato col mark REALE -> unrealized gonfiato
(SH01_ETH -1.36% invece di ~-0.25%) e due trade ETH con lo stesso entry sim 1661.95.
Ora entry = real_entry_price/real_entry_a se eseguito; unrealized vs mark reale su
base coerente. Indicatore '⚠sim' quando il feed di decisione diverge dal reale.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- nuovo grafico multi-linea 'Equity per famiglia' (PnL cumulato realizzato di ogni
famiglia su asse-tempo comune, colori per famiglia, legenda col totale)
- tabella strategie reali raggruppata per famiglia con intestazioni colorate +
PnL di famiglia; attive prima delle ritirate dentro ogni gruppo
- backend: fam_curves (step-wise cumulato per famiglia dai CLOSE reali), tag fam
sui trade chiusi
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Forzare l'altezza del canvas via CSS !important con maintainAspectRatio default
sfalsava la risoluzione interna vs quella mostrata -> hit-test tooltip offset dal
mouse. Fix canonico: canvas in contenitore .chartbox ad altezza fissa + chart
responsive:true/maintainAspectRatio:false + interaction index su tutti e 3 i grafici
(equity, modal, paper).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
I 4 multi-asset (TR01/ROT02/TSM01/XS01, solo statistica fuori dal pool reale) ora
in una zona dedicata con la PROPRIA equity (capitale nozionale + PnL cumulato del
book paper) e tabella separata. La tabella/fam_pnl/closed dell'area principale
diventano SOLO reali. Curva paper Chart.js (ocra), cliccabile -> stesso modal.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- click su una strategia -> modal con descrizione, versione di creazione/modifica,
curva PnL CUMULATO reale vs sim (mostra il leakage), trade, e link alla scheda
dettagliata strategie_attive.html (servita, docs/report montato ro)
- versione di sistema (APP_VERSION) nell'header; per ogni strategia la versione/
origine documentata (mappa VERSIONS da CLAUDE.md)
- equity restyling: gradiente verde/rosso secondo segno, tooltip con EUR e delta,
valore+delta in testata, assi in EUR, piu' alto. /api/strategy con guard
path-traversal.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Le fade 1h sostituite dallo swap 15m sono marcate RITIRATA→15m (rilevate per
status.json stantio >30min, ordinate in fondo, riga barrata). Descrizioni concise
per ogni strategia (da strategie_attive.html) come tooltip + sezione legenda.
Fix rilevazione paper: per directory (portfolio_paper_stats), non per chiave
'weights' (TR01/TSM01/XS01 non ce l'hanno) -> ora i 4 multi-asset sono paper.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Server stdlib http.server (zero dipendenze nuove) che legge data/: KPI equity/PnL/DD,
grafico equity (Chart.js CDN + fallback), PnL per-strategia (barre, realizzato reale),
trade attivi in TEMPO REALE (mark Cerbero best-effort, PnL non realizzato, barre, eta
stantio) e chiusi (ultimi 50). Servizio docker-compose 'dashboard' porta 8787, stessa
immagine, monta data/, restart unless-stopped + healthcheck. Nessuna auth -> rete interna.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Worker nuovo (no status.json) eredita capital/real_capital dal gemello piu'
recente stessa strategia+asset (mai la posizione): niente piu' seed manuale
al prossimo swap. 3 test nuovi, suite 129 passed.
Ricerca: gate 10m ADD bocciato (OOS Sh 10.86->10.76, watchlist chiusa);
XSEC breadth 8->14 Deribit BOCCIATO (gambe flat 91-99% corrompono il ranking)
ma promettente su dati HL reali (-6%->+9% stessa finestra) -> sblocco = routing
dati Hyperliquid quando la storia sara' sufficiente.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
7 finder paralleli sul diff della giornata (8adf388..HEAD), fix dei confermati:
CRITICI (money-path):
- close_amount: GUARD stato-stantio sul fallback netting — il residuo
non-reduce-only e' consentito solo fino al gap (conto reale - libri degli
altri worker - orfani) nella direzione della chiusura (src/live/books.py =
fonte unica, usata anche dal reconciler). Senza guard, un close su stato
stantio (DSL scattato in outage, flatten manuale) APRIVA una posizione nuda
a taglia piena bookata come 'chiusura verificata'. Fail-safe se il gap non
e' calcolabile. Check polvere PRIMA di _quantize_step (che clampa al lotto
minimo: un residuo 1e-17 diventava un ordine nudo da un lotto).
- _real_close: market_amt = filled_amount anche a merged verified=False (i
contratti chiusi dal reduce-only non si buttano se il leg netting fallisce);
REAL_CLOSE_PARTIAL non piu' gateato su verified (era soppresso proprio nel
caso parziale reale).
- pairs: verita' per-FRAZIONE di gamba (gross proporzionale al fillato, orfano
= solo il residuo — prima falsava reconciler e real_capital della parte gia'
chiusa); REAL_OPEN_PAIR booka filled_amount; docstring applied corretta.
- open_pair unwind: chiude il FILLATO, non il richiesto (senza il cap silenzioso
del reduce-only avrebbe mangiato quota altrui).
- place_tp_limit: quantize CONSERVATIVO (sell=floor/buy=ceil) — il rounding al
tick piu' vicino poteva mettere il resting oltre il TP sim -> tocco genuino
classificato phantom sistematicamente.
ROBUSTEZZA/OSSERVABILITA':
- runner: WORKER_ERROR_STREAK a 5 e poi ogni 50 poll + recovery RIPRESO +
flag real_in_position nell'alert (prima: one-shot a n==5, poi silenzio).
- _tp_phantom: TTL 120s sul verdetto (era ~50 HTTP/h per worker a barra
fantasma); merge notes con entrambi gli order_id (audit-trail).
- reset_flatten: _quantize_step Decimal (round float produceva amount che
Deribit rifiuta); hourly_report: book XS01 con gambe SHORT visibili (abs).
- validate_xsec_worker: POS/LEV importati (non hardcoded); xs01_tranche:
regression-lock ESEGUITO vs xsec_sim; reconcile su src/live/books;
drift_monitor: rolling vettoriale + exit code 1 su warn.
Test: +4 guard/dust, fixture filled_amount -> 114 passed.
Deferiti (TODO): resting esposti al netting, lifecycle orphan_legs, finestra
trade-history TP_PHANTOM, validazione feed a monte, dedup minori.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
close_amount ora: (1) tenta il market reduce-only (sicurezza storica: un bug di
stato filla 0 invece di aprire posizioni); (2) il residuo cappato/respinto dal
netting di conto (worker in direzioni opposte sullo stesso strumento) viene
rieseguito in MARKET PURO con label '|net' — muove il conto esattamente del
delta del libro = netta contro le quote opposte. Niente piu' gambe pairs orfane
ne' close cappati per costruzione (close_pair passa da close_amount).
- _merge_close_fills: il chiamante riceve UN Fill (prezzo medio pesato sui fill,
fee sommate, filled_amount totale, verified se copre il richiesto, notes
'netting' quando il fallback scatta)
- worker single-leg + pairs: evento NET_CLOSE (log jsonl + Telegram) a ogni
fallback — osservabilita' della frequenza dei conflitti di netting
- sicurezza persa sul residuo coperta dal reconciler orario (ACCOUNT_DRIFT);
orphan_legs/REAL_CLOSE_PARTIAL restano come ultima difesa
- 4 test nuovi (full r-o senza fallback, cappato, respinto, doppio fail) -> 110 passed
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Da audit live (3 indagini parallele, diario 2026-06-11-system-audit.md): il modello
quote-per-worker reduce-only si rompe con direzioni opposte sullo stesso strumento
(pairs long ETH vs fade short ETH) — close cappati bookati pieni, 3 gambe pairs mai
eseguite col PnL sim nel ledger reale, conto short 0.027 ETH oltre i libri
(riallineato a mano + DSL orfano cancellato).
- Fill.filled_amount (order.filled_amount): TUTTI i ledger usano il fillato reale
- REAL_CLOSE_PARTIAL (log+alert) su close cappato; residuo orfano dichiarato
- pairs: PnL solo per gambe verificate; gamba respinta -> orphan_legs persistito
+ alert PAIR_LEG_ORPHAN; applied solo con entrambe le gambe (else sim_fallback)
- REAL_DIVERGENCE anche su jsonl (prima solo Telegram)
- runner: tick isolato per-worker + WORKER_ERROR_STREAK a 5 fail consecutivi
Strutturale APERTO (decisione utente, opzioni nel diario): position-manager
centrale / sotto-conti per famiglia / status-quo monitorato.
Test: +2 (partial-close, orphan-leg), fixture filled_amount -> 106 passed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Il feed testnet stampa wick che 'toccano' il TP intrabar senza che il prezzo
abbia mai scambiato al livello: il sim bookava +4% fantasma a bars_held=0 e
_real_close chiudeva A MERCATO una posizione col resting TP a zero fill
(-fee/spread a giro, 14 giri l'11-06). Ora StrategyWorker._tp_phantom sopprime
l'exit take_profit quando: tocco sim + resting LIMIT zero-fill + prezzo corrente
che non ha raggiunto il livello (il limit sul book reale e' l'oracolo del tocco).
Zero parametri (verita' d'esecuzione, non filtro di strategia); SL close-confirm
e max_bars restano attivi nello stesso tick; fill parziale/prezzo oltre il
livello/worker non eseguito/errore rete -> comportamento storico. Log TP_PHANTOM
dedup per barra + alert Telegram una tantum. 5 test nuovi (104 passed).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Audit anti-overfit su tutte le 19 sleeve (diario 2026-06-11-stability-sweep.md):
- FIX BasketTrendWorker: mean(rets) sui soli asset in posizione sovrappesava N/k
a paniere parziale (1 long = 0.45 del capitale invece di 0.09) -> replay -44%
vs ref +42%. Ora sum(rets)/N (convenzione canonica 1/N): replay +32% vs +42%
(residuo = convenzione dichiarata). Solo statistica PAPER.
- XS01 PHASE-TRANCHING (gate xs01_tranche_gate: plateau K=2 E K=3 promossi,
PORT06 OOS Sh 10.07->10.15 DD 1.48->1.38, FULL pari): la fase del roll e'
timing-luck (Sharpe daily 1.52-2.33, DD 13.8-33% sulle 12 fasi). Worker con
param tranches (default 1), 3 sub-book sfasati hold/3 su capitale comune,
migrazione status legacy, last_bar_ts solo-avanti; runner forward del param;
_defs tranches=3; hourly_report aggrega i sub-book; validatore esteso e
PASSATO (K=1 == xsec_sim esatto, K=3 == unione fasi esatto).
- Disaster-cap z sui pairs: pre-registrato e BOCCIATO su tutti i criteri (coda
OOS peggiora 4/6 coppie, Sharpe -10..-49%, plateau solo del danno; 5a conferma
stop-su-MR). Record pairs_zstop_research.py; pairs restano senza stop.
- Audit drift: regression-lock trendmax OK (parita' 1.00000, plateau 2.5/3.0/3.5
confermato), correlazioni cross-famiglia ~0 invariate; PORT06 rolling al
19-28mo pct (normale) ma FADE 120g al 2o percentile storico -> monitor in TODO
(nessun ritocco parametri).
- TODO: forming-bar ROT02/TSM01 era gia' fixato (v1.1.10), item chiuso.
Test: pytest 99 passed; validate_honest_workers OK; validate_xsec_worker OK.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>