#!/usr/bin/env python3 """Verlässlichkeit der Bounce-Anzeige ('aktiv'): Wenn _bounce_one(TF)=active feuert (überdehnt + Winkel gedreht), wie oft bewegt sich der Kurs in Bounce-Richtung? Aufgeschlüsselt nach TF (M1/M5/M15/M30) und nach H1-Regime (mit/gegen/flach zur Bounce-Richtung). Nur ONSET (Übergang nicht-aktiv→aktiv) = unabhängige Ereignisse. """ import sys, bisect import MetaTrader5 as mt5 from core.wave_rec import WaveRecommender, _atr, _ema_last, _EMA_FAST, _EMA_SLOW, _HTF_DEADBAND K = 10 # Vorlauf in Bars der jeweiligen TF def _ema_series(v,p): k=2.0/(p+1); o=[]; e=v[0] for i,x in enumerate(v): e=x if i==0 else x*k+e*(1-k); o.append(e) return o def _atr_series(H,L,C,p=14): t=[0.0] for i in range(1,len(C)): t.append(max(H[i]-L[i],abs(H[i]-C[i-1]),abs(L[i]-C[i-1]))) return [(sum(t[max(1,i-p+1):i+1])/max(1,len(t[max(1,i-p+1):i+1]))) if i else None for i in range(len(C))] def main(): n=int(sys.argv[1]) if len(sys.argv)>1 else 40000 mt5.initialize() sym=None for c in ("SpotCrude","USOIL","WTI","XTIUSD"): if mt5.symbol_info(c): sym=c; break # H1-Regime vorbereiten h1=mt5.copy_rates_from_pos(sym,mt5.TIMEFRAME_H1,0,20000) hT=[int(b["time"]) for b in h1]; hc=[float(b["close"]) for b in h1] hh=[float(b["high"]) for b in h1]; hl=[float(b["low"]) for b in h1] hEf=_ema_series(hc,_EMA_FAST); hEs=_ema_series(hc,_EMA_SLOW); hA=_atr_series(hh,hl,hc) def h1_sign(ts): idx=bisect.bisect_right(hT,ts)-1 if idx<_EMA_SLOW or hA[idx] is None or hA[idx]<=0: return 0 d=hEf[idx]-hEs[idx] return 0 if abs(d)<_HTF_DEADBAND*hA[idx] else (1 if d>0 else -1) tfs=[("M1",mt5.TIMEFRAME_M1),("M5",mt5.TIMEFRAME_M5), ("M15",mt5.TIMEFRAME_M15),("M30",mt5.TIMEFRAME_M30)] print("="*86) print(f" Bounce-Anzeige 'aktiv' — Verlässlichkeit je TF & H1-Regime ({sym}, Vorlauf {K} Bars)") print(" Treffer = Kurs bewegt sich in Bounce-Richtung · Ø = Ø-Bewegung in ATR") print("="*86) for lbl,tf in tfs: r=mt5.copy_rates_from_pos(sym,tf,0,n) if r is None or len(r)<200: print(f"{lbl}: zu wenig Bars"); continue T=[int(b["time"]) for b in r]; H=[float(b["high"]) for b in r] L=[float(b["low"]) for b in r]; C=[float(b["close"]) for b in r] buckets={"mit":[], "gegen":[], "flach":[], "alle":[]} prev=False for i in range(120, len(C)-K): wc=C[i-119:i+1]; wh=H[i-119:i+1]; wl=L[i-119:i+1] atr=_atr(wh,wl,wc) if not atr or atr<=0: prev=False; continue b=WaveRecommender._bounce_one(wc,atr) active = bool(b and b["state"]=="active") if active and not prev: d=1 if b["dir"]=="LONG" else -1 fwd=(C[i+K]-C[i])*d/atr # in ATR, Bounce-Richtung reg=h1_sign(T[i]) cls = "mit" if reg==d else "gegen" if reg==-d else "flach" buckets[cls].append(fwd); buckets["alle"].append(fwd) prev=active print(f"\n{lbl} ({len(buckets['alle'])} aktive Bounce-Signale)") for cls in ("alle","mit","gegen","flach"): v=buckets[cls] if not v: print(f" {cls:<6} -"); continue hit=100*sum(1 for x in v if x>0)/len(v) print(f" {cls:<6} n={len(v):>4} Treffer={hit:>3.0f}% Ø={sum(v)/len(v):+.2f}×ATR") mt5.shutdown() print("\n 'mit' = H1-Trend in Bounce-Richtung (Trend-Fortsetzung)") print(" 'gegen' = H1-Trend GEGEN den Bounce (Gegen-Trend-Fade)") print(" 'flach' = H1 neutral (reine Range/Mean-Reversion)") if __name__=="__main__": main()