这门课解决什么问题
面向已经会写基础 Python 的人。 for 循环、函数、列表字典都没问题,平时也能写出几百行能跑的脚本。
但下面这件事你可能做不了:打开一个用面向对象写的框架,看懂它为什么那样写。
这道坎很常见。类的语法本身不难——class、self、__init__,一小时能学完。难的是别的:
- 为什么要建这么多类?一个函数不就行了?
- 这个类看着什么也没干,只是把参数转手传给另一个类,它存在的意义是什么?
- 我要加一个功能,该继承哪个类、填哪几个方法?为什么框架能自己调用我写的代码?
- 哪些是它的核心,哪些是可以先跳过的细节?
这些问题的答案不在语法里,在设计意图里。而设计意图,光看结果是看不出来的——你得知道它当初在躲什么麻烦。
这对量化尤其要紧:主流量化框架(qlib、backtrader、backtesting.py、vnpy)全是面向对象写的。看不懂它的组织方式,你就只能照着文档调 API,改不动、扩不了、出问题也不知道该看哪儿。
这门课和其他 OOP 课的差别

一、不讲语法讲设计,而且让你先踩坑
大多数 OOP 教程的路径是:讲 class → 讲继承 → 讲多态 → 举个「动物/狗/猫」的例子。学完你会写类,但仍然看不懂框架——因为你没经历过它要解决的那个麻烦。
这门课反过来走:拿一个真实的回测框架当研究对象,先用面向过程从零手搓,功能一条条加,直到你自己感觉到”这代码再加下去要撑不住了”;然后再用面向对象重写一遍,看每一个类各自解决了刚才哪个具体的麻烦。最后再让你对照业界的生产级别的回测框架代码看看你手搓的代码与别人专业版本的有啥差别
前面那四个问题因此有了答案,而且是你自己从“坑”里爬出来的答案,不是背下来的。
二、研究对象是量化回测平台,顺带把它搞懂了
给它一段历史价格和一套买卖规则,它模拟”如果当时真按这套规则操作,账户会变成什么样”,跑完打出这张表:
策略 期末资产 总收益率 最大回撤 交易次数 双均线 10/30 1,157,016.04 15.70% -23.87% 26 动量 20 1,288,226.05 28.82% -23.71% 52 布林带 20/2 1,012,095.31 1.21% -32.38% 16
这三行是参考实现真跑出来的,你写完第 4 批需求之后,你的三行应当与之逐字相同。
从零把回测平台造出来,比读十篇讲回测原理的文章管用。 而且这是刻意安排:第二部分重写时业务你已经全懂了,注意力可以百分之百放在”怎么组织代码”上——一次只学一件新东西。
三、不需要金融背景,也不需要装任何第三方库
需求里的”均线””持仓””手续费”全是字面意思,不出现复权、夏普比率、贝塔、因子、做空、保证金、期权。主线 32 讲的配套代码只用标准库:拿到代码不用配环境,python3 文件名.py 直接跑;固定随机种子之后所有人的数字完全一样,谁对谁错一眼看得出。
四、任务书和讲解是分开的
这门课不希望你跟着课件抄代码。所以任务书单独打包:里面只有函数签名、规则、易错点、伪代码和一组可直接跑的验收断言,没有实现。
建议的用法是:先拿任务书自己写一版 → 把断言逐条跑成 True → 再回来读课件里的实现和易错点。自己写过一遍再看讲解,和直接读讲解,是两件完全不同的事。 那些坑的形状,只有自己先踩一遍才看得见。
三个部分:为什么这么设计

第一部分(02–17 讲) 用面向过程手搓一个回测平台
为什么先写”不好”的版本:因为”面向过程不好维护”这句话,听来的和自己撞上的完全是两回事。需求分 5 批下发,一批做完再发下一批——你不知道后面还要加什么,只能按当下最省事的方式写,这正是真实项目的样子。等加到第 14 讲,你会发现加一档手续费要动核心循环、加一个观察项又要动一次。
训练目的:一是搞清回测平台到底要干什么(数据从哪来、信号怎么算、成交怎么撮合、费用怎么扣、结果怎么统计);二是亲手积累出一份问题清单。第 17 讲做一次体检,把踩过的坑集中列一遍,编号 P1–P12——这份清单就是第二部分的施工图。
学完你能:独立写出一个能跑三个策略、带手续费止损、能出资产曲线和最大回撤、能做参数扫描的回测程序。以及说得出它哪里开始变得难改,难改在哪。
顺带说一句,这部分的高光不是”面向过程有多烂”,而是高阶函数和闭包能把面向过程推得比多数人以为的更远——第 11、12 讲专门讲这两把牌能打到哪、以及在哪里打不动了。
第二部分(18–32 讲) 用面向对象重写一遍
为什么这样设计:业务需求已经全懂,这一部分只研究一件事——怎么组织代码。从最朴素的一步开始(把散落的变量和函数装进一个类),一步一步往前推,每一步只引入一个新工具、只解决 P1–P12 里的一两条。到最后你会得到 8 个类,它们各自的存在理由你都说得出来。
这部分有一条铁律:每一步重写完,跑出来的结果必须和重写前逐位相同。 资产曲线 500 个点、每一笔成交,一个都不许差。这是”重构”这个词的定义——重构只改结构,不改行为。跑不过就是改错了。
最后三讲是验收,这也是整门课设计上最讲究的地方:拿两条从一开始就写在需求说明书里、但第一部分故意没做的新需求(限价单 R20、结果落盘 R21),在两个版本上各加一遍,对比改动量。
为什么非得这么验?因为重写本身不产生任何新功能——它没让程序多算一个数。它值不值,只能用”下一次改动有多便宜”来衡量。这是唯一诚实的度量方式。
学完你能:看着一份代码说出它该拆成哪几个类、每个类的边界在哪;给框架加功能时知道该继承什么、填哪几个方法;以及在别人说”这里该上个设计模式”时,判断出该不该。第 32 讲还会承认自己哪几处过度设计了——知道什么时候不该用,和知道什么时候该用一样重要。
第三部分(33 讲) 和专业的框架比一比
为什么要有这一部分:写自己的代码和读别人的代码是两种不同的能力,前面 32 讲练的都是前者。
拿我们造的东西和真实的开源框架 backtesting.py(约 1800 行)逐项对照:它一共 16 个类、彼此什么关系、每个类解决什么问题、哪些我们造过、哪些没造。重点不是比数字,是看专业人士怎么权衡——它的架构是从三条约束推导出来的,有八处设计值得学,也有八处代价值得算。
学完你能:拿到一个陌生的面向对象框架,先看出它的核心是哪几个类,再判断该从哪里下手改。
会涉及的知识点

