live(feed): l'allerta funzionava, la sua CAUSA era una riga cablata

Il 29/07 il feed 5m di SKH01 e' ricaduto sul certificato in 6 giri orari su 8
(eta' 265->685 min, +60 a ogni giro = firma esatta del fallback): latenza
d'uscita da ~1h a ~11h, book flat, nessuna posizione esposta. L'allerta del
26/07 ha segnalato 6/6, poi ha stampato un perche' che non aveva misurato —
la nota "fetch pubblico KO" era cablata, identica in ogni caso, compreso
quello in cui la coda fresca E' attaccata e il vecchio e' il certificato.

E la causa vera non era recuperabile per costruzione: _fetch_recent_5m ingoia
l'eccezione di pagina con un break e a prima pagina fallita ritorna un frame
vuoto, indistinguibile da "il venue non ha barre".

Cablato: livefeed.last_fetch_error() (registra E logga nel punto in cui
l'errore viene ingoiato) -> book_report.skh_feed_errors -> allerta con la
causa. Stesso buco chiuso sul ramo gemello "conto offline", che la ragione
l'aveva gia' in mark_src e non la stampava mai.

La causa del 29/07 resta IGNOTA e va citata cosi': una prima stesura la
attribuiva a un rate limit per-IP come se fosse un fatto -> rimossa, sarebbe
stato lo stesso difetto che stavo correggendo scritto meglio. Cron spostato
al minuto :07 come ripiego da UNA osservazione, dichiarato tale.

Test 11 -> 16 (incluso il caso a meta' paginazione: coda parziale attaccata,
mancano le barre PIU' recenti). Book/pesi/config/strategia INVARIATI.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Adriano Dal Pastro
2026-07-29 12:20:42 +00:00
parent 0a77290636
commit 7d64dd4c2b
7 changed files with 384 additions and 9 deletions
+13 -2
View File
@@ -194,16 +194,23 @@ def book_report(offline: bool = False, equity_override: float | None = None,
cap = _cap(equity=equity, real_equity=sh.get("real_equity"), eq_fallback=sh.get("eq_fallback"))
load5m = None
feed_ages: dict[str, float | None] = {}
feed_errors: dict[str, str] = {}
if live_feed:
from src.live.livefeed import feed_age_minutes, fresh_5m
from src.live.livefeed import feed_age_minutes, fresh_5m, last_fetch_error
def load5m(a: str):
"""Wrapper che MISURA la freschezza del feed effettivamente usato per il segnale.
`fresh_5m` ricade sul certificato in SILENZIO se il fetch pubblico fallisce: senza
questa misura la latenza d'uscita di SKH01 passerebbe da ~1h a ~1 giorno senza che
nulla lo segnali (vedi feed_age_minutes)."""
nulla lo segnali (vedi feed_age_minutes). Raccoglie anche la CAUSA del fallback:
l'eta' dice CHE il feed e' vecchio, non PERCHE' — e senza il perche' la diagnosi
non e' rifacibile a posteriori, perche' quando la si prova il guasto e' rientrato
(29/07: 6 giri stantii su 8, causa mai stabilita -> vedi livefeed._LAST_ERROR)."""
df = fresh_5m(a)
feed_ages[a] = feed_age_minutes(df)
err = last_fetch_error()
if err is not None:
feed_errors[a] = err
return df
skh_error = None
try:
@@ -247,5 +254,9 @@ def book_report(offline: bool = False, equity_override: float | None = None,
# e' stantio, il segnale netto e' sospetto.
skh_feed_age_min=(max((v for v in feed_ages.values() if v is not None), default=None)
if feed_ages else None),
# PERCHE' la coda fresca non e' stata attaccata, per asset ({} = nessun fallback).
# Accompagna skh_feed_age_min: senza, l'allerta puo' solo TIRARE A INDOVINARE la causa
# (ed e' esattamente cio' che faceva, con una nota cablata, fino al 29/07).
skh_feed_errors=dict(feed_errors),
flat=all(abs(x["net_target"]) < FLAT_USD for x in assets),
)