Add EMA200 distance gate — strongest single signal-quality filter
Across 2024 trend / 2023 chop / 2026 hostile windows, distance from the H1 EMA200 was empirically the most discriminative variable. Sweet spot 0.5-1.5% from EMA200; closer = false-breakout chop, farther = chase. Outside the band, confidence is multiplied by 0.55 so the trade falls below the B-grade threshold and is rejected. Cumulative return across the 3 windows: +13.88% baseline -> +35.50%. Win rate improved in every regime; 2023 chop turned positive (-2.56% to +14.94%). Also extends the trade journal with per-timeframe MTF scores, RSI at entry, and EMA200 distance for future filter mining; surfaces ema_trend in key_levels so the gate can read it.
This commit is contained in:
+23
@@ -358,11 +358,24 @@ class WalkForwardBacktester:
|
||||
analysis = report.primary_analysis
|
||||
adx_val = 0.0
|
||||
atr_pct = 0.0
|
||||
rsi_val = 50.0
|
||||
ema_dist = 0.0
|
||||
if analysis is not None:
|
||||
adx_sig = analysis.indicators.get("adx")
|
||||
if adx_sig is not None:
|
||||
adx_val = float(adx_sig.value)
|
||||
atr_pct = float(analysis.key_levels.get("atr_pct", 0.0))
|
||||
rsi_sig = analysis.indicators.get("rsi")
|
||||
if rsi_sig is not None:
|
||||
rsi_val = float(rsi_sig.value)
|
||||
ema_trend = analysis.key_levels.get("ema_trend")
|
||||
if ema_trend and ema_trend > 0:
|
||||
ema_dist = (raw_entry - ema_trend) / ema_trend * 100.0
|
||||
|
||||
# Per-timeframe scores from MTF map (keys are tf.value strings)
|
||||
m15_s = float(report.mtf_scores.get("15min", 0.0))
|
||||
h1_s = float(report.mtf_scores.get("1h", 0.0))
|
||||
h4_s = float(report.mtf_scores.get("4h", 0.0))
|
||||
|
||||
entry_ts = next_bar.name
|
||||
entry_hour = int(entry_ts.hour) if hasattr(entry_ts, "hour") else -1
|
||||
@@ -389,6 +402,11 @@ class WalkForwardBacktester:
|
||||
"market_regime": report.market_regime or "",
|
||||
"volatility_regime": report.volatility_regime or "",
|
||||
"mtf_agreement": bool(report.mtf_agreement),
|
||||
"m15_score": m15_s,
|
||||
"h1_score": h1_s,
|
||||
"h4_score": h4_s,
|
||||
"rsi_at_entry": rsi_val,
|
||||
"ema_distance_pct": ema_dist,
|
||||
}
|
||||
|
||||
def _check_exit(
|
||||
@@ -477,6 +495,11 @@ class WalkForwardBacktester:
|
||||
market_regime=position.get("market_regime", ""),
|
||||
volatility_regime=position.get("volatility_regime", ""),
|
||||
mtf_agreement=position.get("mtf_agreement", False),
|
||||
m15_score=position.get("m15_score", 0.0),
|
||||
h1_score=position.get("h1_score", 0.0),
|
||||
h4_score=position.get("h4_score", 0.0),
|
||||
rsi_at_entry=position.get("rsi_at_entry", 50.0),
|
||||
ema_distance_pct=position.get("ema_distance_pct", 0.0),
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user