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
+40
-5
@@ -314,22 +314,56 @@ def _detect(piv, cur, atr, last_idx):
|
||||
return res
|
||||
|
||||
|
||||
# ⚠⚠ BILD je Mustertyp (User-Vorgabe 2026-08-20: das gerade entstehende Muster
|
||||
# als Bild zeigen). Die Dateien liegen verkleinert in `web/muster/` — die
|
||||
# Originale in `Chartmuster/` sind 436-611 KB je Stueck; das Dashboard
|
||||
# uebertraegt sonst ~14 KB je Snapshot, ein Originalbild waere das 40-fache.
|
||||
# Verkleinert: 7,5 MB -> 379 KB fuer alle 15.
|
||||
# ⚠ Doppeltop und Doppelboden teilen sich ein Bild (die Vorlage zeigt beide),
|
||||
# ebenso Dreifach-Top/-Boden und Flagge bullisch/baerisch.
|
||||
# ⚠ `inv_cup` hat KEIN eigenes Bild — lieber keins als ein falsches.
|
||||
BILD = {
|
||||
"double_top": "double", "double_bottom": "double",
|
||||
"triple_top": "triple", "triple_bottom": "triple",
|
||||
"hs": "hs", "inv_hs": "inv_hs",
|
||||
"cup": "cup",
|
||||
"flag": "flag", "pennant": "pennant",
|
||||
"wedge_rise": "wedge_rise", "wedge_fall": "wedge_fall",
|
||||
"tri_asc": "tri_asc", "tri_desc": "tri_desc", "tri_sym": "tri_sym",
|
||||
"rect": "rect", "rounding_bottom": "rounding_bottom", "diamond": "diamond",
|
||||
}
|
||||
|
||||
|
||||
class PatternDetector:
|
||||
def __init__(self):
|
||||
self._snap = {"patterns": [], "atr": None, "ts": 0.0}
|
||||
def __init__(self, tf=None, label: str = "M30", refresh_s: float = _REFRESH_S,
|
||||
bars: int = _N_BARS):
|
||||
"""⚠ `tf=None` = M30, der bisherige Stand — der Default bleibt bitgleich.
|
||||
|
||||
Die Zeitebene ist seit dem 2026-08-20 ein PARAMETER (User-Wunsch: das
|
||||
gerade entstehende Muster je Minuten-Chart anzeigen). Vorher war sie die
|
||||
Modul-Konstante `_TF`; die bleibt als Default stehen, damit der
|
||||
bestehende Aufruf `PatternDetector()` sich NICHT aendert — er speist
|
||||
das Verdict-Gewicht 0,25, und eine stille Verschiebung dort waere eine
|
||||
Strategie-Aenderung durch die Hintertuer.
|
||||
"""
|
||||
self._tf = _TF if tf is None else tf
|
||||
self._label = label
|
||||
self._refresh_s = float(refresh_s)
|
||||
self._bars = int(bars)
|
||||
self._snap = {"patterns": [], "atr": None, "ts": 0.0, "tf": label}
|
||||
self._last_refresh = 0.0
|
||||
self._lock = threading.Lock()
|
||||
|
||||
def refresh_market(self, sym: str):
|
||||
now = time.time()
|
||||
if now - self._last_refresh < _REFRESH_S:
|
||||
if now - self._last_refresh < self._refresh_s:
|
||||
return
|
||||
self._last_refresh = now
|
||||
try:
|
||||
with mt5_lock(timeout=2) as got:
|
||||
if not got:
|
||||
return
|
||||
bars = mt5.copy_rates_from_pos(sym, _TF, 0, _N_BARS)
|
||||
bars = mt5.copy_rates_from_pos(sym, self._tf, 0, self._bars)
|
||||
if bars is None or len(bars) < 60:
|
||||
return
|
||||
H = [float(b["high"]) for b in bars]
|
||||
@@ -342,7 +376,8 @@ class PatternDetector:
|
||||
patterns = _detect(piv, C[-1], atr, len(H) - 1)
|
||||
with self._lock:
|
||||
self._snap = {"patterns": patterns, "atr": round(atr, 4),
|
||||
"cur": round(C[-1], 3), "ts": now}
|
||||
"cur": round(C[-1], 3), "ts": now,
|
||||
"tf": self._label}
|
||||
except Exception as e:
|
||||
log.warning(f"patterns.refresh_market: {e}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user