844a9d0e22
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>
93 lines
5.8 KiB
Markdown
93 lines
5.8 KiB
Markdown
# 2026-06-11 — Audit di sistema + verità contabile sul netting (v1.1.24)
|
||
|
||
Seconda tornata della giornata (dopo lo sweep strategie): analisi del SISTEMA live
|
||
(esecuzione, stato, feed, processo) con 3 indagini parallele + fix.
|
||
|
||
## Audit live (dal reset 2026-06-10T21:24Z)
|
||
|
||
- **Churn phantom-TP quantificato**: 20 round-trip fantasma sui fade ETH (2 finestre,
|
||
13:06Z e 17:32-17:58Z, feed che stampava wick ~1640 con mercato a 1675-90 per 25 min).
|
||
Somma real_pnl −2.35 USD vs sim_pnl +80 USD: il real-truth ledger ha contenuto, il gate
|
||
TP_PHANTOM (v1.1.23) copre il pattern da stasera.
|
||
- **Il conto NON quadrava coi libri**: short 0.027 ETH in più (l'hedge long ETH del pair
|
||
ETH/SOL mangiato dai close reduce-only dei fade) e BTC flat con MR02_BTC convinto di
|
||
essere short (TP resting fillato da uno spike REALE del book a −3.8%, +6.6$ non bookati,
|
||
che il worker riconcilierà alla chiusura sim) col **disaster-SL residuo sul book a
|
||
posizione flat**. Bonifica eseguita: DSL `USDC-SLMB-26521` cancellato, riallineo
|
||
+0.027 ETH reduce-only (fill 1682.5) → conto == libri (verificato).
|
||
|
||
## Root-cause strutturale
|
||
|
||
Le **quote per-worker con ordini reduce-only su un conto a NETTING si rompono quando due
|
||
worker hanno direzioni opposte sullo stesso strumento** (pairs long ETH vs fade short ETH):
|
||
- un close reduce-only può essere **cappato** (Deribit riduce l'amount in silenzio) → il
|
||
ledger bookava la chiusura PIENA perché `Fill.amount` era il richiesto, non il fillato;
|
||
- un close reduce-only nel verso "sbagliato" rispetto al netto viene **respinto** → la
|
||
gamba pairs resta orfana sul conto, ma il worker bookava il PnL al prezzo sim e azzerava
|
||
lo stato (3 volte oggi: PnL fantasma nel ledger real-truth, ETH/SOL di fatto short nudo).
|
||
|
||
## Fix (v1.1.24) — verità, non workaround
|
||
|
||
1. **`Fill.filled_amount`** (da `order.filled_amount`, fallback trades/history): tutti i
|
||
ledger usano il fillato; nota "FILL PARZIALE" nel Fill.
|
||
2. **`REAL_CLOSE_PARTIAL`** (log + Telegram): close che filla meno del residuo → residuo
|
||
orfano dichiarato, `REAL_CLOSE verified=false`.
|
||
3. **Pairs per-gamba**: PnL bookato SOLO per gambe con fill verificato; gamba respinta →
|
||
record in `orphan_legs` (persistito nello status) + alert `PAIR_LEG_ORPHAN`;
|
||
`applied=True` (real-truth) solo con ENTRAMBE le gambe → altrimenti fallback sim
|
||
DICHIARATO (meglio del numero mezzo-reale di prima).
|
||
4. **`REAL_DIVERGENCE` anche su jsonl** (prima solo Telegram: l'audit ha dovuto
|
||
ricostruire gli episodi dai REAL_CLOSE).
|
||
5. **Runner: tick isolato per-worker** — un'eccezione in un worker non salta più gli
|
||
altri né l'update equity; streak per-worker con alert `WORKER_ERROR_STREAK` a 5.
|
||
|
||
Test: 2 nuovi (partial-close, orphan-leg) + fixture aggiornate → 106 passed.
|
||
|
||
## Decisione di design APERTA (per l'utente)
|
||
|
||
Finché pairs e fade condividono strumenti in direzioni opposte, le chiusure possono
|
||
orfanizzarsi: ora è VISIBILE e contabilizzato giusto, ma non eliminato. Opzioni:
|
||
A) **Position-manager centrale per strumento** (il runner netta i delta di tutti i
|
||
worker e manda UN ordine; ricostruisce le quote contabilmente) — corretto ma
|
||
invasivo, da progettare con calma;
|
||
B) **Sotto-conti Deribit separati** per famiglia (pairs vs fade) — pulito, richiede
|
||
setup conto e client multi-token;
|
||
C) **Status quo monitorato**: alert PAIR_LEG_ORPHAN + riallineo manuale (oggi: 1 giro
|
||
in 2 minuti) — accettabile su testnet, NON per capitale vero.
|
||
Raccomandazione: C ora, A prima di passare a capitale reale.
|
||
|
||
**Secondo passo — FATTO (v1.1.25): NETTING delle chiusure market.** `close_amount`
|
||
tenta il reduce-only e riesegue il residuo cappato/respinto in market puro (= il
|
||
netting contro le quote opposte: il conto si muove del delta esatto del libro).
|
||
Un solo punto di fix (anche `close_pair` ci passa). Fill combinato per il chiamante
|
||
(prezzo pesato, fee sommate), evento `NET_CLOSE` su log+Telegram a ogni fallback,
|
||
4 test dedicati. Niente più orfani per costruzione; `orphan_legs` resta come ultima
|
||
difesa se fallisce anche il market puro. Effetto collaterale benefico: la chiusura
|
||
futura della gamba ETH di ETH_SOL#2 (che sarebbe stata respinta di nuovo) ora
|
||
eseguirà correttamente. La scelta A-vs-B-vs-C resta aperta solo per la parte
|
||
RESTING (TP/DSL su book condiviso) e per i multi-asset.
|
||
|
||
**Primo passo verso A — FATTO (sera stessa): reconciler read-only.**
|
||
`scripts/analysis/reconcile_account.py`: per ogni strumento USDC confronta
|
||
atteso (Σ quote reali dai status.json: single-leg + pairs 2 gambe + orphan_legs
|
||
registrati = drift SPIEGATO) vs conto reale (`get_positions`, size/mark → coin),
|
||
tolleranza 1.5×step, anti-race (ricontrollo a 10s prima di segnalare). In crontab
|
||
host ORARIO (:40) con alert Telegram `ACCOUNT_DRIFT`. Al primo run ha beccato un
|
||
vero positivo: BTC libro short 0.0028 vs conto flat (il TP di MR02_BTC fillato
|
||
dallo spike reale delle 12:22Z, che il worker riconcilierà alla chiusura sim) —
|
||
esattamente la classe di divergenza che prima restava invisibile per ore.
|
||
|
||
## Altri esiti della tornata
|
||
|
||
- **Dedup engine gate** (TODO chiuso): `_port06_gate_common.py`, output 3 gate
|
||
byte-identici, nessun copy-drift trovato (la paura era fondata ma non ancora avverata).
|
||
- **Bug bfill `_daily_equity` quantificato** (TODO aggiornato): NON materiale — OOS
|
||
invariato per costruzione, FULL DD 3.46→3.67 col fix (l'attuale è lievemente ottimista),
|
||
nessun verdetto di gate a rischio. Lasciato documentato.
|
||
- **Drift monitor in produzione**: `drift_monitor.py` in crontab host (07:15 UTC,
|
||
Telegram): rolling 60/120g per famiglia vs distribuzione storica propria, warn < p5.
|
||
Oggi: FADE 120g al p2 (coda storica, nessun intervento), resto normale, XSEC p84.
|
||
- **Dati cerbero-bite refreshati**: catena opzioni a ~153k righe/asset (fino a oggi
|
||
19:30), pannello regime denso (net-GEX 644/673 ultimi 7g). Sempre un solo regime:
|
||
niente validazione edge, valore forward.
|