f151316bdf
Fonte: articolo ufficiale Deribit "Yield/reward bearing coins" (WebFetch lo prende
403, si legge dall'API Help Center in JSON). Tre correzioni alle conclusioni di
ieri.
1) L'ITALIA e' nella lista delle giurisdizioni escluse dai reward USDC. Lo zero
misurato e' confermato dalla fonte, ma la mia ipotesi MiCA era SBAGLIATA: la
lista contiene Canada e Giappone, non e' il perimetro MiCA. E' policy di
giurisdizione Deribit. M27: una fonte normativa si verifica, non si deduce.
2) La finestra di pagamento USDC e' di DUE SETTIMANE ("within the first two
weeks of the following month"), non tre giorni. Avevo verificato su 8/14 e 3/14
giorni. Rifatto sulle finestre vere: LUGLIO conclusivo (atteso $1,72 contro
un'escursione TOTALE dell'equity di $0,48 in 1-16/08, zero scalini compatibili),
GIUGNO no (il libro opera da meta' mese, rumore della taglia del segnale). La
conclusione non cambia, ma l'evidenza e' UNA finestra piu' la lista ufficiale,
non due: il "172x" del 30/08 era sovra-affermato.
3) IL TETTO NON E' UN LIVELLO, E' UNA FRAZIONE. L'articolo documenta un Cap
ETHENA che diluisce il TASSO a livello di exchange e nessun limite sulle
quantita' detenibili: il muro non aveva base documentale e andava ri-sondato.
Fatto il 31/08 (giorno UTC nuovo -> non e' un limite giornaliero): ieri si
tornava a 644,18, oggi no, con l'equity scesa di $8.
30/08 tetto [644,18 · 645,18) equity $2.063,79 = 31,21-31,26%
31/08 tetto [643,18 · 644,18) equity $2.055,56 = 31,29-31,34%
0,05pp di scarto, dentro il rumore dell'equity (+-$2-8/ora). Candidato pulito
5/16 = 31,25%, ma a questa risoluzione non si distingue da una regola sul
collaterale scontato dell'haircut (~29%): si cita la banda (M25).
=> Il tetto SCALA col conto: la quota resta ~31%, il valore in dollari cresce
col capitale, il 70% non e' raggiungibile ne' ora ne' mai. E, essendo pinnati
al tetto, il rischio emittente resta una frazione COSTANTE del conto.
Cablato (rispondeva a "dove e' scritto il valore del tetto": in tre note di
testo e in nessun posto che il codice leggesse, tanto che usde_convert --quota
0.70 dichiarava "piano valido" per un ordine che il venue rifiuta):
- config/live.json usde.venue_cap_frac 0.312 + venue_cap_misurato
- src/live/usde.py lo porta nei default (unica autorita', P1)
- usde_convert.piano() rifiuta il bersaglio sopra il tetto PRIMA di sparare
e stampa il massimo raggiungibile. Verificato su entrambi i rami.
Anche: l'USDe ha un fee Deribit del 5% mai nominato prima. Il nostro misurato
(~4,5%/anno) e' gia' netto: e' l'unico numero da citare.
Stato: USDE 643,175691 (31,29%, al tetto), USDC $1.412,40, totale $2.055,57.
Suite: 795 passati.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
96 lines
3.9 KiB
Python
96 lines
3.9 KiB
Python
"""USDE come collaterale a rendimento — autorita' unica su config, prezzo e valutazione.
|
|
|
|
PERCHE' UN MODULO. Il 2026-08-26 il test di eligibilita' ($500 USDC->USDE) ha scoperto che
|
|
`shadow._equity` leggeva solo il conto USDC: -24% fantasma, falso 'USCITA DI FONDI' e vendite
|
|
indesiderate al giro successivo. La riparazione e' nata dentro shadow.py; qui diventa
|
|
struttura: shadow (equity ORARIA del book) e scripts/live/usde_watch.py (sorveglianza
|
|
GIORNALIERA) derivano entrambi da questo modulo, che a sua volta legge la sezione `usde` di
|
|
`config/live.json` (P1: il bersaglio si deriva, non si ridichiara).
|
|
|
|
LE PROPRIETA' DELLA VALUTAZIONE (blindate in tests/test_shadow_usde.py e test_usde_watch.py):
|
|
* il prezzo viene dall'indice pubblico `usde_usdc` (mediana multi-exchange, clamp +-0.5%
|
|
per fonte) — MAI dal book interno: il 10/10/2025 Binance marco' USDe a $0.65 sull'oracle
|
|
del proprio book mentre l'indice mondo diceva ~$0.99;
|
|
* un depeg sotto la pari PASSA nel sizing (il rischio vero e' il mark-down del collaterale);
|
|
* sopra la pari si clampa a 1.0 (conservativo);
|
|
* prezzo non leggibile -> 1.0 DICHIARATO, mai 0 (contare 0 ricrea il falso -24%; P5: il
|
|
fallback si sceglie sul danno).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
|
CFG_PATH = PROJECT_ROOT / "config" / "live.json"
|
|
SPOT = "USDE_USDC" # coppia spot Deribit (fee 0, spread osservato ~3 bps il 26/08)
|
|
|
|
# Default = i valori decisi il 2026-08-26 (r0826_usde_scenari + verifica sul venue). Usati SOLO
|
|
# se config/live.json non ha la sezione `usde`: la provenienza sta nel campo `fonte` di cfg(),
|
|
# cosi' un report dice quale delle due configurazioni sta guardando (P7).
|
|
_DEFAULTS = {
|
|
"index_name": "usde_usdc",
|
|
"haircut": 0.10,
|
|
"quota_max_frac": 0.50,
|
|
"venue_cap_frac": 0.312, # tetto MISURATO del venue sulla quota USDE (non documentato)
|
|
"venue_cap_misurato": "2026-08-31",
|
|
"depeg_warn": 0.99,
|
|
"depeg_crit": 0.95,
|
|
}
|
|
|
|
|
|
def cfg() -> dict:
|
|
"""Sezione `usde` di config/live.json; default dichiarati se assente. Mai solleva."""
|
|
try:
|
|
raw = json.loads(CFG_PATH.read_text()).get("usde")
|
|
except Exception:
|
|
raw = None
|
|
out = dict(_DEFAULTS)
|
|
if isinstance(raw, dict):
|
|
out.update(raw)
|
|
out["fonte"] = "config/live.json"
|
|
else:
|
|
out["fonte"] = "default (sezione `usde` assente in config)"
|
|
return out
|
|
|
|
|
|
def index_url(index_name: str | None = None) -> str:
|
|
return ("https://www.deribit.com/api/v2/public/get_index_price?index_name="
|
|
f"{index_name or cfg()['index_name']}")
|
|
|
|
|
|
def prezzo_indice(url: str | None = None, timeout: float = 5.0) -> float | None:
|
|
"""Indice pubblico Deribit (tokenless). None se non leggibile o fuori banda. Mai solleva."""
|
|
try:
|
|
import requests
|
|
r = requests.get(url or index_url(), timeout=timeout).json()
|
|
px = float(r["result"]["index_price"])
|
|
return px if 0.0 < px < 2.0 else None
|
|
except Exception:
|
|
return None
|
|
|
|
|
|
def prezzo(client=None, url: str | None = None) -> tuple[float | None, str]:
|
|
"""Catena di prezzo: indice pubblico -> ticker spot via gateway -> None. -> (px, fonte)."""
|
|
px = prezzo_indice(url=url)
|
|
if px is not None:
|
|
return px, "indice"
|
|
if client is not None:
|
|
try:
|
|
px = float(client.ticker(SPOT).get("last_price") or 0) or None
|
|
if px is not None and 0.0 < px < 2.0:
|
|
return px, "ticker spot"
|
|
except Exception:
|
|
pass
|
|
return None, "non leggibile"
|
|
|
|
|
|
def valuta(eq_usde: float, px: float | None) -> tuple[float, str]:
|
|
"""PURA. -> (valore USD del collaterale USDE, nota di provenienza)."""
|
|
if eq_usde <= 0:
|
|
return 0.0, ""
|
|
if px is None or not (0.0 < px < 2.0):
|
|
return eq_usde, f"USDE {eq_usde:,.0f} valutato 1.0000 (indice non leggibile)"
|
|
p = min(px, 1.0)
|
|
return eq_usde * p, f"USDE {eq_usde:,.0f} @ {p:.4f}"
|