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:
Harwinder
2026-05-07 19:28:19 -04:00
parent be42736223
commit 5a392a578d
4 changed files with 54 additions and 0 deletions
+23
View File
@@ -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),
)