venue: la taratura ri-misurata — «zero falsi allarmi in 8 anni» non descriveva la produzione

B1 (memoria) + B2 (misura). Il 19/08 stava solo in un diario e in un commit: la
sessione che ha cambiato il tripwire di venue, la tabella _CONTRACT e le referenze
non era in CLAUDE.md — 2a occorrenza dopo edge_watch, e riguarda di nuovo qualcosa
che gira con soldi veri. Ora c'e', insieme al debito che dichiarava.

B2: il debito era «la taratura non e' ri-misurata a tre referenze». Ri-misurandola
(scripts/research/r0821_venue_refs.py, riusa dislocation/episodes/zero_fp_frontier
di r0726) il problema non era dove ci si aspettava.

1. «Zero falsi allarmi in 8 anni» veniva dal consenso Coinbase+Bitstamp+BITFINEX
   dello script di ricerca; il sorvegliante live gira su Coinbase+Bitstamp. Due
   liste di referenze in due posti diversi, e nessun test poteva accorgersene.
   Sull'insieme reale i falsi allarmi sono 1: 2020-03-13 07:00-10:00 UTC, 4 ore a
   -418 bps di picco su BTC = il crash COVID, cioe' proprio l'evento che CLAUDE.md
   elencava come esempio di cio' su cui NON scattava. La firma che lo dimostra: le
   "65.043 ore BTC" citate in memoria sono esattamente le ore utili del set con
   bitfinex; sul set reale sono 69.633.

2. Kraken non lo ripara: su 8 anni porta un mese. Il tetto ~700 candele
   dell'endpoint pubblico e' stato ri-verificato oggi sulla rete (704 barre su
   70.286 richieste = 1,00%), non creduto da un commento del 26/07.

3. Perche' spariva a 3 referenze, ed e' il punto trasferibile: con bitfinex dentro
   1 delle 4 ore diventa BLIND, lo streak si azzera e l'episodio non esiste — ma la
   dislocazione e' ancora li' (mediana -343 bps). Lo zero non veniva da un consenso
   piu' accurato, veniva da un'ora buttata (ore utilizzabili 93,4% vs 100,0%).

4. La direzione dichiarata il 19/08 ("piu' BLIND, allerta di meno") e' confermata ma
   la sua taglia dipende dal venue, non dal numero tre: confronto appaiato sulle
   stesse ore, con bitfinex -13,91 pp di ore utilizzabili, con kraken +0,00 pp.

5. Controllo positivo intatto: Bitfinex 2018-19, 22 episodi, il piu' lungo 2.324h,
   picco 1.136 bps = 11,4x la soglia.

