#!/usr/bin/env python """r0831_margini_conto.py — riconcilia la pagina margini del conto. Riproduce due numeri. PERCHE'. Due domande erano rimaste aperte e nessuna era rispondibile dal gateway (debito #11: `account_summary` filtrato a 8 campi, niente initial_margin, `extended` ignorato): 1. l'HAIRCUT sull'USDe: la KB ufficiale dice 5%, `config/live.json` diceva 10% "verificato sul venue il 26/08" senza traccia di come; 2. quale MODELLO DI MARGINE e' attivo — che nessuno aveva mai chiesto. Lo screenshot della pagina `Standard Margin` (2026-08-31 07:50:30 UTC, fornito dall'operatore) le chiude entrambe. Qui la riconciliazione, perche' un numero pubblicato deve avere uno script che lo riproduce (N11) e perche' l'haircut non si legge nella pagina: si RICAVA per differenza fra due righe, ed e' un conto che va mostrato invece che asserito. uv run python scripts/research/r0831_margini_conto.py """ from __future__ import annotations # --- dalla schermata (2026-08-31 07:50:30 UTC) --- SEG_USDC = 1400.86 # S:SM (ATTIVO) -> riga USDC, Available Balance. USDE NON e' in tabella. CROSS_XSM = 2011.73 # X:SM -> riga CROSS, Available Balance PX_INDICE = 0.9998 # prezzo mostrato in cima alla pagina # --- dal conto, letti via gateway alle ~07:55 dello stesso giorno --- USDC_EQ = 1412.281074 USDE_EQ = 643.175691 IM_MIS = 11.5530 # riservato in USDC = equity - available (misurato) ETH_DUST_USD = 0.000078 * 2500 # riga ETH della schermata, ~$0.20 TOLL = 2.0 # $: sotto questo scarto due ipotesi non si distinguono def haircut_implicito(cross: float, usdc: float, eth_dust: float, im: float, usde: float, px: float) -> tuple[float, float]: """PURA. -> (contributo dell'USDE al cross in USD, haircut implicito). L'haircut non e' scritto da nessuna parte nella pagina: si ricava perche' il CROSS conta l'USDE scontato e il SEGREGATO non lo conta affatto. La differenza fra le due righe, tolto cio' che e' comune, E' il contributo dell'USDE.""" contributo = cross - (usdc + eth_dust - im) return contributo, 1.0 - contributo / (usde * px) def main() -> int: print("=" * 78) print(" PAGINA MARGINI — riconciliazione (screenshot 2026-08-31 07:50:30Z)") print("=" * 78) atteso_seg = USDC_EQ - IM_MIS print(f"\n [1] S:SM, il modello ATTIVO — solo il silo USDC") print(f" USDC equity {USDC_EQ:,.2f} - IM {IM_MIS:,.2f} = {atteso_seg:,.2f}" f" schermata {SEG_USDC:,.2f} scarto ${abs(atteso_seg-SEG_USDC):.2f}") print(f" → l'USDE non compare in questa tabella: nel modello attivo NON fa margine.") contrib, h = haircut_implicito(CROSS_XSM, USDC_EQ, ETH_DUST_USD, IM_MIS, USDE_EQ, PX_INDICE) print(f"\n [2] X:SM — l'haircut si RICAVA per differenza") print(f" contributo USDE al cross = ${contrib:,.2f} su ${USDE_EQ*PX_INDICE:,.2f} di valore") print(f" → haircut implicito {h:.4%}") for cand, nome in ((0.05, "KB ufficiale"), (0.10, "config al 30/08")): att = USDE_EQ * PX_INDICE * (1 - cand) ok = abs(att - contrib) < TOLL print(f" {cand:.0%} ({nome:16s}) → atteso ${att:,.2f}, scarto ${abs(att-contrib):6.2f}" f" {'TORNA' if ok else 'NON torna'}") verdetto_h = "5%" if abs(USDE_EQ*PX_INDICE*0.95 - contrib) < TOLL else "indeterminato" delta_modelli = CROSS_XSM - SEG_USDC print(f"\n VERDETTO (calcolato a runtime, N11):") print(f" haircut USDe = {verdetto_h} → `config/live.json` diceva 10%: SBAGLIATO") print(f" modello attivo = SEGREGATO (S:SM) → l'USDE non e' collaterale del book") print(f" passare a X:SM aggiungerebbe ${delta_modelli:,.2f} di margine utilizzabile") print(f"\n{'=' * 78}") live() return 0 # --- 2026-08-31 08:34Z: X:SM e' ATTIVO. La pagina non serve piu': si RICOSTRUISCE. -------------- # # L'operatore ha incollato la riga CROSS a X:SM attivo: Available $2.010,81, IM 2,15%, MM 0,37%. # Il gateway, letto allo stesso minuto, dice `available_funds` = 2010.82299383 — **scarto $0,01**. # ⇒ la riga CROSS della pagina E' `available_funds`, che leggiamo da soli. Lo screenshot che ieri # era l'unica fonte per l'haircut e per il modello attivo NON e' piu' necessario a nulla. PAG_AVAIL, PAG_IM_PCT, PAG_MM_PCT = 2010.81, 0.0215, 0.0037 # incollati dall'operatore, 08:34Z GW_AVAIL, GW_MB = 2010.82299383, 2055.07348077 # gateway, stesso minuto GW_USDC_EQ, GW_USDE = 1400.70809113, 654.175691 XPM_AVAIL = 1935.14 # riga X:PM della schermata delle 07:50 (proiezione, modello inattivo) def im_di_posizione(avail: float, usdc_eq: float, usde: float, px: float, h: float, dust: float = ETH_DUST_USD) -> float: """PURA. -> IM di POSIZIONE in USD, ripulita dall'haircut. Inversa esatta della riga CROSS: available = usdc_eq + (1-h)*usde*px + dust - IM. Serve perche' la percentuale stampata dalla pagina NON e' questa (vedi live()).""" return usdc_eq + (1 - h) * usde * px + dust - avail def live() -> None: print(" X:SM ATTIVO (2026-08-31 08:34Z) — la pagina si ricostruisce dal gateway") print("=" * 78) ric = GW_USDC_EQ + 0.95 * GW_USDE + ETH_DUST_USD - IM_MIS print(f"\n [3] la riga CROSS, ricostruita con haircut 5%") print(f" {GW_USDC_EQ:,.2f} + 0,95x{GW_USDE:,.3f} + {ETH_DUST_USD:.2f} dust" f" - {IM_MIS:.3f} IM = ${ric:,.2f}") print(f" pagina ${PAG_AVAIL:,.2f} · gateway ${GW_AVAIL:,.2f} → scarto ${abs(ric-PAG_AVAIL):.4f}") for h in (0.05, 0.10): im = im_di_posizione(GW_AVAIL, GW_USDC_EQ, GW_USDE, 1.0, h) print(f" haircut {h:5.0%} → IM implicita ${im:9,.2f}" f" {'coerente con gli $11,55 misurati' if im > 0 else 'IMPOSSIBILE: IM negativa'}") print(" → terza conferma del 5%, ed e' la prima ESATTA. Il 10% non e' improbabile:" "\n e' aritmeticamente impossibile.") riserv = GW_MB - GW_AVAIL hc = 0.05 * GW_USDE print(f"\n [4] 🚨 l'\"IM %\" della pagina NON e' il margine delle posizioni") print(f" (margin_balance - available)/margin_balance = {riserv/GW_MB:.4%}" f" → la pagina stampa {PAG_IM_PCT:.2%}") print(f" scomposta: haircut USDE ${hc:,.2f} ({hc/GW_MB:.3%})" f" + IM vera ${IM_MIS:,.2f} ({IM_MIS/GW_MB:.3%})") print(f" ⇒ il {hc/riserv:.0%} di quella percentuale e' HAIRCUT, non rischio.") print(f" E' salita da 2,13% a 2,15% perche' abbiamo COMPRATO COLLATERALE A RENDIMENTO.") print(f" La MM invece e' pulita: {PAG_MM_PCT:.2%} = ${PAG_MM_PCT*GW_MB:,.2f}, e non puo'" f" contenere\n l'haircut (${hc:,.2f} da solo la renderebbe negativa):" " le due colonne hanno basi DIVERSE.") print(f"\n [5] X:PM — il confronto rifatto sulla misura pulita") print(f" La KB da' USDe al 5% sotto ENTRAMBI i modelli: l'haircut si CANCELLA nel confronto.") for nome, av in (("X:SM", CROSS_XSM), ("X:PM", XPM_AVAIL)): im = im_di_posizione(av, USDC_EQ, USDE_EQ, PX_INDICE, 0.05) print(f" {nome}: available ${av:,.2f} → IM di POSIZIONE ${im:6,.2f}") im_sm = im_di_posizione(CROSS_XSM, USDC_EQ, USDE_EQ, PX_INDICE, 0.05) im_pm = im_di_posizione(XPM_AVAIL, USDC_EQ, USDE_EQ, PX_INDICE, 0.05) print(f" → PM chiede {im_pm/im_sm:.1f}x il margine iniziale sulle STESSE due posizioni," f"\n e {0.0343/PAG_MM_PCT:.1f}x la MM. Due misure pulite, stesso verso: SCARTATO confermato.") if __name__ == "__main__": raise SystemExit(main())