telegram_daily: gate da monitor_health (non cablati), formato giorni a tre casi, header condizionale su flat (#35 C14)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-27 15:18:25 +00:00
parent 12291709ed
commit 3af6e1f0c3
2 changed files with 130 additions and 14 deletions
+71 -1
View File
@@ -7,6 +7,7 @@ e non invia niente in dry-run.
from __future__ import annotations
import sys
from datetime import date
from pathlib import Path
import pytest
@@ -21,8 +22,33 @@ telegram_daily = pytest.importorskip("telegram_daily")
def test_build_non_solleva_e_ha_le_sezioni():
txt = telegram_daily.build()
assert isinstance(txt, str) and len(txt) > 50
for sezione in ("Conto", "Perche' non opera", "Ordini", "Monitor in osservazione"):
for sezione in ("Conto", "Ordini", "Monitor in osservazione"):
assert sezione in txt, f"sezione mancante: {sezione}"
# (#35 C14) l'header sul trend e' condizionale: esattamente uno dei due, non piu' fisso.
assert ("Perche' non opera" in txt) != ("Stato trend" in txt)
def test_header_perche_non_opera_solo_se_il_libro_e_flat(monkeypatch):
"""(#35 C14) L'header fisso mentiva quando il libro NON e' fermo (posizioni o target != 0):
con flat=True resta "Perche' non opera"."""
monkeypatch.setattr(telegram_daily, "book_state", lambda: ([" equity $1.00"], True))
assert "Perche' non opera" in telegram_daily.build()
def test_header_neutro_se_il_libro_non_e_flat(monkeypatch):
monkeypatch.setattr(telegram_daily, "book_state",
lambda: ([" BTC: pos $300 → target $300"], False))
txt = telegram_daily.build()
assert "Stato trend" in txt and "Perche' non opera" not in txt
def test_header_neutro_se_il_libro_non_e_leggibile(monkeypatch):
"""Se book_state non sa dire se e' flat (eccezione -> None), niente header "non opera"
dichiarato senza saperlo davvero: si usa il neutro."""
monkeypatch.setattr(telegram_daily, "book_state",
lambda: ([" ⚠️ stato libro non leggibile: Errore"], None))
txt = telegram_daily.build()
assert "Stato trend" in txt and "Perche' non opera" not in txt
def test_nessuna_scrittura_ne_ordine():
@@ -82,3 +108,47 @@ def test_soglia_accensione_servono_tutti_i_flip():
= il piu' alto dei due (l'ultimo a bastare), non il minimo."""
r = telegram_daily._soglia_accensione([-1, -1], [200.0, 100.0])
assert r == 200.0
# ---------------------------------------------------------------- (#35 C14) gate: data, formato
def test_gate_date_legge_da_monitor_health():
"""La data non e' una seconda dichiarazione: viene da monitor_health.MONITORS (`gate`),
la stessa tabella che gli alert dei sorveglianti citano come "METTE A RISCHIO il gate"."""
from src.live.monitor_health import MONITORS
m = next(x for x in MONITORS if x.name == "paper_statarb")
assert m.gate[:10] == "2026-09-27"
assert telegram_daily._gate_date("paper_statarb", date(2030, 1, 1)) == date(2026, 9, 27)
m2 = next(x for x in MONITORS if x.name == "paper_xsr")
assert telegram_daily._gate_date("paper_xsr", date(2030, 1, 1)) == date.fromisoformat(m2.gate[:10])
def test_gate_date_usa_la_cablata_se_il_monitor_non_esiste():
"""Rete di sicurezza: se il nome non e' in MONITORS (o cambia), non si inventa una data."""
assert telegram_daily._gate_date("non_esiste_piu'", date(2030, 1, 1)) == date(2030, 1, 1)
def test_fmt_giorni_tre_casi_mai_il_doppio_segno():
"""(#35 C14) giorni>0 -> '-Ng'; 0 -> 'oggi'; <0 -> 'scaduto da Ng'. Mai '(−-1g)'."""
assert telegram_daily._fmt_giorni(5) == "-5g"
assert telegram_daily._fmt_giorni(0) == "oggi"
assert telegram_daily._fmt_giorni(-1) == "scaduto da 1g"
assert "-1g" not in telegram_daily._fmt_giorni(-1).replace("scaduto da 1g", "") # niente doppio segno
def test_monitors_formatta_i_tre_casi_del_giorno(monkeypatch, tmp_path):
"""I rami di monitors() (barra assente qui: file inesistenti in tmp_path) usano tutti
_fmt_giorni, non il vecchio '(−{giorni}g)' cablato: futuro, oggi e passato si distinguono."""
from datetime import timedelta
oggi = date.today()
monkeypatch.setattr(telegram_daily, "ROOT", tmp_path)
monkeypatch.setattr(telegram_daily, "GATES",
[("FUTURO", oggi + timedelta(days=10), "data/nonexiste1/r.jsonl", "k"),
("OGGI", oggi, "data/nonexiste2/r.jsonl", "k"),
("PASSATO", oggi - timedelta(days=3), "data/nonexiste3/r.jsonl", "k")])
righe = telegram_daily.monitors()
assert "(-10g)" in righe[0]
assert "(oggi)" in righe[1]
assert "(scaduto da 3g)" in righe[2]
assert "−-" not in "".join(righe) and "(−" not in "".join(righe) # mai il doppio segno