Files
PythagorasGoal/docs/diary/2026-06-12-resting-reconcile-feedgap.md
T
2026-06-12 12:24:37 +00:00

4.2 KiB
Raw Blame History

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:3217: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.