Files
PythagorasGoal/docs/diary/2026-06-11-system-audit.md
T
Adriano Dal Pastro 844a9d0e22 feat(exec): netting delle chiusure market — il residuo reduce-only cappato/respinto va in market puro
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>
2026-06-11 20:54:43 +00:00

93 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.