cfc42653cc
Un'eccezione sulla lettura del conto USDE valeva 0 USDE: se il conto ne aveva davvero, l'equity totale risultava sottostimata senza che nulla lo dicesse. Ora _collaterale_usde ritorna None + la nota dell'eccezione, e _equity propaga l'ignoto (real_eq None -> eq_fallback, non un numero falso). shadow_report.online guardava solo il mark di BTC: con ETH in fallback il giro si considerava comunque online. Ora richiede TUTTI i mark da mainnet. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
85 lines
3.4 KiB
Python
85 lines
3.4 KiB
Python
"""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_rende_lequity_IGNOTA_non_solo_usdc():
|
|
"""(#20) Comportamento cambiato: un'eccezione sulla lettura del conto USDE NON vale 0 USDE.
|
|
Prima di questa riparazione, `eq` restava $2056 (solo USDC) come se l'USDE non ci fosse:
|
|
se sul conto c'era davvero collaterale USDE, quel $2056 era un equity sottostimato spacciato
|
|
per certo. Ora l'intera equity e' IGNOTA (None) — coerente col trattamento di ogni altra
|
|
lettura fallita nel modulo (posizione, mark): non si assume, si segnala."""
|
|
eq, src = S._equity(_Client(usdc=2056.0, usde=500.0, usde_raises=True), {})
|
|
assert eq is None
|
|
assert "USDE illeggibile" in src and "RuntimeError" in src
|