#!/usr/bin/env python3 """S/R-Close SIGNAL-gegated (User-Idee 2026-07-22): den S/R-Close (P(break)<0,60) UNTERDRÜCKEN, solange die Empfehlung noch in Trade-Richtung zeigt — dann laufen lassen (bis das Signal auf WARTEN dreht). Test-Frage: bringt „bei mit-Trend am Level HALTEN statt schließen" mehr als der reine P(break)-Close? Reuse der gemessenen S/R-Close-Mechanik aus `backtest_srclose_prob.py`: R_run = laufen lassen (Trailing-Exit) · R_close = am Level schließen feat[2] = 1.0 wenn EMA am Touch in Trade-Richtung (= „Empfehlung LONG/SHORT"), 0.0 sonst (= Empfehlung neutral/gegen → ~WARTEN). Regeln je Level-Touch: BASELINE = immer laufen lassen. P(break) = close wenn P<0,60 (der aktuelle Live-Mechanismus). USER-Regel = close wenn P<0,60 UND Empfehlung NICHT in Richtung (feat[2]==0); bei mit-Trend HALTEN (laufen). Differenz nur bei den mit-Trend-Touches. 2 Halbjahre, Echtkosten. Verdict: USER-Regel nur besser, wenn ΣR in BEIDEN Hälften über dem reinen P(break)-Close liegt. """ import sys import numpy as np import MetaTrader5 as mt5 from backtest_srclose_prob import collect, fit_logreg, _ema_series, _atr_series from core.wave_rec import _EMA_FAST, _EMA_SLOW, _N_BARS def main(): n = int(sys.argv[1]) if len(sys.argv) > 1 else 80000 mt5.initialize() sym = next((c for c in ("SpotCrude", "USOIL", "WTI", "XTIUSD") if mt5.symbol_info(c)), None) point = mt5.symbol_info(sym).point bars = None for req in (n, 80000, 60000, 40000): bars = mt5.copy_rates_from_pos(sym, mt5.TIMEFRAME_M5, 0, req) if bars is not None and len(bars) > 2000: break mt5.shutdown() H = [float(b["high"]) for b in bars]; L = [float(b["low"]) for b in bars] C = [float(b["close"]) for b in bars]; SP = [float(b["spread"])*point for b in bars] EF = _ema_series(C, _EMA_FAST); ES = _ema_series(C, _EMA_SLOW); AT = _atr_series(H, L, C) mid = len(C)//2 ev1 = collect(_N_BARS, mid, H, L, C, EF, ES, AT, SP, point) ev2 = collect(mid, len(C), H, L, C, EF, ES, AT, SP, point) # P(break)-Modell auf H1-Touches trainieren (wie im Original) t1 = [e for e in ev1 if e["touched"]] X1 = np.array([e["feat"] for e in t1]); y1 = np.array([e["brk"] for e in t1]) mu = X1.mean(0); sd = X1.std(0)+1e-9 w = fit_logreg((X1-mu)/sd, y1) def pbreak(e): x = (np.array(e["feat"])-mu)/sd return 1/(1+np.exp(-(w@np.concatenate([[1.0], x])))) X = 0.60 print("="*88) print(f" S/R-Close SIGNAL-gegated (bei mit-Trend HALTEN) — {sym} M5, 2 Halbjahre, Echtkosten") print(f" Vergleich: reiner P(break)-Close (P<{X}) vs. deine Regel (nur closen wenn Empf. NICHT in Richtung)") print("="*88) for lbl, ev in (("H1 (alt)", ev1), ("H2 (neu)", ev2)): for e in ev: if e["touched"]: e["_p"] = pbreak(e) untouched = sum(e["R_run"] for e in ev if not e["touched"]) tset = [e for e in ev if e["touched"]] base = sum(e["R_run"] for e in ev) # immer laufen pbrule = sum((e["R_close"] if e["_p"] < X else e["R_run"]) for e in tset) + untouched # USER: close nur wenn P= 0.5] gv_close = sum(e["R_close"] for e in held); gv_run = sum(e["R_run"] for e in held) print(f"\n {lbl}: {len(ev)} Wellen · {len(tset)} Touches") print(f" Baseline (immer laufen) ΣR = {base:+.0f}") print(f" P(break)-Close (Live) ΣR = {pbrule:+.0f} (Δ Baseline {pbrule-base:+.0f})") print(f" DEINE Regel (mit-Trend halten) ΣR = {user:+.0f} (Δ P(break) {user-pbrule:+.0f})") print(f" → betroffen: {len(held)} mit-Trend-Touches. Wenn geHALTEN: ΣR {gv_run:+.0f} " f"vs. geschlossen: ΣR {gv_close:+.0f} → Halten {'BESSER' if gv_run>gv_close else 'SCHLECHTER'} " f"({gv_run-gv_close:+.0f})") print(f"\n Verdict: deine Regel nur einbauen, wenn 'Halten BESSER' in BEIDEN Hälften.") if __name__ == "__main__": main()