Systemzustand in den Tagesreport - der fehlende letzte Meter
Selbstaendige Empfehlung nach der Gesamtpruefung, vom User beauftragt. Befund: die Erkennung funktioniert, die Zustellung nicht. Sieben Waechter, jeder nach einem eigenen Vorfall gebaut, jeder funktioniert - und trotzdem blieben diese Woche sechs Zustaende tagelang unbemerkt, vier davon waren bereits erkannt. Belegt an den Marker-Dateien: cfg_auto_sr_close traegt 06.08. 18:10, cfg_auto_squeeze sogar 02.08. Der Config-Waechter meldet je Schluessel genau einmal und schweigt danach fuer immer. auto_sr_close war damit fuenf Tage aus - gemessen +350,81 EUR ueber 43 Trades. Ursache ist ein Kategorienfehler: die Marker-Logik behandelt einen Dauerzustand wie ein Einmal-Ereignis. Gebaut: engine._system_status() als Block im Tagesreport (07:30, Telegram + E-Mail) - der einzige Kanal, der nachweislich jeden Tag ankommt. Saubere Trennung: Popup = "etwas Neues", Report = "so steht es gerade". Reine Anzeige. - telemetrie_puls() liegt in core/history.py, beide Nutzer rufen dieselbe Funktion (Skripte importieren core, nie umgekehrt) - measurement_reminder wird lazy und gekapselt importiert; ein Fehlschlag wird sichtbar gemeldet statt still verschluckt - tests/test_system_status.py: 7 Tests, Schwerpunkt Ausfallpfade - der Report darf an dieser Zeile nie scheitern Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
dca3c11bbd
commit
b18b594639
@@ -407,6 +407,58 @@ class HistoryLogger:
|
||||
# alert „🔔 CLOSE-Signal") sowie bei Notfall-/Gewinn-Auto-Close. Die terse
|
||||
# „Sym +X"-Bestätigung bei jedem Close ist entfernt.
|
||||
|
||||
# ── TELEMETRIE-PULS ──────────────────────────────────────────────────
|
||||
# ⚠⚠ ANLASS (2026-08-11): `rec_outcomes` stand seit dem Einbau am 06.08. bei
|
||||
# 0 Zeilen — ein falsches dict liess die Schreibbedingung nie wahr werden.
|
||||
# KEIN NameError (der Linter sieht nichts), und das umgebende `except`
|
||||
# loggt auf DEBUG. Fuenf Tage still tot; aufgefallen nur, weil die Tabelle
|
||||
# neben ihren Schwestern mit 0 Zeilen stand.
|
||||
# ⚠ Warum hier und nicht im Reminder-Skript: der Puls ist eine DB-Frage, und
|
||||
# BEIDE Nutzer (Reminder-Popup + Tagesreport) brauchen ihn. Zwei Kopien
|
||||
# waeren genau die Divergenz, die im Projekt dreimal zugeschlagen hat.
|
||||
# Richtungsregel: Skripte duerfen `core` importieren, nicht umgekehrt.
|
||||
PULS = (
|
||||
# (Tabelle, Zeitspalte, erwartete Kadenz in Minuten, wozu)
|
||||
("recommendations", "timestamp", 1, "Empfehlungs-Log"),
|
||||
("candles_m1", "time", 1, "M1-Kerzen-Sammlung"),
|
||||
("verdict_votes", "ts", 1, "Modul-Stimmen"),
|
||||
("m15_states", "ts", 60, "M15-Karte Selbstmessung"),
|
||||
("cone_checks", "ts", 60, "Kegel-Kalibrierung (ACI)"),
|
||||
("pbreak_predictions", "ts", 60, "P(break)-Prognose-Tracking"),
|
||||
("rec_outcomes", "ts", 180, "Selbst-Kalibrierung Empfehlung"),
|
||||
)
|
||||
|
||||
def telemetrie_puls(self) -> list[str]:
|
||||
"""Welche Telemetrie-Tabelle schreibt nicht mehr? → Klartext-Zeilen.
|
||||
|
||||
⚠ Toleranz bewusst grosszuegig (Faktor 20 der Kadenz): ein ruhiger Markt
|
||||
oder ein Wochenende darf keinen Fehlalarm ausloesen — ein Waechter, der
|
||||
oft warnt, wird ignoriert (Lehre vom 02.08.).
|
||||
"""
|
||||
out: list[str] = []
|
||||
try:
|
||||
jetzt = time.time()
|
||||
with self._lock, self._connect() as conn:
|
||||
for tab, sp, kadenz, wozu in self.PULS:
|
||||
try:
|
||||
n = conn.execute(f"SELECT COUNT(*) FROM {tab}").fetchone()[0]
|
||||
letzt = conn.execute(f"SELECT MAX({sp}) FROM {tab}").fetchone()[0]
|
||||
except Exception:
|
||||
continue # Tabelle gibt es (noch) nicht
|
||||
if not n:
|
||||
out.append(f"{tab}: 0 Zeilen — Logger hat NIE geschrieben ({wozu})")
|
||||
continue
|
||||
# ⚠ `candles_m1.time` ist ROHE Brokerzeit (UTC+3) — ohne den
|
||||
# Abzug meldet der Puls dort dauerhaft 3 h Rueckstand.
|
||||
ts = letzt - 10800 if tab == "candles_m1" else letzt
|
||||
alter_min = (jetzt - ts) / 60.0
|
||||
if alter_min > kadenz * 20:
|
||||
out.append(f"{tab}: letzte Zeile vor {alter_min/60:.1f} h "
|
||||
f"(erwartet ~alle {kadenz} min) — {wozu}")
|
||||
except Exception:
|
||||
return out # fail-open wie der Rest der Schicht
|
||||
return out
|
||||
|
||||
def trade_by_ticket(self, ticket: int) -> dict | None:
|
||||
"""Einen Trade komplett lesen — für die Close-Benachrichtigung (2026-08-11).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user