连载第 1 期:从零构建我的量化系统——为什么我先选 backtrader,又为什么在第 3 天想放弃

量化系统自建实录第一篇。选型、环境搭建、Python 3.13 兼容性问题排查,以及第一次想把编辑器关掉的那个晚上。

本文进度快照 2026-11-02
已完成
  • 本地 Python 虚拟环境(uv + Python 3.12.7)
  • backtrader 最小示例跑通,输出净值曲线
  • AKShare 日线数据拉取 + CSV 落盘
  • requirements 锁定文件(保证可复现)
尚未完成
  • 实盘对接 QMT
  • 滑点与手续费模型
  • 多标的组合回测
  • point-in-time 财务数据管道
下期预告
  • 把数据管道从「直接读 CSV」改成带校验的加载层
  • 给回测加第一版陷阱自检:未来函数扫描 + 前视偏差检查

本系列记录一个研发经理从零构建量化系统的真实过程。不是教程,是实录——包括走弯路、返工、想放弃的时刻。只谈工程与方法,不谈标的、不做投资建议。

本期做了什么

这周的目标本来很小:把本地回测环境跑起来,用一份日线数据跑通一个最小策略。

实际发生的事情是:

  1. 花半天做框架选型,选了 backtrader;
  2. 花一天写环境脚本,自以为很稳;
  3. 第 3 天被 Python 3.13 的兼容性问题打崩心态;
  4. 又花一天排查、降级、验证;
  5. 周末终于跑通,但留下了 3 条决定要写进规范的教训。

选型:为什么先试 backtrader

我的需求清单其实很朴素:

需求重要度说明
纯本地运行高研究阶段不碰实盘接口
事件驱动或向量化都行中先跑通,不纠结架构
社区资料多高出问题要搜得到答案
许可证友好高未来可能商用衍生品
支持 A 股日线回测高当前只做日线

候选是三个:backtrader、vectorbt、vnpy。

  • vectorbt 很快,但许可证里带 Commons Clause,禁止把它的功能打包成收费交付物。对我这种「未来可能做数字产品」的规划来说是个雷区——教学可以,产品底座不行。
  • vnpy 是全栈方案,事件引擎、实盘接口都有,但对「我只想先跑个日线回测」来说太重了。
  • backtrader 是 GPL-3.0,社区资料最多、概念最贴近我熟悉的事件驱动模型,先拿它入门最稳。

结论:先用 backtrader 学概念,未来产品底座自研或选 MIT/Apache 系。

第 3 天:撞墙

环境脚本我写得很自信:

# 环境搭建脚本(节选)
uv venv .venv --python 3.13
source .venv/bin/activate
uv pip install backtrader matplotlib pandas

装是装上了。然后跑最小示例:

import backtrader as bt

cerebro = bt.Cerebro()
cerebro.broker.setcash(100_000)
print('启动资金:', cerebro.broker.getvalue())
cerebro.run()
print('结束资金:', cerebro.broker.getvalue())

输出直接给我一记暴击:

ModuleNotFoundError: No module named 'collections.MutableMapping'

不是示例代码的问题,是 backtrader 在 Python 3.13 下的依赖链炸了——collections.MutableMapping 这类 ABC 别名在 Python 3.10 就被移除了,旧版依赖还在用。

排查过程

第一步:确认是依赖问题而不是我的代码问题。 用干净环境复现:

uv venv /tmp/probe --python 3.13
uv pip install backtrader
python -c "import backtrader"

3.13 稳定复现,3.12 正常。锁定解释器版本是触发条件。

第二步:找到具体炸点。 完整 traceback 指向一条间接依赖,它 import 了旧路径的 collections 抽象类:

# 出问题的用法(示意)
from collections import MutableMapping  # Python 3.10+ 已移除

# 正确写法
from collections.abc import MutableMapping

第三步:决策——等上游修复,还是降级 Python?

查了一圈 issue,上游修复的节奏不可控。我的需求是「这周跑通」,不是「贡献 patch」。所以决定:

# 回退到 Python 3.12
uv venv .venv --python 3.12
uv pip install backtrader matplotlib pandas

跑通了。数字终于对了。

为什么第 3 天想放弃

说真的,第 3 天晚上我关掉了编辑器。不是因为技术多难——一个 import 问题而已——而是因为一种熟悉的挫败感:明明是「跑个示例」这种最简单的一步,却要先给整个生态做一次考古。

后来我想明白了一件事:量化系统的工程复杂度,大部分不来自策略,而来自环境、数据和复现性。策略代码可以 20 行写完,但让这 20 行在半年后还能跑出一样的数字,是一套完全不同的工程问题。

这恰恰是我想持续记录的东西——不是「我用了什么策略」,而是「我怎么把这个系统搭起来」。

留下的 3 条规范

这次踩坑直接变成了我自己的工程规范:

  1. Python 版本锁定到小版本。 requires-python = ">=3.12,<3.13",锁文件入库。「用最新解释器」在研究阶段不是美德,是风险。
  2. 所有实验必须能一键复现。 脚本、锁文件、数据快照版本号三件套,缺一个就不算完成。
  3. 每次跑通都要留 evidence 快照:环境、版本、数据来源、验证时间。写文章要用,做产品更要用。

下期预告

两件事:把数据管道从「直接读 CSV」升级成带校验的加载层;给回测结果加第一版陷阱自检——先查未来函数和前视偏差,再看收益率曲线。


本系列只讨论工程实现与方法论,不构成任何投资建议。