4. 策略代码打包与版本控制:Git工作流、Python项目打包(setup.py/Poetry)

说实话,很多做量化的人,策略代码写得挺漂亮,但一说到「工程化」就头疼。我见过太多人直接在服务器上改代码,改完也不记版本,出问题了只能靠回忆找回去。嗯,这其实挺危险的。

这一章,我们就聊聊怎么把策略代码管起来。说白了就两件事:版本控制项目打包。这两件事做好了,你的策略才能从「实验品」变成「产品」。

4.1 为什么需要版本控制?

你想想看,一个策略从想法到实盘,中间要改多少次参数?调多少次逻辑?我自己的经验是,一个策略平均要迭代 20-30 个版本才能稳定上线。如果没有版本控制,你根本不知道哪个版本是「能赚钱的」,哪个版本是「改崩了的」。

Git 就是干这个的。它帮你记录每一次修改,还能让你随时回到任意一个历史状态。更重要的是,多人协作时,Git 能避免「你的代码覆盖了我的代码」这种惨剧。

核心原则:所有策略代码必须进 Git 仓库。哪怕是你一个人写的,也要用 Git 管理。

4.2 Git 工作流:我推荐的分支策略

Git 本身只是个工具,真正重要的是你怎么用它。我见过有人把所有代码都往 master 分支上推,结果一乱就全乱。我个人习惯用 Git Flow 的简化版,适合量化策略开发。

下面这张图是我常用的分支结构:

master develop feature/* release/* master: 生产环境代码 develop: 开发主分支 feature: 功能分支 release: 发布分支

具体怎么用?我一般这样操作:

  1. master 分支:只放线上运行的代码。每次合并前必须经过严格测试。
  2. develop 分支:日常开发的主战场。新功能从这里拉分支,开发完再合并回来。
  3. feature/* 分支:每个新功能或策略修改,都开一个独立分支。比如 feature/add_momentum_filter
  4. release/* 分支:准备上线前,从 develop 拉一个 release 分支,做最后的测试和修复。

我的习惯:每次提交代码前,先跑一遍单元测试。如果测试没过,坚决不提交。这个习惯帮我避免过至少 5 次线上事故。

4.3 Python 项目打包:从 setup.py 到 Poetry

代码写好了,怎么部署到服务器上?总不能每次都手动复制粘贴吧?

Python 项目打包,就是把你的策略代码变成一个「可安装的包」。这样在服务器上一条命令就能装好所有依赖。

4.3.1 传统方式:setup.py

这是 Python 最经典的打包方式。你需要在项目根目录下创建一个 setup.py 文件:

from setuptools import setup, find_packages

setup(
    name="quant-strategy",
    version="1.0.0",
    packages=find_packages(),
    install_requires=[
        "pandas>=1.3.0",
        "numpy>=1.21.0",
        "ccxt>=1.80.0",
        "redis>=4.0.0",
    ],
    entry_points={
        "console_scripts": [
            "run_strategy=strategy.main:main",
        ],
    },
)

然后运行 python setup.py install 就能安装。但说实话,这种方式有个坑——它不会自动管理依赖的版本冲突。我曾经因为一个依赖版本不对,在服务器上折腾了整整一个下午。

4.3.2 现代方式:Poetry

后来我改用 Poetry 了。它比 setup.py 好用太多,尤其是依赖管理这块。

先安装 Poetry:

curl -sSL https://install.python-poetry.org | python3 -

然后在项目目录初始化:

poetry init

它会生成一个 pyproject.toml 文件,像这样:

[tool.poetry]
name = "quant-strategy"
version = "1.0.0"
description = "我的量化交易策略"
authors = ["Your Name <you@example.com>"]

[tool.poetry.dependencies]
python = "^3.9"
pandas = "^1.3.0"
numpy = "^1.21.0"
ccxt = "^1.80.0"
redis = "^4.0.0"

[tool.poetry.dev-dependencies]
pytest = "^6.2.0"
black = "^21.0"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

Poetry 最大的好处是:它会生成一个 poetry.lock 文件,锁定所有依赖的精确版本。这样你在任何机器上安装,得到的依赖版本都是一模一样的。

注意:一定要把 poetry.lock 提交到 Git 仓库里。这样团队其他人拉下来后,运行 poetry install 就能得到完全一致的环境。

4.4 我的项目结构模板

下面是我常用的量化策略项目结构,你可以直接拿来用:

quant-strategy/
├── strategy/              # 策略代码
│   ├── __init__.py
│   ├── main.py           # 入口文件
│   ├── signals.py        # 信号生成
│   ├── risk.py           # 风控模块
│   └── utils.py          # 工具函数
├── tests/                 # 测试代码
│   ├── __init__.py
│   ├── test_signals.py
│   └── test_risk.py
├── config/                # 配置文件
│   ├── config.yaml
│   └── secrets.yaml
├── data/                  # 数据文件(不提交到 Git)
│   └── .gitkeep
├── logs/                  # 日志文件(不提交到 Git)
│   └── .gitkeep
├── pyproject.toml         # Poetry 配置
├── poetry.lock            # 依赖锁定文件
├── README.md              # 项目说明
└── .gitignore             # Git 忽略规则

这个结构我用了好几年,基本没出过问题。核心思路是:代码和配置分离,数据和日志不提交

4.5 避坑指南

最后分享几个我踩过的坑:

  • 不要把 API Key 提交到 Git。我见过有人把交易所的密钥直接写在代码里,然后 push 到 GitHub 上。结果第二天账户就被盗了。用环境变量或配置文件管理密钥。
  • 不要用 pip freeze > requirements.txt。这个命令会把所有依赖都列出来,包括那些你根本不需要的。用 Poetry 或 Pipenv 管理依赖更靠谱。
  • 每次上线前打 Tag。比如 git tag v1.2.0,这样万一线上出问题,可以快速回滚到上一个 Tag。

总结一下:Git 管版本,Poetry 管依赖。这两件事做好了,你的策略代码就能稳定、可复现地运行在任何机器上。别嫌麻烦,这些「工程化」的功夫,迟早会帮你省下大把时间。

专注资料整理