不用现在学,每一样都是在实现某条需求时顺手讲的,不单独开小节讲语法。
第一部分 函数与参数、多返回值、作用域与 global、可变默认参数的坑、容器选择、切片、就地修改与副本、None 的语义、try/except、高阶函数、闭包与 nonlocal、字典查表代替 if 链、csv 与文件读写
第二部分 class / self / __init__、类变量、@property、@dataclass、组合优先于继承、super()、自定义异常层级、抽象基类与 @abstractmethod、模板方法、控制反转(你不调框架,框架调你)、封装与命名约定、dunder 协议、运算符重载、typing.Protocol、依赖注入、Mixin 与 MRO、迭代器与生成器、装饰器、__init_subclass__、上下文管理器、unittest / pytest / Mock、多进程与 pickle 约束
设计模式 策略、适配器、模板方法、观察者、命令、状态、注册表。不讲元类——第 29 讲用 __init_subclass__ 达到同样目的。
课程目录
全课 33 讲,三部分。第 01 讲不写代码,讲清接下来 32 讲在干什么。
第 01 讲 导论
| 讲 | 标题 | 内容 |
|---|---|---|
| 01 | 这门课要造什么 | 课程设计思路、三个部分的走法、回测平台要做什么、任务书怎么用 |
第一部分 面向过程手搓(02–17)
需求分 5 批下发:能跑起来 → 贴近现实 → 规则变严 → 要能比较 → 工程化。
| 讲 | 任务 | 会撞上什么 |
|---|---|---|
| 02 | 造数据、算均线、发信号 | |
| 03 | 模拟买卖、算总收益 | 现金和持仓必须一起改,语言不管这事 |
| 04 | 手续费与下单约束 | P2 参数从 3 个涨到 6 个 |
| 05 | 止损 | P1 P5 状态散在全局;一组状态没一起更新 |
| 06 | 成交流水 | P3 P4 P7 返回值爆炸、dict 冒充对象、可变默认参数 |
| 07 | 资产曲线与最大回撤 | P6 存了一份 equity,某个分支忘了更新 |
| 08 | 当天不能卖、卖出多扣一道 | 循环里的 if 越堆越高 |
| 09 | 错误要报出来 | P9 用返回值表示失败,调用方不检查 |
| 10 | 再加两个策略 | P8 三份 81% 相同的循环 |
| 11 | 把策略当函数传 | 高阶函数干净地消灭 P8 |
| 12 | 策略要记住自己的东西 | P10 全局变量/字典/闭包,三种都有问题 |
| 13 | 参数扫描 | 元组靠下标、字典靠键名,都不牢 |
| 14 | 手续费与数据源可切换 | P12 换一种规则就要改核心循环 |
| 15 | 日志、曲线、报警 | 循环 31 行里 16 行是观察代码 |
| 16 | 偷看明天的策略 | P11 不报错、跑得飞快、收益率离谱 |
| 17 | 体检报告 | P1–P12 集中重演,给出治疗计划 |
第二部分 面向对象重写(18–32)
每一步只引入一个新工具,只消灭一两条 P。每步跑出来的结果必须和上一步逐位相同。
| 讲 | 任务 | 消灭 |
|---|---|---|
| 18 | 把状态和函数装进一个类 | P1 P3;P2 P4 各一半 |
| 19 | 能算出来的别存(@property) |
P5 P6 |
| 20 | 拆成 Position / Broker / Trade | P7 |
| 21 | 自定义异常层级 | P9 |
| 22 | 抽象基类与模板方法 | P8 |
| 23 | 控制反转、类变量作参数 | P10 |
| 24 | 策略不该看到明天(_DataView) |
P11 |
| 25 | 让对象接入语言的语法(dunder) | |
| 26 | 把会变的东西注入进来 | P12 前半 |
| 27 | 观察者与 Mixin | P12 |
| 28 | 数据按 bar 喂进来(迭代器/生成器) | |
| 29 | 装饰器与策略注册 | |
| 30 | 验收一:加限价单,两版各加一遍 | |
| 31 | 验收二:结果落盘 + 单元测试 | |
| 32 | 多进程扫描;P1–P12 结账;承认哪几处过度设计了 |
第三部分 读真库(33)
| 讲 | 任务 |
|---|---|
| 33 | 和 backtesting.py 逐项对照:16 个类的全景、架构从三条约束推导、值得学的八处、代价清单八条、我们多出来的四处 |

发表回复