Chartmuster je Zeitebene als Bild + M1/M5 in der Meldungskarte (v=204)
User-Vorgabe: die hinterlegten Muster-Bilder sollen je Minuten-Chart das gerade entstehende Muster zeigen, M1 und M5 zusaetzlich in der Meldungskarte. BILDER: 15 Vorlagen aus /Chartmuster, 436-611 KB je Stueck (7,5 MB gesamt). Das Dashboard uebertraegt ~14 KB je Snapshot ueber WireGuard - ein Originalbild waere das 40-fache. Verkleinert auf 520 px / JPEG q80 nach web/muster/: 7,5 MB -> 379 KB (Faktor 20), im Frontend zusaetzlich loading="lazy". Die Originale sind gitignored, nur die Web-Fassungen kommen ins Repo. DETEKTOR: core/patterns.py bekommt die Zeitebene als PARAMETER. Der Default bleibt M30 und damit bitgleich - `PatternDetector()` speist das Verdict-Gewicht 0,25, eine stille Verschiebung dort waere eine Strategie-Aenderung durch die Hintertuer. Daneben laufen vier weitere Instanzen (M1/M5/M15/H1) mit gestaffelten Refresh-Zeiten (20/25/35/60 s), damit sie den mt5_lock nicht im Pulk belegen. Sie haben KEINE Stimme. Neu Snapshot `patterns_tf`: je Zeitebene das STAERKSTE Muster (bestaetigte vor sich bildenden, dann Symmetrie-Guete; ungueltige fallen raus) samt Bildnamen ueber die Karte `patterns.BILD`. Doppeltop/-boden, Dreifach-Top/-Boden und Flagge bull/baer teilen sich je ein Bild (die Vorlagen zeigen beide Richtungen); `inv_cup` bekommt KEINS - lieber kein Bild als ein falsches. ⚠⚠ REINE ANZEIGE, und das steht auch dran. Die Muster-Klasse ist als SIGNAL gemessen und verworfen (Ziel-Trefferquote nur 13-38 %, backtest_patterns.py), und auf M1 ist sie am schwaechsten: dort liegt der Spread bei 0,319xATR, ein Muster ueber wenige Bars ist weitgehend Rauschen. Kein Verdict-Gewicht, kein Trade-Trigger; die Tooltips nennen die Messung. ⚠ Beim Bau zwei eigene Fehler gefangen: (1) ich hatte die Feldnamen GERATEN - es heisst `type`, nicht `typ`, und der Status ist "confirmed"/"forming"/ "invalidated". Ein falscher Schluessel haette still None geliefert, die Karte waere leer geblieben ohne jede Fehlermeldung. (2) Der Emoji-Surrogat-Abbruch zum sechsten Mal - die .tmp-Regel hat app.js erneut gerettet (0 Bytes verhindert), danach mit literalen Zeichen statt \u-Escapes geschrieben. Live verifiziert: M1 Doppelboden, M5 Tasse+Henkel, M15 aufsteigendes Dreieck, M30 Doppeltop; alle Bilder HTTP 200 (22-28 KB). Pipeline A-G gruen, 97 Tests, 14 render*-Funktionen laufen durch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
fd2ca46dc0
commit
02bede7ef9
+68
-2
@@ -47,7 +47,7 @@ from core.market_hours import session_state
|
||||
from core.daily_levels import DailyLevels
|
||||
from core.gaps import GapAnalyzer
|
||||
from core.structure import MarketStructure
|
||||
from core.patterns import PatternDetector
|
||||
from core.patterns import BILD as _PAT_BILD, PatternDetector
|
||||
from core.candles import CandleAnatomy
|
||||
from core.cone import build as _cone_build
|
||||
from core.candle_logger import CandleLogger
|
||||
@@ -341,6 +341,24 @@ class TradingEngine:
|
||||
self.elliott = ElliottAnalyzer(mt5.TIMEFRAME_M5)
|
||||
self.structure = MarketStructure() # Marktstruktur (M30) — reine Anzeige
|
||||
self.patterns = PatternDetector() # visuelle Chartmuster (M30) — reine Anzeige
|
||||
# ⚠⚠ ZUSAETZLICHE Detektoren je Zeitebene (User-Vorgabe 2026-08-20: das
|
||||
# gerade entstehende Muster je Minuten-Chart als BILD zeigen).
|
||||
# ⚠ `self.patterns` (M30) bleibt UNVERAENDERT — es speist das
|
||||
# Verdict-Gewicht 0,25. Die neuen laufen daneben und haben KEINE
|
||||
# Stimme; sonst waere es eine Strategie-Aenderung durch die Hintertuer.
|
||||
# ⚠ Die Muster-Klasse ist als SIGNAL gemessen und verworfen
|
||||
# (Ziel-Trefferquote nur 13-38 %, `backtest_patterns.py`) — und auf M1
|
||||
# ist sie am schwaechsten: dort liegt der Spread bei 0,319×ATR, ein
|
||||
# Muster ueber wenige Bars ist dort weitgehend Rauschen. Reine Anzeige.
|
||||
# ⚠ Gestaffelte Refresh-Zeiten: fuenf Detektoren im selben Takt wuerden
|
||||
# den `mt5_lock` im Pulk belegen.
|
||||
self.patterns_tf = {
|
||||
"M1": PatternDetector(mt5.TIMEFRAME_M1, "M1", 20.0, 240),
|
||||
"M5": PatternDetector(mt5.TIMEFRAME_M5, "M5", 25.0, 240),
|
||||
"M15": PatternDetector(mt5.TIMEFRAME_M15, "M15", 35.0, 240),
|
||||
"M30": self.patterns,
|
||||
"H1": PatternDetector(mt5.TIMEFRAME_H1, "H1", 60.0, 240),
|
||||
}
|
||||
# Kerzen-Anatomie (M5) — REINE ANZEIGE. Die Lehrbuch-Deutung ist gemessen
|
||||
# invertiert (`backtest_candles.py`), das Handelssignal fiel durch
|
||||
# (`backtest_candle_fade.py`) → kein Verdict-Gewicht, kein Trigger.
|
||||
@@ -845,7 +863,11 @@ class TradingEngine:
|
||||
except Exception as ee: log.warning(f"elliott.refresh_market: {ee}")
|
||||
try: self.structure.refresh_market(self.data.symbol)
|
||||
except Exception as se2: log.warning(f"structure.refresh_market: {se2}")
|
||||
try: self.patterns.refresh_market(self.data.symbol)
|
||||
try:
|
||||
# ⚠ `self.patterns` steckt als "M30" mit in der Karte —
|
||||
# NICHT doppelt aufrufen (eigene Drossel je Instanz).
|
||||
for _pd in self.patterns_tf.values():
|
||||
_pd.refresh_market(self.data.symbol)
|
||||
except Exception as pe2: log.warning(f"patterns.refresh_market: {pe2}")
|
||||
try: self.candle_anat.refresh_market(self.data.symbol)
|
||||
except Exception as ka: log.warning(f"candles.refresh_market: {ka}")
|
||||
@@ -3017,6 +3039,47 @@ class TradingEngine:
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
# TRADE-AKTIONEN (für die Trade-Endpoints in server.py — Schritt 3)
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
def _patterns_tf(self) -> dict:
|
||||
"""Je Zeitebene das STAERKSTE gerade entstehende Muster (+ Bildname).
|
||||
|
||||
⚠ "Staerkste" = zuerst BESTAETIGT vor "bildet sich", dann hoehere Guete.
|
||||
Ein bestaetigtes Muster ist die konkretere Aussage; bei gleichem Status
|
||||
entscheidet die Symmetrie-Guete, die `_detect` ohnehin vergibt.
|
||||
⚠ REINE ANZEIGE. Die Muster-Klasse ist als Signal gemessen und
|
||||
verworfen (Ziel-Trefferquote 13-38 %) — hier wird nur sichtbar gemacht,
|
||||
was ein Chartleser saehe, nichts gewichtet.
|
||||
"""
|
||||
out = {}
|
||||
for lbl, det in (getattr(self, "patterns_tf", None) or {}).items():
|
||||
try:
|
||||
ps = (det.snapshot() or {}).get("patterns") or []
|
||||
if not ps:
|
||||
out[lbl] = None
|
||||
continue
|
||||
# ⚠ Das Feld heisst `type`, nicht `typ`, und der Status ist
|
||||
# "confirmed"/"forming"/"invalidated" — beim ersten Entwurf
|
||||
# hatte ich beides geraten statt nachgelesen. Ein falscher
|
||||
# Schluessel haette hier still `None` geliefert: die Karte
|
||||
# waere leer geblieben, ohne dass irgendwo ein Fehler steht.
|
||||
ps = [m for m in ps if m.get("status") != "invalidated"]
|
||||
if not ps:
|
||||
out[lbl] = None
|
||||
continue
|
||||
best = sorted(ps, key=lambda m: (
|
||||
0 if m.get("status") == "confirmed" else 1,
|
||||
-float(m.get("quality") or 0)))[0]
|
||||
out[lbl] = {
|
||||
"type": best.get("type"), "name": best.get("name"),
|
||||
"dir": best.get("dir"), "status": best.get("status"),
|
||||
"quality": best.get("quality"), "trigger": best.get("trigger"),
|
||||
"target": best.get("target"),
|
||||
"height_atr": best.get("height_atr"),
|
||||
"bild": _PAT_BILD.get(best.get("type")),
|
||||
}
|
||||
except Exception:
|
||||
out[lbl] = None
|
||||
return out
|
||||
|
||||
def _slot(self, source: str):
|
||||
"""Welcher Trader fuer welche Quelle? (Zwei-Slot-Umbau 2026-08-19)
|
||||
|
||||
@@ -5098,6 +5161,9 @@ class TradingEngine:
|
||||
"gaps": self.gaps.snapshot(),
|
||||
"structure": self.structure.snapshot(),
|
||||
"patterns": _pat_snap,
|
||||
# ⚠ Je Zeitebene das STAERKSTE Muster + sein Bild. Reine Anzeige,
|
||||
# kein Verdict-Gewicht (die Klasse ist als Signal verworfen).
|
||||
"patterns_tf": self._patterns_tf(),
|
||||
# Kerzen-Anatomie (M5) — reine Anzeige, KEIN Verdict-Gewicht (gemessen:
|
||||
# Lehrbuch-Deutung invertiert, Handelssignal durchgefallen).
|
||||
"candle_anat": self.candle_anat.snapshot(),
|
||||
|
||||
Reference in New Issue
Block a user