RQAlpha 项目研究站 · 参数调优与批量回测
RQAlpha 参数调优:把参数注入 context,批量回测再排序
官方文档给了一条清晰路径:策略里把可调参数存成 context 属性(如长短均线周期),启动时通过 --extra-vars 或配置里的 extra.context_vars 传值;再用多进程把参数组合批量跑完,最后把每个结果文件的 summary 汇总排序。这样「调参」就从手工改代码变成了可重复的流程。
context.XXX
extra-vars/context_vars
结果写 results/
按指标选区间
依据官方参数调优文档整理的四步闭环示意;非官方流程图。
两种参数注入方式
官方文档给出的两条路:命令行传 --extra-vars,或配置里写 extra.context_vars。
| 方式 | 写法 | 适合 | 注意点 |
|---|---|---|---|
命令行 --extra-vars | 传 JSON 字符串,如 --extra-vars '{"SHORTPERIOD": 5, "LONGPERIOD": 40}' | 脚本批量循环、外部调度 | 注意引号与转义;JSON 里的 key 要与策略中读取的一致 |
配置 extra.context_vars | {"extra": {"context_vars": {"SHORTPERIOD": 5}}} | 用 run_file 在 Python 里循环生成配置 | 结构清晰、不需要拼命令行字符串 |
| 策略侧读取 | 把参数挂在 context 上:context.SHORTPERIOD = 20 | 策略内部随处可用 | 策略里尽量不要硬编码;官方示例在 init 里设置默认值 |
多进程批量回测
官方文档给了两种实现:Python 内调用与 Shell 循环,都靠系统多核并行。
方式一:在 Python 里调用(官方示例结构)
1. 双重循环生成参数组合,每组构造一个 config 字典(含 extra.context_vars、base.start_date/end_date、base.accounts、mod.sys_analyser.output_file);
2. 把所有 config 收集进列表;
3. 用 concurrent.futures.ProcessPoolExecutor(max_workers=multiprocessing.cpu_count()) 提交任务,每个任务里调用 from rqalpha import run; run(config);
4. 官方示例里把 log_level 设为 error 降低日志噪音,并把输出文件命名为 results/out-{short}-{long}.pkl。
方式二:拼命令行交给系统执行
官方同样给出「命令行传参」的示例:循环生成 rqalpha run -fq 1d -f 策略.py --start-date … --end-date … -o results/out-xx.pkl --account stock 100000 --progress -bm 000001.XSHE --extra-vars '{...}',再用 os.system 在进程池中执行。适合把批量任务交给已有调度系统。
multiprocessing.cpu_count(),但实际可用核数取决于机器与数据包读取的 IO 开销。建议先用较小并行数跑通流程、确认输出文件命名不冲突,再逐步加并行。汇总结果:把 pkl 摊平成对比表
官方示例的分析写法,三步就能得到可排序的参数表。
| 步骤 | 做法 | 产出 |
|---|---|---|
| 1. 收集文件 | glob.glob("results/*.pkl") | 本次批量回测的全部结果 |
| 2. 提取指标 | 逐个 pd.read_pickle,取 summary 中的年化收益、sharpe、回撤幅度(max_drawdown) | 每行 = 一组参数 + 一组指标 |
| 3. 排序观察 | 分别按 sharpe 与 annualized_returns 排序,打印前若干行 | 识别「参数高原」而非单点领先 |
调优的六条纪律
这一节是方法层面的边界提示,与框架功能无关但更影响结论质量。
| 纪律 | 为什么 |
|---|---|
| 固定数据与撮合口径后再比参数 | 否则差异可能来自撮合引擎、滑点或数据版本,而不是参数 |
| 至少看收益与风险两类指标 | 官方示例同时按 sharpe 与年化收益排序,单指标领先往往不可用 |
| 把数据分成训练段与验证段 | 在全部历史上挑表现好的参数,等同于用未来信息做决策 |
| 控制参数个数 | 组合爆炸会拖长回测时间,也更容易拟合噪声 |
| 记录每次回测的完整配置 | 结果文件命名带参数是官方示例的做法,便于追溯 |
| 把调优结果当假设而非结论 | 历史表现不构成未来收益承诺;本站不对任何策略结果作评价或推荐 |
批量回测排查表
并行与传参是最容易出问题的地方。
| 现象 | 原因 | 处理 |
|---|---|---|
| 结果文件互相覆盖 | 输出文件名没有带参数 | 按官方示例命名:results/out-{short}-{long}.pkl |
| 参数传了但结果没变 | 策略里写死了参数(优先级最高),或 JSON 的 key 名不一致 | 先确认策略用 context.XXX 读取;核对其命名 |
| 命令行传 JSON 报错 | 引号转义问题(尤其 Windows cmd) | 改用 run_file 传 config 字典,绕开字符串拼接 |
| 批量跑不动 / 机器卡死 | 并行数过高、内存不足 | 降低 max_workers,分批跑;长周期回测先缩区间验证流程 |
| 日志淹没关键信息 | 默认日志级别太详细 | 按官方示例设 extra.log_level: error,关掉 progress 输出 |
| 汇总时报结果文件缺失 | 部分组合因数据区间不足或报错未产出 | 在汇总脚本里跳过缺失文件并登记失败组合,别静默当成功 |
常见问题
参数组合应该取多密?
官方示例用的是「短周期 3 到 10、步长 2;长周期 30 到 90、步长 5」这类粗扫方式。建议先粗后细:粗扫定位有希望的区域,再在小范围内加密验证稳定性,避免一次性生成大量组合。
批量回测很慢,有什么优化思路?
三个方向:缩短单次回测区间先验证流程;提高并行度但别超过物理核数太多;降低日志与绘图输出(批量阶段通常不需要 plot)。官方示例用进程池并行,本身就是在利用多核。
如何避免过拟合?
框架不会替你防过拟合。至少做三件事:留出样本外区间、优先选择「参数高原」、把参数个数控制在能解释的范围内。任何「历史表现拔尖的参数」都不能直接当作未来收益依据。
可以把调优结果再做可视化吗?
可以:把摊平后的 DataFrame 用 matplotlib 画热力图或折线(框架依赖里已有 matplotlib),也可以导出 CSV 用别的工具看。框架本身不提供专门的调优可视化界面。
调参需要多久、要跑多少组?
取决于数据区间、频率与机器性能,官方文档没有给时间承诺。经验上先保证「流程可复现、结果可追溯」,再考虑扩大搜索范围。
EasyClaw 技能能做这类调参吗?
EasyClaw 本机的 quant-analyst 技能方向覆盖回测与风险指标建模,可以用自然语言发起研究任务;但它不是 本项目的运行环境,两者无已证实集成。详见对比页。