109 lines
5.0 KiB
Python
109 lines
5.0 KiB
Python
import multiprocessing
|
||
from typing import Tuple, Dict, Any, Optional
|
||
|
||
from src.analysis.result_analyzer import ResultAnalyzer
|
||
from src.backtest_engine import BacktestEngine
|
||
from src.data_manager import DataManager
|
||
|
||
|
||
# --- 单个回测任务函数 ---
|
||
# 这个函数将在每个独立的进程中运行,因此它必须是自包含的
|
||
def run_single_backtest(
|
||
combination: Tuple[float, float], # 传入当前参数组合
|
||
common_config: Dict[str, Any] # 传入公共配置 (如数据路径, 初始资金等)
|
||
) -> Optional[Dict[str, Any]]:
|
||
"""
|
||
运行单个参数组合的回测任务。
|
||
此函数将在一个独立的进程中执行。
|
||
"""
|
||
p1_value, p2_value = combination
|
||
|
||
# 从 common_config 中获取必要的配置
|
||
symbol = common_config['symbol']
|
||
data_path = common_config['data_path']
|
||
initial_capital = common_config['initial_capital']
|
||
slippage_rate = common_config['slippage_rate']
|
||
commission_rate = common_config['commission_rate']
|
||
start_time = common_config['start_time']
|
||
end_time = common_config['end_time']
|
||
roll_over_mode = common_config['roll_over_mode']
|
||
# bar_duration_seconds = common_config['bar_duration_seconds'] # 如果DataManager需要,可以再传
|
||
param1_name = common_config['param1_name']
|
||
param2_name = common_config['param2_name']
|
||
|
||
# 每个进程内部独立初始化 DataManager 和 BacktestEngine
|
||
# 确保每个进程有自己的数据副本和模拟状态
|
||
data_manager = DataManager(
|
||
file_path=data_path,
|
||
symbol=symbol,
|
||
# bar_duration_seconds=bar_duration_seconds, # 如果DataManager需要,根据数据文件路径推断或者额外参数传入
|
||
# start_date=start_time.date(), # DataManager 现在通过 file_path 和 symbol 处理数据
|
||
# end_date=end_time.date(),
|
||
)
|
||
# data_manager.load_data() # DataManager 内部加载数据
|
||
|
||
strategy_parameters = {
|
||
'main_symbol': common_config['main_symbol'],
|
||
'trade_volume': 1,
|
||
param1_name: p1_value, # 15分钟扫荡K线下影线占其总范围的最小比例。
|
||
param2_name: p2_value, # 15分钟限价单的入场点位于扫荡K线低点到收盘价的斐波那契回撤比例。
|
||
'order_direction': common_config['order_direction'],
|
||
'enable_log': False, # 建议在调试和测试时开启日志
|
||
}
|
||
# strategy_parameters['spectral_window_days'] = 2
|
||
strategy_parameters['low_freq_days'] = strategy_parameters['spectral_window_days']
|
||
strategy_parameters['high_freq_days'] = int(strategy_parameters['spectral_window_days'] / 2)
|
||
strategy_parameters['exit_threshold'] = max(strategy_parameters['trend_strength_threshold'] - 0.3, 0)
|
||
|
||
# 打印当前进程正在处理的组合信息
|
||
# 注意:多进程打印会交错显示
|
||
print(f"--- 正在运行组合: {strategy_parameters} (PID: {multiprocessing.current_process().pid}) ---")
|
||
|
||
try:
|
||
# 初始化回测引擎
|
||
engine = BacktestEngine(
|
||
data_manager=data_manager,
|
||
strategy_class=common_config['strategy'],
|
||
strategy_params=strategy_parameters,
|
||
initial_capital=initial_capital,
|
||
slippage_rate=slippage_rate,
|
||
commission_rate=commission_rate,
|
||
roll_over_mode=True, # 保持换月模式
|
||
start_time=common_config['start_time'],
|
||
end_time=common_config['end_time']
|
||
)
|
||
# 运行回测,传入时间范围
|
||
engine.run_backtest()
|
||
|
||
# 获取回测结果并分析
|
||
results = engine.get_backtest_results()
|
||
portfolio_snapshots = results["portfolio_snapshots"]
|
||
trade_history = results["trade_history"]
|
||
bars = results["all_bars"]
|
||
initial_capital_result = results["initial_capital"]
|
||
|
||
if portfolio_snapshots:
|
||
analyzer = ResultAnalyzer(portfolio_snapshots, trade_history, bars, initial_capital_result)
|
||
|
||
# analyzer.generate_report()
|
||
# analyzer.plot_performance()
|
||
metrics = analyzer.calculate_all_metrics()
|
||
|
||
# 将当前组合的参数和性能指标存储起来
|
||
result_entry = {**strategy_parameters, **metrics}
|
||
return result_entry
|
||
else:
|
||
print(
|
||
f" 组合 {strategy_parameters} 没有生成投资组合快照,无法进行结果分析。(PID: {multiprocessing.current_process().pid})")
|
||
# 返回一个包含参数和默认0值的结果,以便追踪失败组合
|
||
return {**strategy_parameters, "total_return": 0.0, "annualized_return": 0.0, "sharpe_ratio": 0.0,
|
||
"max_drawdown": 0.0, "error": "No portfolio snapshots"}
|
||
except Exception as e:
|
||
import traceback
|
||
error_trace = traceback.format_exc()
|
||
print(
|
||
f" 组合 {strategy_parameters} 运行失败: {e}\n{error_trace} (PID: {multiprocessing.current_process().pid})")
|
||
# 返回错误信息,以便后续处理
|
||
return {**strategy_parameters, "error": str(e), "traceback": error_trace}
|
||
|