fee_watch: sorvegliava i perpetual INVERSE mentre il book trada i LINEARI USDC
Trovato in un check generale. INSTRUMENTS era la tupla cablata
("BTC-PERPETUAL","ETH-PERPETUAL") — gli inverse, regolati in BTC/ETH — mentre
src.live.book.INSTRUMENT punta a BTC_USDC-PERPETUAL / ETH_USDC-PERPETUAL.
Due conseguenze, e la seconda era gia' visibile ogni giorno nel log:
1. Il tier sorvegliato era di un prodotto che il book non tratta. Oggi coincidono
(3.50/1.50 su entrambe le linee) ma la prova che si muovono in modo indipendente
e' nel progetto: il cambio del 18/08 tocco' tick e size dei SOLI lineari USDC
(inverse ancora tick 0.5 / min 10.0, lineari 0.1 / 0.0001). Un aumento sulla sola
linea lineare sarebbe stato invisibile, e la regola decisa in anticipo
(<=5bps nulla / >10bps rivedere il peso SKH01) applicata al numero sbagliato.
2. Il cross-check sui trade REALI — la fonte autorevole, cioe' quanto abbiamo
davvero pagato — non poteva misurare nulla per costruzione: chiedeva la storia di
uno strumento con zero fill. Stampava "NON MISURATO (nessun trade recente
leggibile)" anche in un giorno con 4 esecuzioni. Verificato sul conto: inverse
0 trade, _USDC-PERPETUAL 3 (BTC) e 1 (ETH).
FIX. INSTRUMENTS si DERIVA da src.live.book.INSTRUMENT: la divergenza non e' piu' un
rischio da ricordare, e' impossibile.
E non era un rename di due stringhe: le due famiglie hanno unita' DIVERSE. Inverse
amount = nozionale USD e fee in valuta base; lineare amount = quantita' base e fee
gia' in USDC. Ripuntare senza correggerle avrebbe dato, su un fill vero (0.001 BTC
@ 74.305,80, fee 0,02600703 USDC), ~2,6e8 bps invece di 3,50 — senza sollevare
nulla. Aggiunte convenzione() (lineare / inverse / IGNOTA: una famiglia non nota non
si indovina, si dichiara) e fee_bps_di_un_fill(), entrambe pure. Il cross-check ora
gira e da' 3,50 bps effettivi = il tier esatto; il report stampa lo scarto
effettivo-tier con ⚠️ oltre 1 bps.
Test 13 -> 17, verificati per MUTAZIONE: rimettendo la tupla cablata fallisce
test_sorveglia_esattamente_gli_strumenti_DEL_BOOK; scambiando le convenzioni
fallisce test_le_due_famiglie_hanno_unita_DIVERSE_e_scambiarle_non_fa_rumore, che
contiene il controllo positivo (la convenzione sbagliata NON solleva niente, mente).
3a occorrenza in un giorno della stessa forma di difetto, dopo i test di book_live
(potenza zero a libro flat) e la taratura di venue_watch (misurata con bitfinex
mentre il live girava senza): un controllo puntato su una configurazione diversa da
quella che gira passa sempre, e non sta controllando niente. REGOLA: un sorvegliante
DERIVA il proprio bersaglio dal codice sorvegliato, mai lo ridichiara.
Book, pesi, config, cron, soglie fee: INVARIATI. Suite 625 verdi, 1 rosso noto
(test_gtaa_band_gate). NB: la prima corsa dopo il fix ha inviato una notifica
Telegram legittima ("strumento nuovo nella sorveglianza"); lo stato e' poi assestato.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -108,3 +108,57 @@ def test_sorveglia_il_tier_base_e_lo_dichiara():
|
||||
def test_fee_reali_assenti_non_sono_fee_zero():
|
||||
"""{} = 'non misurata'. Un dict vuoto letto come 'zero' direbbe che il book trada gratis."""
|
||||
assert FW.realized_fee_bps.__doc__ and "non misurata" in FW.realized_fee_bps.__doc__
|
||||
|
||||
|
||||
# ===========================================================================
|
||||
# STRUMENTI E UNITA' — il difetto trovato il 2026-08-21.
|
||||
# `INSTRUMENTS` era la tupla cablata ("BTC-PERPETUAL", "ETH-PERPETUAL"), cioe' gli INVERSE,
|
||||
# mentre il book esegue sui LINEARI USDC. Il tier sorvegliato era di un prodotto mai tradato
|
||||
# e il cross-check sui trade reali non poteva misurare nulla per costruzione.
|
||||
# ===========================================================================
|
||||
def test_sorveglia_esattamente_gli_strumenti_DEL_BOOK():
|
||||
"""La divergenza non dev'essere un rischio da ricordare: dev'essere impossibile.
|
||||
|
||||
Il 18/08 Deribit ha cambiato tick e size dei SOLI perpetual lineari USDC lasciando intatti
|
||||
gli inverse: le due linee di prodotto si muovono in modo indipendente, quindi sorvegliare
|
||||
l'una mentre si trada l'altra e' un controllo che non controlla.
|
||||
"""
|
||||
from src.live.book import INSTRUMENT as BOOK
|
||||
assert set(FW.INSTRUMENTS) == set(BOOK.values()), \
|
||||
"gli strumenti sorvegliati devono essere quelli su cui il book esegue"
|
||||
assert all(i.endswith("_USDC-PERPETUAL") for i in FW.INSTRUMENTS)
|
||||
|
||||
|
||||
def test_la_convenzione_di_unita_e_dichiarata_e_non_indovinata():
|
||||
assert FW.convenzione("BTC_USDC-PERPETUAL") == "lineare"
|
||||
assert FW.convenzione("BTC-PERPETUAL") == "inverse"
|
||||
# una famiglia che non conosciamo NON si indovina: un fill misurato con la convenzione
|
||||
# sbagliata non da' un errore, da' un numero.
|
||||
assert FW.convenzione("BTC-28MAR27-100000-C") == "ignota"
|
||||
assert FW.fee_bps_di_un_fill("BTC-28MAR27-100000-C", 1.0, 100.0, 0.01) is None
|
||||
|
||||
|
||||
def test_le_due_famiglie_hanno_unita_DIVERSE_e_scambiarle_non_fa_rumore():
|
||||
"""⚠️ Il punto che rende il difetto pericoloso: applicare la convenzione sbagliata non
|
||||
solleva niente. Su un fill VERO del 21/08 (0.001 BTC @ 74.305,80, fee 0,02600703 USDC) la
|
||||
formula giusta da' il tier taker esatto; quella inverse da' un numero enorme e muto.
|
||||
"""
|
||||
amount, price, fee = 0.001, 74305.8, 0.02600703
|
||||
giusto = FW.fee_bps_di_un_fill("BTC_USDC-PERPETUAL", amount, price, fee)
|
||||
assert giusto is not None and abs(giusto - 3.50) < 0.01, f"atteso ~3.50 bps, ottenuto {giusto}"
|
||||
|
||||
# la stessa riga letta con la convenzione inverse: nessuna eccezione, solo un numero falso
|
||||
sbagliato = FW.fee_bps_di_un_fill("BTC-PERPETUAL", amount, price, fee)
|
||||
assert sbagliato is not None and sbagliato > 1e6, \
|
||||
"il controllo positivo deve mostrare che la convenzione sbagliata NON fallisce, mente"
|
||||
|
||||
# e su un fill inverse la convenzione inverse e' quella giusta (amount in USD, fee in BTC)
|
||||
inv = FW.fee_bps_di_un_fill("BTC-PERPETUAL", 74.3058, 74305.8, 74.3058 * 3.5e-4 / 74305.8)
|
||||
assert inv is not None and abs(inv - 3.50) < 0.01
|
||||
|
||||
|
||||
def test_un_fill_non_misurabile_e_None_non_zero():
|
||||
for bad in ((0.0, 100.0, 1.0), (1.0, 0.0, 1.0), (None, 100.0, 1.0), ("x", 100.0, 1.0)):
|
||||
assert FW.fee_bps_di_un_fill("BTC_USDC-PERPETUAL", *bad) is None
|
||||
# fee nulla e' invece una misura legittima (ordine maker a rebate zero)
|
||||
assert FW.fee_bps_di_un_fill("BTC_USDC-PERPETUAL", 1.0, 100.0, 0.0) == 0.0
|
||||
|
||||
Reference in New Issue
Block a user