Files
PythagorasGoal/docs/diary/2026-07-26-venue-tripwire.md
T
Adriano Dal Pastro ab5bcace16 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>
2026-07-26 19:38:19 +00:00

9.6 KiB

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.