M00 量化投资全景与思维转换¶
层级:L0 入门与全景 | 优先级:★★★ | 预计学时:8–10 小时 对应原书:黑箱 第 1–2、11 章;陈 第 1、8 章 前置知识:无。需要有实际买卖股票的经验。统计细节查 M01,基本定律的完整推导在 M09。 读书笔记:黑箱第 1–2、11 章地图 · 陈第 1、8 章地图 状态:reviewed 数据截至:2026-09|最近复核:2026-10-22
学习目标¶
学完本章,你应该能够:
- 画出量化系统的五模块,并说出每个模块的输入、输出,以及本仓库里对应的代码或实验室。
- 把一个策略放进「时序 / 截面 / 配置」和「四类收益来源」两张地图,并给出学术出处。
- 用手算完成夏普、最大回撤、换手成本拖累和杠杆后夏普,并知道哪一步和
src/quant/backtest/metrics.py对齐。 - 说明个人投资者在港美股(富途 OpenAPI、IB
ib_async)上的主战场,以及印花税、融资利差、做空约束会怎样改写回测。 - 用至少两个真实事件讲清「拥挤 + 杠杆」的传导链,并指出教学实验室净值里哪些数字不能直接当成实盘预期。
本章知识拓扑图¶
本章是整套教材的地图。后面每一章都往这张图的某一个模块里填细节。
flowchart TB
subgraph who[钱从谁手里来]
RP[风险补偿]
BH[行为偏差]
ST[制度与结构]
LQ[提供流动性]
end
subgraph sys[五模块系统 · 黑箱第 2 章]
D[(数据 M03)] --> A[Alpha 模型<br/>M02 M06 M10]
D --> R[风险模型<br/>M04 M11]
D --> C[成本模型<br/>M13]
A --> P[组合构建 M12]
R --> P
C --> P
P --> E[执行 M13 M15]
E --> F[绩效归因 M14]
F -.迭代.-> A
end
who --> A
subgraph seat[个人生态位]
LF[中低频 · 港美股<br/>富途 / IB]
PIT[时点数据与幸存者偏差<br/>M03 M08]
end
P --> LF
D --> PIT
五模块在仓库里的落点:
| 模块 | 教材 | 工程路径 |
|---|---|---|
| 数据与研究纪律 | M03、M08 | src/quant/data/、src/quant/research/、docs/workflow.md |
| Alpha | M02、M06、M07、M10 | src/quant/strategies/、src/quant/factors/、knowledge/Labs/ |
| 风险与仓位 | M04、M11 | src/quant/risk/、docs/risk_policy.md |
| 成本、组合、执行 | M12、M13、M15 | src/quant/portfolio/、src/quant/backtest/、src/quant/execution/ |
| 归因 | M14 | src/quant/backtest/metrics.py、src/quant/backtest/report.py |
🟢 入门层:直觉、经济学逻辑与第一性原理¶
1. 量化在决策链上的位置¶
量化投资是用可检验的规则代替临场判断。电脑、公式、自动下单都只是工具。规则要同时满足三件事:买什么、买多少、何时卖能写成明确条件;这些条件能在历史数据上被检验,也能在未来被证伪;执行时不因为当天的情绪改规则。
市场里常被混在一起的三个词,决策链位置不同:
| 名称 | 规则化的是哪一步 | 例子 | 个人投资者 |
|---|---|---|---|
| 程序化 / 自动交易 | 下单 | 盘中看完新闻,手动把「买入 1000 股」交给程序拆单 | 富途、IB 都能做,本身还不是量化 |
| 量化投资 | 投资决策 | 「每月末做多过去 12 个月扣除最近 1 个月涨幅最高的一档」 | 本教材的主线 |
| 高频交易 | 决策 + 微秒级通道 | 排队抢价差 | 个人的 API 延迟在几十到数百毫秒,这一层不参与(⊘) |
你过去的主观交易里,已经有一部分可以写成规则。比如「跌破 200 日均线就减仓」可以回测;「我认识管理层,所以加仓」写不成可重复的数据条件。写不成的那部分,要单独拿出来问:它是信息优势,还是事后编的故事。
2. 钱是从谁手里赚来的¶
一条能长期活下来的规则,必须回答:对手为什么在成交的另一侧。教学上把收益来源分成四类。这是地图,是对文献的归纳,没有一个定理证明世界上的收益恰好分成互不重叠的四块。很多策略同时沾两类,研究时要写明主机制。
| 收益来源 | 对手是谁 | 对手为什么成交 | 代表策略 | 出处 |
|---|---|---|---|---|
| 风险补偿 | 不愿承担某种风险的持有人 | 把波动、衰退、流动性枯竭转给你,并支付溢价 | 价值、规模 | Fama & French (1993), JFE 33(1) |
| 行为偏差 | 反应慢或反应过度的交易者 | 盈余公告后还在慢慢改预期,或追涨杀跌 | 截面动量、PEAD | Jegadeesh & Titman (1993), JF 48(1);Bernard & Thomas (1989), JAR 27:1–36 |
| 制度与结构 | 被迫交易的机构 | 指数委员会改成分、保证金规则、月末考核 | 指数纳入 | Harris & Gurel (1986), JF 41(4) |
| 提供流动性 | 急着成交的人 | 愿意付价差换立即成交 | 短期反转、做市 | Nagel (2012), RFS 25(7) |
四个微观场景:
- 风险补偿。 经济差的时候,高账面市值比的股票往往一起跌。愿意在那种时候继续持有的人,长期拿到的是「衰退风险」的报酬。你赚的是保险费,承保的年份会很难看。
- 行为偏差。 公司刚公布好于预期的盈利,一部分资金要等研报、等委员会、等下一次调仓,买盘在公告后几周到几个月里慢慢进来。提前按规则买入的人,赚的是别人决策流程的时滞。动量在中期(约 3–12 个月)常被归到这一类;它也会在拥挤时反向崩掉(见案例 4,展开在 M07)。
- 制度。 某只股票被宣布纳入标普 500,跟踪指数的基金必须在生效日附近买进,不管贵不贵。规则交易者研究的是这股买压的时间表,以及生效之后价格是否回吐。
- 流动性。 有人因为赎回、保证金、止损必须在今天卖掉。你在宽价差上接盘,赚的是「马上成交」的服务费。服务费在平静日很小,在 2008 年、2020 年 3 月这种别人一起逃命的日子里,接盘的人会先亏一截。
以后每见到一个新因子,先填这张表。填不出对手是谁,就把它送去 M08 的数据窥探清单,先不要加杠杆。
3. 策略谱系:你在回答哪一个问题¶
量化规则
├─ 时序(这只资产现在该多还是该空) 持有:日 ~ 月 → M02
│ 趋势 / 时序动量、均值回归、简单期权叠加
├─ 截面(这一篮子里谁比谁好) 持有:月 ~ 季 → M05–M08
│ 因子选股、配对、事件(财报、指数调整)
└─ 配置(各类资产或因子各放多少) 持有:季 ~ 年 → M17
风险平价、Smart Beta、因子 ETF
时序和截面可以同时为真,因为它们看的时钟不同。Jegadeesh & Titman 的截面动量用的是数月;短期反转(大约一周到一个月)常来自流动性回补。同一只股票可以「这个月相对别的股票强,但这五天涨太多、下周均值回归」。M02 会把时钟拆开。
4. 个人投资者的生态位:港美股、富途与 IB¶
机构的五模块可以配一个团队。个人账户通常是:一条 Alpha 规则 + 明确的仓位上限 + 成本假设 + 限价或收盘价成交。省略风险模型和执行算法是允许的,省略的后果要写进规则:行业扎堆、冲击成本、成交失败都由你自己承担。
劣势要按市场写实:
| 摩擦 | 港股 | 美股 | 对策略的含义 |
|---|---|---|---|
| 印花税 | 2023-11-17 起,买卖双方各付成交金额的 0.1%(GovHK 印花税税率) | 股票交易无港式印花税;卖出侧另有随政策变动的 SEC/FINRA 费用 | 港股一轮来回仅印花税就约 0.2%,月换仓的高换手规则很难活 |
| 做空 | 需券源,借券费随个股变化,券商可随时召回 | 易借券的大盘股较容易,小盘和挤仓时费率会跳升 | 教材里的「多空对冲」在个人账户上经常只能做多 |
| 交易时段 | 开市前时段、持续交易、收市竞价各有规则 | 常规时段外的盘前盘后价差更宽,很多回测只用常规时段收盘价 | 用收盘价成交的回测,不要假装自己成交在竞价盘口的中间 |
| 数据 | 财报有公告时点;复权、停牌、交易所转换要单独处理 | ADR 与港股正股不是 1:1 价格,汇率每天在变 | 腾讯 ADR 实验室专门处理这一层,见下文图表 |
优势同样具体:资金量小,用得了机构容量不够的规则;没有季度排名,可以拿住一年以上的回撤;跟踪误差、行业偏离没有合规上限。欧内斯特·陈把「容量」写成个人量化的核心租金:机构因为规模被迫放弃的规则,小账户还执行得动。
由此得到本项目的主战场:港美股、周或月调仓、以做多为主、先在模拟盘验证。日内和高频不在范围内。模拟盘只在 VPS 上跑,开发机不发单、不写账本(见仓库 AGENTS.md)。
5. 从主观到规则的三步¶
- 故事改成可计算的条件。 「护城河深」改成「过去三年毛利率高于行业中位数,且资本开支低于折旧」。改不了的句子不要进回测。
- 单只股票改成一篮子的期望。 一次看对只说明这一次。Grinold 的基本定律说,信息比率大约是预测相关度乘以独立下注次数的平方根(下一节手算,严格推导在 M09)。个人投资者靠次数,不靠单票神预测。
- 用过程评价规则。 一笔亏损可以来自正确规则里的正常方差。评价对象是规则在大量独立样本上的期望,以及这个期望被成本、拥挤和制度摩擦削掉之后还剩多少。
🟡 进阶层:公式、算法与工程实现¶
本节的绩效定义与 src/quant/backtest/metrics.py 对齐:一年按 252 个交易日;波动用样本标准差(分母 n − 1);夏普先减日无风险利率再乘 √252;单边换手等于成交名义金额的一半除以净值。下面每个公式都给符号表、推导和手算。手算是算术检查,不是历史业绩。
6. 收益率、年化与波动¶
6.1 简单收益与对数收益¶
Rₜ = Pₜ/Pₜ₋₁ − 1, rₜ = ln Pₜ/Pₜ₋₁ = ln(1 + Rₜ)
| 符号 | 含义 |
|---|---|
| Pₜ | 第 t 日的复权价格(分红再投资之后的价格) |
| Rₜ | 简单收益率,组合净值相乘时用它 |
| rₜ | 对数收益率,跨期相加、近似正态分布时用它 |
推导:ln(Pₜ/Pₜ₋₁) = ln Pₜ − ln Pₜ₋₁,所以两天的对数收益直接相加。简单收益必须连乘:(1 + R₁)(1 + R₂) − 1。价格下跌 50% 再上涨 50%,简单收益连乘得到 0.5 × 1.5 − 1 = −25%,对数收益相加是 ln 0.5 + ln 1.5 = ln 0.75,再指数回去仍是 −25%。两者描述同一段财富,汇总方式不同。
手算。 Pₜ₋₁ = 100,Pₜ = 100.04。
Rₜ = 0.0004, rₜ = ln(1.0004) ≈ 0.00039992
差在第四位以后。日收益很小的时候,两者几乎一样;出现 ±20% 的单日时必须用简单收益连乘净值,不能把对数收益当成投资者拿到的百分比。
6.2 算术年化、几何年化(CAGR)与波动年化¶
μ_arith = ¯R × 252, CAGR = (V_T/V₀)^(1/Y) − 1, σ_ann = s(R) √252
| 符号 | 含义 |
|---|---|
| ¯R | 样本内日简单收益的算术平均 |
V₀, V_T |
期初、期末净值,且整段净值都为正 |
| Y | 年数。本仓库用 (交易日数 − 1) / 252,见 metrics.py 的 PERIODS = 252 |
| s(R) | 日简单收益的样本标准差,分母 n − 1 |
波动乘 √252 的理由:若日收益近似不相关,N 日收益的方差约等于 N 倍日方差,标准差因而乘 √N。美股常规年份大约 252 个交易日,所以用 √252。月频序列年化才用 √12,两条不能混乘。日收益若强自相关,这个缩放会偏;M01 的 Newey–West 就是在处理这件事。
手算。 日收益恒为 0.04%,日波动 1%,一年 252 天。
μ_arith = 0.0004 × 252 = 10.08%
CAGR = (1.0004)²⁵² − 1 = 10.6033%
σ_ann = 0.01 × √252 = 0.01 × 15.8745 = 15.8745%
本例日收益是常数,复利使 CAGR(10.6033%)高于「日均 × 252」(10.08%)。日收益有波动时,几何平均通常低于算术平均,差额大约是半个方差,M01 再证。对外说「年化收益」时写明是 CAGR 还是算术平均。本仓库绩效表里的 CAGR 是净值复利,夏普里的平均是算术日收益。
7. 夏普比率,以及杠杆为什么不创造夏普¶
Sharpe = (¯R − r_f/252) / s(R) × √252
| 符号 | 含义 |
|---|---|
r_f |
年化无风险利率,按 252 均摊到每个交易日。代码里零波动返回空值,避免除以零得到无穷大 |
| 分子 | 日超额收益的样本均值 |
| 分母 | 日简单收益的样本标准差(n − 1) |
这是超额收益的夏普。只拿 ¯R / s(R) × √252 会把现金利率算进「策略技能」。
手算 A(对齐代码的三日样本,只检验算术)。 三日收益 1%、−0.5%、0.8%,r_f = 4%。
¯R = (0.01 − 0.005 + 0.008) / 3 = 0.00433333
r_f/252 = 0.04/252 = 0.00015873
离差平方和除以 3 − 1:
s(R) = √(6.63333 × 10⁻⁵) = 0.00814453
Sharpe = (0.00433333 − 0.00015873) / 0.00814453 × 15.8745 = 8.137
三日样本年化出 8.14,只说明公式跑通了。样本越短,这个数字越不能当成技能。M14 会讲需要多长的记录才能把运气和技能分开。
手算 B(投资决策用的年化简式)。 某策略预期收益 12%,波动 15%,无风险利率 4%。在收益和波动都已经是年化、且融资成本等于无风险利率时:
Sharpe = (0.12 − 0.04) / 0.15 = 0.5333
杠杆 L 表示每 1 元本金持有 L 元资产,另外 L − 1 元按借款利率 r_b 融资。股权收益:
R_E = L R_A − (L − 1) r_b, σ_E = L σ_A
若 r_b = r_f,超额收益和波动同乘 L,夏普不变:
(L(μ_A − r_f)) / Lσ_A = (μ_A − r_f) / σ_A
L = 2、r_b = 4%:股权预期收益 2 × 12% − 4% = 20%,相对 4% 的超额是 16%,波动 30%,夏普仍是 0.16/0.30 = 0.5333。
个人账户的融资利率通常高于国债。设 r_b = 5%:
E[R_E] = 2 × 0.12 − 0.05 = 0.19
Sharpe = (0.19 − 0.04) / 0.30 = 0.500
融资利差把夏普从 0.533 打到 0.500。富途、IB 的融资利率还要再加一层,并且维持保证金在波动放大时会强制减仓——那一步会让你在低点卖掉,夏普公式里的「波动同比例放大」不再成立。半凯利和回撤约束放在 M04,不要在 M00 就把杠杆当成免费的放大镜。
8. 最大回撤¶
DDₜ = Vₜ / (max_(s≤t) Vₛ) − 1, MDD = minₜ DDₜ
本仓库把回撤存成正的跌幅(峰值到谷值),并记下从峰值到谷值经过的交易日数。对外交流时写清楚符号:下面手算用负号表示「净值掉了多少」。
手算。 净值序列 100, 110, 105, 90, 95, 120。
| t | 净值 | 截至当日峰值 | 回撤 |
|---|---|---|---|
| 1 | 100 | 100 | 0 |
| 2 | 110 | 110 | 0 |
| 3 | 105 | 110 | 105/110 − 1 = −4.545% |
| 4 | 90 | 110 | 90/110 − 1 = −18.182% |
| 5 | 95 | 110 | −13.636% |
| 6 | 120 | 120 | 0 |
最大回撤是 −18.182%,发生在峰值 110 到谷值 90。后面创新高不会把这段回撤从历史里擦掉。卡玛比率 CAGR/|MDD| 在 M04、M14 用作「每承受一单位深坑换来多少复利」,它对窗口很敏感,单独一个数字不够。
9. 换手与成本拖累¶
metrics.py 的定义:
τ_单边 = 区间成交名义金额 / (2 × 平均净值)
卖出 0.5 倍净值、同时买入 0.5 倍净值,成交名义金额是 1 倍净值,单边换手是 0.5。单边成本 c(佣金、税费、滑点,按每一元成交计)打在全部成交上:
成本拖累 = 2 τ_单边 c
| 符号 | 本例取值 | 含义 |
|---|---|---|
τ_单边 |
见下 | 年化单边换手,单位是「倍 / 年」 |
| c | 15 bps = 0.0015 | 每一侧、每一元成交的成本。教学实验室默认这一档,真实港股还要另加印花税 |
手算。
- 每月换掉一半仓位:年化单边换手 0.5 × 12 = 6。拖累 2 × 6 × 0.0015 = 1.80%/年。
- 每个交易日单边换手 20%:年化单边换手 0.20 × 252 = 50.4。拖累 2 × 50.4 × 0.0015 = 15.12%/年。
15 bps 对美股大盘股的月度调仓是粗略教学假设。港股印花税买卖双方各 0.1%,一轮完整换仓光印花税就接近 20 bps 的量级(卖出旧仓 10 bps、买入新仓 10 bps,再加佣金和价差)。日度换手的规则在个人账户上,成本项会大于多数公开论文里的「毛收益」。
复现:uv run python knowledge/books/figures/M00/plot_cost_leverage.py。
10. 主动管理基本定律(地图级)¶
信息比率的上界是三件事相乘:准头、真正分开的赌桌、以及手脚被捆住之后还能照做的比例。 IC 是准头,预测和后来的残差收益有多齐,通常只有几个百分点。 BR 是一年里互不相干的赌桌数。同买 100 只银行股,行业涨跌是同一张桌子,BR 接近 1,不是 100。 TC 是知行合一的折扣,想买的方向和实际持仓夹角的余弦。不能做空、不能加杠杆,折扣就小于 1。 下面的式子先写理想情形,再乘上这个折扣。
Grinold (1989, Journal of Portfolio Management 15(3)) 在一系列理想化假设下得到:
IR ≈ IC × √BR
有约束时再乘转移系数 TC ∈ (0, 1](Grinold & Kahn, Active Portfolio Management, 2000):
IR ≈ TC × IC × √BR
| 符号 | 含义 |
|---|---|
| IC | 预测值与后续残差收益的相关系数。截面选股里常见的月度数量级是百分之几 |
| BR | 一年内近似独立的下注次数(广度) |
| TC | 理想组合里,有多少主动权重真的下到了账户上。做空限制、行业约束、换手上限都会把它压到 1 以下 |
| IR | 信息比率:相对基准的超额收益除以跟踪误差。它和夏普的区别在 M09 |
平方根从哪里来。把每一注看成一个小策略,信息比率都是 IC,且互不相关。N 个互不相关的信息比率 IRᵢ,最优叠加后的信息比率是 √(Σᵢ IRᵢ²)。各注相同则等于 IR₁ √N。下注次数进到根号里,所以「多看 100 只股票」的贡献是 10 倍而不是 100 倍,而且这 100 次必须近似独立——同一个行业动量算 100 次,广度仍接近 1。
手算。 IC = 0.05,一年 100 次独立下注,TC = 0.5(个人账户不能做空、单票有上限):
IR ≈ 0.5 × 0.05 × √100 = 0.25
没有约束时是 0.50。0.05 的相关度听起来很小,乘上广度之后才变成可用的信息比率。假设(残差收益结构、预测标准化、独立性)在 M09 逐条拆开。本章只要求你会代这个数,并拒绝把相关的下注重复计数。
11. 可复现代码:防前视的信号与绩效骨架¶
下面这段不下载数据、不声称任何历史业绩。它做两件事:信号只用 t − 1 及更早的价格;绩效函数与 summarize() 同一套年化。生产回测走 src/quant/backtest/engine.py,不要在教材片段里另写一套撮合。
import numpy as np
import pandas as pd
def sharpe_ratio(daily_ret: pd.Series, risk_free_annual: float) -> float:
"""与 metrics.py 一致:样本标准差、日无风险利率、再乘 sqrt(252)。"""
r = daily_ret.dropna()
if len(r) < 2:
return float("nan")
std = float(r.std(ddof=1)) # 分母 n-1;总体标准差会在短样本上高估夏普
if std == 0.0:
return float("nan")
daily_rf = risk_free_annual / 252.0
return (float(r.mean()) - daily_rf) / std * np.sqrt(252.0)
def max_drawdown(nav: pd.Series) -> float:
"""返回负的跌幅,便于和手算表对照。仓库内部存的是正的跌幅。"""
peak = nav.cummax()
return float((nav / peak - 1.0).min())
def one_way_turnover(traded_notional: float, nav: float) -> float:
"""成交额的一半才是单边换手。成本要打在全部成交额上,见第 9 节。"""
return traded_notional / (2.0 * nav)
# 短序列只演示时点:21 日动量在样本外为 NaN,shift(1) 再往右推一天。
price = pd.Series([100.0, 101.0, 103.0, 102.0, 106.0])
momentum = price.pct_change(2).shift(1)
toy = pd.Series([0.01, -0.005, 0.008])
print(round(sharpe_ratio(toy, 0.04), 3)) # 8.137,仅算术核对
print(round(max_drawdown(pd.Series([100, 110, 105, 90, 95, 120.0])), 4)) # -0.1818
# 第 0、1 日没有 2 日收益,第 2 日的动量要到第 3 日才可见。
print(momentum.round(4).tolist())
price 使用复权价。yfinance 要显式 auto_adjust=True,否则分红日会出现假的价格跳空,动量和回撤都会被污染。未复权价只能和单独的分红现金流一起记账,两套不能混用。
实验室里的真实净值(带幸存者偏差声明,见深入层)在:
同一次实验的迭代对比(含一次把收益做差的反面教材):
这些图由 uv run python -m knowledge.Labs.momentum_lab.run_lab 生成。报告窗口是 2008-07-01 至 2026-09-28,单边成本 15 bps。Iter 5 的 CAGR 29.96%、夏普 1.24、最大回撤 29.72%,是相对同一事后股票池等权基准的教学结果。基准本身的 CAGR 是 21.79%。把 29.96% 当成「动量在美股上的无偏预期」会直接违反 M03 的幸存者偏差纪律。
🔴 深入层:边界、争论与 2020 年代的实证¶
12. 五模块各自会在哪里失效¶
| 模块 | 平静市场里的假设 | 破裂时发生什么 | 个人账户最先碰到的形式 |
|---|---|---|---|
| Alpha | 对手的偏差或风险溢价还在 | 规则公布后拥挤,溢价被交易掉 | 公开动量、低波 ETF 拥挤 |
| 风险 | 协方差稳定、因子暴露算得准 | 相关突然升到 1,分散失效 | 2020-03、2022 股债同跌 |
| 成本 | 价差和冲击近似常数 | 流动性蒸发,限价单不成交 | 小盘、港股竞价、ADR 盘前 |
| 组合 | 权重可以按最优解调整 | 做空券源消失、保证金上调 | 多空模型被砍成纯多头,TC 下降 |
| 执行 | 收盘价代表可成交价 | 信号用了收盘,成交在下一跳 | 回测用 close、实盘用下一根 open 仍可能滑点 |
失效往往是几条一起发生。2007 年 8 月的量化危机里,Alpha(相似的多空因子)遇上风险(持仓相关)和执行(大家同时平仓,冲击不再是常数)。只改一个模块的参数,救不了这种周。
13. 两场还没结束的争论¶
风险补偿还是错误定价。 Fama–French 传统把价值、规模写成风险的价格:便宜股票在差的经济状态下赔付更差,溢价是保险费。行为金融把同一组收益写成反应不足、过度反应和套利限制(Shleifer & Vishny, 1997, JF 52(1))。对个人投资者,区分的实操意义是仓位政策:若你相信风险补偿,深度回撤时应当有预算继续持有;若你相信错误定价,就要同时监控套利限制是否消失(交易成本下降、参与者变多),消失之后溢价可以永久变薄。M05、M08 展开检验,本章不宣布哪一派获胜。
因子动物园还是贝叶斯复制。 Harvey, Liu & Zhu (2016, RFS 29(1)) 整理了数百个已发表因子,认为在这么多次尝试之后,t 统计量大约要到 3 才值得认真看。Jensen, Kelly & Pedersen (2023, JF 78(5)) 在全球样本上做贝叶斯收缩,结论是一大批特征在收缩之后仍然有样本外表现。两篇可以同时为真:单个研究者在自己电脑上试了 50 个参数,局部仍是数据窥探;全球共同存在的那一小撮特征,又比「全部都是假的」更稳。个人流程采用更严的那一边:先写经济机制,再限制尝试次数,t≈2 的结果只配进观察名单。门槛的推导在 M08。
预测精度可以很低,组合仍可能有用。 Gu, Kelly & Xiu (2020, RFS 33(5)) 报告,个股月超额收益的样本外 R²,三层神经网络在表内是 0.40%,只用规模、账面市值比和动量的 OLS 是 0.16%。0.40% 的 R² 意味着绝大部分波动不可预测。论文同时报告,用这些预测构造的多空组合,样本外夏普可以明显高于这个三变量基准。哪一列是 1.35,写在 M16:那是 NN4 的价值加权多空,不是 NN3。读的时候把两句分开:拟合优度低,描述的是个股;经济价值来自截面排序和分散。M16 再讲为什么普通 K 折交叉验证会在这个问题上泄漏未来。
14. 顶级业绩不能外推到个人账户¶
Zuckerman《The Man Who Solved the Market》(2019) 记载,文艺复兴科技 Medallion 基金 1988–2018 年费前年化约 66%,费后约 39%。同一机构对外的基金没有这条曲线。公开报道里,2025 年 10 月那轮量化回撤中,其外部股票基金的年内回撤达到两位数(媒体二次来源,引用前请核对原文)。可迁移的事实只有三条:高收益和高换手、低容量绑在一起;外部资金的规模会改变策略;个人账户复制的是规则说明书,复制不了数据、执行和仓位约束。
15. 批评与可以接受的回应¶
纳兰在《黑箱》里把外界批评收成一组反复出现的句子。可用的回应都是流程,不是口号:
| 批评 | 流程上的回应 | 落到哪一章 |
|---|---|---|
| 量化等于数据挖掘 | 先写机制和对手,再限制搜索次数,样本外和成本之后还在,才保留 | M08、docs/workflow.md |
| 量化会踩踏 | 假设同业持仓相关,杠杆和同质化暴露单独设上限 | M04、案例 1 与案例 3 |
| 历史不代表未来 | 机制消失(规则修改、对手离开)时退役策略,而不是把参数再优化一轮 | M02、M17 |
| 模型不可解释 | 个人账户坚持能说出收益来源的规则;机器学习只做研究和辅助 | M16 |
真实案例¶
下面四个事件都有公开复盘或指数编制机构的序列。媒体转述的基金收益率是二次来源,数量级用于理解机制,下单前以原始报告为准。
案例 1:2007 年 8 月量化地震¶
- 窗口:2007-08-06 至 2007-08-09 连续大幅亏损,随后数日快速修复。
- 背景:次贷压力已经出现,一批多策略基金需要现金,股票多空只是它们账本上最容易变现的一仓。
- 传导:大型基金降低股票多空杠杆 → 卖出共同持有的多头、回补共同持有的空头 → 同行的风险模型显示波动和相关上升 → 同行也减杠杆 → 冲击成本不再是常数。Khandani & Lo (2011, Journal of Financial Markets 14(1)) 用交易数据记录了这几天市场中性组合的异常亏损与反弹。
- 数字:论文记录的是因子组合在那几天的异常日收益,不同复制口径差几个百分点;本章不另造一个「全行业回撤 xx%」。
- 启示:你的「独特 Alpha」若和其他人的动量、价值名单重合,杠杆会把别人的平仓变成你的保证金通知。个人账户的防御是低杠杆和暴露清单,不是更复杂的信号。
案例 2:2022 年趋势跟踪的高光,以及随后的低谷¶
- 窗口:2022 全年,以及 2023 至 2025 年的一段回撤。
- 背景:通胀和加息形成持续的股债趋势。趋势跟踪在这种环境下靠持有方向赚钱,它在震荡市里会反复止损。
- 数字:Société Générale 的 SG Trend Index 在 2022 年约为 +27%(编制方指数,引用时核对年末水平);2023 年转为小幅负收益。2024–2025 年公开评论中出现过约 20% 量级的区间回撤(Cambridge Associates 等二次来源)。
- 启示:危机里表现好的规则,会有一到两年的平庸期。M04 的问题是你的生活现金流能不能覆盖这段平庸,而不是再找一个「只在 2022 年有效」的过滤器。
案例 3:2024 年初小微盘拥挤¶
- 窗口:2024-01-02 至 2024-02-05 前后。
- 背景:大量量化选股产品共享小市值暴露;一部分产品用收益互换加杠杆;雪球产品敲入增加了股指期货的对冲卖盘。
- 传导:小市值因子拥挤 → 杠杆产品净值下跌触发减仓 → 期货贴水加深、基差交易者风险上升 → 现货小盘流动性变差 → 超额收益和绝对收益一起恶化。中证 2000 在上述窗口下跌约三成(指数点位可在中证指数公司核对)。媒体统计的指增超额回撤大约是两位数,各家样本不同。
- 启示:主战场是港美股,这条案例仍然适用。超额可以只是风格 Beta。M14 的归因就是用来回答「我赚的是选股,还是无意中的小盘和行业」。个人投资者没有 DMA 的 4 倍杠杆,但两倍融资已经足够在同类 ETF 赎回时被动减仓。
案例 4:2025 年夏季美股量化回撤¶
- 窗口:2025 年 6 月至 7 月,以及 2025 年 10 月初的第二段。
- 背景:系统化股票基金持有相似的动量和质量暴露,空头集中在高卖空比例的股票上。
- 传导:低质量股票反弹 → 空头回补推高空头组合 → 动量多头被卖出以降低风险 → 几天内的动量回撤吞噬数月收益。高盛主经纪商曾报道 2025-06-01 至 07-22 系统化股票基金约 −4.2%(经纪商客户样本,不是全市场普查)。MSCI 的评论文章把驱动写成垃圾股反弹、动量抛售和轧空。动量崩溃的经典机制见 Daniel & Moskowitz (2016, JFE 122(2)):动量多头常常是近期强势股,市场急跌时它们的 beta 会升高,跌幅大于历史波动模型的预期。
- 启示:美股是最成熟的市场,因子仍会在几周内回吐。中低频个人账户避开的是「必须在这几周内加杠杆抢反弹」,保留的是「回撤预算事先写进
docs/risk_policy.md」。
方法论来源¶
| 概念 | 出处 |
|---|---|
| 量化系统的模块结构 | Narang, Inside the Black Box, Wiley, 第 2 版 2013,第 3 版 2024 |
| 信息比率与基本定律 | Grinold (1989), JPM 15(3);Grinold & Kahn, Active Portfolio Management (2000) |
| 三因子模型 | Fama & French (1993), JFE 33(1) |
| 截面动量 | Jegadeesh & Titman (1993), JF 48(1) |
| 盈余公告后漂移 | Bernard & Thomas (1989), JAR 27(1) |
| 指数纳入的价格压力 | Harris & Gurel (1986), JF 41(4) |
| 流动性蒸发与短期反转 | Nagel (2012), RFS 25(7) |
| 套利限制 | Shleifer & Vishny (1997), JF 52(1) |
| 2007 年 8 月 | Khandani & Lo (2011), JFM 14(1) |
| 因子动物园与 t 值门槛 | Harvey, Liu & Zhu (2016), RFS 29(1) |
| 全球因子复制 | Jensen, Kelly & Pedersen (2023), JF 78(5) |
| 机器学习的样本外 R² | Gu, Kelly & Xiu (2020), RFS 33(5) |
| 动量崩溃 | Daniel & Moskowitz (2016), JFE 122(2) |
| 港股印花税 0.1% | 香港《印花税条例》修订,2023-11-17 生效,买卖双方各计 |
| 绩效定义 | 本仓库 src/quant/backtest/metrics.py |
💡 思考回顾与巩固¶
核心认知纠偏¶
| 常见误区 | 反例 | 专业用法 |
|---|---|---|
| 用了 API 自动下单就是量化 | 主观看完图形再让程序下单,决策仍是临场判断 | 先写决策规则,再决定下单是否自动化 |
| 夏普高就可以加杠杆放大收益 | 借款利率 5%、资产夏普 0.533 时,两倍杠杆的夏普降到 0.50;保证金强平还会在低点成交 | 先扣融资利差,再设回撤和保证金约束(M04) |
| 单边换手 50%、成本 15 bps,一年只亏 0.9% | 单边换手 0.5 对应成交额 1.0 倍净值。月度规则的拖累是 2 × 6 × 0.15% = 1.8% | 成本打在每一元成交上,和 metrics.py 的单边定义配套使用 |
| 实验室 CAGR 30% 就是策略的期望 | 动量实验室的股票池是今天的大市值名单,等权基准已有 21.79% 的 CAGR | 只引用相对同一股票池的超额,并在实盘研究里改用时点成分(M03) |
| 信息比率约等于 IC 乘以股票只数 | 100 次独立下注只贡献 √100 = 10;100 只同行业股票不是 100 次独立下注 | 先问独立性,再乘 TC。个人不能做空时 TC 明显小于 1 |
| 回测在收盘价成交,实盘也能成交在那个价格 | 信号若用了当日收盘才算得出来,当日收盘的成交就是前视 | shift(1),或明确写成「次日开盘 / 次日收盘」并扣价差 |
费曼自测¶
用口述回答。写不下来的那一句,就是下一章要补的洞。
- 五模块里,你准备在第一年亲自建造哪几个?省略的模块会在什么行情下先出问题?
- 给家人解释:动量赚钱时,钱是从哪一类参与者那里来的?他们为什么还在卖?
- 为什么港股印花税按买卖双方各 0.1% 计,会直接否决一类美股论文里看起来可行的换手率?
- 三日样本算出夏普 8.14,这个数字哪一步是对的,哪一步不能拿去比较基金?
自测要点
1. 第一年至少要有数据(复权、时点)、一条 Alpha、一个仓位上限、一个成本假设、一张成交记录。可以暂时没有 Barra 风险模型。省略风险模型时,行业和风格集中会在案例 3、案例 4 那种拥挤里先爆;省略成本模型时,日换仓会在实盘第一季就被印花税和价差吃掉。 2. 中期截面动量对应的是反应偏慢的资金:盈利和价格已经变了,委员会和指数基金还没完成调仓。他们卖(或买得不够快)是因为决策流程、跟踪误差约束和职业风险,不是因为没看见价格。这个机制在拥挤和急跌里会暂时反转,所以要有回撤预算。 3. 美股论文里的 5–10 bps 单边成本,到港股要先加上约 10 bps 印花税(每一侧)。月换仓一半,仅印花税的量级就接近本节 15 bps 教学成本的全部。再叠加价差之后,靠微小价差的日频规则没有个人容量。 4. 对的是公式:减了日无风险利率,用了 n − 1,乘了 √252,和仓库代码一致。不能比较基金,是因为 3 个观测的标准差几乎是噪声,年化把噪声放大了 √252。比较用多年的超额收益分布,并报告最大回撤和换手,见 M14。四维习题¶
A. 概念题¶
- 用决策链区分量化投资、程序化交易、高频交易,各举一个港美股账户里真实会发生的例子。
- 画出五模块,标明输入输出,并写上本仓库的一个目录。
- 价值、截面动量、标普纳入、一周反转,各自更接近四类收益来源中的哪一类?指出可能重叠的第二类。
- 解释 IR ≈ TC × IC × √BR 里每一个符号。为什么 BR 不能按持仓只数直接填写?
B. 计算题¶
- 日收益恒为 0.04%,日波动 1%。给出算术年化、CAGR 和年化波动。算术年化与 CAGR 哪一个等于投资者的复利?
- 年化收益 12%,年化波动 15%,无风险利率 4%。计算不融资的夏普。若两倍杠杆、借款利率分别为 4% 和 5%,股权夏普各是多少?
- 单边成本 15 bps。每月单边换手 50%,以及每个交易日单边换手 20%,年化成本拖累各是多少?若改到港股、每一侧另加 10 bps 印花税(佣金和价差仍用 15 bps,即单边总成本 25 bps),月度规则的拖累变成多少?
- IC = 0.03,一年独立下注 36 次,TC = 1 和 TC = 0.4 的信息比率各是多少?
- 净值 100, 110, 105, 90, 95, 120。最大回撤是多少?若从谷值算到下一次新高,修复用了几步(按表中的观测次数,不年化)?
C. 编程实战题¶
- 用 yfinance 下载 SPY、MTUM、VLUE、USMV 自 2015-01-01 起的日收盘价,
auto_adjust=True。计算 CAGR、年化波动、夏普(无风险利率取你写进代码的常数,并在输出里打印这个常数)、最大回撤。信号若要做「过去 21 日动量」,必须shift(1)。把 2022 年全年和 2025-06-01 至 2025-07-22 两个窗口的收益率单独打印出来。不要把某一次运行的数字抄进笔记当成永久事实;把代码、数据截止日期和无风险利率假设一起留下。
D. 个人实战思考题¶
- 写出你过去三笔交易的规则版本。哪一句写不成数据条件?那一句若保留,它将以什么方式破坏回测(前视、不可得数据、还是不可执行)?
- 在「时序 / 截面 / 配置」里选一到两类作为一年内的主攻,并说明富途或 IB 的做空与税费为什么排除了其余类型。
- 如果你持有的是一个「量化超额」产品,事前哪三项公开信息能帮助你识别案例 3 那种风格拥挤?这三项在美股因子 ETF 上分别对应什么?
完整参考答案与解析
**A1.** 量化的例子:每月最后一个交易日,按过去 12 个月扣除最近 1 个月的收益对股票排序,等权持有前 20 名,跌破组合波动目标就降仓。决策在收盘后计算,次日执行。程序化的例子:你盘中决定买入腾讯,让 API 按 TWAP 拆成 10 笔,买卖决策仍是你当天做的。高频的例子:在买卖价差上排队,持仓几秒。个人 API 的延迟和券商收费都使第三种不成立。 **A2.** 数据 → Alpha(预期收益或分数)、风险(协方差或暴露)、成本(每笔拖累)。三者进入组合构建,输出目标权重。执行把目标权重变成订单。归因比较成交后的净值与基准,再返回 Alpha。目录示例:`src/quant/data/`、`src/quant/strategies/`、`src/quant/risk/`、`src/quant/backtest/fees.py`、`src/quant/portfolio/`、`src/quant/execution/`、`src/quant/backtest/report.py`。 **A3.** 价值:主机制是风险补偿(衰退状态赔付差),第二类可以是行为上的过度悲观。截面动量:主机制是反应不足,拥挤之后会叠上「别人被迫平仓」的结构因素。标普纳入:主机制是指数基金的强制买盘。一周反转:主机制是提供流动性,接的是短期冲击;若冲击来自公告,则与行为偏差重叠。重叠要写出来,不能为了填表删掉第二句。 **A4.** IC 是预测和后续残差收益的相关。BR 是独立下注次数。TC 是约束留下的可投资比例。持仓 100 只若受同一个行业因子驱动,残差几乎同步,独立次数远小于 100,根号里应填有效次数。M09 给出更正式的广度定义。 **B5.** 算术年化 0.0004 × 252 = 10.08%。CAGR (1.0004)²⁵² − 1 = 10.6033%。年化波动 0.01 × √252 = 15.8745%。投资者的财富复利由净值之比决定,对应 CAGR。算术年化是日均收益的缩放,用于夏普的分子,不能直接当成「一年后账户多出来的百分比」。本题日收益恒定且为正,所以 CAGR 高于算术年化;收益有波动时,常见情况是 CAGR 低于算术平均(M01)。 **B6.** 不融资:(0.12 − 0.04) / 0.15 = 0.5333。借款 4%、杠杆 2:股权收益 0.24 − 0.04 = 0.20,超额 0.16,波动 0.30,夏普 0.5333。借款 5%:股权收益 0.19,超额 0.15,夏普 0.15/0.30 = 0.500。推导用的是 `R_E = L R_A − (L − 1) r_b`,并假设波动随 L 线性放大、中途不被强平。 **B7.** 月度:年化单边换手 6,拖累 2 × 6 × 0.0015 = 0.018。日度:年化单边换手 50.4,拖累 2 × 50.4 × 0.0015 = 0.1512。港股月度:单边成本 25 bps,拖累 2 × 6 × 0.0025 = 0.030,即 3.0%/年。印花税只是制度摩擦里最硬的一项,价差和冲击还要另估(M13)。 **B8.** √36 = 6。TC = 1 时 IR = 0.03 × 6 = 0.18。TC = 0.4 时 IR = 0.4 × 0.18 = 0.072。0.072 的信息比率在扣成本之前就已经很薄,这类低 IC、又被做空限制削掉一截的信号,不值得日频交易。 **B9.** 峰值路径 100, 110, 110, 110, 110, 120。最大回撤 90/110 − 1 = −18.182%。谷值在第 4 个观测,第 6 个观测创新高,中间隔了 1 个观测(第 5 个),从谷值到新高走过 2 步。这是教学序列的步数,不是交易日修复时间。 **C10.** 参考实现只规定计算契约,不内置某日的行情结果。运行后把打印的 `asof` 和四行指标记到自己的笔记,不要回写进教材。from datetime import date
import numpy as np
import pandas as pd
import yfinance as yf
# 无风险利率是假设,不是模型输出。换一个常数,夏普会变,CAGR 不变。
RF_ANNUAL = 0.04
START = "2015-01-01"
TICKERS = ["SPY", "MTUM", "VLUE", "USMV"]
px = yf.download(TICKERS, start=START, auto_adjust=True, progress=False)["Close"]
px = px.dropna(how="any").sort_index()
# 21 日动量在当日收盘才完整。shift(1) 后,t 日可见的是 t-1 的动量。
mom = px.pct_change(21).shift(1)
ret = px.pct_change().dropna()
years = (len(ret)) / 252.0
cagr = (1.0 + ret).prod() ** (1.0 / years) - 1.0
vol = ret.std(ddof=1) * np.sqrt(252.0)
sharpe = (ret.mean() - RF_ANNUAL / 252.0) / ret.std(ddof=1) * np.sqrt(252.0)
nav = (1.0 + ret).cumprod()
mdd = (nav / nav.cummax() - 1.0).min()
out = pd.DataFrame({"cagr": cagr, "vol": vol, "sharpe": sharpe, "mdd": mdd})
print("asof", date.today(), "rf", RF_ANNUAL)
print(out.round(4))
print("momentum_uses_shifted_signal", bool(mom.iloc[-1].notna().any()))
win_2022 = ret.loc["2022-01-01":"2022-12-31"]
win_2025 = ret.loc["2025-06-01":"2025-07-22"]
print("ret_2022", ((1.0 + win_2022).prod() - 1.0).round(4))
print("ret_2025_summer", ((1.0 + win_2025).prod() - 1.0).round(4))
📌 章节知识总结¶
一句话核心洞察¶
- 规则先回答「对手是谁」,再写代码。答不出对手的回测,先去 M08,不加杠杆。
- 个人主战场是港美股的中低频。印花税、借券和收盘价不可成交,会在公式之外删掉一整类策略。
- 夏普用超额收益;杠杆在借款利率等于无风险利率时不改变夏普,融资利差和强平会把它变差。
- 成本打在全部成交额上。月换仓一半、单边 15 bps,年化拖累是 1.8%,日换仓 20% 则是 15.12%。
- 广度在根号里,而且要独立。教学实验室的高 CAGR 必须和同一股票池的基准一起读,并声明幸存者偏差。
公式与参数速查¶
| 名称 | 表达式 | 本章使用的前提 |
|---|---|---|
| 简单 / 对数收益 | R = Pₜ/Pₜ₋₁ − 1,r = ln(1 + R) | 净值用简单收益连乘 |
| CAGR | (V_T/V₀)^(1/Y) − 1,Y = N/252 |
净值始终为正 |
| 年化波动 | s √252,s 分母 n − 1 | 日收益弱自相关;否则见 M01 |
| 夏普 | (¯R − r_f/252) / s · √252 |
与 metrics.py 一致;短样本只做算术核对 |
| 杠杆后股权收益 | L R_A − (L − 1) r_b |
未被强平,波动按 L 放大 |
| 最大回撤 | min(Vₜ / max_(s≤t) Vₛ − 1) |
峰值到谷值,创新高不清零历史 |
| 成本拖累 | 2τ_单边 c |
τ 是成交额的一半;c 是每一元成交 |
| 教学成本 | c = 15 bps | 美股大盘月频的数量级,不是券商合同 |
| 港股印花税 | 买卖各方 0.1% | 2023-11-17 起,以 GovHK 现行税率复核 |
| 基本定律 | IR ≈ TC · IC · √BR | 独立性不满足时不要代入持仓只数 |
| 月频 IC 的直觉量级 | 百分之几 | 0.05 已经不低;经济价值看 IR 和成本之后 |
| t 值观察门槛 | 约 3 | Harvey, Liu & Zhu (2016) 的建议,证明在 M08 |
跨模块联结¶
| 本章结论 | 下游 | 工程落点 |
|---|---|---|
| 决策规则与下单分离 | M02 写范式,M15 写券商适配 | src/quant/strategies/ 不直接发单;发单在 src/quant/execution/ |
| 复权、时点、shift(1) | M03 | src/quant/data/、回测引擎的成交时点 |
| 成本用单边换手的两倍 | M13 | src/quant/backtest/fees.py、src/quant/research/costs.py |
| 杠杆和回撤预算 | M04 | docs/risk_policy.md、src/quant/risk/ |
| IC、BR、TC | M09、M10 | 研究评估 src/quant/research/evaluate.py |
| 实验室净值不可外推 | M08 | knowledge/Labs/momentum_lab/README.md 第五节 |
学习指引¶
- 精读:黑箱第 1–2 章建立模块地图,第 11 章把批评变成流程。配合 读书笔记,笔记只复述论证结构,推导以本章公式为准。
- 对照:陈第 1 章、第 8 章,看个人投资者为什么把容量和低换手放在技术指标之前。笔记在 chan_qt/ch01_08_map.md。
- 延伸:Khandani & Lo (2011) 的 2007 年复盘;Zuckerman (2019) 用来建立容量直觉,不用来设定收益目标。
- 下一步:进入 M02 交易策略范式。年化、t 检验、自相关在 M01 按需回查。
自检清单¶
- 能默画五模块,并指出一个仓库目录
- 能给四类收益来源各举一篇论文
- 手算过 1.8% 与 15.12% 两档成本,知道 2 从何而来
- 能说明两倍杠杆、借款 5% 时夏普为何变成 0.50
- 能讲清 2007 年 8 月或 2025 年夏季其中一条传导链
- 编程题留下了数据截止日期,没有把单次下载结果写死
- 读实验室净值时能复述幸存者偏差和「相对同池基准」


