diff --git a/docs/research/RESULTS-0822.md b/docs/research/RESULTS-0822.md index 554e67e..6af6c9b 100644 --- a/docs/research/RESULTS-0822.md +++ b/docs/research/RESULTS-0822.md @@ -711,6 +711,7 @@ stessi hanno nominato senza poterli eseguire**. Stesso contratto di consegna, st | 43 | DATA-UNUSED | quali dati il progetto possiede e nessuna strategia legge — e uno di essi sostiene un'ipotesi? | _in corso_ | | 44 | DEPOSIT-TIMING | un calendario di versamento CONDIZIONALE batte il piatto, a pari soldi? | _in corso_ | | 45 | SPOT-NETTING | separare TP01 e SKH01 su due strumenti: quanto vale, e il margine lo uccide? | _in corso_ | +| — | **NOTIFIER** (audit di fatto) | 🚨 **PUNTO SINGOLO DI GUASTO nella rete di sicurezza** | il `send()` di Telegram e' **un solo tentativo da 10s, senza retry, con l'esito MAI registrato** — e lo stato `alerted=True` viene scritto **prima** dell'invio: un 🚨 di `venue_watch` perso e' perso **per l'intero episodio**. Tasso di fallimento **misurato 6,9%** (2/29, IC95 [1,9%, 22,0%]) | | 22 | MAKER | l'esecuzione passiva e' una fonte di ritorno, al netto del costo di non essere eseguiti? | **SCARTATO** — il segno dipende da `<` contro `<=` | | 23 | BOCPD | un rilevatore di cambio di regime vero batte il miglior lookback COSTANTE? | **SCARTATO** — filone chiuso definitivamente | | 24 | CRITICO | cosa NON e' stato misurato, e quale singola misura mancante vale di piu' | **3 correzioni all'ondata**, 1 regola mia ritirata | @@ -2055,3 +2056,67 @@ percorso, *e la domanda non ne aveva bisogno.* **VERDETTO: `IL DISASTER-SL E' ROTOLANTE (costo vero 37,5% contro 37,5% — un episodio solo alla cadenza di produzione; sale a ~75% solo con cron a 24h, che non e' la configurazione che gira)`.** + +--- + +## — NOTIFIER (audit di fatto, coordinatore) — l'allarme puo' non arrivare, e nessuno lo sa + +**Non e' un filone di ricerca: e' un difetto di produzione trovato leggendo i log mentre l'ondata 7 +girava.** Nessun file di produzione toccato. + +**Come e' venuto fuori.** Il giro `cron_daily` di stanotte finisce con +`NON inviato (config Telegram assente o rete KO)`. La nota conflaziona due cause; **la prima e' +falsa** — `TELEGRAM_BOT_TOKEN` e `TELEGRAM_CHAT_ID` sono **presenti** in `.env`, e +`src/live/notifier._cfg()` lo legge (verificato). Quindi la causa e' la rete, e il messaggio manda +a controllare la configurazione. E' la **stessa forma** del difetto codificato il 29/07 sul +`venue_watch` (*"una nota di diagnosi cablata e' peggio di nessuna nota"*), su un percorso diverso. + +**Il difetto vero, che e' piu' grande della nota.** `src/live/notifier.send()`: + +``` +urllib.request.urlopen(url, data, timeout=10) # UN tentativo +except Exception: return False # esito ingoiato +``` + +- **nessun retry** — un singolo blip di rete perde il messaggio; +- **l'esito non viene registrato da nessuna parte**: `notify()` ritorna `bool` e + `scripts/live/venue_watch.py:80` **non lo guarda**; `logs/cron_book.log` contiene **0** + occorrenze di un qualsiasi esito d'invio (verificato con grep). *Quando serve sapere se + l'allarme e' arrivato, l'informazione non e' stata scritta.* +- 🚨 **e lo stato viene marcato PRIMA dell'invio.** In `src/live/venue_watch.lock_step`/streak + la riga `new.alerted = True` sta **dentro la logica pura**, e viene persistita comunque; alle ore + successive `already = st.alerted and st.sign == sign` fa tornare `"WATCH"` invece di `"ALERT"` → + **`notify` non viene piu' chiamata per quell'episodio**. Un 🚨 perso **e' perso per l'episodio + intero**, e gli episodi storici (Mt.Gox, FTX, Bitfinex 2018-19) durano **da 200 a 2.324 ore con + segno costante**: e' esattamente il caso in cui la ri-notifica non arriva mai. + +**Quanto vale, misurato.** Sullo stesso `send()`, il digest giornaliero ha tentato **29** invii e +ne ha **falliti 2** → **6,9%**, IC95 Wilson **[1,9%, 22,0%]**. +⚠️ **Fonte del numero, dichiarata:** e' il percorso del **digest** (messaggio lungo, una volta al +giorno), usato come **proxy** del percorso d'allarme (messaggio corto, orario) — che **non ha +nessun dato proprio, ed e' questo il punto**. Stessi endpoint, stesso timeout, stessa funzione. + +**Perche' conta piu' del suo numero.** L'economia del `venue_watch` (26/07) e' calcolata assumendo +che il vero positivo **arrivi**: costo atteso di un falso allarme 0,248% di equity contro il +**100%** che un vero positivo evita, break-even `p > 0,031%`. Una perdita del ~7% degli allarmi +non ribalta quel conto — ma **sorveglia l'unico rischio che il progetto ha prezzato come capace di +portare il conto a zero** (P(perso tutto) 10/18/34/64% a p=0,5/1/2/5%), e la sorveglianza e' +l'unica mitigazione rimasta dopo la decisione del 26/07 di stare **100% su Deribit fino a $20k**. +*Su una perdita totale, un allarme su quattordici che non arriva non e' un arrotondamento.* + +**Cosa NON e' stato fatto, e perche'.** Nessuna riparazione: `src/live/notifier.py` e +`scripts/live/venue_watch.py` sono produzione, il cron esegue dalla working tree, e un ramo di +ricerca non manda codice live. La riparazione e' piccola e ha tre pezzi indipendenti — (a) retry +con backoff su `send()`; (b) **registrare l'esito** nel punto in cui l'eccezione viene ingoiata +(la regola del 29/07, mai applicata al notifier); (c) marcare `alerted=True` **solo a invio +riuscito**, cosi' che un allarme non consegnato **si ripresenti** l'ora dopo. Il pezzo (c) e' +quello che cambia il comportamento e va deciso dall'operatore: rende l'allarme ripetitivo finche' +non passa, che e' il verso giusto per un 🚨 e il verso sbagliato per un ⚠️. + +⚠️ **Cio' che questo audit NON dice:** che il `venue_watch` non funzioni. Il rilevatore e' tarato, +validato su un controllo positivo (22 episodi Bitfinex) e ha 1 solo falso allarme in 8 anni. Il +difetto e' **a valle del rilevatore**, nel trasporto — la parte che nessuno aveva guardato perche' +non produce numeri. + +**VERDETTO: `LA RETE DI SICUREZZA HA UN TRASPORTO SENZA RETRY, SENZA REGISTRO E CON LO STATO +MARCATO PRIMA DELL'INVIO — ~7% DEGLI ALLARMI PUO' NON ARRIVARE, PER L'EPISODIO INTERO`**