Files
PythagorasGoal/docs/diary/2026-08-30-usde-quota-tetto-venue.md
T
Adriano Dal Pastro a45794d2cb usde: il venue mette un TETTO al 31,21% — e l'USDC paga gia' 3,40%
Richiesta dell'operatore: "porta in usde tutto il capitale che non viene
usato". Il margine consuma $11 su $2.063 e l'USDE e' cross-collateral: preso
alla lettera vale una quota ~99%, cioe' il 100% che il gate esclude. Portata
all'operatore con le cifre, ha scelto 70%.

Il 70% non e' un argmax (M8): e' il massimo compatibile col CUSCINO DI
REGOLAMENTO, il vincolo che r0830_usde_quota non aveva guardato. P&L e funding
dei perp USDC-lineari si regolano in USDC, non nel collaterale, quindi la
quota non la limita l'haircut ma il saldo USDC che deve reggere il disaster-SL
sulla massima esposizione: 2 x 0,5 x 0,30 = 30% dell'equity, che lascia il 70%.

ESEGUITO +144 USDE (500,1757 -> 644,175691), quota 24,24% -> 31,21%, fee 0.
Poi il muro.

(a) TETTO DEL VENUE, misurato e non documentato da nessuna parte. Provato a
saldo neutro: BUY 20 rifiutato, SELL 20 OK, BUY 20 OK, BUY 5 rifiutato, con
$1.408 disponibili. E' un tetto sul LIVELLO. Il messaggio del venue
(not_enough_funds_in_currency) e' fuorviante e ha fatto inseguire tre ipotesi
sbagliate: taglia (falso, ma min_trade_amount=1 e' vero), rate-limit (falso),
prezzo (vero in parte: il book REST pubblico e' in ritardo sul matching engine
e prezzavo l'ordine sull'INDICE invece che sul BOOK — l'indice marca il
collaterale, il book prezza lo scambio). La cronaca resta nel diario: chi
rilegge non deve rifare il giro.

(b) L'USDC PAGA 3,40%. public/get_currencies: USDE 4,1071%, USDC 3,4000%, e i
nostri reward USDE misurati (~4,5%/anno) confermano che quelle APR sono reali.
Il guadagno non e' il tasso, e' lo SPREAD: 0,71 punti, ~$4,6/anno sui $644 che
teniamo, non i $21 che il gate implicava. Il gate ha misurato il reward
dell'USDE e non ha mai chiesto cosa facesse l'USDC fermo: manca il
controfattuale, M1 in un'altra veste. NON dimostrato che sia accreditato sul
nostro conto — da verificare su un giorno senza trade.

Nuovo attrezzo scripts/live/usde_convert.py: dry-run di default, banda prezzo,
tetto hard di quota, cuscino di regolamento derivato da config. NON passa da
execution.ALLOWED, che resta ai soli due perp.

config: quota_target 0.70 registrato; quota_max_frac alzato a 0.85 e RIMESSO a
0.50 nella stessa sessione — la soglia larga presupponeva un 70% che non
esiste, e lasciarla avrebbe disarmato la guardia per uno scenario che non si e'
verificato.

Suite: 795 passati, 0 falliti.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-30 20:18:31 +00:00

8.2 KiB
Raw Blame History

2026-08-30 — "porta in USDE tutto il capitale che non viene usato": il venue dice 31%

Richiesta dell'operatore, verbatim: "porta in usde tutto il capitale che non viene usato". Arriva il 30/08, cioè un giorno prima della data a cui l'operatore stesso aveva rinviato la decisione di quota (gate USDE-01, rinvio al 31/08). L'anticipo è esplicito e vale come decisione.

1. "Il capitale che non viene usato" non è una quantità piccola: è quasi tutto

Stato letto dal gateway alle 19:50Z: USDC $1.563,09 (di cui $11,36 impegnati a margine), USDE 500,1757 → $500,18, totale $2.063,26, quota 24,2%. Posizioni BTC $354,72 + ETH $213,36 = $568,08 lordi (0,275x).

Il margine consuma $11 su $2.063, e l'USDE è cross-collateral: convertirlo non lo toglie dall'uso. Anche a piena esposizione del libro (lordo 1,0x) il margine sarebbe ~$41. Presa alla lettera la richiesta è una quota ~99% — il 100% che il gate esclude per nome ("mai 100%: R1 emittente non recuperabile"). Le due letture plausibili ("non a margine" e "non esposto dal libro") convergono entrambe su ~97-99%: non è un'ambiguità che si risolve scegliendo, è una che si porta all'operatore.

2. Il vincolo che r0830_usde_quota non aveva guardato: il cuscino di REGOLAMENTO

L'analisi del 30/08 aveva misurato il margine e concluso — correttamente — che l'haircut non morde a nessuna quota fino al 90%, nemmeno a leva 1,50x con USDE a 0,95. Vero, e irrilevante: il P&L e il funding dei perp USDC-lineari si regolano in USDC, non nel collaterale. Lo si vede nel conto: equity balance = $7,24 di floating, tutto nel secchio USDC.

A quota 99% resterebbero $41 di USDC contro un libro che, col disaster-SL a 30% sulla massima esposizione, può perderne **$619**: il saldo va negativo e Deribit lo finanzia a interesse, che si mangia la resa che si stava comprando. Il vincolo non è il margine, ma non è nemmeno assente.

Criterio dichiarato: cuscino USDC ≥ disaster-SL sulla massima esposizione lorda del libro = n_asset × frac × disaster_sl_pct = 2 × 0,5 × 0,30 = 30% dell'equity — tutto derivato da config/live.json e src/live/book.py, mai ridichiarato (P1). Che lascia esattamente 70%. Non è un argmax (M8): la quota massima e il criterio coincidono per costruzione, e infatti il 70% cade esattamente sul limite, con zero slack.

Tabella portata all'operatore (APR allora creduta 3,26% [1,13-4,51], n=4 — vedi §5, è sbagliata):

quota converti USDC che resta resa/anno evento emittente vs maxDD libro
24,2% (allora) $1.563 $16 3,1×
50% $531 $1.032 $34 6,3×
70% $944 $619 $47 8,8×
~99% $1.522 $41 $66 12,3×

Scelta dell'operatore: 70%, il massimo compatibile col cuscino.

3. Esecuzione: da 500 a 644 USDE, poi il muro

Nuovo attrezzo scripts/live/usde_convert.py (dry-run di default). Non passa da DeribitTrader: execution.ALLOWED ammette solo i due perp del libro ed è il guardrail anti-fat-finger del percorso soldi — non si allarga per farci entrare uno spot che col libro non c'entra. Lo script porta le proprie guardie: banda prezzo [0,995 1,005], tetto HARD di quota 0,95, il cuscino di regolamento, dry-run.

Convertiti +144 USDE (500,1757 → 644,175691), quota 24,24% → 31,21%, tutti i fill a 1,0002-1,0003, fee 0. Poi ogni acquisto ha smesso di passare.

4. not_enough_funds_in_currency è un messaggio FUORVIANTE — la cronaca delle ipotesi sbagliate

Si tiene apposta, perché chi rilegge non deve rifare questo giro. Tre ipotesi, tutte plausibili, tutte sbagliate:

  1. "È la taglia." 943,98 rifiutato per Invalid params → vero: min_trade_amount: 1 e contract_size: 1, il passo è intero (confermato da public/get_instrument; il gateway non espone quel tool, la risposta è arrivata dall'API pubblica). Quantizzato a intero: 933 rifiutato per fondi, con $1.541 disponibili. Falso indizio.
  2. "È il rate-limit." 100 passava e 300 no; poi anche 1 rifiutato otto volte di fila. Aggiunto backoff sul tempo fino a 90s: rifiutato lo stesso. Falso.
  3. "È il prezzo." Diagnosi a tre ordini da 1 USDE: SELL @1,0000 OK, BUY @1,0003 OK, BUY @1,0002 e BUY market rifiutati. Vero in parte: il book REST pubblico è in ritardo sul matching engine, e un limite a ask+1 tick a volte non incrocia davvero. Difetto mio, e istruttivo: prezzavo l'ordine sull'indice invece che sul book. Sono due prezzi con due mestieri — l'indice marca il collaterale (usde.valuta, mediana multi-exchange: la lezione Binance 10/10), il book prezza lo scambio. Corretto con 5 tick di margine e tetto duro 1,0010: il fill avviene al prezzo del libro, quindi il margine non si paga.

Ma corretto il prezzo, 200 e 800 continuavano a fallire con 4.552 di profondità all'ask.

5. 🚨 Il fatto vero: un TETTO DEL VENUE sull'USDE, a 644,175691 (31,21%)

Esperimento a saldo neutro, quattro ordini di fila (20:14Z):

BUY  20 @1.0007 -> not_enough_funds_in_currency    USDE 644.1757
SELL 20 @0.9996 -> OK                              USDE 624.1757
BUY  20 @1.0007 -> OK                              USDE 644.1757
BUY   5 @1.0007 -> not_enough_funds_in_currency    USDE 644.1757

È un tetto sul LIVELLO: non taglia, non prezzo, non liquidità, non cadenza, non fondi ($1.408 disponibili). Lo stesso ordine che viene rifiutato passa subito dopo una vendita di pari taglia. La quota del 70% non è raggiungibile, e nemmeno il 50%.

La formula del tetto non è leggibile da qui: public/get_currencies non espone un cap (in_cross_collateral_pool: true, nient'altro), e il gateway non espone né get_order_bookavailable_withdrawal_funds — è il debito #11, il gateway è l'unico pezzo della catena che possediamo e si ha solo quel che espone. Registrato come fatto misurato, non spiegato (D5: un buco quantificato è un risultato, uno taciuto è un debito).

6. 🚨 E la resa non è quella che credevamo: l'USDC paga 3,40%

public/get_currencies, letta oggi:

valuta APR pubblicata
USDE 4,1071%
USDC 3,4000%

I nostri reward USDE misurati (+0,052055 · +0,061815 · +0,061821 al giorno su 500 → ~4,5%/anno) confermano che la APR pubblicata di USDE è reale. Il che rende credibile anche l'altra riga.

Se l'USDC frutta già 3,40%, il guadagno del passaggio a USDE non è il tasso: è lo spread, 0,71 punti. Sui $644 che teniamo vale ~$4,6/anno, non $21; sui $144 convertiti oggi, ~$1,0/anno. Il gate USDE-01 ha misurato con cura il reward dell'USDE e non ha mai chiesto cosa facesse l'USDC fermo: è il controfattuale mancante — M1 in un'altra veste, si giudica il marginale, non il livello. E cambia il verso della decisione: si prende un rischio emittente non recuperabile (a 31,2% vale 3,9× il maxDD dell'intero libro) per 0,71 punti.

⚠️ Quello che NON è dimostrato: che la APR USDC sia effettivamente accreditata sul nostro conto. Sull'USDE l'abbiamo vista arrivare per delta; sull'USDC il P&L di trading copre $0,13/giorno di interesse e il gateway non espone il Transaction Log. Va verificato su un giorno senza trade prima di trattarlo come misura — qui è una APR pubblicata dal venue più una conferma indiretta, non un reward osservato.

7. Cosa resta a terra

  • Conto: USDC $1.419,61 · USDE 644,175691 ($644,18) · totale $2.063,79 · quota 31,21%. Nessun ordine spot appeso (restano i due tp01-disaster reduce_only). Posizioni invariate. Equity vista dal book $2.063,86 ("mainnet USDC + USDE 644 @ 1.0000"): sizing corretto, nessun falso "uscita di fondi".
  • config/live.json: aggiunto quota_target: 0.70 (la decisione dell'operatore, oggi bloccata dal venue). quota_max_frac alzato a 0,85 e rimesso a 0,50 nella stessa sessione: la soglia larga presupponeva un 70% che non esiste, e lasciarla avrebbe disarmato la guardia per uno scenario che non si è verificato. Con la quota reale al 31%, il 50% morde di nuovo.
  • Non fatto: portare la quota al 70%. Il venue non lo consente. Non è una rinuncia discrezionale, è un rifiuto misurato e riproducibile.