RQAlpha 项目研究站 · 参数调优与批量回测

RQAlpha 参数调优:把参数注入 context,批量回测再排序

官方文档给了一条清晰路径:策略里把可调参数存成 context 属性(如长短均线周期),启动时通过 --extra-vars 或配置里的 extra.context_vars 传值;再用多进程把参数组合批量跑完,最后把每个结果文件的 summary 汇总排序。这样「调参」就从手工改代码变成了可重复的流程。

参数注入:--extra-vars / context_vars并行:ProcessPoolExecutor依据官方参数调优文档(2026-09 核验)
策略留出参数
context.XXX
传参
extra-vars/context_vars
多进程批量回测
结果写 results/
汇总排序
按指标选区间

依据官方参数调优文档整理的四步闭环示意;非官方流程图。

Inject

两种参数注入方式

RQAlpha 官方文档给出的两条路:命令行传 --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 里设置默认值
为什么强调「参数不要写死在策略里」:一旦写死,命令行传参就失效(策略内配置优先级最高),批量调参只能改文件——既慢又容易出错。把可调项全部提升为 context 属性,是这套流程成立的前提。
Batch

多进程批量回测

RQAlpha 官方文档给了两种实现: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 在进程池中执行。适合把批量任务交给已有调度系统。

并行数怎么定:RQAlpha 官方示例用 multiprocessing.cpu_count(),但实际可用核数取决于机器与数据包读取的 IO 开销。建议先用较小并行数跑通流程、确认输出文件命名不冲突,再逐步加并行。
Analyze

汇总结果:把 pkl 摊平成对比表

RQAlpha 官方示例的分析写法,三步就能得到可排序的参数表。

步骤做法产出
1. 收集文件glob.glob("results/*.pkl")本次批量回测的全部结果
2. 提取指标逐个 pd.read_pickle,取 summary 中的年化收益、sharpe、回撤幅度(max_drawdown)每行 = 一组参数 + 一组指标
3. 排序观察分别按 sharpe 与 annualized_returns 排序,打印前若干行识别「参数高原」而非单点领先
看趋势,不挑个案:若相邻参数值的表现忽好忽坏,说明结果对参数极度敏感(更可能是过拟合噪声);如果一整片参数区间表现都不错,才有进一步研究的价值。
Discipline

调优的六条纪律

这一节是方法层面的边界提示,与 RQAlpha 的功能实现无关,但更影响结论质量。

纪律为什么
固定数据与撮合口径后再比参数否则差异可能来自撮合引擎、滑点或数据版本,而不是参数
至少看收益与风险两类指标官方示例同时按 sharpe 与年化收益排序,单指标领先往往不可用
把数据分成训练段与验证段在全部历史上挑表现好的参数,等同于用未来信息做决策
控制参数个数组合爆炸会拖长回测时间,也更容易拟合噪声
记录每次回测的完整配置结果文件命名带参数是官方示例的做法,便于追溯
把调优结果当假设而非结论历史表现不构成未来收益承诺;本站不对任何策略结果作评价或推荐
Troubleshooting

批量回测排查表

RQAlpha 的并行与传参是最容易出问题的地方。

现象原因处理
结果文件互相覆盖输出文件名没有带参数按官方示例命名:results/out-{short}-{long}.pkl
参数传了但结果没变策略里写死了参数(优先级最高),或 JSON 的 key 名不一致先确认策略用 context.XXX 读取;核对其命名
命令行传 JSON 报错引号转义问题(尤其 Windows cmd)改用 run_file 传 config 字典,绕开字符串拼接
批量跑不动 / 机器卡死并行数过高、内存不足降低 max_workers,分批跑;长周期回测先缩区间验证流程
日志淹没关键信息默认日志级别太详细按官方示例设 extra.log_level: error,关掉 progress 输出
汇总时报结果文件缺失部分组合因数据区间不足或报错未产出在汇总脚本里跳过缺失文件并登记失败组合,别静默当成功
Pipeline

参数注入链路:从 context_vars 到最终成绩表,一共要配哪些键?

官方《参数调优》文档给的链路是「策略留出参数 → 传进 context → 批量跑组合 → 汇总排序」。下表把每个环节落到哪个配置键、哪个文件名摊开,字段名照官方文档与 config.yml 模板原文排列。

配置键写在哪作用注意点
base.strategy_fileconfig 字典,或命令行 -f指定要跑的策略文件官方批量示例指向 rqalpha/examples/golden_cross.py
base.start_date / base.end_dateconfig,或命令行 -s / -e回测起止日期所有组合必须完全一致,否则指标之间不可比
base.frequencyconfig,或命令行 -fq回测频率 1d / 1m文档明确开源版不提供分钟级数据源,换频率前先解决数据(获取方式见 安装与数据)
base.matching_typeconfig,或命令行 -me撮合引擎 current_bar / next_bar官方批量示例固定 current_bar;改撮合方式等于换掉全部结果
base.benchmarkconfig,或命令行 -bm基准指数运行文档写明「如果不设置,默认没有基准参照」,相对类指标就失去参照
base.accounts.stockconfig,或命令行 -a账户类型与初始资金官方示例为 100000;调整资金等于换了一套结果,别与参数变量混在一起改
extra.context_varsconfig 字典,或命令行 --extra-vars 传 JSON把预定义变量传进 context配置模板里的注释就是这句;key 要与策略里读取的 context.XXX 完全一致
extra.log_levelconfig,或命令行 -lverbose / info / warning / error官方批量示例设成 error,把回测过程日志压掉
mod.sys_analyser.output_fileconfig 的 mod 段回测结果 pkl 的输出路径官方按参数命名 results/out-{short_period}-{long_period}.pkl,避免多组结果互相覆盖
mod.sys_progress.enabled / showconfig 的 mod 段,或命令行 --progress命令行进度条批量阶段通常关掉,输出更干净、也少一层干扰

