#!/usr/bin/env python3 """ER-Chop-Gate testen (Track B): Signal → WARTEN, wenn Efficiency Ratio der letzten N Bars < X (choppy). Frage: haben die Chop-Signale (niedrige ER) wirklich schlechteren Edge als die Trend-Signale (hohe ER)? Über 2 Zeiträume. Exit-Sim SL 2×ATR + Trailing. Validiert nur, wenn in BEIDEN Hälften: behaltene (ER≥X) besser als alle, verworfene (ER0 else (hi>=eff): return (eff-entry)*d/atr hw=max(hw,hi) if d>0 else min(hw,lo) if (C[j]-entry)*d>=_TRAILON*atr: trail=True if trail: lock=hw-d*_TPTRAIL*atr eff=max(eff,lock) if d>0 else min(eff,lock) return (exit_px-entry)*d/atr def st(Rs): if not Rs: return "n=0" n=len(Rs); w=sum(1 for r in Rs if r>0) g=sum(r for r in Rs if r>0); ls=-sum(r for r in Rs if r<0) return f"n={n:>5} WR={100*w/n:>3.0f}% Ø-R={sum(Rs)/n:+.3f} PF={(g/ls if ls>0 else 99):>4.2f} ΣR={sum(Rs):+.0f}" def er_at(C,i,N): if i-N<0: return None net=abs(C[i]-C[i-N]); path=sum(abs(C[j]-C[j-1]) for j in range(i-N+1,i+1)) return net/path if path>0 else 0.0 def collect(H,L,C,ES,EF,AT,lo,hi,N): TH=_REVERSAL_STRETCH; out=[] for i in range(max(lo,_N_BARS,N+2), min(hi,len(C)-_MAXH-1)): atr=AT[i] if not atr or atr<=0: continue atr=max(atr,_ATRMIN); es=ES[i]; ef=EF[i] stretch=(C[i]-es)/atr ang=calc_trend_angle(C[i-_ANGLE_LR-2:i],_ANGLE_LR); ad=ang-90.0 d=0 if stretch<=-TH and ad>=_ANGLE_DEAD: d=1 elif stretch>=TH and ad<=-_ANGLE_DEAD: d=-1 elif abs(stretch)<_STRETCH_MAX: d=1 if ef>es else -1 if ef1 else 80000 N=int(sys.argv[2]) if len(sys.argv)>2 else 20 # ER-Lookback in Bars mt5.initialize(); sym=None for c in ("SpotCrude","USOIL","WTI","XTIUSD"): if mt5.symbol_info(c): sym=c; break bars=None for req in (n,100000,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] EF=_ema_series(C,_EMA_FAST); ES=_ema_series(C,_EMA_SLOW); AT=_atr_series(H,L,C) mid=len(C)//2 halves=[("H1 (alt)",_N_BARS,mid),("H2 (neu)",mid,len(C))] print("="*90) print(f" ER-Chop-Gate — {sym} M5 ({len(C)} Bars) ER-Lookback N={N} Bars Exit SL2+Trail") print("="*90) EV={lbl: collect(H,L,C,ES,EF,AT,a,b,N) for lbl,a,b in halves} for lbl,_,_ in halves: base=[R for _,R in EV[lbl]] print(f"\n{lbl}: BASELINE (alle Signale) {st(base)}") for X in (0.15,0.20,0.25,0.30): keep=[R for er,R in EV[lbl] if er is not None and er>=X] drop=[R for er,R in EV[lbl] if er is not None and er< X] print(f" ER≥{X:.2f} behalten {st(keep)}") print(f" ER<{X:.2f} verworfen {st(drop)}") print("\n Gate lohnt NUR, wenn 'verworfen' in BEIDEN Hälften deutlich schlechteres") print(" Ø-R hat als 'behalten' — sonst schneidet er nur Volumen ohne Edge-Gewinn.") if __name__=="__main__": main()