venue_watch: disciplina degli allarmi, specifiche contratto controllate, terza referenza
Il 18/08 sono usciti quattro 🚨 identici con 'PRIMO PASSO: prelievo di prova' per una manutenzione Deribit annunciata, e tutti e quattro DOPO che il book aveva gia' ripreso a eseguire. Il book si era comportato bene (due giri di astensione, 'non eseguo a cieco'); il difetto era negli allarmi. 1. Il blocco piattaforma era un if secco senza memoria, accanto a un rilevatore tarato con cura che allerta una volta per streak. Ora passa da lock_step(), pura e testata: manutenzione entro tolleranza = un solo avviso morbido, che sfora = un solo 🚨 ('ha SFORATO'), blocco inspiegato = 🚨 subito, rientro annunciato una volta. public/status illeggibile NON e' un rientro. 2. Il messaggio diceva 'locked=true' cablato mentre il parser accetta anche 'partial': dichiarava un valore che non aveva letto, e il runbook manda a controllare proprio quel campo. Ora stampa e salva il valore grezzo. 3. Deribit ha cambiato tick e size dei perpetual lineari USDC il 18/08 e la tabella _CONTRACT, cablata a mano, non se n'era accorta. Nessun ordine rifiutato solo perche' i cambi erano riduzioni: e' andata bene per la direzione, non perche' ce ne fossimo accorti. Tabella aggiornata ai valori verificati e aggiunto check_specs(), che gira nel venue_watch orario (fuori dal percorso ordini) e dichiara la direzione: 'granularita'' = conforme, 'rifiuto' = il venue rifiuta. La tabella dichiarata resta l'autorita' per costruire un ordine, il venue e' il controllore. 4. Aggiunta Kraken come terza referenza: Coinbase ha comprato Deribit, e una referenza che e' la casa madre non misura piu' se Deribit scolla dal mondo. THRESHOLD_BPS e PERSIST_HOURS invariati, ma il consenso ora e' su tre serie e quel numero non e' ri-misurato: dichiarato nel codice e nel diario. La direzione dell'errore e' 'allerta di meno', non 'grida al lupo'. Test 23 -> 35 su venue_watch, suite intera 618 verdi. Book, pesi e config invariati; dry-run del book verificato. Diario: docs/diary/2026-08-19-*. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,7 @@ from pathlib import Path
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
from src.live.deribit import check_specs # noqa: E402
|
||||
from src.live.notifier import notify # noqa: E402
|
||||
from src.live.venue_watch import (PERSIST_HOURS, THRESHOLD_BPS, # noqa: E402
|
||||
run_once)
|
||||
@@ -30,7 +31,10 @@ def main() -> int:
|
||||
print("=" * 78)
|
||||
print(f" soglia: {THRESHOLD_BPS:.0f} bps persistenti {PERSIST_HOURS}h a segno costante")
|
||||
lock = rep["platform_locked"]
|
||||
print(f" public/status locked: {lock if lock is not None else 'non leggibile'}")
|
||||
print(f" public/status locked: {rep.get('locked_raw') or 'non leggibile'}"
|
||||
+ (f" (da {rep['lock_hours']}h"
|
||||
+ (", manutenzione dichiarata" if rep.get("maintenance") else "") + ")"
|
||||
if lock else ""))
|
||||
for a, lvl in rep["levels"].items():
|
||||
d = rep["detail"][a]
|
||||
bps = f"{d['bps']:+7.1f} bps" if d["bps"] is not None else " n/d "
|
||||
@@ -38,14 +42,45 @@ def main() -> int:
|
||||
f"spread {d['ref_spread_bps']:.1f} bps)" if d["ref_spread_bps"] is not None
|
||||
else f" {a:<4} {lvl:<6} {bps} ({d['n_refs']} referenze)")
|
||||
|
||||
# --- specifiche contratto: la tabella dichiarata si e' scostata dal venue?
|
||||
# ⚠️ Gira qui e non nel book: e' un controllo di SOLA LETTURA e non deve stare sul percorso
|
||||
# che manda ordini. Il 18/08 Deribit ha cambiato tick e size dei perpetual lineari USDC e
|
||||
# niente se n'era accorto: e' andata bene perche' i cambi erano riduzioni.
|
||||
spec = check_specs()
|
||||
if spec["divergenze"]:
|
||||
rifiuto = [d for d in spec["divergenze"] if d["rischio"] == "rifiuto"]
|
||||
righe = {f"{d['strumento']} {d['campo']}": f"dichiarato {d['dichiarato']} / "
|
||||
f"venue {d['venue']} -> {d['rischio']}"
|
||||
for d in spec["divergenze"]}
|
||||
if rifiuto:
|
||||
righe["azione"] = ("il dichiarato e' PIU' FINE del venue: gli ordini verranno "
|
||||
"RIFIUTATI. Correggi _CONTRACT in src/live/deribit.py adesso.")
|
||||
notify("🚨 SPEC CONTRATTO — Deribit rifiutera' gli ordini", righe)
|
||||
else:
|
||||
righe["azione"] = ("il dichiarato e' piu' GROSSO del venue: gli ordini restano "
|
||||
"conformi, si perde solo granularita'. Aggiorna _CONTRACT "
|
||||
"in src/live/deribit.py.")
|
||||
notify("⚠️ SPEC CONTRATTO — la tabella dichiarata e' vecchia", righe)
|
||||
for k, v in righe.items():
|
||||
print(f" SPEC: {k}: {v}")
|
||||
|
||||
if rep["alerts"]:
|
||||
# ⚠️ Il titolo dice cosa FARE, non solo cosa e' successo: chi lo legge sul telefono deve
|
||||
# sapere il primo passo senza aprire il repo (runbook completo in src/live/venue_watch.py).
|
||||
notify("🚨 VENUE WATCH — possibile stress su Deribit. PRIMO PASSO: prelievo di prova",
|
||||
{f"alert {i+1}": a for i, a in enumerate(rep["alerts"])})
|
||||
# ⚠️ Dal 19/08 il titolo DIPENDE dalla gravita'. Prima era sempre il 🚨 col prelievo di
|
||||
# prova, anche per un blocco da manutenzione annunciata: il 18/08 sono usciti quattro
|
||||
# messaggi identici che chiedevano di prelevare, tutti dopo che il book aveva gia'
|
||||
# ripreso. Un allarme massimo speso per un evento atteso e' un allarme che non verra'
|
||||
# letto il giorno che e' vero — ed e' l'unico giorno che conta.
|
||||
if rep.get("severity") == "warn":
|
||||
titolo = "⚠️ VENUE WATCH — Deribit non operativa, ma spiegata. Nessuna azione"
|
||||
else:
|
||||
titolo = ("🚨 VENUE WATCH — possibile stress su Deribit. "
|
||||
"PRIMO PASSO: prelievo di prova")
|
||||
notify(titolo, {f"alert {i+1}": a for i, a in enumerate(rep["alerts"])})
|
||||
for a in rep["alerts"]:
|
||||
print(f" ALERT: {a}")
|
||||
return 2
|
||||
return 2 if rep.get("severity") == "alert" else 0
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user