五步链路:每一步的命令与预期输出

1. 在策略里留出可调项:官方示例在 init 里给默认值 context.SHORTPERIOD = 20、context.LONGPERIOD = 120 —— 预期:策略单独也能跑通,读取端始终是 context.SHORTPERIOD;
2. 命令行注入单组参数:rqalpha run -f rqalpha/examples/golden_cross.py --extra-vars '{"SHORTPERIOD": 5, "LONGPERIOD": 40}' —— 预期:同一份策略这次使用 5 / 40,结果与默认值不同;
3. 或改用配置注入:{"extra": {"context_vars": {"SHORTPERIOD": 5, "LONGPERIOD": 40}}} —— 预期:run(config) 或 run_file(path, config) 生效,不必拼命令行字符串;
4. 生成参数组合:官方示例用 for short_period in range(3, 10, 2) 套 for long_period in range(30, 90, 5) —— 预期:4 × 12 = 48 个 config 进入任务列表;
5. 汇总排序:glob.glob("results/*.pkl") → pd.read_pickle(name)["summary"] 取 annualized_returns / sharpe / max_drawdown → sort_values(..., ascending=False)[:10] —— 预期:先打印按 sharpe 排序的表,再打印按年化收益排序的表(字段含义见 回测指标)。

先看优先级,再动手批量:运行文档用警告框强调过顺序——「策略代码中配置 > 命令行传参 = run_file | run_code | run_func 函数传参 > 用户配置文件 > 系统默认配置文件」。所以批量注入之前先确认策略里没有写死参数:写死了,你传进去的值永远不会生效。
Field notes

批量调参容易踩的七个点:结果看起来跑完了,为什么结论不能用?

这些不是框架缺陷,而是「批量场景」特有的口径问题。每条都给一个可以立刻执行的检查动作。

现象原因处理
组合数比手算的少range(3, 10, 2) 只取 3、5、7、9 四个值,range(30, 90, 5) 取 30 到 85 共 12 个批量启动前打印 len(tasks),与手算的组合数对账
Windows 上进程反复新建、数量失控多进程入口没有放在 if __name__ == '__main__': 之后,子进程导入模块时又触发一次提交照官方示例的写法保护入口,再提交进程池任务
两批结果放在一起比不出来批与批之间改了撮合方式、回测区间或初始资金把 base / mod 的公共段抽成一个字典,只替换参数相关字段
相对类指标算不出来没有设置 base.benchmark,文档写明默认没有基准参照两批都固定同一个 -bm,再比较排序结果
跑到后半段读不到数据回测区间落在数据包覆盖范围之外(免费数据包每月月初更新一次)先用 1 组确认区间内有数据(数据包与更新节奏见 安装与数据),再放大到全部组合
整批因频率失败批量脚本里写了 -fq 1m,而分钟级数据需要自备数据源批量阶段固定 1d,把频率当成单独一次变量实验来做
靠文件时间分辨不出哪组参数output_file 是自定义字符串模板,不会自动带时间戳或参数在文件名里写进参数组合(官方示例就是短周期与长周期),别依赖文件修改时间
两种官方批量写法的差别:函数调用版在每个任务里执行 run(config),同一个进程可以连续跑多组回测;命令行版是 os.system(cmd),一条命令一个独立进程,外面套 ProcessPoolExecutor(max_workers=multiprocessing.cpu_count()) 并行。两种写法混用时,日志会交叉、输出文件名更不能重复。建议先用 4 组把链路跑通,再放大到全部组合。
FAQ

常见问题

参数组合应该取多密?

官方示例用的是「短周期 3 到 10、步长 2;长周期 30 到 90、步长 5」这类粗扫方式。建议先粗后细:粗扫定位有希望的区域,再在小范围内加密验证稳定性,避免一次性生成大量组合。

批量回测很慢,有什么优化思路?

三个方向:缩短单次回测区间先验证流程;提高并行度但别超过物理核数太多;降低日志与绘图输出(批量阶段通常不需要 plot)。官方示例用进程池并行,本身就是在利用多核。

如何避免过拟合?

RQAlpha 不会替你防过拟合。至少做三件事:留出样本外区间、优先选择「参数高原」、把参数个数控制在能解释的范围内。任何「历史表现拔尖的参数」都不能直接当作未来收益依据。

可以把调优结果再做可视化吗?

可以:把摊平后的 DataFrame 用 matplotlib 画热力图或折线(RQAlpha 的依赖里已有 matplotlib),也可以导出 CSV 用别的工具看。RQAlpha 本身不提供专门的调优可视化界面。

调参需要多久、要跑多少组?

取决于数据区间、频率与机器性能,官方文档没有给时间承诺。经验上先保证「流程可复现、结果可追溯」,再考虑扩大搜索范围。

不想自己搭这套批量调参流程,有别的方式吗?

可以看 EasyClaw 本机的 quant-analyst 技能方向(覆盖回测与风险指标建模),用自然语言发起研究任务;但它不是 RQAlpha 的运行环境,两者无已证实集成。详见对比页。

动手前先确认许可与数据边界

本项目的许可与数据范围有明确边界,尤其在商业使用与分钟级回测两个场景上。