DECISIONE: (100 bps, 4h) NON si tocca, ma la giustificazione cambia. 1 falso allarme
in 8 anni costa 0,031%/anno di equity attesa contro il 100% che un vero positivo
evita (ogni p plausibile e' 16-160x sopra il break-even); alzare a 150 bps per
ripristinare lo zero porterebbe il margine su FTX da 3,0x a 2,0x, sotto la gamba (b)
del criterio dichiarato prima di guardare i dati. La memoria si contraddiceva da
sola — «zero falsi allarmi» al punto (2), «a 1 ogni 8 anni serve p > 0,031%» al
punto (4) — e la meta' giusta era quella dell'economia.

Congelato il MECCANISMO, non il numero: tests/test_venue_watch.py 35 -> 37, due test
puri (lo spread max-min e' monotono nel numero di referenze; una sola ora BLIND
spezza lo streak, con un caso di controllo che DEVE scattare).

Soglie, book, pesi, config, cron: INVARIATI. Suite 621 verdi, 1 rosso noto
(test_gtaa_band_gate, altro asse). Diario: docs/diary/2026-08-21-venue-taratura-*.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Adriano Dal Pastro
2026-08-21 17:55:16 +00:00
parent e69cc5bd81
commit fac9978d87
4 changed files with 493 additions and 10 deletions
+64 -2
View File
@@ -1,8 +1,16 @@
"""Test del tripwire di venue (src/live/venue_watch.py + scripts/research/r0726_venue_tripwire.py).
Il test che conta di piu' e' `test_controllo_positivo_*`: un rilevatore che non segnala mai nulla
e' indistinguibile da uno rotto, e questo qui e' TARATO per non segnalare (zero falsi allarmi su
8 anni). Senza un controllo positivo, "non e' mai scattato" non e' una buona notizia.
e' indistinguibile da uno rotto, e questo qui e' TARATO per non segnalare. Senza un controllo
positivo, "non e' mai scattato" non e' una buona notizia.
⚠️ CORREZIONE 2026-08-21 (`scripts/research/r0821_venue_refs.py`): la taratura NON e' "zero falsi
allarmi in 8 anni" sull'insieme di referenze che gira in PRODUZIONE. Quel numero fu misurato con
`bitfinex` nel consenso, che il sorvegliante live non ha mai avuto; sul consenso reale (Coinbase +
Bitstamp, e da oggi + Kraken) i falsi allarmi in 8 anni sono **1**, il 2020-03-13 (crash COVID,
4 ore a -418 bps di picco su BTC) — cioe' proprio l'evento che la memoria citava come esempio di
cio' su cui NON scattava. Il punto (100 bps, 4h) resta invariato per economia, non per assenza di
falsi allarmi: 1 ogni 8 anni costa ~0.031%/anno di equity attesa contro il 100% che evita.
"""
from __future__ import annotations
@@ -354,3 +362,57 @@ def test_la_tabella_dichiarata_combacia_col_venue_oggi():
"BTC-PERPETUAL": {"tick_size": 0.5, "min_trade_amount": 10.0, "contract_size": 10.0},
"ETH-PERPETUAL": {"tick_size": 0.05, "min_trade_amount": 1.0, "contract_size": 1.0},
}) == []
# ===========================================================================
# MECCANICA scoperta il 2026-08-21 ri-misurando la taratura a tre referenze.
# Sono i due fatti PURI che spiegano i numeri di r0821_venue_refs.py; i numeri
# empirici stanno nel diario, riprodotti da quello script.
# ===========================================================================
def test_una_terza_referenza_non_puo_aumentare_le_ore_utilizzabili():
"""Aggiungere una referenza puo' solo ALLARGARE lo spread max-min, mai stringerlo ->
la quota di ore utilizzabili e' monotona NON crescente nel numero di referenze.
E' la ragione strutturale per cui "piu' referenze" non e' gratis: la modifica del 19/08
sposta il sistema verso BLIND, che e' lo stato morbido (allerta di MENO, non di piu').
"""
base = [100.0, 100.4] # spread 40 bps: concordi
ok, n, spread = dislocation_bps(100.2, base)
assert ok is not None and n == 2 and spread < THRESHOLD_BPS
# una terza referenza lontana allarga lo spread oltre la soglia -> BLIND, non allarme
fuori, n3, spread3 = dislocation_bps(100.2, base + [102.0])
assert n3 == 3 and spread3 > spread, "lo spread deve essere monotono nel numero di referenze"
assert fuori is None, "referenze in disaccordo -> si SCARTA il campione, non si allerta"
# e una terza referenza CONCORDE non toglie nulla: il caso Kraken misurato il 21/08
dentro, n3b, spread3b = dislocation_bps(100.2, base + [100.2])
assert dentro is not None and n3b == 3 and spread3b >= spread
def test_una_sola_ora_BLIND_spezza_lo_streak_e_impedisce_l_allarme():
"""⚠️ Il fatto che rende ambiguo un "zero falsi allarmi" misurato con piu' referenze.
Lo streak si AZZERA su un'ora BLIND (non si accumula evidenza su dati che non parlano).
Quindi un insieme di referenze che manda in BLIND una sola ora dentro una finestra di
dislocazione fa SPARIRE l'episodio senza che la dislocazione sia diminuita: e' esattamente
cio' che e' successo al falso allarme del 2020-03-13, presente a 2 referenze e assente a 3
perche' 1 delle 4 ore diventava BLIND (dislocazione mediana ancora -343 bps).
Morale: "zero falsi allarmi" puo' voler dire "piu' accurato" oppure "piu' cieco", e le due
si distinguono solo guardando la quota di ore utilizzabili.
"""
st = AssetState()
# 4 ore consecutive oltre soglia a segno costante -> ALERT alla quarta
for _ in range(PERSIST_HOURS - 1):
st, lvl = step(st, -400.0)
assert lvl == "WATCH"
st_alert, lvl = step(st, -400.0)
assert lvl == "ALERT", "il caso di controllo deve scattare, altrimenti il test non prova nulla"
# stessa dislocazione, ma con UNA ora cieca in mezzo -> nessun allarme
st2 = AssetState()
for bps in (-400.0, -400.0, None, -400.0):
st2, lvl2 = step(st2, bps)
assert lvl2 != "ALERT"
assert st2.streak_hours < PERSIST_HOURS, "l'ora BLIND deve azzerare lo streak"