Meldungen oben links im MT5-Chart (MS;<text>, Indikator v1.36)

User-Wunsch. Neue CSV-Zeile MS;<text>, im Indikator als gestapelte OBJ_LABEL an
CORNER_LEFT_UPPER (oben rechts sind Kurs, G/V und HL belegt). Inhalt = dieselben
Zeilen wie die Dashboard-Karte "Meldungen": Squeeze, Ueberdehnung, S/R-Ziel mit
P(break), Stop-Seite, News-Blackout.

NUR ZUSAMMENGESETZT, NICHT NEU GERECHNET -- alles aus bereits berechneten
Snapshot-Teilen bzw. _last_sr_close_hint/_last_stop_approach; calendar.blackout()
ist ein reiner Speicher-Zugriff. Der Konsens-Pfeil hat im 5-s-Export-Takt einmal
ein komplettes zweites _verdict() gezogen.

Zwei Felder vorher geprueft statt angenommen: _last_calendar und
_export_meldungen gab es NICHT -- ohne die Pruefung haette das umgebende
except Exception es still verschluckt und die Meldungen waeren dauerhaft leer
geblieben (dieselbe Klasse wie der wave_snap-Fallstrick vom 04.08.).

ASCII-SICHER, real noetig: der erste Lauf lieferte "MS; Kompression  Ausbruch
steht bevor" -- Emoji und Gedankenstrich waren zu Leerzeichen geworden. Der
Indikator liest die CSV nicht als UTF-8 (deshalb steht dort auch
"Unterstuetzung"). Jetzt Ersetzung + Filter auf 32-126.
Verifiziert: MS;Squeeze-Ausbruch LONG @ 82.413, 0 Nicht-ASCII-Zeichen.

Deckel 5 Zeilen a 70 Zeichen; eigener Praefix SRB_MSG_*, damit die Labels beim
Redraw verschwinden. Abschaltbar per [trading] export_meldungen=false oder
InpShowMeldungen. Kompiliert ins richtige Terminal (0 errors, 0 warnings),
deployt und am laufenden Server verifiziert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Axel Hocks
2026-08-17 11:00:34 +02:00
co-authored by Claude Opus 5
parent 55dc69ef42
commit 204e80bb68
3 changed files with 140 additions and 1 deletions
+66
View File
@@ -490,6 +490,10 @@ class TradingEngine:
self._export_mql5 = self.cfg["trading"].get("export_mql5_levels", "true").lower() == "true"
# Kegel im MT5-Chart: per Default AUS, seit die Pfeile ihn ersetzen (2026-07-31).
self._export_cone = self.cfg["trading"].get("export_cone", "false").lower() == "true"
# Meldungen oben links im MT5-Chart (User-Wunsch 2026-08-17) — dieselben
# Zeilen wie die Dashboard-Karte, nur zusammengesetzt, nicht neu gerechnet.
self._export_meldungen = (
self.cfg["trading"].get("export_meldungen", "true").lower() == "true")
# Konsens-Pfeil (AR;K) — Default AUS, spiegelt `InpShowConsensus=false` im
# Indikator. Bei `true` wird je Export ein zweites `_verdict()` gerechnet.
self._export_consensus_arrow = self.cfg["trading"].get(
@@ -2801,6 +2805,68 @@ class TradingEngine:
lines.append(f"PL;{_p:.2f};{_cur}")
except Exception:
pass
# ── MELDUNGEN oben links (MS;<text>) — User-Wunsch 2026-08-17 ────
# Dieselben Zeilen wie die Dashboard-Karte „Meldungen" (`#card-pos`).
# ⚠⚠ NUR ZUSAMMENSETZEN, NICHT NEU RECHNEN. Der Konsens-Pfeil hat im
# ~5-s-Export-Takt ein komplettes zweites `_verdict()` gezogen —
# doppelte Last UND die Gefahr, dass Chart und Dashboard
# auseinanderlaufen. Alles hier kommt aus bereits berechneten
# Snapshot-Teilen bzw. den `_last_*`-Feldern.
# ⚠ Abschaltbar: `[trading] export_meldungen=false`.
if self._export_meldungen:
try:
_ms: list[str] = []
_ws2 = self.wave.snapshot() or {}
_sq2 = _ws2.get("squeeze") or {}
if _sq2.get("state") == "active" and _sq2.get("dir"):
_ms.append(f"🚀 Squeeze-Ausbruch {_sq2['dir']} "
f"@ {_sq2.get('level')}")
elif _sq2.get("state") == "armed":
_ms.append("🎯 Kompression — Ausbruch steht bevor")
_bo = _ws2.get("bounce") or {}
if _bo.get("state") in ("expected", "active") and _bo.get("dir"):
_pf = "aktiv" if _bo["state"] == "active" else "erwartet"
_ms.append(f"⚠ Ueberdehnung ({_pf}) — Reaktion "
f"{'nach oben' if _bo['dir'] == 'LONG' else 'nach unten'}"
f" moeglich [{_bo.get('tf') or ''}]")
_sh = self._last_sr_close_hint
if _sh and _sh.get("level"):
_pb2 = _sh.get("p_break")
_txt = ("unentschieden" if _pb2 is None or 45 <= _pb2 <= 55
else f"{_pb2}% Bruch" if _pb2 > 55
else f"{100 - _pb2}% Abprall")
_ms.append(f"S/R-Ziel {_sh['level']} · {_txt}"
+ (" · Bot wuerde schliessen" if _sh.get("close") else ""))
_st2 = self._last_stop_approach
if _st2 and _st2.get("level"):
_pb3 = _st2.get("p_break")
_ms.append(f"Stop-Seite {_st2['level']} · "
+ ("bricht wahrscheinlich" if (_pb3 or 0) >= 50
else "haelt wahrscheinlich"))
# ⚠ `self.calendar` ist das Objekt (kein `_last_*`-Feld) —
# `blackout()` ist ein reiner Speicher-Zugriff, kein Netz.
_bl = self.calendar.blackout()
if _bl:
_ms.append(f"News-Blackout: {_bl.get('title') or ''}")
# ⚠⚠ ASCII-SICHER. Der Indikator liest die CSV NICHT als
# UTF-8 — Emoji und Sonderzeichen kommen als Leerzeichen an
# (real gesehen: „🎯 Kompression — …" wurde „ Kompression
# …"). Genau deshalb steht im Indikator auch
# „Unterstuetzung" statt „Unterstützung". Ersetzen statt
# hoffen.
_ers = {"": "-", "": "-", "·": "-", "": "->", "": ">=",
"": "<=", "ü": "ue", "ö": "oe", "ä": "ae",
"Ü": "Ue", "Ö": "Oe", "Ä": "Ae", "ß": "ss"}
for _z in _ms[:5]: # Deckel: der Chart soll lesbar bleiben
_t = str(_z)
for _a, _b in _ers.items():
_t = _t.replace(_a, _b)
_t = "".join(c for c in _t if 32 <= ord(c) < 127)
_t = " ".join(_t.split()) # Mehrfach-Leerzeichen weg
if _t:
lines.append("MS;" + _t.replace(";", ",")[:70])
except Exception:
pass
# Trade-Marker: TR;<O|C>;<broker_time> → der Indikator umrandet die Kerze,
# in der eröffnet (hellgrün) bzw. geschlossen (dunkelgrün) wurde
# (User-Vorgabe 2026-07-30). Offene Position + die letzten Trades des Tages.