3、代码仓库管理:Git工作流设计、分支策略与CI/CD集成
代码仓库管理这事儿,说大不大,说小不小。我见过太多团队,策略写得天花乱坠,结果一上线就乱成一锅粥。说白了,Git 工作流就是给团队定规矩——谁在什么分支上干活,代码怎么合,什么时候触发自动化流程。
我个人习惯把仓库管理分成三个层次:分支策略定规矩,工作流设计定流程,CI/CD 集成定自动化。咱们一个一个来拆。
3.1 分支策略:master / dev / feature 三层结构
量化策略的代码,最怕的就是「改完就跑」。你想想看,一个策略参数调错了,回测数据对不上,实盘直接亏钱。所以分支策略必须清晰,容不得半点含糊。
我推荐的分支模型是这样的:
| 分支名称 | 用途 | 谁可以合并 | 生命周期 |
|---|---|---|---|
master |
生产环境代码,只接受经过充分测试的合并 | 仅限运维/架构师 | 永久 |
dev |
日常开发集成分支,所有 feature 合到这里 | 开发团队 | 永久 |
feature/* |
具体功能开发,比如 feature/risk-control-v2 |
个人开发者 | 开发完成后删除 |
hotfix/* |
紧急修复线上问题 | 运维/核心开发 | 修复完成后删除 |
核心原则:master 分支永远是可部署状态。dev 分支可以「脏」,但 master 必须「干净」。
我在项目中遇到过一件事:有个同事直接在 master 上改了个参数,然后 push 上去。结果 CI 自动部署到生产环境,策略直接跑飞了。嗯,从那以后我就加了一条硬性规定——master 分支写保护,任何人不能直接 push。
3.2 Git 工作流设计:从 feature 到 master 的完整路径
工作流不是拍脑袋定的,得跟你的发布节奏匹配。量化策略的发布节奏通常是:回测验证 → 模拟盘 → 实盘。所以 Git 工作流也得对应上。
我常用的流程是这样的:
- 从 dev 拉出 feature 分支:比如
feature/add-macd-indicator - 在 feature 上开发、提交:小步快跑,每次提交都写清楚改动原因
- 发起 Pull Request 到 dev:代码审查 + 自动化测试
- 合并到 dev:触发 CI 跑回测验证
- 从 dev 发起 PR 到 master:需要至少两人 approve
- 合并到 master:触发 CD 部署到生产环境
小技巧:我习惯在 PR 描述里加上「回测结果截图」和「风险点说明」。这样 reviewer 一眼就能看出改动的影响范围。
为什么会这样设计?因为量化策略的代码改动,往往牵一发而动全身。你改了一个止损逻辑,可能影响所有持仓品种。所以每一步都要留痕,每一步都要验证。
3.3 CI/CD 集成:GitHub Actions 与 GitLab CI
CI/CD 说白了就是「自动化流水线」。代码一推,机器自动帮你跑测试、做回测、甚至部署到模拟盘。我个人的经验是:CI 要快,CD 要稳。
3.3.1 GitHub Actions 实战
GitHub Actions 的配置很直观。我给你看一个我常用的工作流文件:
name: Quant Strategy CI
on:
push:
branches: [ dev, feature/* ]
pull_request:
branches: [ dev, master ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: 安装依赖
run: pip install -r requirements.txt
- name: 运行单元测试
run: pytest tests/unit/
- name: 运行回测验证
run: python scripts/backtest_check.py
- name: 代码风格检查
run: flake8 src/
这个配置做了三件事:跑单元测试、跑回测验证、检查代码风格。我建议把回测验证放在 CI 里,因为很多 bug 在回测阶段就能暴露出来。
注意:回测验证如果耗时太长(比如超过 30 分钟),建议拆成两个 job:一个跑快速验证(5 分钟以内),一个跑全量回测(可以异步触发)。别让 CI 卡太久,开发效率会受影响。
3.3.2 GitLab CI 实战
GitLab CI 的配置思路跟 GitHub Actions 类似,但语法上有些区别。我拿一个实际项目举例:
stages:
- test
- backtest
- deploy
unit-test:
stage: test
script:
- pip install -r requirements.txt
- pytest tests/unit/
only:
- dev
- feature/*
backtest-check:
stage: backtest
script:
- python scripts/backtest_check.py --mode=fast
only:
- dev
deploy-sim:
stage: deploy
script:
- ansible-playbook deploy-sim.yml
only:
- master
when: manual
注意最后那个 when: manual。我故意把部署到模拟盘设成手动触发。为什么?因为实盘部署必须有人确认,机器不能替你做决定。我曾经吃过这个亏——CI 自动部署了一个有 bug 的策略到模拟盘,结果模拟盘数据全乱了,花了两天才恢复。
3.4 避坑指南:我踩过的几个坑
- 分支命名不规范:有人用
fix-bug,有人用my-changes。时间一长,根本不知道哪个分支是干嘛的。我建议统一用类型/描述格式,比如feature/risk-control、hotfix/order-timeout。 - CI 跑太久:全量回测动辄一两个小时,开发等不起。我的做法是:PR 触发快速回测(只测最近 30 天数据),合并到 master 后再触发全量回测。
- 忽略代码审查:量化策略的代码审查不能只看语法,还得看逻辑。我要求每次 PR 必须附带「策略逻辑说明」,reviewer 要确认改动不会影响现有持仓。
- 没有回滚方案:万一部署出问题了怎么办?我习惯在 master 上打 tag,比如
v1.2.3。出问题直接回滚到上一个 tag,比重新改代码快得多。
3.5 知识体系总览
下面这张图,是我对本章核心逻辑的总结。你可以把它当成一个「决策地图」:
这张图从左到右,从上到下,就是一套完整的代码管理流程。你照着这个框架搭,基本不会出大问题。
最后说一句:工具是死的,人是活的。Git 工作流也好,CI/CD 也好,最终目的是让团队协作更顺畅,而不是给团队添堵。我见过有人把分支策略定得极其复杂,结果开发一天有一半时间在搞合并。嗯,那就过头了。适可而止,够用就好。