Chartmuster grafisch: SVG-Skizze in Karte + Trigger/Ziel-Linien im PWA-Chart
- patterns.py: nur AKTIVE, kursnahe Muster (abgearbeitete/Ziel erreicht raus, _MAX_DIST_ATR=5.0 Distanz-Filter) - get_bars liefert bei M30 die Muster (patterns.snapshot) fürs Chart-Overlay - app.js: _patternSvg-Skizze je Muster-Karte + 2 stärkste Muster als Trigger-/Ziel-Preislinien im M30-Chart; Gitternetz dezenter (#10151c) - style.css: .pt-svg; index.html v=116->117; CLAUDE.md aktualisiert Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
21d855b163
commit
ae6bbb2f35
+7
-1
@@ -586,16 +586,22 @@ class TradingEngine:
|
||||
# Regressionskanal — nur M30 (dort ist die Marktstruktur berechnet), als
|
||||
# Linien-Arrays deckungsgleich mit den Bars (Overlay im Charts-Tab).
|
||||
channel = None
|
||||
patterns = []
|
||||
if tf_label == "M30":
|
||||
try:
|
||||
from core.structure import channel_series
|
||||
channel = channel_series(closes, atr, k)
|
||||
except Exception:
|
||||
channel = None
|
||||
# Visuelle Chartmuster (M30) fürs Overlay — Trigger-/Ziel-Preislinien.
|
||||
try:
|
||||
patterns = (self.patterns.snapshot() or {}).get("patterns") or []
|
||||
except Exception:
|
||||
patterns = []
|
||||
return {"tf": tf_label, "symbol": sym, "trend": trend, "bars": bars,
|
||||
"ema12": [round(x, 3) for x in e12[-k:]],
|
||||
"ema50": [round(x, 3) for x in e50[-k:]],
|
||||
"levels": levels, "channel": channel,
|
||||
"levels": levels, "channel": channel, "patterns": patterns,
|
||||
"broker_utc_offset": 3 * 3600}
|
||||
|
||||
def _in_startup_grace(self) -> bool:
|
||||
|
||||
+15
-2
@@ -38,6 +38,8 @@ _MIN_HEIGHT_ATR = 1.2 # Muster-Höhe muss ≥ so viel ATR sein (sonst Rausche
|
||||
_TOL_ATR = 0.7 # zwei "gleiche" Extrema dürfen so weit auseinander (×ATR)
|
||||
_NECK_TOL_ATR = 0.9 # Nackenlinie "flach": zwei Tröge/Hochs so weit (×ATR)
|
||||
_MAX_LOOKBACK = 9 # nur die letzten N Swings betrachten (aktuelle Muster)
|
||||
_MAX_DIST_ATR = 5.0 # Trigger max. so weit vom AKTUELLEN Kurs (sonst nicht mehr
|
||||
# aktionabel — alte, weit weg gelaufene Muster ausblenden)
|
||||
|
||||
|
||||
def _atr(highs, lows, closes, p=14):
|
||||
@@ -189,8 +191,19 @@ def _detect(piv, cur, atr, last_idx):
|
||||
key = (m["type"], round(m["trigger"], 2))
|
||||
if key not in best or m["quality"] > best[key]["quality"]:
|
||||
best[key] = m
|
||||
# ungültige raus, dann nach Status (confirmed/forming) + Qualität + Recency
|
||||
res = [m for m in best.values() if m["status"] != "invalidated"]
|
||||
def played_out(m):
|
||||
"""Ziel bereits erreicht → Muster abgearbeitet, nicht mehr zeigen."""
|
||||
t = m.get("target")
|
||||
if t is None:
|
||||
return False
|
||||
return (cur <= t) if m["dir"] == "bear" else (cur >= t)
|
||||
|
||||
# raus: ungültig · abgearbeitet (Ziel erreicht) · zu weit vom Kurs (nicht mehr
|
||||
# aktionabel — nur AKTIVE, kursnahe Muster zeigen).
|
||||
res = [m for m in best.values()
|
||||
if m["status"] != "invalidated"
|
||||
and not played_out(m)
|
||||
and abs(m["trigger"] - cur) <= _MAX_DIST_ATR * atr]
|
||||
rank = {"confirmed": 2, "forming": 1}
|
||||
res.sort(key=lambda m: (rank.get(m["status"], 0), m["quality"], -m["bars_ago"]), reverse=True)
|
||||
return res
|
||||
|
||||
Reference in New Issue
Block a user