MT5-Chart v1.18: Trade-Marker, Liquiditaetszonen, Kurs oben rechts + Pfeil-Bugfix
Pfeil-Bugfix (User: "liquiditaetspfeile werden immer noch nicht angezeigt"):
(1) ANCHOR_LEFT ist fuer OBJ_ARROW UNGUELTIG (nur TOP/BOTTOM)
(2) Pfeile sitzen rechts neben der letzten Kerze -> ohne CHART_SHIFT kein
sichtbarer Bereich dort
Blink-Fix (User: "blinken nur manchmal auf"): hl_walls setzte den Cache bei jedem
Fehlschlag auf None -> LQ-Zeilen fehlten -> Indikator loeschte die Pfeile. Jetzt
letzter guter Stand 120s Grace.
Neu (alles reine Anzeige):
- TR;<O|C>;zeit -> Kerze der Eroeffnung HELLGRUEN, des Close DUNKELGRUEN umrandet
- EQ;<H|L>;lo;hi;zeit -> Equal Highs/Lows aus M30-Pivots als goldenes Band +
gestrichelte Kante (wie im User-Referenzbild). Als Signal gemessen verworfen.
- PX;bid -> aktueller Kurs fett oben rechts
- Beschriftung der Liquiditaets-Trendlinie per Default aus (v1.16)
Alles kompiliert und live in sr_levels.csv verifiziert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
b75997d703
commit
03567adf6b
@@ -80,6 +80,8 @@ _SQ_REFRESH_S = 5.0 # eigener, schneller M5-Fetch NUR für den Squeeze (entkoppe
|
||||
# raus (z. B. Short im M30-Aufwärtstrend). Nur für Basis-TF < M30 aktiv.
|
||||
_HTF = mt5.TIMEFRAME_M30
|
||||
_HTF_LABEL = "M30"
|
||||
_EQ_TOL_ATR = 0.15 # „gleich" für Equal Highs/Lows: beide Pivots innerhalb x×ATR
|
||||
_EQ_MIN_H_ATR = 0.10 # Mindest-Bandhöhe der Liquiditätszone (sonst unsichtbar dünn)
|
||||
_HTF_DEADBAND = 0.15 # |EMA12−EMA50| < x×ATR(M30) → HTF gilt als neutral
|
||||
|
||||
# Multi-TF-Konfluenz (nur Konfidenz/Anzeige): wenn M30 UND H1 die Richtung
|
||||
@@ -296,6 +298,10 @@ class WaveRecommender:
|
||||
if _lbl == "M5":
|
||||
self._m5_hl = (_h, _l)
|
||||
elif _lbl == "M30":
|
||||
# Bar-ZEITEN mit ablegen — die Liquiditätszonen (Equal
|
||||
# Highs/Lows) brauchen den Zeitpunkt der beiden Pivots,
|
||||
# um im Chart als Band gezeichnet werden zu können.
|
||||
self._m30_t = [int(b["time"]) for b in _tb]
|
||||
# M30-H/L für die S/R-LEVEL (Chart + P(break)-Auto-Close).
|
||||
# Gemessen 2026-07-30 (`backtest_level_tf.py`): M30-Level
|
||||
# schlagen M5 in BEIDEN Hälften (R-Ertrag ~2×, Level 1,95
|
||||
@@ -398,6 +404,35 @@ class WaveRecommender:
|
||||
pl30 = [round(_ls[j], 3) for j in range(_K, len(_ls) - _K)
|
||||
if _ls[j] == min(_ls[j - _K:j + _K + 1])]
|
||||
self._pb_levels30 = {"ph": ph30, "pl": pl30}
|
||||
# ── Liquiditätszonen: EQUAL HIGHS / EQUAL LOWS (SMC, User-Wunsch
|
||||
# 2026-07-30 „zeichne mir die Liquiditätszonen wie im Bild ein").
|
||||
# Zwei ~gleiche M30-Pivots (innerhalb _EQ_TOL×ATR, 2–40 Bars
|
||||
# auseinander) = Stop-Cluster. ⚠ REINE ANZEIGE — als SIGNAL gemessen
|
||||
# und verworfen (`backtest_liquidity_sweep.py`: Equal Highs/Lows
|
||||
# fallen in fast allen Varianten durch, der SMC-Exit sogar überall).
|
||||
_a30 = turn_data.get("M30", (None, None))[1] if turn_data else None
|
||||
_t30 = getattr(self, "_m30_t", None)
|
||||
if _a30 and _a30 > 0 and _t30 and len(_t30) >= len(_hs):
|
||||
_tol = _EQ_TOL_ATR * _a30
|
||||
_toff = len(_t30) - len(_hs) # Index-Versatz Fenster→Voll-Liste
|
||||
def _equal(vals, want_high):
|
||||
# jüngstes Paar zuerst suchen (rückwärts)
|
||||
idx = [j for j in range(_K, len(vals) - _K)
|
||||
if ((vals[j] == max(vals[j - _K:j + _K + 1])) if want_high
|
||||
else (vals[j] == min(vals[j - _K:j + _K + 1])))]
|
||||
for a in range(len(idx) - 1, 0, -1):
|
||||
for b in range(a - 1, -1, -1):
|
||||
gap = idx[a] - idx[b]
|
||||
if gap < 2: continue
|
||||
if gap > 40: break
|
||||
if abs(vals[idx[a]] - vals[idx[b]]) <= _tol:
|
||||
lo = min(vals[idx[a]], vals[idx[b]])
|
||||
hi = max(vals[idx[a]], vals[idx[b]])
|
||||
pad = max(0.0, (_EQ_MIN_H_ATR * _a30 - (hi - lo)) / 2)
|
||||
return {"lo": round(lo - pad, 3), "hi": round(hi + pad, 3),
|
||||
"t": int(_t30[idx[b] + _toff])}
|
||||
return None
|
||||
self._liq_zones = {"eqh": _equal(_hs, True), "eql": _equal(_ls, False)}
|
||||
# Multi-TF-Bounce: stärksten Status über M1/M5/M15/M30 wählen (H1 ist NUR
|
||||
# für die Ampel im turn_data, NICHT im gemessen-neutralen Bounce → skip).
|
||||
cands = []
|
||||
@@ -420,6 +455,8 @@ class WaveRecommender:
|
||||
# M30-Level = Quelle für Chart-Linien UND P(break)-Auto-Close (gemessen besser);
|
||||
# `pb_levels` (M5) bleibt für das Entry-Raum-Gate.
|
||||
snap["pb_levels30"] = dict(self._pb_levels30) if getattr(self, "_pb_levels30", None) else None
|
||||
# Liquiditätszonen (Equal Highs/Lows, M30) — REINE ANZEIGE (Signal verworfen)
|
||||
snap["liq_zones"] = dict(self._liq_zones) if getattr(self, "_liq_zones", None) else None
|
||||
snap["squeeze"] = dict(self._squeeze) if getattr(self, "_squeeze", None) else \
|
||||
{"state": None, "dir": None, "level": None, "box_atr": None}
|
||||
# ── Entry-Raum-Gate (gemessen `backtest_entryroom.py`, beide Hälften
|
||||
|
||||
Reference in New Issue
Block a user