From fd7595e8194e26d648ac9284d5345eb721756316 Mon Sep 17 00:00:00 2001 From: Adriano Dal Pastro Date: Mon, 31 Aug 2026 08:01:21 +0000 Subject: [PATCH] =?UTF-8?q?margini:=20haircut=205%=20(la=20config=20aveva?= =?UTF-8?q?=20torto)=20=E2=80=94=20e=20il=20conto=20NON=20e'=20cross-colla?= =?UTF-8?q?teral?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lo screenshot della pagina margini era su Wasabi (rclone remote wasabi:, bucket adp-work, cartella _scambio), non sulla VPS: per questo il percorso non esisteva. Riconciliazione riproducibile in scripts/research/r0831_margini_conto.py (N11). (a) HAIRCUT = 5%. La pagina non lo espone come numero: si ricava per differenza, perche' il CROSS conta l'USDE scontato e il SEGREGATO non lo conta affatto. S:SM (attivo) USDC Available 1.400,86 vs equity 1.412,28 - IM 11,55 = 1.400,73 X:SM CROSS Available 2.011,73 contributo USDE al cross = $610,81 su $643,05 -> 5,0137% 5% (KB) atteso $610,89 scarto $ 0,09 TORNA 10% (nostra) atteso $578,74 scarto $32,06 NON torna config/live.json: haircut 0.10 -> 0.05. Il 26/08 il 10% fu registrato come "verificato sul venue" senza traccia di COME, e non lo era. (b) 🚨 IL CONTO NON E' CROSS-COLLATERAL: modello attivo "Segregated: Standard Margin" (S:SM). Nella tabella del modello attivo l'USDE NON COMPARE: non fa margine per i perp USDC-settled del book, e l'haircut oggi non si applica. Il che spiega a posteriori perche' la misura di stamattina trovava $0,0000 accantonati: non stavo guardando nel secchio sbagliato, cercavo un parametro che sul nostro conto non e' in vigore. NON MORDE: al massimo lordo del libro (1,0x = ~$2.056 di nozionale) l'IM sarebbe ~$41 contro $1.400 di USDC disponibile, 34x di copertura. Nessuna decisione operativa cambia oggi. Ma la premessa in CLAUDE.md era falsa, e il modo in cui lo era e' istruttivo: "l'equity del book e' il TOTALE cross-collateral" metteva due cose sotto un nome solo. Come RICCHEZZA sommare USDC+USDE e' giusto ed era il punto della riparazione del 26/08 (evito' il falso "USCITA DI FONDI -24%"); come CAPACITA' DI MARGINE e' sbagliato, perche' nel modello attivo l'USDE vale zero. Finche' il margine non morde le due coincidono nell'uso, e infatti non era mai emerso. Corretta anche la riga di usde_watch che stampava "margine utilizzabile ~$2.013 (haircut 10%)": era falsa due volte insieme. Ora stampa il solo silo USDC e, accanto, cosa darebbe il cross. La quota USDE non e' "collaterale diversificato": e' cassa a rendimento FUORI dal sistema di margine. Passare a X:SM aggiungerebbe $610,87 di margine utilizzabile ma porta la meccanica cross (collateral fee 0,05%/giorno sul saldo negativo, ribilanciamento automatico): decisione dell'operatore, oggi non serve. Ipotesi nuova e non verificata: il tetto del ~31,2% potrebbe dipendere proprio dal modello segregato. Si saprebbe passando a X:SM e ri-sondando. Suite: 800 passati. Co-Authored-By: Claude Opus 5 (1M context) --- CLAUDE.md | 6 +- config/live.json | 4 +- docs/diary/2026-08-31b-venue-news-annunci.md | 67 +++++++++++++++++ scripts/live/usde_watch.py | 12 +++- scripts/research/r0831_margini_conto.py | 76 ++++++++++++++++++++ 5 files changed, 158 insertions(+), 7 deletions(-) create mode 100644 scripts/research/r0831_margini_conto.py diff --git a/CLAUDE.md b/CLAUDE.md index 0758e17..7edc73d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -67,11 +67,13 @@ lorda massima 1,0x**, e nessun livello di capitale cambia il profilo di rischio `min_order_usd` 5 · `disaster_sl_pct` 0.30 on-book sulla posizione **netta** · staleness-gate feed 2 giorni (blocca) · `skh_feed_max_age_min` 30 (allerta, **non** blocca) · alert Telegram. -📌 **Dal 2026-08-26 l'equity del book e' il TOTALE cross-collateral** (USDC + USDE valutato +🚨 **Il conto NON e' cross-collateral: il modello attivo e' `Segregated: Standard Margin`** (S:SM), letto sulla pagina margini il 2026-08-31. Nella tabella del modello attivo **l'USDE non compare**: non fa margine per i perp USDC-settled del book, e l'haircut **non si applica** — ecco perche' la misura trovava $0,0000 accantonati. **NON MORDE**: al massimo lordo del libro (1,0x = ~$2.056 di nozionale) l'IM e' ~$41 contro **$1.400 di USDC disponibile**, 34× di copertura. Ma la premessa va corretta: **l'equity che il book somma e' la RICCHEZZA, non la capacita' di margine** — giusta per accorgersi di un'uscita di fondi (il difetto del 26/08), sbagliata se un giorno la si usasse per dire quanto margine c'e'. La quota USDE non e' 'collaterale diversificato': e' **cassa messa da parte a rendimento, FUORI dal sistema di margine**. Passare a X:SM aggiungerebbe **$610,87** di margine utilizzabile — decisione dell'operatore, e porta con se' la meccanica cross (collateral fee 0,05%/g sul saldo negativo, ribilanciamento automatico). 📌 Ipotesi nuova e non verificata sul tetto del ~31,2%: potrebbe essere legato proprio al modello segregato — si saprebbe passando a X:SM e ri-sondando. + +📌 **Dal 2026-08-26 l'equity del book somma USDC + USDE** (valutato all'indice pubblico `usde_usdc`): il conto tiene **643 USDE** (**IDONEO** dal 28/08; portati da 500 a 644 il 30/08 su decisione dell'operatore, **quota 31,21%** — e li' si e' fermato: 🚨 **il venue ha un TETTO sull'USDE** e ogni acquisto oltre quel livello e' rifiutato. GATE USDE-01 in §4). Autorita' dei parametri: sezione `usde` di `config/live.json` -(haircut 10% — ⚠️ la KB ufficiale dice **5%**, divergenza APERTA e non riparata, non osservabile dal gateway e non vincolante: dettaglio in `_nota_usde` — tetto ALLERTA quota 50%, soglie depeg 0,99/0,95 coi criteri in `_nota_usde`), letta +(haircut **5%** — ✅ divergenza chiusa il 31/08, la config diceva 10% ed era sbagliato (`r0831_margini_conto.py`); oggi comunque **non si applica**, vedi sopra — tetto ALLERTA quota 50%, soglie depeg 0,99/0,95 coi criteri in `_nota_usde`), letta da `src/live/usde.py` — shadow (sizing orario) e `usde_watch` (sorveglianza 12:35 UTC, cron proprio, sotto `monitor_health`) derivano entrambi da li'. ⚠️ Il difetto d'origine: `shadow._equity` leggeva SOLO il conto USDC — la prima conversione avrebbe causato un falso "USCITA DI FONDI −24%" diff --git a/config/live.json b/config/live.json index 8d23739..3bd1ef7 100644 --- a/config/live.json +++ b/config/live.json @@ -10,10 +10,10 @@ "max_data_age_days": 2, "_nota_skh_feed": "Freschezza del feed 5m usato per il segnale SKH01 (2026-07-26). fresh_5m ricade sul feed certificato IN SILENZIO se il fetch pubblico Deribit fallisce, e il certificato si rigenera 1x/giorno: senza controllo la latenza d'uscita di SKH01 passa da ~1h a ~1 giorno senza segnalazione. Sopra soglia book_execute ALLERTA e NON blocca (bloccare fermerebbe anche TP01, nettato sullo stesso strumento, per un guasto di rete). Diario 2026-07-26-t1-esecuzione-skh-live.md.", "skh_feed_max_age_min": 30, - "_nota_usde": "Collaterale USDE a rendimento (test di eligibilita' 2026-08-26: 500 USDE, verdetto entro il 29/08 — diario 2026-08-26-usde-analisi). L'autorita' che LEGGE questa sezione e' src/live/usde.py; la usano shadow._collaterale_usde (equity oraria del book) e scripts/live/usde_watch.py (sorveglianza giornaliera 12:35 UTC). Criteri delle soglie, dichiarati (P6): depeg_warn 0.99 = fuori dalla banda operativa dello spot (~3 bps) e oltre il clamp +-0.5% per fonte dell'indice usde_usdc — a quel prezzo non e' rumore di book; depeg_crit 0.95 = meta' del buffer di haircut (10%) consumata. quota_target 0.70 = la quota DECISA dall'operatore il 2026-08-30 (la decisione di quota che il gate USDE-01 apriva; anticipata di un giorno sul rinvio al 31/08, su richiesta esplicita dell'operatore \"porta in usde tutto il capitale che non viene usato\"). Il 70% NON e' un argmax (M8): e' il massimo compatibile col CUSCINO DI REGOLAMENTO, cioe' il vincolo che r0830_usde_quota non aveva guardato — il P&L e il funding dei perp USDC-lineari si regolano in USDC, non nel collaterale, quindi a quota alta il saldo USDC va negativo alla prima perdita del libro e Deribit lo finanzia a interesse. Il cuscino richiesto e' il disaster-SL sulla massima esposizione lorda: n_asset x frac x disaster_sl_pct = 2 x 0.5 x 0.30 = 30% dell'equity, che lascia esattamente il 70%. quota_max_frac 0.50 = tetto di ALLERTA sulla quota USDE/equity totale (N4: la quota e' l'unica leva contro il rischio emittente, -100% = 25 anni di resa, non recuperabile). Alzato a 0.85 il 2026-08-30 in previsione della quota al 70% e RIMESSO A 0.50 lo stesso giorno: il 70% NON e' raggiungibile. 🚨 venue_cap_frac 0.312 = TETTO DEL VENUE sull'USDE, misurato e NON documentato da Deribit (l'articolo ufficiale 'Yield/reward bearing coins' descrive un Cap ETHENA che diluisce il TASSO a livello di exchange, e nessun limite sulle quantita' detenibili da un conto). Ogni acquisto oltre il tetto e' rifiutato con `not_enough_funds_in_currency` pur avendo $1.400 disponibili: messaggio FUORVIANTE, non c'entrano fondi/taglia/prezzo/liquidita'/cadenza. E' una FRAZIONE DELL'EQUITY TOTALE, non un livello fisso — provato il 31/08 facendo scendere l'equity di $8: il tetto e' sceso con lei (30/08 in [644,18·645,18) con equity $2.063,79 = 31,21-31,26%; 31/08 in [643,18·644,18) con equity $2.055,56 = 31,29-31,34%; i due bracket distano 0,05pp, dentro il rumore dell'equity che oscilla +-$2-8/ora). ⇒ **il tetto SCALA col conto**: la quota resta ~31% e il valore in dollari cresce col capitale, e il 70% di quota_target NON e' raggiungibile ne' ora ne' mai. Il valore 0.312 e' il bordo BASSO dei bracket, scelto per far fallire il piano PRIMA dell'ordine invece che dopo il rifiuto; va ri-sondato se cambia qualcosa sul venue. Con la quota reale al 31% il tetto d'allerta 0.50 e' di nuovo quello giusto e MORDE: allargarlo a 0.85 avrebbe disarmato la guardia per uno scenario che non si e' verificato. Se il tetto del venue si alzera', il criterio per 0.85 e' 'meta' del cuscino di regolamento consumata' (USDC sotto il 15% dell'equity). haircut 0.10 registrato il 26/08 come 'verificato sul venue' (USDC 0%). 🚨 DIVERGENZA APERTA, non riparata (P12: fra due fonti che non concordano, una riparazione silenziosa e' un'invenzione): l'articolo ufficiale 'Cross collateral specifications' (Knowledge Base, aggiornato 2026-02-20) tabula USDe al **5%** — e il conto e' **X:SM (cross-collateral STANDARD margin)**, dichiarato dall'operatore il 31/08, quindi la colonna da leggere e' `Haircut (X:SM)`, che per USDe vale **5%** come la PM. Il tipo di conto e' corroborato dalla misura indipendente: IM = 2,0000% del nozionale = 1/50 = il `C1=50` (start leverage, tier 1) del nuovo modello di margine per i conti STANDARD annunciato il 2026-08-05 — e con lui stETH 7.5%, PAXG 2.5/5%, USDT 2%, USYC 2%, BUIDL 2%, SOL 0/15%, e USDC/BTC/ETH a ZERO. Il 26/08 non ha lasciato traccia di COME fu verificato, e l'articolo e' ANTERIORE a quella data: non si sa quale delle due sia stale. Si TIENE 0.10 perche' e' il lato CONSERVATIVO (sottostima il margine utilizzabile) e perche' l'haircut non e' sul percorso soldi — non entra nel sizing, lo usa solo il report di usde_watch, ed e' gia' misurato che non morde a nessuna quota fino al 90%. Da chiudere leggendo la pagina margini del conto, che e' dove Deribit dice di guardare.", + "_nota_usde": "Collaterale USDE a rendimento (test di eligibilita' 2026-08-26: 500 USDE, verdetto entro il 29/08 — diario 2026-08-26-usde-analisi). L'autorita' che LEGGE questa sezione e' src/live/usde.py; la usano shadow._collaterale_usde (equity oraria del book) e scripts/live/usde_watch.py (sorveglianza giornaliera 12:35 UTC). Criteri delle soglie, dichiarati (P6): depeg_warn 0.99 = fuori dalla banda operativa dello spot (~3 bps) e oltre il clamp +-0.5% per fonte dell'indice usde_usdc — a quel prezzo non e' rumore di book; depeg_crit 0.95 = meta' del buffer di haircut (10%) consumata. quota_target 0.70 = la quota DECISA dall'operatore il 2026-08-30 (la decisione di quota che il gate USDE-01 apriva; anticipata di un giorno sul rinvio al 31/08, su richiesta esplicita dell'operatore \"porta in usde tutto il capitale che non viene usato\"). Il 70% NON e' un argmax (M8): e' il massimo compatibile col CUSCINO DI REGOLAMENTO, cioe' il vincolo che r0830_usde_quota non aveva guardato — il P&L e il funding dei perp USDC-lineari si regolano in USDC, non nel collaterale, quindi a quota alta il saldo USDC va negativo alla prima perdita del libro e Deribit lo finanzia a interesse. Il cuscino richiesto e' il disaster-SL sulla massima esposizione lorda: n_asset x frac x disaster_sl_pct = 2 x 0.5 x 0.30 = 30% dell'equity, che lascia esattamente il 70%. quota_max_frac 0.50 = tetto di ALLERTA sulla quota USDE/equity totale (N4: la quota e' l'unica leva contro il rischio emittente, -100% = 25 anni di resa, non recuperabile). Alzato a 0.85 il 2026-08-30 in previsione della quota al 70% e RIMESSO A 0.50 lo stesso giorno: il 70% NON e' raggiungibile. 🚨 venue_cap_frac 0.312 = TETTO DEL VENUE sull'USDE, misurato e NON documentato da Deribit (l'articolo ufficiale 'Yield/reward bearing coins' descrive un Cap ETHENA che diluisce il TASSO a livello di exchange, e nessun limite sulle quantita' detenibili da un conto). Ogni acquisto oltre il tetto e' rifiutato con `not_enough_funds_in_currency` pur avendo $1.400 disponibili: messaggio FUORVIANTE, non c'entrano fondi/taglia/prezzo/liquidita'/cadenza. E' una FRAZIONE DELL'EQUITY TOTALE, non un livello fisso — provato il 31/08 facendo scendere l'equity di $8: il tetto e' sceso con lei (30/08 in [644,18·645,18) con equity $2.063,79 = 31,21-31,26%; 31/08 in [643,18·644,18) con equity $2.055,56 = 31,29-31,34%; i due bracket distano 0,05pp, dentro il rumore dell'equity che oscilla +-$2-8/ora). ⇒ **il tetto SCALA col conto**: la quota resta ~31% e il valore in dollari cresce col capitale, e il 70% di quota_target NON e' raggiungibile ne' ora ne' mai. Il valore 0.312 e' il bordo BASSO dei bracket, scelto per far fallire il piano PRIMA dell'ordine invece che dopo il rifiuto; va ri-sondato se cambia qualcosa sul venue. Con la quota reale al 31% il tetto d'allerta 0.50 e' di nuovo quello giusto e MORDE: allargarlo a 0.85 avrebbe disarmato la guardia per uno scenario che non si e' verificato. Se il tetto del venue si alzera', il criterio per 0.85 e' 'meta' del cuscino di regolamento consumata' (USDC sotto il 15% dell'equity). haircut 0.05 — ✅ DIVERGENZA CHIUSA il 2026-08-31 (era 0.10, SBAGLIATO). La pagina margini del conto non espone l'haircut come numero: si RICAVA per differenza fra le due righe, perche' il modello CROSS conta l'USDE scontato e il SEGREGATO non lo conta affatto. Contributo dell'USDE al cross $610,81 su $643,05 di valore -> 5,0137%: l'ipotesi 5% torna a $0,09, la 10% sbaglia di $32,06. Riproducibile: `scripts/research/r0831_margini_conto.py` (N11). Il 26/08 il 10% fu registrato come 'verificato sul venue' senza lasciare traccia di come, e non lo era. 🚨 SCOPERTO NELLA STESSA LETTURA, e vale piu' dell'haircut: il modello di margine ATTIVO e' **Segregated: Standard Margin (S:SM)**, NON cross-collateral. Nella tabella del modello attivo l'USDE **non compare**: non fa margine per i perp USDC-settled del book. Percio' l'haircut oggi non si applica affatto — ed e' esattamente il motivo per cui la misura del 31/08 trovava $0,0000 accantonati. Passare a X:SM aggiungerebbe $610,87 di margine utilizzabile: e' una decisione dell'operatore, non un refactor, e porta con se' la meccanica cross (collateral fee 0,05%/giorno sul saldo negativo, ribilanciamento automatico).", "usde": { "index_name": "usde_usdc", - "haircut": 0.1, + "haircut": 0.05, "quota_target": 0.7, "venue_cap_frac": 0.312, "venue_cap_misurato": "2026-08-31", diff --git a/docs/diary/2026-08-31b-venue-news-annunci.md b/docs/diary/2026-08-31b-venue-news-annunci.md index 287d673..22fbfc9 100644 --- a/docs/diary/2026-08-31b-venue-news-annunci.md +++ b/docs/diary/2026-08-31b-venue-news-annunci.md @@ -212,3 +212,70 @@ prima che il conto conferma.* **mostrato sulla pagina Standard Margin del conto**. Se dice 5%, la nostra config è stale e il 26/08 registrò male; se dice 10%, la KB è stale e la config ha ragione. Finché non c'è, si tiene 0.10 — lato conservativo, fuori dal percorso soldi, e **senza un solo effetto operativo misurabile**. + +--- + +## 6. La pagina margini arriva davvero — e la seconda cosa che dice vale più della prima + +Lo screenshot era su **Wasabi** (`rclone` remote `wasabi:`, bucket `adp-work`, cartella `_scambio`), +non sulla VPS: per questo il percorso non esisteva. Scaricato e letto. +Riconciliazione riproducibile in **`scripts/research/r0831_margini_conto.py`** (N11). + +### (a) ✅ Haircut = **5%**. La nostra config aveva torto. + +La pagina **non espone l'haircut come numero**: si ricava per differenza, perché il modello CROSS +conta l'USDE scontato e il SEGREGATO non lo conta affatto. + +``` +S:SM (attivo) USDC Available 1,400.86 · USDC equity 1,412.28 − IM 11.55 = 1,400.73 (scarto $0.13) +X:SM CROSS Available 2,011.73 +contributo USDE al cross = 2,011.73 − (1,412.28 + 0.20 − 11.55) = $610.81 su $643.05 di valore + → haircut implicito 5,0137% + ipotesi 5% (KB) → atteso $610.89 scarto $ 0.09 ✅ + ipotesi 10% (nostra) → atteso $578.74 scarto $32.06 ❌ +``` + +`config/live.json` passa da `0.10` a **`0.05`**. Il 26/08 il 10% fu registrato come «verificato sul +venue» **senza lasciare traccia di come**, e non lo era. *Una nota di provenienza che dice «verificato» +senza dire con quale lettura non è provenienza: è la stessa parola usata come garanzia.* + +### (b) 🚨 Il conto **non è cross-collateral**. È `Segregated: Standard Margin`. + +Lo dice la schermata in cima — *Current status: **Segregated: Standard Margin*** — e la tabella del +modello attivo elenca **BTC, ETH, USDC. L'USDE non c'è.** + +⇒ **L'USDE non fa margine per i perp USDC-settled del book**, e l'haircut **oggi non si applica +affatto**. Il che spiega, a posteriori e in modo pulito, perché la misura di stamattina trovava +**$0,0000** accantonati: non stavo guardando nel secchio sbagliato, *stavo cercando un parametro +che sul nostro conto non è in vigore*. + +**NON MORDE**, e va detto subito per non allarmare: al massimo lordo del libro (1,0x ≈ $2.056 di +nozionale) l'IM sarebbe ~$41 contro **$1.400 di USDC disponibile** — 34× di copertura. Nessuna +decisione operativa cambia oggi. + +**Ma la premessa scritta in CLAUDE.md era falsa**, e il modo in cui era falsa è istruttivo. Diceva: +*«l'equity del book è il TOTALE cross-collateral»*. Sono due cose diverse messe sotto un nome solo: + +- come **ricchezza**, sommare USDC+USDE è **giusto** — ed era il punto della riparazione del 26/08, + che evitò il falso «USCITA DI FONDI −24%» e una vendita indesiderata; +- come **capacità di margine**, è **sbagliato**: nel modello attivo l'USDE vale zero. + +Finché il margine non morde le due coincidono nell'uso, e infatti non è mai emerso. *Un errore che +non ha conseguenze finché una terza cosa resta vera è un debito, non un'assoluzione.* Corretto in +CLAUDE.md, e corretta anche la riga di `usde_watch` che stampava «margine utilizzabile ~$2.013 +(haircut 10%)»: era falsa due volte insieme. + +### (c) Come cambia il modo di pensare alla quota USDE + +Non è «collaterale diversificato»: è **cassa messa da parte a rendimento, fuori dal sistema di +margine**. Il che rende il tetto del venue al ~31,2% meno una limitazione e più un caso fortunato — +tiene automaticamente dentro al 31% la parte di conto che non lavora come margine. + +E apre una **decisione dell'operatore**, non mia: passare a **X:SM** aggiungerebbe **$610,87** di +margine utilizzabile, ma porta con sé la meccanica cross — *collateral fee 0,05%/giorno* sul saldo +negativo e ribilanciamento automatico. Oggi non serve (34× di copertura); servirebbe solo a leve +che non sono autorizzate. + +📌 **Ipotesi nuova sul tetto del ~31,2%**, non verificata: potrebbe dipendere proprio dal modello +segregato. Si saprebbe passando a X:SM e ri-sondando — un esperimento che ora ha un senso, dove +prima non si sapeva nemmeno cosa variare. diff --git a/scripts/live/usde_watch.py b/scripts/live/usde_watch.py index edcf06e..d3962b0 100755 --- a/scripts/live/usde_watch.py +++ b/scripts/live/usde_watch.py @@ -302,9 +302,15 @@ def main() -> int: print(f" equity USDE : {eq_usde:,.4f} @ {px if px is not None else 'n/d'}" f" ({px_fonte}) -> ${usd:,.2f}" if usd is not None else " equity USDE : n/d") if quota is not None: - margine = eq_usdc + usd * (1.0 - c["haircut"]) - print(f" quota : {quota:.1%} del totale (tetto allerta {c['quota_max_frac']:.0%})" - f" · margine utilizzabile ~${margine:,.0f} (haircut {c['haircut']:.0%})") + # Il conto e' Segregated Standard Margin (letto sulla pagina margini il 31/08): + # l'USDE NON fa margine per i perp USDC-settled, e l'haircut non si applica. Il + # margine del book e' il solo silo USDC. Si stampa anche cosa DAREBBE il cross, + # perche' e' la differenza che rende la cosa una decisione invece che un dettaglio. + cross = eq_usdc + usd * (1.0 - c["haircut"]) + print(f" quota : {quota:.1%} del totale (tetto allerta {c['quota_max_frac']:.0%})") + print(f" margine : ~${eq_usdc:,.0f} — il solo USDC (conto SEGREGATO: l'USDE non" + f" fa margine). Con cross X:SM sarebbero ~${cross:,.0f} (haircut" + f" {c['haircut']:.0%})") if an["delta"] is not None: attr = ("non attribuibile (trade non leggibili)" if an["reward_stimato"] is None else f"reward stimato {an['reward_stimato']:+.6f} USDE" diff --git a/scripts/research/r0831_margini_conto.py b/scripts/research/r0831_margini_conto.py new file mode 100644 index 0000000..c2d48bd --- /dev/null +++ b/scripts/research/r0831_margini_conto.py @@ -0,0 +1,76 @@ +#!/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") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())