🌿 版本控制与协作(Git)

研究代码为什么要分支而不是复制文件夹、commit 信息如何变成研究日志(附量化版 commit 模板)、.gitignore 的血泪清单、数据版本的轻量方案。

量化代码的特殊性在于:三个月后你必须能精确复现某一天的信号——监管问询、客户问询、或仅仅是「为什么当时的仓位和现在不一样」。Git 是这个能力的地基,但量化场景的 Git 用法与软件开发有几个关键差异。

分支策略:研究分支是用来「敢于尝试」的

个人研究者的常见做法是复制 策略_v3_最终版_真最终版.py——三个月后没人知道哪个是活的。正确的最小工作流:

  • main 分支永远保持「可直接实盘」状态:每次合并前必须通过回测复核(见策略上线流程 );
  • 每个研究假设开一个分支:factor/reversal-20d、fix/stop-loss-queue——实验失败就删分支,零成本。分支命名的约定本身就值回票价:factor/ 前缀的分支 = 未验证假设,prod/ 前缀 = 在跑策略,一眼分清「想法」与「资产」;
  • 合并(merge/PR)即「上线决策」:合并记录 = 上线记录,回滚 = git revert。这与灰度放量 衔接:分支可以合并了,资金百分比逐步放大;
  • 团队协作再加两条:PR 必须有第二人 review(QE 或另一位 QR,重点查前视与成本假设——代码评审在量化里的重心不是风格而是「这行会不会偷看未来」);main 打 tag 对应每个实盘版本(prod-2026-09-15),实盘异常时第一动作是核对生产进程跑的是哪个 tag。

Commit:写给三个月后的自己的研究日志

「fix bug」「update」式的 commit 信息在量化里的成本极高。推荐的格式是**「动机 + 口径 + 结果」**:

1
2
3
4
5
factor/momentum-60d: 剔除停牌超过20日的样本后重估IC

- 原因:长期停牌股的动量因子值冻结,IC被高估约15%
- 口径:2020-2025,月频,行业市值中性,含双边成本
- 结果:RankIC 0.031→0.024,夏普 1.8→1.5,仍显著(t=2.9)

这条记录三个月后就是现成的研究笔记 。回测结果写进 commit 的价值:绩效数字会随数据更新漂移,把「当时看到什么」钉死在时间轴上,是诚实研究的一部分——三个月后数据更新导致 IC 变成 0.028,你能精确定位变化发生在哪次数据或代码变更。

.gitignore:量化仓库的第一道安全门

必进 ignore 清单的东西比一般软件项目多:

1
2
3
4
5
data/            # 原始行情数据(GB级,且可能有授权限制)
*.h5 *.parquet   # 因子中间产物
config/prod.yaml # 含交易账户、密钥的生产配置
*.log
.ipynb_checkpoints/

血泪教训两条:把几十 GB 的行情数据 push 进仓库拖垮所有人(git 对大二进制的历史是永久负担,即使后续删除,历史里还在);把 API key(券商接口、数据商账号)提交进公开仓库——密钥一旦入网即视为泄露,必须作废重置, gods and regulators 都帮不了你(见安全 )。配置管理用模板 + 本地覆盖:config.example.yaml 进仓库,真实配置本地放并 ignore。

Notebook 与实验的版本化

Jupyter Notebook 对 Git 不友好(diff 全是 JSON 噪声),三个实用妥协:

  1. Notebook 只做探索,成形逻辑落 .py(见研究复现 ),.py 严格进 Git;
  2. 确要进仓库的 Notebook,提交前清空输出(nbstripout 工具自动化);
  3. 实验结果(指标表格、净值截图)不进 Git,进实验登记表(一行一个实验:分支名、参数、绩效、结论)——Git 管代码,表格管结果,两者用分支名关联。

数据版本:Git 之外的轻量方案

数据本身不适合 Git(体积大、二进制、更新频繁),但数据版本号必须被 Git 记录:因子计算脚本读取的每张表,在其旁边维护一个 manifest.json(行数、日期范围、生成时间、来源脚本版本);脚本启动时校验 manifest 与预期一致,不一致直接报错拒跑。

1
2
3
4
5
6
7
8
{
  "table": "daily_bar_hfq",
  "rows": 5820344,
  "date_range": ["2014-01-02", "2026-09-17"],
  "built_at": "2026-09-17T17:12:04",
  "source_commit": "a3f9c2d",
  "adj_factor_version": "20260917"
}

这就是因子存储与版本管理 的最小实现——没有它,「同一个策略上周和今天回测结果不一样」将永远无法归因。这句话值得展开:99% 的「回测结果对不上」最终归因于三者之一——数据变了(manifest 能抓)、代码变了(git 能抓)、参数变了(配置 diff 能抓)。三样都版本化,神秘感消失。

关联阅读:代码质量 接管合并前的质量门禁;因子存储与版本管理 是数据层版本化的完整方案;DevOps 与 CI/CD 把本篇的手工流程自动化。