#!/usr/bin/env python3 """Misst den Effekt eines Higher-TF-Trendfilters auf die Empfehlung. Vergleicht den Richtungs-Edge der echten _build-Logik OHNE Filter gegen MIT Filter: Signal wird verworfen, wenn der uebergeordnete Trend (H1 bzw. M30, EMA12 vs EMA50) klar dagegen steht (Totband in xATR der HTF). """ from __future__ import annotations import sys import MetaTrader5 as mt5 from core.wave_rec import (WaveRecommender, _atr, _ema_last, _EMA_FAST, _EMA_SLOW, _N_BARS) _TF = {"M1": mt5.TIMEFRAME_M1, "M5": mt5.TIMEFRAME_M5, "M15": mt5.TIMEFRAME_M15, "M30": mt5.TIMEFRAME_M30, "H1": mt5.TIMEFRAME_H1} class _NeutralTU: def snapshot(self): return {"intervals": {}} def _ema_series(vals, period): """Komplette EMA-Reihe (gleiche Laenge wie vals).""" k = 2.0 / (period + 1) out = [] e = vals[0] for i, v in enumerate(vals): e = v if i == 0 else v * k + e * (1.0 - k) out.append(e) return out def _rep(name, rets): if not rets: print(f" {name:<16} keine Signale"); return n = len(rets); win = sum(1 for x in rets if x > 0) print(f" {name:<16} n={n:>4} Treffer={100*win/n:>3.0f}% " f"Oe-Edge={sum(rets)/n:+.4f} Summe={sum(rets):+.2f}") def main(): base_lbl = (sys.argv[1].upper() if len(sys.argv) > 1 else "M5") htf_lbl = (sys.argv[2].upper() if len(sys.argv) > 2 else "H1") n_bars = int(sys.argv[3]) if len(sys.argv) > 3 else 4000 dead = float(sys.argv[4]) if len(sys.argv) > 4 else 0.10 # HTF-Totband xATR K = 10 tf, htf = _TF[base_lbl], _TF[htf_lbl] if not mt5.initialize(): print("MT5-Init fehlgeschlagen:", mt5.last_error()); sys.exit(1) sym = None for cand in ("SpotCrude", "USOIL", "WTI", "XTIUSD"): if mt5.symbol_info(cand): sym = cand; break sym = sym or "SpotCrude" bars = mt5.copy_rates_from_pos(sym, tf, 0, n_bars + _N_BARS + K + 5) hbars = mt5.copy_rates_from_pos(sym, htf, 0, n_bars // 2 + 300) mt5.shutdown() if bars is None or hbars is None: print("Zu wenige Bars."); sys.exit(1) T = [int(b["time"]) for b in bars] H = [float(b["high"]) for b in bars] L = [float(b["low"]) for b in bars] C = [float(b["close"]) for b in bars] hT = [int(b["time"]) for b in hbars] hC = [float(b["close"]) for b in hbars] hH = [float(b["high"]) for b in hbars] hL = [float(b["low"]) for b in hbars] hEf = _ema_series(hC, _EMA_FAST) hEs = _ema_series(hC, _EMA_SLOW) def htf_trend(ts): """Vorzeichen des HTF-Trends zum Zeitpunkt ts: +1 auf, -1 ab, 0 flach.""" # letzte HTF-Bar mit time <= ts lo, hi = 0, len(hT) - 1 idx = -1 while lo <= hi: mid = (lo + hi) // 2 if hT[mid] <= ts: idx = mid; lo = mid + 1 else: hi = mid - 1 if idx < _EMA_SLOW: return 0 atr = _atr(hH[:idx+1], hL[:idx+1], hC[:idx+1]) if not atr: return 0 d = hEf[idx] - hEs[idx] if abs(d) < dead * atr: return 0 return 1 if d > 0 else -1 w = WaveRecommender(_NeutralTU(), tf) raw = {"LONG": [], "SHORT": []} flt = {"LONG": [], "SHORT": []} dropped = 0 for i in range(_N_BARS, len(C) - K): win_c = C[i-_N_BARS:i]; win_h = H[i-_N_BARS:i]; win_l = L[i-_N_BARS:i] atr = _atr(win_h, win_l, win_c) if not atr or atr <= 0: continue ef = _ema_last(win_c, _EMA_FAST); es = _ema_last(win_c, _EMA_SLOW) rec, _ = w._build(ef, es, C[i-1], atr, base_lbl, 5) sig = rec["signal"] if sig == "WARTEN": continue fwd = C[i+K] - C[i] r = fwd if sig == "LONG" else -fwd raw[sig].append(r) ht = htf_trend(T[i]) d = 1 if sig == "LONG" else -1 if ht != 0 and ht != d: # HTF steht klar dagegen → verwerfen dropped += 1 continue flt[sig].append(r) print("=" * 66) print(f" HTF-Filter — {sym} Basis={base_lbl} Filter={htf_lbl} " f"Totband={dead}xATR Vorlauf={K}") print("=" * 66) print("OHNE Filter:") _rep("LONG", raw["LONG"]); _rep("SHORT", raw["SHORT"]) _rep("ALLE", raw["LONG"] + raw["SHORT"]) print(f"MIT Filter (verworfen: {dropped}):") _rep("LONG", flt["LONG"]); _rep("SHORT", flt["SHORT"]) _rep("ALLE", flt["LONG"] + flt["SHORT"]) if __name__ == "__main__": main()