analista: manda l'analisi giornaliera su Telegram, con l'esito registrato
La notifica porta una testata coi numeri che si leggono senza aprire nulla
(equity, delta del giorno, cumulato, posizioni, leva, fill e round-trip) e
sotto l'analisi del modello.
Il trasporto Telegram e' pero' il punto singolo di guasto gia' misurato in
questo progetto: un tentativo, nessun retry, esito mai registrato, 6,9% di
invii persi (2/29). Su un messaggio al giorno sono ~25 messaggi persi
all'anno, quindi qui sono state fatte due delle tre riparazioni dichiarate
il 2026-08-23 e mai eseguite:
(a) `send(text, tentativi=1)` — retry OPZIONALE con backoff. Il default resta
1, cosi' il comportamento e' invariato per tutti i chiamanti esistenti:
alzarlo per tutti cambierebbe la latenza degli allarmi di venue_watch e
book_execute su un percorso con soldi veri, e non e' una modifica da fare
di straforo dentro un'altra funzionalita'. L'analista chiede 3.
(b) `ultimo_errore()` — il motivo si registra nel punto in cui l'eccezione
veniva ingoiata, e NON sopravvive a un invio riuscito. Regola gia'
codificata il 29/07 su un altro percorso e mai applicata al notifier.
La terza (marcare `alerted=True` solo a invio riuscito in venue_watch) cambia
il comportamento degli allarmi e resta una decisione dell'operatore.
L'esito finisce nel DB in tre stati: inviata / non configurato / FALLITA col
motivo. Un invio perso che non lascia traccia, il giorno dopo, non si
distingue da "non e' successo niente".
E se l'analisi manca, il messaggio parte lo stesso dicendo PERCHE': senza
quel ramo un guasto del modello si leggerebbe come una giornata senza nulla
da dire. Taglio a 4096 caratteri dichiarato, mai silenzioso; HTML del modello
neutralizzato.
708 test passano. Strategia, pesi, config INVARIATI.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
uv run python scripts/live/analista.py --giorno 2026-08-21
|
||||
uv run python scripts/live/analista.py --modello claude-opus-5
|
||||
uv run python scripts/live/analista.py --secco # stampa e non salva
|
||||
uv run python scripts/live/analista.py --no-telegram # non manda la notifica
|
||||
|
||||
NON tocca `nota` (dell'operatore) e non tocca nessuna sezione misurata: scrive SOLO in `analisi`.
|
||||
Se il modello non risponde, l'analisi di ieri NON diventa quella di oggi: si registra l'errore
|
||||
@@ -19,6 +20,7 @@ ROOT = Path(__file__).resolve().parents[2]
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
from src.live import analista as A # noqa: E402
|
||||
from src.live import notifier as N # noqa: E402
|
||||
from src.live import journal as J # noqa: E402
|
||||
from src.live import tradesdb as T # noqa: E402
|
||||
|
||||
@@ -48,7 +50,28 @@ def storico(con, g: date, n: int = GIORNI_STORICO) -> str:
|
||||
return "\n".join(righe)
|
||||
|
||||
|
||||
def scrivi(con, g: date, modello: str, secco: bool = False, verbose: bool = True) -> str:
|
||||
def invia(con, g: date, voce: dict, analisi: str, stato: str, motivi: list[str],
|
||||
verbose: bool = True) -> str:
|
||||
"""Manda su Telegram e REGISTRA l'esito. Tre stati, non due: inviata / non-configurato /
|
||||
fallita-con-motivo. Un invio perso che non lascia traccia e' peggio di un invio non fatto:
|
||||
il giorno dopo non si distingue da 'non e' successo niente'."""
|
||||
testo = A.per_telegram(voce, analisi, stato, motivi)
|
||||
if not N.is_configured():
|
||||
esito = "non configurato"
|
||||
else:
|
||||
# `tentativi=3`: il tasso misurato di invii persi su questo percorso e' 6,9% (2/29).
|
||||
# Su un messaggio al giorno, un tentativo solo perde ~25 messaggi in un anno.
|
||||
esito = "inviata" if N.send(testo, tentativi=3) else f"FALLITA — {N.ultimo_errore()}"
|
||||
con.execute("UPDATE journal SET inviata_ts=?, inviata_stato=? WHERE giorno=?",
|
||||
(T.ora(), esito, g.isoformat()))
|
||||
con.commit()
|
||||
if verbose:
|
||||
print(f" telegram: {esito} ({len(testo)} caratteri)")
|
||||
return esito
|
||||
|
||||
|
||||
def scrivi(con, g: date, modello: str, secco: bool = False, verbose: bool = True,
|
||||
telegram: bool = True) -> str:
|
||||
voce = J.costruisci(con, g)
|
||||
J.salva(con, voce) # le sezioni misurate prima, cosi' il modello le legge
|
||||
pagina = J.rendi_markdown(con, voce)
|
||||
@@ -87,6 +110,8 @@ def scrivi(con, g: date, modello: str, secco: bool = False, verbose: bool = True
|
||||
(modello, T.ora(), stato, "; ".join(motivi) or None, g.isoformat()))
|
||||
con.commit()
|
||||
J.scrivi_file(con, voce)
|
||||
if telegram:
|
||||
invia(con, g, voce, testo, stato, motivi, verbose=verbose)
|
||||
return stato
|
||||
|
||||
|
||||
@@ -94,6 +119,7 @@ if __name__ == "__main__":
|
||||
con = T.connect()
|
||||
g = date.fromisoformat(_arg("--giorno", datetime.now(timezone.utc).date().isoformat()))
|
||||
st = scrivi(con, g, modello=_arg("--modello", A.MODELLO_DEFAULT),
|
||||
secco="--secco" in sys.argv[1:], verbose="--quiet" not in sys.argv[1:])
|
||||
secco="--secco" in sys.argv[1:], verbose="--quiet" not in sys.argv[1:],
|
||||
telegram="--no-telegram" not in sys.argv[1:])
|
||||
con.close()
|
||||
sys.exit(0 if st in ("ok", "sospetta") else 1)
|
||||
|
||||
Reference in New Issue
Block a user