live: l'equity del book e' il TOTALE cross-collateral — USDE valutato all'indice pubblico

Trovato eseguendo il test di eligibilita' USDE ($500 convertiti alle 13:04Z,
fill 1.0003 fee 0): shadow._equity leggeva solo il conto USDC -> il giro
successivo avrebbe visto -24,3%, mandato un falso "USCITA DI FONDI" e venduto
~$140 di posizioni. Riparato prima del giro delle 13:47: _collaterale_usde()
valuta l'USDE all'indice pubblico usde_usdc (mediana multi-exchange, lezione
Binance 10/10/2025), depeg passa nel sizing, clamp a 1.0 sopra la pari,
fallback 1.0 dichiarato (mai 0: il fallback si sceglie sul danno, P5).
6 test nuovi in tests/test_shadow_usde.py.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B9UyJLHzR7EJzxR3iQ3RN1
This commit is contained in:
Adriano Dal Pastro
2026-08-26 13:07:29 +00:00
parent 562e95338b
commit 631e854b29
3 changed files with 142 additions and 1 deletions
+78
View File
@@ -0,0 +1,78 @@
"""L'equity del book e' il TOTALE cross-collateral, non il solo conto USDC.
Il difetto (2026-08-26, trovato DURANTE il test di eligibilita' USDE): convertiti $500 in
USDE, `_equity` leggeva solo il conto USDC -> il book avrebbe visto -24%, mandato un falso
'USCITA DI FONDI' e VENDUTO ~$140 di posizioni al giro successivo. La riparazione valuta
l'USDE all'indice pubblico; questi test blindano le proprieta' che contano:
un depeg PASSA nel sizing (non viene nascosto), sopra la pari si clampa, e il fallback
a indice illeggibile e' 1.0 dichiarato (contare 0 ricreerebbe il falso -24%).
"""
from __future__ import annotations
import sys
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
from src.live import shadow as S # noqa: E402
class _Client:
def __init__(self, usdc=1556.0, usde=0.0, ticker_last=None, usde_raises=False):
self._usdc, self._usde = usdc, usde
self._last, self._raises = ticker_last, usde_raises
def account_summary(self, cur):
if cur == "USDE":
if self._raises:
raise RuntimeError("gateway giu'")
return {"equity": self._usde}
return {"equity": self._usdc}
def ticker(self, instrument):
if self._last is None:
raise RuntimeError("ticker non disponibile")
return {"last_price": self._last}
@pytest.fixture(autouse=True)
def _niente_indice_pubblico(monkeypatch):
# l'indice pubblico non si interroga nei test: URL invalido -> fallback al ticker finto
monkeypatch.setattr(S, "USDE_INDEX_URL", "http://127.0.0.1:1/nope")
def test_senza_usde_nulla_cambia():
eq, src = S._equity(_Client(usdc=2056.0, usde=0.0), {})
assert eq == 2056.0 and src == "mainnet USDC"
def test_l_usde_entra_nel_totale_al_prezzo_di_mercato():
eq, src = S._equity(_Client(usdc=1556.0, usde=500.0, ticker_last=0.9999), {})
assert abs(eq - (1556.0 + 500.0 * 0.9999)) < 1e-9
assert "USDE" in src and "0.9999" in src
def test_un_depeg_PASSA_nel_sizing_non_viene_nascosto():
# 10/10/2025: il rischio vero e' il mark-down del collaterale in un crash.
eq, src = S._equity(_Client(usdc=1556.0, usde=500.0, ticker_last=0.97), {})
assert abs(eq - (1556.0 + 500.0 * 0.97)) < 1e-9
def test_sopra_la_pari_si_clampa_a_uno():
eq, _ = S._equity(_Client(usdc=1556.0, usde=500.0, ticker_last=1.02), {})
assert abs(eq - (1556.0 + 500.0)) < 1e-9
def test_indice_illeggibile_vale_uno_DICHIARATO_mai_zero():
# contare 0 ricreerebbe il falso -24% (alert + vendite): il fallback e' 1.0 con nota
eq, src = S._equity(_Client(usdc=1556.0, usde=500.0, ticker_last=None), {})
assert abs(eq - 2056.0) < 1e-9
assert "non leggibile" in src
def test_gateway_usde_giu_non_rompe_la_lettura_usdc():
eq, src = S._equity(_Client(usdc=2056.0, usde=500.0, usde_raises=True), {})
assert eq == 2056.0 and src == "mainnet USDC"