Remove EUR/USD support — XAU/USD-only codebase
EUR/USD never had a validated edge (2026-07-11/12 verdict: no config
passed validation on M5/M15/H1 at 1-pip cost; cost-to-volatility root
cause). Removed: EurUsdStrategyConfig, pair_signals/eurusd.py, EUR
gates 6h + weekend/day filters + strategy marker + trade geometry in
signal_aggregator, EUR pair registry/aliases in main.py and
gpu_backtest.py, EUR/USD news pair mappings, test_all.py Module 10.
Generic multi-currency news keyword infra kept (GBP/JPY/EUR keyword
table is not pair code). Full EUR history remains at 7d3fd95.
Suite: 162/162 green (was 187; 25 EUR-specific tests removed).
Claude-Session: https://claude.ai/code/session_015kby7M9JwpYi8NQT2yoxAi
This commit is contained in:
@@ -45,8 +45,6 @@ def produce_signal(
|
||||
|
||||
|
||||
from pair_signals import xauusd as _xau_mod
|
||||
from pair_signals import eurusd as _eur_mod
|
||||
from config import XAUUSD, EURUSD
|
||||
from config import XAUUSD
|
||||
|
||||
register_pair(XAUUSD, _xau_mod.make_config)
|
||||
register_pair(EURUSD, _eur_mod.make_config)
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
"""EUR/USD signal producer config.
|
||||
|
||||
Re-tuned 2026-07-10 against the realistic backtester (1-pip round-trip
|
||||
cost, next-open fills, raw-path resolution) on 2025-07-08 → 2026-07-08
|
||||
M5 with M15/H1 confirmations. RESULT: no configuration passed the
|
||||
acceptance rule (positive in BOTH train and val halves, PF >= 1.3).
|
||||
|
||||
The M5 defaults below are the best found — roughly breakeven
|
||||
(-1.1R / 53 trades / PF 0.93 / 62% WR on 12mo) versus the donor
|
||||
branch's -6.7R. Findings that shaped them:
|
||||
- transitioning regime bled -27R/88 trades wide-open → blocked
|
||||
- A-grade entries LOSE (-26R) while B-grade wins — max conviction
|
||||
fires at move extremes (same pathology as gold M5)
|
||||
- Fridays (-17R) and hours 8, 12, 13, 18, 19 UTC negative
|
||||
- score 30-35 band is where the train-half losses live → floor 35
|
||||
- trailing exits beat static TP1 (arm 0.45R / dist 0.5R best)
|
||||
|
||||
M15 + H1 investigated 2026-07-11, verdict NO VALIDATED EDGE either
|
||||
(all at 1-pip round-trip cost, real fills):
|
||||
- M15 wide-open (all gates off): -2.5R/270 trades 2025-26;
|
||||
-54.8R/308 trades on 2024-25 out-of-sample. PF 0.61-0.98.
|
||||
- Best in-sample slice (transitioning-regime-only: +15.4R, PF 1.59,
|
||||
positive both halves, month-spread) FAILED 2024-25 OOS at PF 0.55.
|
||||
Within-year train/val splits are not sufficient for EUR — always
|
||||
re-test on the 2024 window before believing a config.
|
||||
- Raw-parquet forward-return screens (M15 and M5, ~14 entry
|
||||
conditions x 4-5 horizons: momentum, mean-reversion, breakout,
|
||||
streak, session families): nothing clears +1 pip in both years.
|
||||
- H1 wide-open: +9.8R PF 1.32 in 2025-26 (both halves positive) but
|
||||
-5.7R PF 0.82 on 2024-25. Positive from Jan 2025 onward; H2-2024
|
||||
regime negative. Closest to workable, still unvalidated.
|
||||
|
||||
Root cause is cost-to-volatility: EUR M15 ATR ~= 10 pips, so the 1-pip
|
||||
spread taxes every trade ~10% of ATR (M5 worse). The XAU signal engine
|
||||
survives because gold's ATR/spread ratio is several times larger.
|
||||
|
||||
EUR/USD therefore ships FUNCTIONAL BUT OFF by default: it is not in
|
||||
PlatformConfig.scan_pairs. Scan it on demand (main.py --pair EURUSD,
|
||||
or add to scan_pairs) but treat all EUR M5/M15 signals as informational
|
||||
only.
|
||||
|
||||
Calendar + hybrid avenues CLOSED 2026-07-12 (see backtest/research/):
|
||||
- Surprise-conditioned entries (real Forex Factory archive, verified
|
||||
timestamps): follow-surprise loses 2-5 pips at every horizon in
|
||||
both years under every conditioning. The market prices the
|
||||
surprise within the release bar.
|
||||
- Event-window avoidance: EUR effect marginal/inconsistent (and on
|
||||
XAU it would REMOVE profit — event-window trades outperform).
|
||||
- H1-anchored direction + M15 pullback execution (pre-registered
|
||||
kill criteria): 2025-26 +2.8R PF 1.11, 2024-25 OOS -1.5R PF 0.92
|
||||
-> killed.
|
||||
Remaining avenues need data we don't have: tick-level fills for
|
||||
limit-entry cost reduction, or H4/D1 swing horizons.
|
||||
"""
|
||||
|
||||
from typing import Optional, List
|
||||
from config import PlatformConfig, Timeframe, EURUSD
|
||||
|
||||
_CONFIRMATIONS = {
|
||||
Timeframe.M5: [Timeframe.M15, Timeframe.H1],
|
||||
Timeframe.M15: [Timeframe.M5, Timeframe.H1],
|
||||
Timeframe.H1: [Timeframe.M15, Timeframe.H4],
|
||||
Timeframe.H4: [Timeframe.H1, Timeframe.D1],
|
||||
}
|
||||
|
||||
_TRENDING = {
|
||||
"ema_trend": 2.0, "rsi": 1.0, "macd": 2.0,
|
||||
"bollinger": 0.5, "keltner": 1.0, "roc": 1.5,
|
||||
"candlestick": 0.5, "divergence": 2.0, "adx": 1.0,
|
||||
}
|
||||
|
||||
EUR_REGIME_WEIGHTS = {
|
||||
"trending_up": _TRENDING,
|
||||
"trending_down": _TRENDING,
|
||||
"trending": _TRENDING,
|
||||
"ranging": {
|
||||
"ema_trend": 0.3, "rsi": 2.0, "macd": 1.0,
|
||||
"bollinger": 2.0, "keltner": 1.5, "roc": 0.5,
|
||||
"candlestick": 0.8, "divergence": 2.5, "adx": 0.5,
|
||||
},
|
||||
"transitioning": {
|
||||
"ema_trend": 1.5, "rsi": 1.5, "macd": 2.0,
|
||||
"bollinger": 1.0, "keltner": 1.5, "roc": 2.0,
|
||||
"candlestick": 0.8, "divergence": 2.0, "adx": 1.0,
|
||||
},
|
||||
}
|
||||
|
||||
_M5_TRENDING = {
|
||||
"ema_trend": 1.5, "rsi": 1.0, "macd": 2.5,
|
||||
"bollinger": 0.5, "keltner": 2.0, "roc": 2.0,
|
||||
"candlestick": 0.3, "divergence": 1.0, "adx": 1.0,
|
||||
}
|
||||
|
||||
M5_REGIME_WEIGHTS = {
|
||||
"trending_up": _M5_TRENDING,
|
||||
"trending_down": _M5_TRENDING,
|
||||
"trending": _M5_TRENDING,
|
||||
"ranging": {
|
||||
"ema_trend": 0.3, "rsi": 1.5, "macd": 1.5,
|
||||
"bollinger": 1.5, "keltner": 2.0, "roc": 1.0,
|
||||
"candlestick": 0.3, "divergence": 1.5, "adx": 0.5,
|
||||
},
|
||||
"transitioning": {
|
||||
"ema_trend": 1.0, "rsi": 1.0, "macd": 2.5,
|
||||
"bollinger": 0.5, "keltner": 2.5, "roc": 2.0,
|
||||
"candlestick": 0.3, "divergence": 1.0, "adx": 1.0,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def make_config(
|
||||
primary_tf: Timeframe,
|
||||
confirmation_tfs: Optional[List[Timeframe]] = None,
|
||||
) -> PlatformConfig:
|
||||
config = PlatformConfig()
|
||||
config.symbol = EURUSD
|
||||
config.display_name = "EUR/USD"
|
||||
config.pip_value = 0.0001
|
||||
config.primary_timeframe = primary_tf
|
||||
config.confirmation_timeframes = (
|
||||
confirmation_tfs or _CONFIRMATIONS.get(primary_tf, [Timeframe.M15, Timeframe.H4])
|
||||
)
|
||||
|
||||
# XAU gates are display-gated in the aggregator; disabling here is
|
||||
# belt-and-braces so no gold logic can ever fire on an EUR config.
|
||||
config.xau_strategy.enabled = False
|
||||
|
||||
# Keep event-risk signal gating ON for EUR (the XAU-tuned default
|
||||
# turned it off after the 2026-07-11 audit — that evidence is
|
||||
# gold-specific; EUR event-window trades were flat-to-negative).
|
||||
config.news.event_risk_caps_signals = True
|
||||
|
||||
config.backtest.session_start_hour = 7
|
||||
config.backtest.session_end_hour = 20
|
||||
config.backtest.blocked_hours_utc = [22, 23, 0, 1, 2, 3]
|
||||
config.backtest.allowed_weekdays = [0, 1, 2, 3, 4]
|
||||
|
||||
if primary_tf == Timeframe.M5:
|
||||
config.technical.regime_weights_override = M5_REGIME_WEIGHTS
|
||||
config.technical.swing_sr_lookback = 20
|
||||
config.eur_strategy.sl_atr_floor = 0.7
|
||||
config.eur_strategy.sl_atr_multiplier = 0.3
|
||||
config.eur_strategy.min_quality_grades = ["A+", "A", "B"]
|
||||
# Best-found 2026-07-10 (breakeven, see module docstring):
|
||||
config.eur_strategy.min_entry_score = 35.0
|
||||
config.eur_strategy.min_entry_confidence = 45.0
|
||||
config.eur_strategy.blocked_vol_regimes = []
|
||||
config.eur_strategy.min_indicator_agreement = 0
|
||||
config.eur_strategy.allowed_weekdays = [0, 1, 2, 3] # Fridays bled -17R
|
||||
config.backtest.allowed_weekdays = [0, 1, 2, 3]
|
||||
config.backtest.blocked_hours_utc = [22, 23, 0, 1, 2, 3, 8, 12, 13, 18, 19]
|
||||
# Trailing exit beat static TP1; earlier/tighter than gold's 0.6/0.75.
|
||||
config.signals.trail_arm_r = 0.45
|
||||
config.signals.trail_dist_r = 0.5
|
||||
else:
|
||||
config.technical.regime_weights_override = EUR_REGIME_WEIGHTS
|
||||
|
||||
return config
|
||||
Reference in New Issue
Block a user