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:
@@ -0,0 +1,108 @@
|
||||
# 2026-06-12 — Reconcile resting + guard feed↔book + epoca report (v1.1.27)
|
||||
|
||||
## Contesto: la notte ha validato (di nuovo) il tema osservabilità
|
||||
|
||||
Due eventi nelle 24h hanno motivato la tornata:
|
||||
|
||||
1. **MR02_BTC (06:00):** il TP resting LIMIT ha fillato sul **book reale** a 60481
|
||||
nella notte (+6.55 USD reali) mentre il **feed sim** non è mai sceso sotto 63285
|
||||
(−443 bps di divergenza, sim chiuso a time_limit con −1.25). Il disaster-SL è
|
||||
risultato `order_not_found` alla cancel (probabile auto-cancel a posizione flat).
|
||||
Caso SPECULARE del TP_PHANTOM: lì il feed stampa wick che il book non ha; qui il
|
||||
book si muove e il feed non lo vede. Real-truth ha bookato il reale (corretto),
|
||||
ma il sistema se n'è accorto solo ORE dopo, al close sim.
|
||||
2. **Incidente venue (dalle ~09:47):** il conto Deribit testnet ha iniziato a
|
||||
rifiutare ordini (`locked_by_admin`, `invalid_reduce_only_order`) e le posizioni
|
||||
sul conto sono cambiate da sole (ETH LONG 0.141 con avg 1849.5 — prezzo vecchio
|
||||
di settimane): **rollback/reset admin del testnet**, non un nostro bug. Difese OK:
|
||||
`REAL_CLOSE_PARTIAL`, leg-fail con unwind, orfani registrati (ETH −0.026,
|
||||
SOL +0.7), `sim_fallback` dichiarato. MA: il reconciler delle 11:40 è **morto in
|
||||
silenzio** su un 502 — il guardiano che non suona è indistinguibile dal tutto-ok.
|
||||
|
||||
## Fatto
|
||||
|
||||
### 1. Reconcile degli ordini RESTING (cron :40, read-only)
|
||||
|
||||
- **cerbero-mcp 9a74052:** nuovo endpoint Deribit `get_open_orders`
|
||||
(`private/get_open_orders_by_currency`; per i trigger untriggered interrogare
|
||||
anche `type='trigger_all'` e merge per order_id). Pattern già presente per
|
||||
Hyperliquid/IBKR. Rebuild + smoke su testnet (book vuoto == stato atteso).
|
||||
- **`books.expected_resting()`:** TP/DSL attesi dai libri dei worker single-leg
|
||||
in posizione reale (i pairs non hanno resting).
|
||||
- **`reconcile_account.compute_resting_drift()`** — tre classi:
|
||||
`FILLED_UNBOOKED` (atteso non in book + fill nel trade history col worker ancora
|
||||
in posizione = il caso MR02), `MISSING` (atteso, non in book, zero fill — per il
|
||||
DSL triggered il fill ha order_id NUOVO → appare qui e il drift posizioni
|
||||
completa), `STALE` (in book con label di un nostro worker ma nessun libro:
|
||||
fillerebbe a sorpresa). Anti-race come per le posizioni; alert `RESTING_DRIFT`.
|
||||
- **`RECONCILE_FAIL`:** il main è ora guardato — su eccezione alert Telegram +
|
||||
exit 2 (fix del crash silenzioso delle 11:40).
|
||||
|
||||
### 2. Guard FEED_BOOK_GAP nel runner
|
||||
|
||||
`_check_feed_book_gap`: ad ogni poll confronta il close della candela in corso col
|
||||
**mark dello strumento d'ESECUZIONE** (USDC, `get_ticker_batch`, 1 chiamata);
|
||||
oltre soglia (`overrides.feed_book_gap_bps`, default 150) → alert per episodio,
|
||||
recovery con isteresi a soglia/2, fail-open su errori di rete. Le decisioni
|
||||
restano sul feed (il sim è la verità che guida): questo dice solo QUANDO i fill
|
||||
reali possono divergere dal sim. Avrebbe segnalato il caso MR02 in tempo reale.
|
||||
|
||||
### 3. Epoca v1.1.26 nell'hourly_report
|
||||
|
||||
I conteggi CHIUSI cumulativi erano inquinati dal churn TP-fantasma dell'11-06
|
||||
17:32–17:58 (~24 giri pre-fix). Nuova riga `epoca v1.1.26+ (TP_PHANTOM attivo)`
|
||||
da `EPOCH_V1126 = 2026-06-11T21:40` (deploy del gate): oggi legge **7/1** contro
|
||||
il 18/17 storico — è il numero da confrontare col backtest da qui in poi.
|
||||
|
||||
## Test e deploy
|
||||
|
||||
`pytest` 121 passed (114 + 7 nuovi: `test_reconcile_resting.py`,
|
||||
`test_feed_book_gap.py`). Deploy **v1.1.27** (runner nel container; reconciler e
|
||||
hourly_report girano da host → già attivi). cerbero-mcp rebuildato (endpoint).
|
||||
|
||||
## Aperto / lezioni
|
||||
|
||||
- **Drift ETH +0.167 non spiegato** dal rollback testnet: quando il conto si
|
||||
sblocca serve `reset_flatten` + riallineamento ledger (decisione utente).
|
||||
- I **residui dei close single-leg falliti** (`REAL_CLOSE_PARTIAL`, es. MR07
|
||||
0.102) NON finiscono in `orphan_legs` → il reconciler li vede come drift NON
|
||||
spiegato. Estendere la registrazione orfani anche al single-leg è il naturale
|
||||
passo successivo (punto in analisi sviluppi).
|
||||
- Il testnet può **riscrivere il conto sotto i piedi** (lock + rollback): nessuna
|
||||
invariante "il conto cambia solo per nostri ordini" è affidabile. Il reconciler
|
||||
orario è l'unico rilevatore; valutare cadenza più fitta in presenza di
|
||||
posizioni reali aperte.
|
||||
|
||||
## Addendum (pomeriggio, v1.1.28): orfani single-leg + circuit-breaker venue-lock
|
||||
|
||||
I due punti promossi dall'analisi sviluppi, entrambi figli dell'incidente di oggi:
|
||||
|
||||
1. **Orfani anche per i close single-leg.** `REAL_CLOSE_PARTIAL` ora registra la
|
||||
quota residua in `StrategyWorker.orphan_legs` (stessa semantica dei pairs,
|
||||
persistita in status.json, letta da `books.real_books`) → il reconciler vede
|
||||
il drift come SPIEGATO invece che anomalo (il caso MR07 0.102 ETH delle 09:47
|
||||
restava invisibile ai libri). Inoltre `_close_position` ora persiste lo stato
|
||||
a fine booking (prima solo al save del tick: un crash li' in mezzo perdeva
|
||||
capital e orfano). NB: nessun save a meta' chiusura — con `real_in_position`
|
||||
ancora true l'orfano conterebbe doppio nei libri.
|
||||
2. **Circuit-breaker venue-lock in `ExecutionClient`.** Dopo `lock_trip=3` reject
|
||||
'locked' consecutivi (es. `locked_by_admin` di oggi) le APERTURE sono sospese
|
||||
senza toccare l'API (Fill failed → path REAL_OPEN_FAIL/sim_fallback esistente;
|
||||
per i pairs entrambe le gambe rifiutate localmente → niente leg parziali da
|
||||
unwindare, niente fee sprecate). Le CHIUSURE si tentano SEMPRE (path gia'
|
||||
sicuro: partial/orphan/netting) e un loro reject 'locked' rinfresca il
|
||||
cooldown. Riarmo: dopo `lock_cooldown_s=900` la prossima apertura fa da probe.
|
||||
Alert `VENUE_LOCK` al trip + RIENTRATO al primo ordine accettato.
|
||||
|
||||
Test: `test_single_leg_orphan.py`, `test_venue_lock_breaker.py` (126 passed).
|
||||
|
||||
## Chiusura incidente (13:05): testnet sbloccato, conto riallineato
|
||||
|
||||
Sequenza eseguita a venue sbloccato: stop runner → `reset_flatten` (chiusi i due
|
||||
artefatti del rollback: ETH long 0.141 @1664.25, SOL long 0.7 @66.651, conto FLAT)
|
||||
→ svuotati gli `orphan_legs` di ETH_SOL (le quote orfane non esistono piu' sul
|
||||
conto post-flatten; edit a container fermo, altrimenti il worker li riscrive
|
||||
dalla memoria) → restart. **Reconciler: OK — conto allineato ai libri** (posizioni
|
||||
e resting), runner healthy, log puliti. Il ledger NON e' stato toccato: i booking
|
||||
dell'incidente erano gia' dichiarati (`sim_fallback`/real) e l'equity (€2020.82)
|
||||
resta la verita' contabile del paper.
|
||||
Reference in New Issue
Block a user