Telegram bei gruener M15-Karte (m15_alert) + Tests verschmutzen nicht mehr das Log

User: "wenn es eine Empfehlung gibt (gruen), schicke eine Telegram-Nachricht."
engine._check_m15_alert, direkt hinter _log_m15_state -- dieselbe Quelle wie
Anzeige und Selbstmessung, damit die drei nicht auseinanderlaufen koennen.

DIE ENTPRELLUNG IST DER GANZE BAU. Roh springt die Karte 85x/Tag auf gruen
(m15_states, 3 Tage nach der Hysterese vom 12.08.) -- das waere Spam. Alle
Stufen an den echten Daten kalibriert, nicht geraten:

  nur Flanke                          85,0/Tag
  + Level & Richtung als Schluessel   23,7/Tag
  + 30 min Mindestabstand             13,3/Tag
  + Fenster 8-20 Uhr (Default)         7,7/Tag
  (Vergleich: Close-Meldung ab 50 EUR  2,4-6,1/Tag)

Nach 4 h darf dasselbe Level erneut melden, sonst verschweigt der Alert ein
Setup, das den ganzen Tag wiederkommt.

Der Text sagt ausdruecklich, dass es KEINE Prognose ist: die Karte automatisch
zu handeln faellt gemessen durch (backtest_m15_auto.py: OeR -0,162/-0,094). Die
Meldung ist ein Hinweis zum Hinsehen fuer den Menschen (+3,20 EUR/Lot ueber 146
Trades). Die P(break)-Formulierung ist wortgleich zu Karte und Chart (v1.35).

13 Tests, Schwerpunkt auf dem was NICHT gesendet werden darf. Mutationsprobe in
vier Zweige, alle gefangen.
DIE PROBE HAT EIN TESTLOCH AUFGEDECKT: das Entfernen der Flankenerkennung liess
zunaechst ALLE Tests gruen, weil Cooldown und 4-h-Schluessel dasselbe abfangen.
Zwei Schutzschichten, die sich maskieren -- dasselbe Muster wie beim Fill-Dedup.
Geschlossen durch test_flankenerkennung_ISOLIERT.

NEBENBEFUND, behoben: Tests schrieben ins Produktions-Log (ueber 150
M15-Alert-Zeilen + Close-Push #4711 aus test_close_buchung). Ich hielt die
Entprellung deshalb zuerst fuer live defekt. conftest.py entfernt den
FileHandler des oil-Loggers jetzt fuer die Sitzung -- vierte Grundregel der
Suite. Verifiziert: Log-Groesse vor und nach einem Komplettlauf identisch.

Live verifiziert: seit dem Serverstart genau 1 Alert trotz mehrfachem
gruen/gelb-Wechsel. 85 Tests gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Axel Hocks
2026-08-14 08:37:53 +02:00
co-authored by Claude Opus 5
parent c251652d33
commit 44191947ac
4 changed files with 353 additions and 0 deletions
+28
View File
@@ -17,6 +17,7 @@ damit dokumentiert, statt still zu passieren.
"""
import sys
import types
import logging
from pathlib import Path
import pytest
@@ -28,6 +29,33 @@ from core.engine import TradingEngine # noqa: E402
from core.history import HistoryLogger # noqa: E402
@pytest.fixture(autouse=True, scope="session")
def _kein_produktions_log():
"""VIERTE Grundregel der Suite: Tests schreiben NICHT ins Produktions-Log.
⚠⚠ ANLASS (2026-08-14, real passiert): beim Bau des M15-Alerts standen nach
den Testläufen **über 150** `📨 M15-Alert`-Zeilen in `oil_widget.log` — dazu
`Close-Push #4711` mit dem synthetischen Ticket aus `test_close_buchung.py`.
Ich habe daraufhin zuerst geglaubt, die Entprellung sei live defekt, und
musste die Herkunft mühsam an der Level-Folge (82.00, 82.01, …) nachweisen.
In einem Projekt, dessen Forensik am Log hängt (der 18-h-Ausfall des
Copiloten, der stille `positions_get`-Fehlbuchung), sind erfundene Zeilen
im Produktions-Log ein echtes Risiko — nicht nur Unordnung.
`core/logger.py` haengt einen `RotatingFileHandler` an den Logger `oil`,
sobald `core.engine` importiert wird. Hier wird er fuer die Dauer der
Sitzung entfernt und danach zurueckgegeben — die Log-AUFRUFE laufen weiter
(sie gehoeren zum getesteten Code), nur ihr Ziel entfaellt.
"""
lg = logging.getLogger("oil")
weg = [h for h in lg.handlers if isinstance(h, logging.FileHandler)]
for h in weg:
lg.removeHandler(h)
yield
for h in weg:
lg.addHandler(h)
@pytest.fixture
def db(tmp_path):
"""Frische, vollständig angelegte Test-Datenbank.