Tune EUR/USD trade setup: quality-scaled TP and tighter SL
EUR/USD A-grade signals had inverted quality curve (-1.65R) because all trades got RR≈0.50 and mature_move logic penalized high-score entries. Fix: add per-pair trade setup params (sl_atr_floor=1.2, min_rr=1.0, mature_move_threshold=35) and apply quality_scale to both tp_mult and min_rr so A-grade gets wider TP targets. Also wire EUR config into backtest via PAIR_PRODUCERS registry. Result: A-grade now +1.24R (was -1.65R), total EUR/USD +10.06R (was +4.20R). XAU/USD unchanged at +13.01R. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+30
-11
@@ -53,10 +53,12 @@ from config import ( # noqa: E402
|
||||
SignalStrength,
|
||||
Timeframe,
|
||||
XAUUSD,
|
||||
EURUSD,
|
||||
)
|
||||
from data_provider import ForexDataProvider # noqa: E402
|
||||
from engine import IndicatorSignal, TechnicalAnalysis, TechnicalEngine # noqa: E402
|
||||
from signal_aggregator import SignalAggregator, SignalReport, TradeSetup # noqa: E402
|
||||
from pair_signals import PAIR_PRODUCERS # noqa: E402
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# GPU shim — CuPy if available AND CUDA runtime works, else NumPy.
|
||||
@@ -96,6 +98,8 @@ PAIR_ALIASES = {
|
||||
"XAUUSD": XAUUSD,
|
||||
"XAU/USD": XAUUSD,
|
||||
"GOLD": XAUUSD,
|
||||
"EURUSD": EURUSD,
|
||||
"EUR/USD": EURUSD,
|
||||
}
|
||||
|
||||
# Bar duration in seconds — used to compute "fully-closed" cutoffs so
|
||||
@@ -1310,6 +1314,16 @@ def _is_xau_blocked_by_calendar(ts: pd.Timestamp, cfg: PlatformConfig) -> Option
|
||||
return None
|
||||
|
||||
|
||||
def _is_pair_blocked_by_calendar(ts: pd.Timestamp, cfg: PlatformConfig) -> Optional[str]:
|
||||
"""Generic weekend + weekday filter using FilterConfig (backtest field)."""
|
||||
bt = cfg.backtest
|
||||
if ts.weekday() >= 5:
|
||||
return "WEEKEND_FILTER"
|
||||
if bt.allowed_weekdays and ts.weekday() not in bt.allowed_weekdays:
|
||||
return "DAY_FILTER"
|
||||
return None
|
||||
|
||||
|
||||
def run_backtest(
|
||||
bt_cfg: BacktestConfig,
|
||||
platform_cfg: Optional[PlatformConfig] = None,
|
||||
@@ -1387,12 +1401,14 @@ def run_backtest(
|
||||
# Decision time = close of the current primary bar.
|
||||
decision_time = ts + primary_dur
|
||||
|
||||
# XAU calendar filter (matches live analyze_pair behavior).
|
||||
# Calendar filter (matches live analyze_pair behavior).
|
||||
if PAIR_INFO[bt_cfg.pair]["display"] == "XAU/USD":
|
||||
block = _is_xau_blocked_by_calendar(ts, platform_cfg)
|
||||
if block:
|
||||
skipped_reasons[block] = skipped_reasons.get(block, 0) + 1
|
||||
continue
|
||||
else:
|
||||
block = _is_pair_blocked_by_calendar(ts, platform_cfg)
|
||||
if block:
|
||||
skipped_reasons[block] = skipped_reasons.get(block, 0) + 1
|
||||
continue
|
||||
|
||||
# Cooldown.
|
||||
if pos - last_entry_pos < bt_cfg.cooldown_bars:
|
||||
@@ -1890,13 +1906,16 @@ def main(argv: Optional[List[str]] = None) -> int:
|
||||
f"Pair: {PAIR_INFO[pair]['display']} | Window: {start.date()} → {end.date()}"
|
||||
)
|
||||
|
||||
platform_cfg = PlatformConfig(
|
||||
symbol=pair,
|
||||
display_name=PAIR_INFO[pair]["display"],
|
||||
pip_value=PAIR_INFO[pair]["pip_value"],
|
||||
primary_timeframe=primary_tf,
|
||||
confirmation_timeframes=confirm_tfs,
|
||||
)
|
||||
if pair in PAIR_PRODUCERS:
|
||||
platform_cfg = PAIR_PRODUCERS[pair](primary_tf, confirm_tfs)
|
||||
else:
|
||||
platform_cfg = PlatformConfig(
|
||||
symbol=pair,
|
||||
display_name=PAIR_INFO[pair]["display"],
|
||||
pip_value=PAIR_INFO[pair]["pip_value"],
|
||||
primary_timeframe=primary_tf,
|
||||
confirmation_timeframes=confirm_tfs,
|
||||
)
|
||||
if args.swing_sr_lookback > 0:
|
||||
platform_cfg.technical.swing_sr_lookback = args.swing_sr_lookback
|
||||
|
||||
|
||||
Reference in New Issue
Block a user