软件工程的 CI/CD(持续集成/持续部署)在量化里有一个特殊的翻译:每一次代码变更,都要自动证明「回测结果没有意外变坏」。本篇讲量化 CI 的特有检查项与部署自动化——它对个人研究者的价值不是「专业感」,而是把「我不记得上次改了什么」从根源上消灭。
量化 CI 的检查流水线
每次 git push / PR 触发,依次通过四层:
第一层:代码质量(快速反馈,秒级)
lint(ruff)+ 格式(black)+ 类型检查(mypy)+ 单元测试(pytest)——与一般软件工程相同(工具链见代码质量 ),失败即终止,反馈周期要短(< 5 分钟)——反馈越慢,越有人绕过它。
第二层:策略特有的静态检查(量化独有)
- 前视模式扫描:规则化的代码检查——「信号计算函数内访问了当日/未来列」「merge 后未校验对齐」「shift 方向错误」的高危模式清单。规则只能抓常见形态,但抓到一个都是真事故。可执行的起步版:一个 ruff 自定义规则 + 一份「禁用 API 清单」(如禁止在信号函数内调用
shift(-n)); - 魔法数字与口径审计:成本费率、涨跌停幅度等制度参数是否引用统一配置(而非散落硬编码,见A 股执行 的参数卡)——「印花税从 0.1% 降到 0.05%」的政策变更(2023 年 8 月真实发生),散落硬编码的仓库要改十处、漏三处;
- 依赖注入检查:因子/策略函数的输入是否全部显式传参(禁止隐式读全局数据——它是「研究环境对、生产环境错」的常见根源)。
第三层:回测回归测试(核心闸门,分钟级)
固定基准数据集 + 固定策略集:对一组「守门策略」(1–2 个简单已验证策略)在基准数据上跑回测,与上次通过版本的净值曲线 diff:
- diff 为零或极小(< 数值噪声)→ 通过;
- 有变化 → 必须能解释:本次变更预期影响什么?变化的方向与幅度是否匹配?
这条闸门的杀手级用途:它把「我只是改了一行工具代码,不影响策略」变成自动证伪——无数「顺手的小改动」造成的静默策略变化,都在这里现形。一个典型场景:重构数据加载模块时顺手改了默认复权方式,三个策略的净值曲线同时漂移 2%——没有回归测试,这要在实盘偏差出现后才被发现(那时已经亏了)。守门策略的选择要点:覆盖主要代码路径(至少一条含财务因子、一条纯量价)、绩效指标稳定(本身不是高方差的策略)。
第四层:性能与数据契约
因子计算的运行时长上限(超时报警——计算退化常暗示数据结构变化);输出数据的 schema 校验(列名/类型/日期连续性)——数据契约是研究层与生产层之间的合同(见架构 的环境一致性)。
部署自动化
CI 全绿之后的 CD(持续部署)按风险分级:
- 数据管道与因子计算:自动部署(夜车流水线,见调度 )——前提是第二、三、四层全绿;部署后自动跑一次「冒烟回测」(最近 20 日)验证;
- 信号/策略代码:半自动——CI 绿 + 人工点批准(审批记录留痕,见安全 );部署后先影子模式运行一个交易日(与旧版本并行对比信号 diff)再正式接管;
- 风控参数与限额:最高审查级别——双人审批 + 变更窗口(不在盘中改限额);
- 回滚:每次部署保留「一键回滚到上一版本」(镜像/快照化),回滚也是部署、也要走审计(与回滚预案 衔接)。
部署频率的真相:量化系统的正确节奏是「低频而严格」——策略代码的变更以周/月计(每笔变更都过全闸门),数据与监控的变更可以日频。「持续部署」在量化里的正确读法是「持续验证、谨慎部署」。
一个人的 CI:GitHub Actions 最小配置
个人研究者半天可建的最小 CI(GitHub Actions / Gitea Actions / 本地 pre-commit + 定时跑):
| |
投入产出的账:搭建 1 天 + 每次变更多等 15 分钟 ↔ 换来「任何历史版本可复现、任何静默破坏被拦截」——对以年为单位的策略资金,这是整个工程体系里性价比最高的单项投资。