回测基本一致
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
"""Smoke test: run the scalper engine end-to-end on real XAUUSD bars.
|
||||
|
||||
Uses the frozen baseline params (the saved .set config). Verifies the engine
|
||||
+ signals + metrics produce a sane result (trades, PnL, drawdown) before we
|
||||
wire the optimizer. This is the Phase 4 validation gate — not yet the MT5
|
||||
fidelity check (that's Phase 7).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
PROJECT = Path(__file__).resolve().parent.parent
|
||||
sys.path.insert(0, str(PROJECT))
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
from shared.core.engine import SizingInputs
|
||||
from shared.core.metrics import compute_metrics
|
||||
from shared.data.loaders import load_bars
|
||||
from strategies.gold_scalper_pro.instruments import XAUUSD_REAL
|
||||
from strategies.gold_scalper_pro.scalper_engine import ScalperConfig, ScalperEngine
|
||||
from strategies.gold_scalper_pro.search_space import FROZEN_BASELINE
|
||||
from strategies.gold_scalper_pro.signals import build_signals
|
||||
|
||||
|
||||
def main() -> int:
|
||||
bars_path = PROJECT / "data" / "XAUUSD_M5_2024-06-26_2026-06-26.parquet"
|
||||
print(f"loading {bars_path.name} ...")
|
||||
bars = load_bars(bars_path)
|
||||
print(f" {len(bars):,} bars {bars['timestamp'].iloc[0]} → {bars['timestamp'].iloc[-1]}")
|
||||
|
||||
print("\nbuilding signals (frozen baseline params) ...")
|
||||
pack = build_signals(FROZEN_BASELINE, bars, XAUUSD_REAL)
|
||||
n_long = int(pack.signals_long.sum())
|
||||
n_short = int(pack.signals_short.sum())
|
||||
print(f" long signals : {n_long}")
|
||||
print(f" short signals: {n_short}")
|
||||
|
||||
# Build ScalperConfig from frozen baseline (mirrors EA inputs).
|
||||
cfg = ScalperConfig(
|
||||
use_break_even=FROZEN_BASELINE["InpUseBreakEven"],
|
||||
use_trailing=FROZEN_BASELINE["InpUseTrailing"],
|
||||
use_session=FROZEN_BASELINE["InpUseSession"],
|
||||
session_start_hour=FROZEN_BASELINE["InpSessionStartHour"],
|
||||
session_end_hour=FROZEN_BASELINE["InpSessionEndHour"],
|
||||
max_positions=FROZEN_BASELINE["InpMaxPositions"],
|
||||
max_trades_per_day=FROZEN_BASELINE["InpMaxTradesPerDay"],
|
||||
daily_loss_limit_pct=FROZEN_BASELINE["InpDailyLossLimit"],
|
||||
daily_profit_target_pct=FROZEN_BASELINE["InpDailyProfitTarget"],
|
||||
min_seconds_between=FROZEN_BASELINE["InpMinSecondsBetween"],
|
||||
sizing_mode=FROZEN_BASELINE["InpSizingMode"],
|
||||
fixed_lots=FROZEN_BASELINE["InpFixedLots"],
|
||||
risk_percent=FROZEN_BASELINE["InpRiskPercent"],
|
||||
break_even_points=FROZEN_BASELINE["InpBreakEvenPoints"],
|
||||
break_even_lock=FROZEN_BASELINE["InpBreakEvenLock"],
|
||||
trail_start_points=FROZEN_BASELINE["InpTrailStartPoints"],
|
||||
trail_step_points=FROZEN_BASELINE["InpTrailStepPoints"],
|
||||
)
|
||||
sizing = SizingInputs() # unused — sizing lives in ScalperConfig for this EA
|
||||
|
||||
print("\nrunning engine ...")
|
||||
engine = ScalperEngine()
|
||||
result = engine.run(
|
||||
bars, pack.signals_long, pack.signals_short,
|
||||
pack.sl_prices, pack.tp_prices,
|
||||
XAUUSD_REAL, sizing, initial_deposit=10000.0,
|
||||
scalper_cfg=cfg,
|
||||
)
|
||||
|
||||
metrics = compute_metrics(result, periods_per_year=252 * 24 * 12) # M5 → ~72/year
|
||||
print("\n=== result (frozen baseline) ===")
|
||||
print(f" trades : {metrics.total_trades}")
|
||||
print(f" net profit : {metrics.net_profit:,.2f}")
|
||||
print(f" profit factor : {metrics.profit_factor:.2f}")
|
||||
print(f" win rate : {metrics.win_rate:.2%}")
|
||||
print(f" equity DD max : {metrics.max_equity_dd:,.2f} ({metrics.max_equity_dd_pct:.2%})")
|
||||
print(f" sharpe : {metrics.sharpe:.2f}")
|
||||
if result.trades:
|
||||
reasons = {}
|
||||
for t in result.trades:
|
||||
reasons[t.exit_reason] = reasons.get(t.exit_reason, 0) + 1
|
||||
print(f" exit reasons : {reasons}")
|
||||
print(f" final balance : {result.final_balance:,.2f}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user