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
+21
View File
@@ -383,6 +383,27 @@ class SignalAggregator:
elif report.volatility_regime == "low":
report.warnings.append("Low volatility — potential for breakout, tight ranges")
# EMA200 distance gate — empirically the strongest single discriminator
# across 2024 trend / 2023 chop / 2026 hostile windows. Sweet spot is
# 0.5–1.5% from EMA200: closer = false-breakout chop, farther = chase.
# Within band keeps confidence; outside band cuts it sharply so the
# trade falls below the B-grade threshold and is rejected.
primary = report.primary_analysis
if primary is not None:
ema200 = primary.key_levels.get("ema_trend")
if ema200 and ema200 > 0 and report.current_price > 0:
ema_dist_pct = abs(report.current_price - ema200) / ema200 * 100.0
if ema_dist_pct < 0.5:
report.warnings.append(
f"NEAR EMA200 ({ema_dist_pct:.2f}%) — chop risk, signal damped"
)
confidence *= 0.55
elif ema_dist_pct > 1.5:
report.warnings.append(
f"FAR FROM EMA200 ({ema_dist_pct:.2f}%) — over-extended, signal damped"
)
confidence *= 0.55
# Final signal
if score >= 40 and confidence >= 65:
report.final_signal = SignalStrength.STRONG_BUY