feat: VENUE WATCH — tripwire di fallimento exchange, cablato live
Risposta a "trova un sistema di protezione da fallimento exchange" SOTTO IL VINCOLO della decisione appena presa (100% Deribit fino a $20k). Se non si puo' ridurre l'ESPOSIZIONE, l'unica leva e' il TEMPO: il modello di rischio del mattino assumeva il salto a zero istantaneo, ma i fallimenti reali non lo sono (Mt.Gox mesi, FTX ~72h, e misurato qui: Bitfinex 2018-19 dislocato per 2.324 ore consecutive). SEGNALE: un venue che gata i prelievi rompe l'ARBITRAGGIO -> il prezzo si stacca dal consenso e ci resta. E' |scarto|, non il segno (Mt.Gox a premio, un venue in fuga a sconto: stessa cosa). Consenso = venue USD indipendenti (Coinbase, Bitstamp), mai USDT. Deribit sta a 3 bps dal consenso in mediana su 8 anni (65.043 ore BTC + 64.541 ETH). TARATURA CONGELATA: 100 bps persistenti 4h a segno costante. Criterio DICHIARATO PRIMA, perche' i due ovvi sbagliano in versi opposti (provati entrambi): "minimi bps" -> 25/24h consuma 24 delle ~72h di FTX; "minime ore" -> 500/2h MANCA FTX (margine 0.6x). Regola: zero falsi allarmi in 8 anni + margine >=3x sul caso storico piu' debole -> soglia <=100bps -> poi minima latenza. Margine 3x FTX / 5x Quadriga / 10-20x Mt.Gox, zero falsi allarmi con crash COVID, maggio 2021, LUNA e novembre 2022 inclusi. CONTROLLO POSITIVO SUPERATO (un rilevatore tarato per non segnalare e' indistinguibile da uno rotto): puntato su Bitfinex 2018-19 scatta 22 volte, episodio piu' lungo 2.324h a +447bps. 22 dove il problema c'era, 0 su Deribit. E la durata risponde alla domanda vera: un venue gated resta dislocato per settimane, quindi 4h di latenza sono trascurabili. ECONOMIA: falso allarme = 0.248% atteso (flat 3g misurato sul book reale a ogni data d'inizio); vero positivo = 100% salvato. Break-even p > (falsi/anno) x 0.00248: a 1 ogni 8 anni serve p > 0.031%. Il valore sta nella SPECIFICITA', non nella sensibilita'. CABLATO: src/live/venue_watch.py (nucleo puro) + scripts/live/venue_watch.py, in cron_book.sh PRIMA di book_execute (se Deribit e' in stress l'allarme deve partire anche quando l'esecuzione fallisce per la stessa ragione). Tre stati OK/ALERT/BLIND — "non vedo" non e' "va bene". ALLERTA, NON BLOCCA: l'azione e' prelevare (manuale; una chiave con permesso di prelievo sarebbe essa stessa un rischio) e bloccare non protegge un saldo che e' a rischio anche stando flat. Runbook pre-deciso nel docstring. NON COPRE, e non e' un argomento per riaprire il 26/07: un fallimento SENZA finestra (furto chiavi, sequestro, exit-scam) non lo prende nessun tripwire. ERRORI CATTURATI IN SESSIONE: - break-even calcolato sul p5 invece che sulla media (8.3x piu' severo, conclusione ribaltata); - ipotesi meccanica sbagliata: credevo che i crash dislocassero a segno ALTERNATO. Falso, sono a segno costante anche loro (perp sotto spot per ore in cascata). A separare sono ampiezza e durata, non il segno; - la prima corsa tronco' il campione da 8 anni a 29 GIORNI per un inner-join con Kraken (che serve solo ~700 candele) e la copertura era gia' stampata a video: una diagnostica stampata NON e' un controllo. Ora c'e' una guardia che ferma lo script. 2a occorrenza in un giorno dopo GTAA01; - il controllo positivo era finito dentro il ramo `else` -> non girava mai, cioe' esattamente il difetto che doveva prevenire. Book, pesi, config INVARIATI. 359 test verdi (+23). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
# 2026-07-26 — Un sistema di protezione dal fallimento exchange, a capitale concentrato
|
||||
|
||||
**Richiesta:** *"trova un sistema di protezione da fallimento exchange"* — subito dopo la decisione
|
||||
di restare **100% su Deribit fino a $20k**.
|
||||
|
||||
Il vincolo e' quello che rende il problema interessante: **la riduzione dell'esposizione e' fuori
|
||||
discussione**. Lo split di venue e' stato valutato e rifiutato con motivo (§5 del diario
|
||||
`2026-07-26-venue-risk.md`). Quindi non si puo' ridurre *quanto* si perde: si puo' solo ridurre
|
||||
**la probabilita' di essere ancora dentro quando succede**.
|
||||
|
||||
**Script:** `r0726_venue_tripwire.py` (il segnale), `r0726_venue_response.py` (il costo di
|
||||
rispondere). **Produzione:** `src/live/venue_watch.py` + `scripts/live/venue_watch.py`, cablato in
|
||||
`cron_book.sh`. **Test:** `tests/test_venue_watch.py` (23). **Book, pesi, config: INVARIATI.**
|
||||
|
||||
---
|
||||
|
||||
## 0. L'idea in una riga
|
||||
|
||||
Il modello di rischio del mattino assumeva il **salto a zero istantaneo**. I fallimenti reali non
|
||||
lo sono: Mt.Gox gato' i prelievi per mesi, FTX ebbe ~72 ore, e — misurato qui — **Bitfinex nel
|
||||
2018-19 resto' dislocato dal consenso per 2.324 ore consecutive**. Se dentro quella finestra il
|
||||
saldo esce, la perdita non e' totale. Il sistema e' quindi un **rilevatore di finestra**, non una
|
||||
riduzione di esposizione.
|
||||
|
||||
## 1. Il segnale, e perche' e' falsificabile
|
||||
|
||||
Quando un exchange gata i prelievi **l'arbitraggio si rompe**: non si puo' piu' comprare li' e
|
||||
vendere altrove per chiudere lo scarto, quindi il suo prezzo si stacca dal consenso e ci resta.
|
||||
Il segnale e' **|scarto|, non il segno** — su Mt.Gox il BTC andava a *premio* (si comprava BTC per
|
||||
far uscire valore), su un venue in fuga si vede lo *sconto*. Dicono la stessa cosa.
|
||||
|
||||
Misurato su 8 anni di feed certificato, consenso = mediana di venue **USD indipendenti** (Coinbase,
|
||||
Bitstamp; mai USDT — il depeg 2022 sposta BTC/USDT fino al 3% e genererebbe falsi allarmi giganti):
|
||||
|
||||
```
|
||||
asset ore mediana p95 p99 p99.9 max >50bps >100bps
|
||||
BTC 65,043 3.1 11.4 18.0 34.4 712.9 0.06% 0.018%
|
||||
ETH 64,541 3.3 13.3 22.2 44.3 453.1 0.07% 0.017%
|
||||
```
|
||||
|
||||
Deribit sta a **3 bps** dal consenso in mediana. E' un fondo di rumore bassissimo, ed e' cio' che
|
||||
rende possibile una soglia con margine.
|
||||
|
||||
## 2. L'ipotesi meccanica era in parte SBAGLIATA
|
||||
|
||||
Avevo scritto, prima di misurare, che il discriminante sarebbe stato la **costanza del segno**:
|
||||
un venue gated resta da un lato, un crash rimbalza fra i due. **Falso.** Gli episodi peggiori su
|
||||
Deribit sono tutti a segno costante anche loro:
|
||||
|
||||
```
|
||||
BTC 2020-03-13 10:00 12h picco 158 bps segno -1 (crash COVID)
|
||||
ETH 2022-09-14 20:00 10h picco 97 bps segno -1 (Merge)
|
||||
ETH 2020-03-12 23:00 3h picco 453 bps segno -1
|
||||
BTC 2021-07-01 13:00 2h picco 150 bps segno +1
|
||||
```
|
||||
|
||||
In un cascata di liquidazioni il perp sta **sotto** lo spot per ore di fila: e' un run a segno
|
||||
costante come quello di un venue gated. Il segno costante resta nel rilevatore (toglie il rumore
|
||||
simmetrico), ma **non e' lui a separare i due casi**: separano **ampiezza e durata**. Ipotesi
|
||||
corretta nella conclusione, sbagliata nel meccanismo.
|
||||
|
||||
## 3. La taratura va DICHIARATA, perche' due criteri ovvi sbagliano in versi opposti
|
||||
|
||||
Provati entrambi in sessione:
|
||||
|
||||
| criterio ingenuo | esito | perche' e' sbagliato |
|
||||
|---|---|---|
|
||||
| **minimi bps** | 25 bps / 24h | consuma 24 delle ~72 ore che diede FTX |
|
||||
| **minime ore** | 500 bps / 2h | **manca FTX** (300 bps): margine 0.6x |
|
||||
|
||||
Criterio adottato, in quest'ordine: **(1)** zero falsi allarmi su entrambi gli asset in 8 anni;
|
||||
**(2)** margine ≥3x sul caso storico **piu' debole** (FTX ~300 bps) → soglia ≤100 bps; **(3)** a
|
||||
quei vincoli, **minima latenza**.
|
||||
|
||||
```
|
||||
2h -> 500 bps (scartata: 0.6x < 3x su FTX)
|
||||
3h -> 150 bps (scartata: 2.0x < 3x su FTX)
|
||||
4h -> 100 bps <- SCELTA
|
||||
6h -> 75 bps
|
||||
24h -> 25 bps
|
||||
```
|
||||
|
||||
**→ 100 bps persistenti 4 ore a segno costante.** Margine 3x su FTX, 5x su QuadrigaCX, 10-20x su
|
||||
Mt.Gox. Zero falsi allarmi in 8 anni, **crash COVID / maggio 2021 / LUNA / novembre 2022 inclusi**.
|
||||
|
||||
## 4. Il controllo positivo — senza, "non scatta mai" non e' una buona notizia
|
||||
|
||||
Un rilevatore tarato per non segnalare e' indistinguibile da uno rotto. Puntato su **Bitfinex
|
||||
2018-19** (problemi bancari/Tether, premio persistente), consenso Coinbase+Bitstamp con Bitfinex
|
||||
escluso dal proprio consenso:
|
||||
|
||||
```
|
||||
BTC: 33.000 ore, scarto mediano 11 bps, max 1136 bps -> 22 EPISODI a 100bps/4h
|
||||
2018-12-26 2324h picco 447 bps segno +1
|
||||
2018-11-08 1151h picco 663 bps segno +1
|
||||
2018-10-10 496h picco 1136 bps segno +1
|
||||
2019-04-25 363h picco 734 bps segno +1
|
||||
```
|
||||
|
||||
**22 scatti su un venue realmente in stress, zero su Deribit in 8 anni.** E la *durata* di quegli
|
||||
episodi risponde alla domanda che conta davvero: un venue gated resta dislocato per **settimane**,
|
||||
quindi 4 ore di latenza di rilevamento costano una frazione trascurabile del preavviso.
|
||||
|
||||
## 5. Il lato risposta: quanto costa sbagliarsi
|
||||
|
||||
Un allarme senza il costo della risposta non e' un sistema. Misurato sul book Deribit reale
|
||||
(TP01+SKH01 75/25) forzando flat una finestra a **ogni** data d'inizio possibile:
|
||||
|
||||
```
|
||||
giorni costo medio mediana p5 (peggio) p95 (meglio) % dannosi
|
||||
1 -0.149% -0.100% -1.093% 0.590% 76.4%
|
||||
3 -0.248% -0.100% -2.065% 1.006% 67.9%
|
||||
7 -0.442% -0.100% -4.072% 1.505% 62.4%
|
||||
30 -1.537% -0.455% -9.236% 2.993% 57.3%
|
||||
```
|
||||
|
||||
⚠️ **Errore mio, corretto:** avevo impostato il break-even sul **p5** (la coda). Per un valore
|
||||
atteso ripetuto nel tempo si usa la **media** — con la coda il numero esce 8.3x piu' severo e la
|
||||
conclusione si ribalta. Il p5 serve a sapere quanto puo' bruciare *una* volta, non a decidere.
|
||||
|
||||
```
|
||||
Il tripwire conviene se p_annua > (falsi allarmi/anno) x 0.00248:
|
||||
1 ogni 8 anni -> p > 0.031% conviene per ogni p del ventaglio
|
||||
1/anno -> p > 0.248% conviene per ogni p del ventaglio
|
||||
4/anno -> p > 0.991% conviene da p=1%
|
||||
12/anno -> p > 2.974% conviene solo a p=5%
|
||||
52/anno -> p > 12.889% NON conviene mai
|
||||
```
|
||||
|
||||
**Il valore del sistema sta tutto nella SPECIFICITA', non nella sensibilita'.** Un tripwire che
|
||||
strilla 12 volte l'anno sarebbe dannoso; questo, a zero falsi allarmi misurati su 8 anni, ha un
|
||||
break-even di **p > 0.031%** — un ordine di grandezza sotto l'ipotesi piu' ottimistica del
|
||||
venue-risk (0.5%).
|
||||
|
||||
## 6. Cosa e' stato cablato
|
||||
|
||||
`src/live/venue_watch.py` (nucleo puro, testabile) + `scripts/live/venue_watch.py` (runner), in
|
||||
`cron_book.sh` **prima** di `book_execute` — se Deribit e' in stress l'allarme deve partire anche
|
||||
quando l'esecuzione fallisce per la stessa ragione.
|
||||
|
||||
**Tre stati, e il terzo non e' il primo:** `OK` (misurato, sotto soglia) / `ALERT` (misurato,
|
||||
sopra soglia e persistente → Telegram) / **`BLIND`** (non misurabile: referenze irraggiungibili o
|
||||
in disaccordo fra loro). *"Non vedo" non e' "va tutto bene"*: dopo 12 ore di cecita' scatta un
|
||||
allarme suo. Stessa lezione della contabilita' a 3 stati di `paper_dvolspread`.
|
||||
|
||||
**Allerta, non blocca.** L'azione giusta a un vero positivo e' *prelevare*, che richiede comunque
|
||||
un intervento manuale — una chiave API con permesso di prelievo sarebbe essa stessa un rischio.
|
||||
E bloccare l'esecuzione non protegge il saldo: il saldo e' a rischio anche stando flat.
|
||||
|
||||
**Runbook pre-deciso** (nel docstring del modulo, per non doverlo decidere nel momento sbagliato):
|
||||
1. escludere il guasto delle referenze (`n_refs`, `ref_spread_bps`);
|
||||
2. `public/status` (`platform_locked`) e canali ufficiali;
|
||||
3. **prelievo di prova piccolo** — l'unica evidenza DIRETTA; se non passa in tempi normali
|
||||
l'allarme e' vero qualunque altra spiegazione esista;
|
||||
4. se non passa: flat + prelievo totale. Sbagliarsi costa **0.248%**, aver ragione salva il 100%.
|
||||
|
||||
## 7. Cio' che questo sistema NON copre — e va detto
|
||||
|
||||
Il tripwire prezza la finestra, non la sua esistenza. **Un fallimento senza finestra non lo prende
|
||||
nessuno**: furto di chiavi, sequestro, exit-scam notturno. Quella parte di `p` resta scoperta, e la
|
||||
sola difesa e' quella che l'operatore ha rifiutato fino a $20k — lo split. Il sistema **riduce** il
|
||||
rischio di venue, non lo elimina, e non e' un argomento per cambiare la decisione del 26/07.
|
||||
|
||||
Secondo limite dichiarato: il preavviso storico di 200-2300 ore viene da **un** caso osservato
|
||||
(Bitfinex). E' un'ancora, non una distribuzione.
|
||||
|
||||
## 8. Regole trasferibili
|
||||
|
||||
1. **Un rilevatore tarato per non segnalare va validato su un controllo positivo**, o "non e' mai
|
||||
scattato" e' indistinguibile da "e' rotto". Qui: 22 scatti su Bitfinex, zero su Deribit.
|
||||
2. **Una soglia si sceglie con un criterio dichiarato PRIMA**, perche' i criteri ovvi sbagliano in
|
||||
versi opposti: "minimi bps" perde preavviso, "minime ore" perde il caso da prendere.
|
||||
3. **La persistenza richiesta e' latenza, e la latenza va sottratta al preavviso.** Va confrontata
|
||||
con la durata del fenomeno da rilevare, non scelta in astratto.
|
||||
4. **Un break-even si calcola sulla media, non sulla coda.** La coda dice quanto fa male una volta;
|
||||
la media dice se conviene ripeterlo.
|
||||
5. **Un outer-join con una referenza corta e' una trappola** (2ª volta oggi, dopo GTAA01): la
|
||||
prima corsa tronco' il campione da 8 anni a 29 giorni *in silenzio*, e la diagnostica di
|
||||
copertura era gia' stampata. **Una diagnostica stampata non e' un controllo** — ora c'e' una
|
||||
guardia che ferma lo script.
|
||||
6. **Un controllo positivo dentro il ramo `else` non gira mai.** Trovato in sessione: era finito
|
||||
nel ramo di fallimento, cioe' esattamente il difetto che doveva prevenire.
|
||||
Reference in New Issue
Block a user