Files
AH-Oil-Trader/backtest_srclose_signal.py
T
Axel HocksandClaude Opus 4.8 75d28827e8 Initial commit: Oil Trading Bot (MT5, WTI)
Headless FastAPI-Backend (server.py + core/engine.py) mit Mobile-PWA (web/),
Strategie-/Backtest-Suite und Doku. Secrets, DB, Logs und Laufzeit-State sind
via .gitignore ausgeschlossen; Config-Vorlage: oil_widget_config.ini.example.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 08:29:23 +02:00

83 lines
4.3 KiB
Python

#!/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<X UND Empfehlung NICHT in Richtung (feat[2]<0.5)
user = sum((e["R_close"] if (e["_p"] < X and e["feat"][2] < 0.5) else e["R_run"])
for e in tset) + untouched
# Die betroffenen Touches: P<X UND mit-Trend (die deine Regel jetzt HÄLT statt closed)
held = [e for e in tset if e["_p"] < X and e["feat"][2] >= 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()