"""全局配置:路径、日期、资金、策略参数等。 所有路径尽量通过 BASE_DIR 派生,避免硬编码。 """ from pathlib import Path from utils.logger import setup_logger logger = setup_logger(__name__) # 项目根目录:假设本文件位于 strategy_backtest/config/settings.py BASE_DIR: Path = Path(__file__).resolve().parent.parent.parent # 数据与结果目录 DATA_DAY_DIR: Path = BASE_DIR / "data" / "day" DATA_INDEX_DIR: Path = BASE_DIR / "data" / "index" # 指数数据目录 CODE_DIR: Path = BASE_DIR / "data" / "code" RESULTS_DIR: Path = BASE_DIR / "strategy_backtest" / "results" # 股票代码列表文件(如果存在,可以作为股票池来源) STOCK_CODE_FILE: Path = CODE_DIR / "all_stock_codes.txt" # 基准指数配置 BENCHMARK_FILE: Path = DATA_INDEX_DIR / "000001.SH.txt" # 上证指数 BENCHMARK_NAME: str = "上证指数" # 基准指数名称 # 回测时间区间(含首尾),格式:YYYYMMDD START_DATE: str = "20220101" END_DATE: str = "20251231" # 初始资金 INITIAL_CASH: float = 1000000.0 # ==================== 策略参数配置 ==================== # 每个策略都有自己独立的一套参数 # 均线交叉策略参数 MACROSS_MA_SHORT: int = 5 # 快速均线周期 MACROSS_MA_LONG: int = 15 # 慢速均线周期 MACROSS_HOLD_DAYS: int = 3 # 持有天数 MACROSS_MAX_POSITIONS: int = 2 # 最多持仓股票数 MACROSS_POSITION_PCT_PER_STOCK: float = 0.2 # 每只个股占总资金的比例(0.2 = 20%) # 均线交叉策略风控参数 MACROSS_RISK_CONTROL = { "stop_loss": { "method": "fixed_pct", # 止损方法:fixed_pct / atr / trailing "stop_pct": 0.05, # 固定百分比止损(5%) "atr_period": 14, # ATR周期 "atr_multiplier": 2.0, # ATR倍数 "trailing_pct": 0.10, # 跟踪止损回撤比例 }, "take_profit": { "method": "fixed_pct", # 止盈方法:fixed_pct / atr / trailing "stop_pct": 0.10, # 固定百分比止盈(10%) "atr_period": 14, "atr_multiplier": 3.0, "trailing_pct": 0.15, # 跟踪止盈回撤比例 }, } # OCZ策略参数 OCZ_N: int = 30 # 阻力回望长度 OCZ_B: float = 60.0 # 实体占比门槛(%) OCZ_V1: float = 1.5 # 放量倍数 OCZ_TOL: float = 1.5 # 回踩容错(%) OCZ_R: float = 6.0 # 收盘涨幅门槛(%) OCZ_HOLD_DAYS: int = 5 # 持有天数 OCZ_MAX_POSITIONS: int = 2 # 最多持仓股票数 OCZ_POSITION_PCT_PER_STOCK: float = 0.2 # 每只个股占总资金的比例 OCZ_VOLATILITY_MIN: float = 2.5 # 最小波动率(%) OCZ_VOLATILITY_MAX: float = 8.0 # 最大波动率(%) # OCZ策略风控参数(突破回踩策略特点:特殊止损止盈逻辑) # 注意:OCZ策略使用策略内部的特殊止损止盈逻辑,不使用通用风控模块 # 止损位 = 突破的阻力位,止盈位 = 买入价 + (买入价 - 阻力位) * 2 (盈亏比1:2) OCZ_RISK_CONTROL = { "stop_loss": { "method": "custom", # 使用策略自定义逻辑,不使用通用风控模块 "stop_pct": 0, # 占位参数,实际不使用 }, "take_profit": { "method": "custom", # 使用策略自定义逻辑 "stop_pct": 0, # 占位参数,实际不使用 }, } # ==================== 策略配置 ==================== # 所有策略定义(统一管理) STRATEGIES = { "MaCrossStrategy": { "module": "strategies.ma_cross", "params": { "ma_short": MACROSS_MA_SHORT, "ma_long": MACROSS_MA_LONG, "hold_days": MACROSS_HOLD_DAYS, "max_positions": MACROSS_MAX_POSITIONS, "position_pct_per_stock": MACROSS_POSITION_PCT_PER_STOCK, }, "risk_control": MACROSS_RISK_CONTROL, # 每个策略独立的风控配置 }, "OczStrategy": { "module": "strategies.ocz_strategy", "params": { "N": OCZ_N, "B": OCZ_B, "V1": OCZ_V1, "TOL": OCZ_TOL, "R": OCZ_R, "hold_days": OCZ_HOLD_DAYS, "volatility_min": OCZ_VOLATILITY_MIN, "volatility_max": OCZ_VOLATILITY_MAX, "max_positions": OCZ_MAX_POSITIONS, "position_pct_per_stock": OCZ_POSITION_PCT_PER_STOCK, }, "risk_control": OCZ_RISK_CONTROL, # 每个策略独立的风控配置 }, } # 策略开关(0=不回测, 1=回测) # 作用:控制哪些策略需要回测,无需注释代码 STRATEGY_SWITCHES = { "MaCrossStrategy": 1, # 1=开启均线交叉策略回测 "OczStrategy": 0, # 1=开启OCZ策略回测 } # 为了兼容旧代码,保留STRATEGY变量(指向首个开启的策略) STRATEGY = None for strategy_name, switch in STRATEGY_SWITCHES.items(): if switch == 1 and strategy_name in STRATEGIES: STRATEGY = { "name": strategy_name, "module": STRATEGIES[strategy_name]["module"], "params": STRATEGIES[strategy_name]["params"], } break # 如果没有任何策略开启,默认使用第一个策略 if STRATEGY is None and STRATEGIES: first_strategy_name = list(STRATEGIES.keys())[0] STRATEGY = { "name": first_strategy_name, "module": STRATEGIES[first_strategy_name]["module"], "params": STRATEGIES[first_strategy_name]["params"], } # 回测相关其他参数(预留) TRADING_DAYS_PER_YEAR: int = 252 # 股票过滤规则 MIN_LISTING_DAYS: int = 60 # 最小上市天数,过滤新股(默认 60 天) # Tushare 配置(仅用于获取交易日历) # 注意:不要在公共仓库中提交真实 token,可在本地修改此值, # 或设置环境变量 TUSHARE_TOKEN 来提供。 TUSHARE_TOKEN: str = "9343e641869058684afeadfcfe7fd6684160852e52e85332a7734c8d" # 在这里填写你的 Tushare token,或留空使用环境变量 TUSHARE_CALENDAR_EXCHANGE: str = "SSE" # 交易所代码:SSE 上交所,SZSE 深交所 # ==================== 参数优化配置 ==================== OPTIMIZATION_N_JOBS: int = 4 # 并行进程数 OPTIMIZATION_TOP_N: int = 10 # 保存前N个最优结果 OPTIMIZATION_METRIC: str = "sharpe" # 排序指标:sharpe / total_return / max_drawdown / annual_return # 参数空间定义(根据策略配置不同的参数范围) # 格式:{参数名: [最小值, 最大值, 步长]} 或 {参数名: [离散值列表]} PARAM_SPACES: dict = { # 均线交叉策略参数空间 "ma_cross": { "ma_short": [5, 10, 2], # 短期均线:3-20,步長2 -> [3,5,7,9,11,13,15,17,19] "ma_long": [15, 30, 5], # 长期均线:20-60,步長5 -> [20,25,30,35,40,45,50,55] "hold_days": [3, 10, 1], # 持有天数:3-10,步長1 -> [3,4,5,6,7,8,9] "position_pct_per_stock": [0.2, 0.4, 0.5], # 单股仓位比例(离散值) }, # OCZ策略参数空间 "ocz": { "N": [20, 40, 5], # 阻力回望长度:20-40,步長5 "B": [50, 70, 10], # 实体占比门槛:50-70%,步長10 "V1": [1.2, 1.8, 0.2], # 放量倍数:1.2-1.8,步長0.2 "TOL": [1.0, 2.0, 0.5], # 回踩容错:1.0-2.0%,步長0.5 "R": [3, 5, 1], # 涨幅门槛:3-5%,步長1 "hold_days": [3, 10, 1], # 持有天数:3-10,步長1 "position_pct_per_stock": [0.2, 0.3, 0.5], # 单股仓位比例 }, # 可以添加其他策略的参数空间 # "other_strategy": { # "param1": [1, 10, 1], # "param2": [0.1, 0.5, 0.1], # }, } # 参数约束条件(避免无意义的参数组合) # 格式:lambda params: 返回True表示合法,False表示过滤 PARAM_CONSTRAINTS: dict = { "ma_cross": lambda params: ( # 约束1:短期均线必须小于长期均线 params.get("ma_short", 0) < params.get("ma_long", 999) # 可以添加更多约束,例如: # and params.get("hold_days", 0) >= 3 # and params.get("position_pct_per_stock", 0) <= 0.6 ), "ocz": lambda params: ( # 约束1:N 必须大于持有天数(确保有足够历史数据) params.get("N", 30) > params.get("hold_days", 0) # 约束2:实体占比必须大于0且小于100 and 0 < params.get("B", 60) < 100 # 约束3:放量倍数必须大于1 and params.get("V1", 1.5) > 1.0 ), } # ==================== 风险控制配置 ==================== # 止损止盈方法:fixed_pct / atr / trailing STOP_LOSS_METHOD: str = "fixed_pct" STOP_LOSS_PCT: float = 0.05 # 固定百分比止损(5%) TAKE_PROFIT_PCT: float = 0.10 # 固定百分比止盈(15%) ATR_PERIOD: int = 14 # ATR周期 ATR_MULTIPLIER: float = 2.0 # ATR倍数 TRAILING_PCT: float = 0.10 # 跟踪止盈回撤比例(10%) # ==================== 持仓规模优化配置 ==================== # 持仓方法:equal_weight / kelly / volatility_target POSITION_METHOD: str = "equal_weight" KELLY_RISK_FREE: float = 0.03 # Kelly公式无风险利率 KELLY_MAX_FRACTION: float = 0.25 # Kelly最大仓位比例(防止过度杠杆) VOLATILITY_TARGET: float = 0.15 # 目标波动率(年化15%) VOLATILITY_WINDOW: int = 20 # 计算波动率的窗口期(天) logger.info("settings.py 已加载配置")