fix(backtest): benchmark全链路透传(API→runner→engine) + metrics分支用_dcfg修cfg=None导致relative_metrics空

This commit is contained in:
2026-07-11 14:27:19 +08:00
parent 5e5a6cf84a
commit f7c2e2eea3
3 changed files with 17 additions and 11 deletions
+9 -5
View File
@@ -47,7 +47,7 @@ def guess_exchange(symbol: str) -> Exchange:
return Exchange("SSE")
def run_cta_backtest(strategy_class, symbol: str, params: dict, start: str, end: str, cfg, db_path: str) -> BacktestResult:
def run_cta_backtest(strategy_class, symbol: str, params: dict, start: str, end: str, cfg, db_path: str, benchmark: str = "hs300") -> BacktestResult:
"""
Run CTA strategy backtest using vnpy_ctastrategy BacktestingEngine.
@@ -98,6 +98,9 @@ def run_cta_backtest(strategy_class, symbol: str, params: dict, start: str, end:
# Configure vnpy DB → A-share quant_trading.db. Worker process (spawn)
# doesn't inherit main-process SETTINGS, so set before engine.load_data.
# _dcfg is also reused by the metrics branch (benchmark data_paths) since the
# cfg param can be None when called via the API.
_dcfg = None
try:
from vnpy.trader.setting import SETTINGS
from sanguo_data.config import load_config, find_config_path
@@ -129,16 +132,17 @@ def run_cta_backtest(strategy_class, symbol: str, params: dict, start: str, end:
if not isinstance(daily_df.index, pd.DatetimeIndex):
daily_df.index = pd.to_datetime(daily_df.index)
# Get benchmark config (default hs300)
benchmark_key = getattr(cfg, "benchmark", "hs300") if hasattr(cfg, "benchmark") else "hs300"
benchmark_code = BENCHMARK_SYMBOL.get(benchmark_key, "sh000300")
# Get benchmark code (default hs300) + a cfg that has data_paths.
# _dcfg is the loaded config; fall back to the passed cfg if loading failed.
benchmark_code = BENCHMARK_SYMBOL.get(benchmark, "sh000300")
bench_cfg = _dcfg if (_dcfg is not None and hasattr(_dcfg, "data_paths")) else cfg
# Load benchmark data
start_date = start_dt if isinstance(start_dt, datetime) else datetime.strptime(start, "%Y-%m-%d")
end_date = end_dt if isinstance(end_dt, datetime) else datetime.strptime(end, "%Y-%m-%d")
try:
bench_df = read_index_daily(benchmark_code, start_date, end_date, cfg)
bench_df = read_index_daily(benchmark_code, start_date, end_date, bench_cfg)
if bench_df is not None and not bench_df.empty and "close" in bench_df.columns:
# Calculate benchmark daily returns
bench_df["date"] = pd.to_datetime(bench_df["date"])