c250c04371
Domanda dell'operatore: "verifica se l'USDC frutta davvero sul nostro conto". Sembrava dover aspettare: il gateway non espone il Transaction Log (get_transaction_log, get_settlement_history, get_deposits, get_transfers, get_interest_history: tutti 404 — debito #11) e l'unica serie storica e' trades.db.equity, oraria ma arrotondata a 2 decimali e sporcata dal P&L non realizzato (+-$2-8/ora a posizioni aperte), dove $0,13/giorno sparisce. La fonte ufficiale Deribit ha spostato il problema dal rumore al calendario: i reward USDC si pagano UNA VOLTA AL MESE ("paid out as a single monthly payment early in the following month"), accrual alle 00:00 UTC sulla minima equity — non ogni giorno come l'USDE. Ecco perche' una sorveglianza giornaliera non poteva vederli. E un accredito mensile da qualche dollaro si vede benissimo anche a 2 decimali, purche' il libro sia FLAT: allora equity == balance == USDC e ogni scalino e' un accredito. MISURA, due confini di mese entrambi a libro flat: 29/06 -> 08/07 equity 598,06 costante, 237/237 ore ferme, 0 scalini (attesi $0,45) 31/07 -> 03/08 equity 596,92 costante per 4 giorni pieni (attesi $1,72) Il secondo e' decisivo: $1,72 contro una risoluzione di $0,01, 172x. Zero MISURATO, non zero sotto soglia. => La premessa originale del gate USDE-01 e' RESTAURATA: il guadagno di tenere USDE e' il tasso pieno ~4,1%, non lo spread 0,71 punti che avevo scritto poche ore fa. Sui $644: ~$26/anno, non ~$4,6. Cosa avevo sbagliato: ho letto `apr: 3.4` in public/get_currencies e l'ho trattato come una proprieta' del NOSTRO CONTO. Era un listino del VENUE. La "conferma indiretta" che invocavo provava che il listino e' reale per l'USDE e non diceva nulla sull'idoneita' dell'USDC. Un tasso pubblicato non e' un tasso incassato: si verifica sul conto — ed e' costato una query su una serie che avevamo gia'. Esclusione plausibile ma NON verificata: MiCA (USDC e' e-money token, USDe no); Deribit dice solo "eligibility is based on their location". Il fatto misurato e' lo zero, non il suo motivo. Nuovo: scripts/live/balance_watch.py + scripts/cron_balance.sh (orario al minuto :42, libero fra :25/:35/:47, sola lettura). Registra il BALANCE a 8 decimali per valuta — la serie che mancava — col conteggio dei fill dall'ultimo campione e il nozionale lordo, cosi' una finestra sporca si riconosce invece di essere mediata dentro. Etichetta PULITA le finestre a 0 fill e libro flat, dove il delta USDC E' l'interesse, e ne stampa l'APR implicita. Suite: 795 passati. L'ERROR di teardown e' il falso positivo dichiarato dalla guardia stessa: il cron :47 ha scritto un fill reale (ETH BUY $+9, 23:47:19) mentre la suite girava. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
214 lines
13 KiB
Markdown
214 lines
13 KiB
Markdown
# 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_book` né
|
||
`available_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.
|
||
|
||
---
|
||
|
||
# APPENDICE (stessa sera, 23:40-23:55Z) — **l'USDC NON frutta sul nostro conto: §6 era sbagliata**
|
||
|
||
Richiesta dell'operatore: *"verifica se l'USDC frutta davvero sul nostro conto"*. Verificato.
|
||
**La risposta ribalta la §6 di questo stesso diario**, che va letta con questa appendice accanto.
|
||
|
||
## Perché la domanda sembrava dover aspettare, e invece no
|
||
|
||
Il gateway non espone il Transaction Log (provati `get_transaction_log`, `get_settlement_history`,
|
||
`get_deposits`, `get_transfers`, `get_interest_history`: **tutti 404** — debito #11). L'unica serie
|
||
storica del conto è `trades.db.equity`: **oraria ma arrotondata a 2 decimali**, e contiene il P&L
|
||
non realizzato, che a posizioni aperte oscilla di ±$2-8/ora. $0,13/giorno di interesse ci sparisce.
|
||
|
||
Poi la fonte ufficiale Deribit ha spostato il problema dal *rumore* al *calendario*:
|
||
|
||
> «Every day at 00:00 UTC, Deribit calculates the **minimum equity** of USDC that a user has been
|
||
> holding over the previous 24 hours. […] After the month is over, the rewards from each day are
|
||
> summed together and **paid out as a single monthly payment early in the following month**.»
|
||
> — `insights.deribit.com/education/usdc-rewards-now-paid-on-deribit/`
|
||
|
||
**I reward USDC si pagano UNA VOLTA AL MESE**, non ogni giorno come quelli USDE. Ecco perché non li
|
||
avevamo mai visti: guardavamo a cadenza giornaliera, dove l'USDE si vede e l'USDC per costruzione no.
|
||
E un accredito mensile da qualche dollaro **si vede benissimo anche a 2 decimali** — purché il libro
|
||
sia FLAT, perché allora `equity == balance == USDC` e ogni scalino è un accredito.
|
||
|
||
## La misura: due confini di mese, entrambi a libro flat
|
||
|
||
| finestra | punti orari | equity min | equity max | ore senza alcun movimento | scalini >1 cent | reward atteso se idoneo |
|
||
|---|---|---|---|---|---|---|
|
||
| **29/06 → 08/07** | 238 | **598,06** | **598,06** | **237 / 237** | **0** | $0,45 (8 gg dal 23/06) |
|
||
| **31/07 → 03/08** | 96 | **596,92** | **596,92** | **tutte** | **0** | **$1,72** (luglio intero) |
|
||
|
||
Il secondo è il caso decisivo: **$1,72 attesi contro una risoluzione di $0,01 — 172×** — e l'equity
|
||
non si muove di un centesimo per quattro giorni pieni, coprendo tutta la finestra "early in the
|
||
following month". Non è un'assenza sotto la soglia di rilevabilità: è uno zero misurato.
|
||
|
||
⇒ **Il conto NON riceve i reward USDC.** N=2 confini indipendenti, entrambi puliti per costruzione.
|
||
|
||
## Perché, e perché è coerente col fatto che l'USDE invece paga
|
||
|
||
Deribit: *«A user's eligibility to receive USDC is based on their location»*. L'ipotesi che spiega
|
||
entrambe le osservazioni è **MiCA**: USDC è un *e-money token* regolamentato, e a un residente UE
|
||
non se ne può corrispondere rendimento; **USDe non è un EMT**, e infatti i suoi reward arrivano
|
||
(li abbiamo visti per delta: +0,052055 · +0,061815 · +0,061821). ⚠️ *Questa è la spiegazione
|
||
plausibile, non una fonte normativa verificata* (P13/M27: una norma citata si verifica come un
|
||
numero). **Il fatto misurato è lo zero, non il suo motivo.**
|
||
|
||
## Cosa cambia (e cosa la §6 aveva sbagliato)
|
||
|
||
- **La premessa originale del gate USDE-01 è RESTAURATA.** Il guadagno di tenere USDE **non è lo
|
||
spread 0,71 punti: è il tasso pieno ~4,1%**, perché l'alternativa sul nostro conto rende **0**.
|
||
Sui $644 che teniamo: **~$26/anno** (e ~$29 al ritmo misurato di ~4,5%), non i ~$4,6 di §6.
|
||
- **Cosa avevo sbagliato, e la lezione.** Ho letto `apr: 3.4` in `public/get_currencies` e l'ho
|
||
trattato come una proprietà **del nostro conto**. È una proprietà **del venue**: un listino, non
|
||
un accredito. La conferma indiretta che invocavo ("i reward USDE misurati coincidono con la loro
|
||
APR pubblicata") provava che il listino è reale **per l'USDE**, e non diceva nulla sull'idoneità
|
||
dell'USDC. 📌 **Un tasso pubblicato non è un tasso incassato: si verifica sul CONTO, e la verifica
|
||
costava una query sulla serie che avevamo già.** È N10 in una veste nuova — la verifica a €0 va
|
||
fatta *prima*, e si fa **sul venue, non sul sito**; qui perfino il venue non bastava, serviva il
|
||
conto.
|
||
- Resta vero e non toccato: il **tetto del venue al 31,21%**, il **cuscino di regolamento** (30%
|
||
dell'equity, che lascia il 70%), e che a 31,2% l'evento emittente vale ~3,9× il maxDD del libro.
|
||
La decisione "tenere o no i $644" cambia però di segno rispetto a come l'avevo chiusa: si compra
|
||
**$26/anno**, non $4,6.
|
||
|
||
## Strumento lasciato in piedi
|
||
|
||
**`scripts/live/balance_watch.py`** + **`scripts/cron_balance.sh`** (orario al minuto **:42**, libero
|
||
fra :25/:35/:47; sola lettura). Registra il **balance a 8 decimali** per valuta — la serie che
|
||
mancava — con il conteggio dei fill dall'ultimo campione e il nozionale lordo, così una finestra
|
||
sporca si riconosce invece di essere mediata dentro. Etichetta PULITA le finestre a 0 fill e libro
|
||
flat, dove il Δ USDC **è** l'interesse, e ne stampa l'APR implicita accanto a quella attesa.
|
||
Serve a sorvegliare che lo zero resti zero (o che cambi, se l'idoneità cambia): l'inizio di
|
||
settembre è il prossimo confine di mese, ed è già strumentato.
|