docs: sync xquant tutorial updates

This commit is contained in:
xingwudao
2026-06-21 23:17:19 +08:00
parent a0d05d966f
commit c1a6decc56
25 changed files with 1955 additions and 2214 deletions
+154 -170
View File
@@ -1,96 +1,94 @@
# 第三章:给 ETF 分钱3 种分法实测
# 第 3 章:决定各买多少3 种分法实测
章我们从全市场几千标的中,一步步筛选出了三只 ETF——沪深300、纳指100、黄金,构建了自己的投资宇宙。选标的的问题解决了,但紧接着一个新问题摆在面前:三只 ETF,各买多少?
2 章我们从全市场几千标的中,一步步筛选出了三只 ETF沪深 300、纳指 100、黄金,构建了自己的标的池。选资产的问题解决了,但紧接着一个新问题摆在面前:三只 ETF,各买多少?
这听起来像个分钱小问题——平均分一下不就完了吗?别急着下这个结论。同样三只 ETF、同一段历史,**只是分法不同,累计收益能差 1 倍以上、最大回撤能差三分之一**:等权 80%、风险平价 100%、动量排名 180%;回撤从 -16% 到 -12% 又到 -15%。“买什么决定了你站在哪条赛道上,**“买多少决定了赛道上你能不能跑下去**——这就是为什么一整章都解决这个问题。
这听起来像个分钱小问题平均分一下不就完了吗?别急着下这个结论。同样三只 ETF、同一段历史,只是分法不同,本章这段历史数据里的累计收益确实差出 1 倍以上。买什么决定你参与哪些市场;买多少决定每个市场对账户的影响有多大。这就是为什么一整章都解决这个问题。
### 路线图
我们正在走一条完整的策略构建之路:
本章进入四个阶段里的**制定规则**阶段。本章分三步探索三种分钱方式,每节做 1 次实验,最后你来判断哪种更合理。全章一共要动手做 3 次实验。
**选什么标的(第二章 已完成)→ 每个买多少(第三章 本章)→ 什么时候买卖(第四章)→ 怎么验证有效(第五章)**
**表 3-1 第 3 章路线图**
**这一章你在飞轮的“组合层”,主练“做”——把“各买多少”从凭感觉变成有据可依的规则。** 本章解决“买多少”,分三步探索三种分钱方式,最后你来判断哪种更合理。三节分别对应的方法如表 3-1 所示。
**表 3-1 第三章三节问题与方法对照**
| 节 | 问题 | 方法 |
| 节 | 内容 | 实验 |
|----|------|------|
| 3.1 | 最简单的回答:各买三分之一 | 等权 |
| 3.2 | 波动大的少买点,波动小的多买点 | 风险平价 |
| 3.3 | 涨得好的多买点,跌的别买 | 动量排名 |
(操作流程见前言“怎么使用这本书”。每一节按相同流程:阅读 → 复制 spec 给 AI → 看结果与解读。)
| 3.1 | 最简单的回答:各买三分之一 | 1 |
| 3.2 | 波动大的少买点,波动小的多买点 | 1 |
| 3.3 | 涨得好的多买点,跌的别买 | 1 |
---
## 3.1 最简单的回答:各买三分之一
三只 ETF,各买多少?最自然的回答:平均分,每只买三分之一。不偏不倚,公平合理。毕竟,如果你不确定哪只会涨得更好,平均分至少不会犯大错——对吧?
三只 ETF,各买多少?最自然的回答:平均分,每只买三分之一。不偏不倚,公平合理。毕竟,如果你不确定哪只会涨得更好,平均分至少不会犯大错对吧?
我们来验证一下这个直觉。
### 动手实验 1:等权组合回测
这个实验用到 open-xquant 的几个模块:`EqualWeightOptimizer`等权优化器——把钱平均分)、`Engine`(回测引擎——模拟历史买卖)、`SimBroker`(模拟券商)。你不需要了解它们的代码,spec 会告诉 AI 怎么用。
这个实验用到 open-xquant 的几个模块:`EqualWeightOptimizer`(把钱平均分的组合优化器)、`Engine`(回测引擎模拟历史买卖)、`SimBroker`(模拟券商)。你不需要了解它们的代码,spec 会告诉 AI 怎么用。
我们一起把这份 spec 写出来。这次重点看三件新东西:**oxq 模块的“先读后写”**、**权重和=1.0 的关键断言**、**跨市场组合的共同交易日处理**。
我们一起把这份 spec 写出来。这次重点看三件新东西:**oxq 模块的“先读后写”**、**权重和 = 1.0 的关键断言**、**将多只资产的交易日对齐**。
#### 起草上下文 + 任务
#### 第一、二段:上下文和任务描述
这是 q3 的第一份 spec,直接接续第二章——三只 ETF 已经选好了,现在只关心权重。两段都很短:
这是 q3 的第一份 spec,直接接续第 2 章。三只 ETF 已经选好了,现在只关心权重。上下文说前提,任务描述说要做什么,两段都很短:
> **上下文**:第章选好了 3 只 ETF(沪深300、纳指100、黄金),现在要回答:每只各买多少?
> **上下文**:第 2 章选好了 3 只 ETF(沪深 300、纳指 100、黄金),现在要回答:每只各买多少?
>
> **任务**:在 notebook `q3-how-much.ipynb` 中创建代码,跑等权组合回测,并展示三只 ETF 各自的表现差异。
> **任务描述**:在 notebook `q3-how-much.ipynb` 中创建代码,跑等权组合回测,并展示三只 ETF 各自的表现差异。
#### 起草要求
#### 第三段:任务要求
q3 起 open-xquant 框架正式上场。spec 主体的第一件事不是写代码,而是要求 AI 先读源码——这样它调的是真实接口,不会用过时或编造的写法。
spec 主体的第一件事不是写代码,而是要求 AI 先读源码这样它调的是真实接口,不会用过时或编造的写法。
> **要求**
> **任务要求**
>
> 1. 阅读以下 oxq 模块的源码(按用途分四组):
> - 引擎与策略:`oxq.core.Engine` / `Strategy`
> - 数据:`oxq.data.YFinanceDownloader` / `LocalMarketDataProvider`
> - 仓位优化`oxq.portfolio.optimizers.EqualWeightOptimizer`
> - 权重分配`oxq.portfolio.optimizers.EqualWeightOptimizer`
> - 信号、指标、规则:`oxq.signals.Threshold` / `oxq.indicators.RollingVolatility` / `oxq.rules.RebalanceFrequencyRule` / `oxq.universe.StaticUniverse` / `oxq.trade.SimBroker`
> 2. 下载 3 只 ETF`SYMBOLS = ("510300.SS", "513100.SS", "518880.SS")`,起 `2021-01-01`)。
> 3. 计算共同交易日:中美交易日历不同步,要把三只 ETF 的索引取交集,后续所有图都用这对齐索引
> 4. 用 `EqualWeightOptimizer` + `Threshold` 信号(column=close, threshold=0, relationship=gt)组装策略,再平衡 `RebalanceFrequencyRule(interval_days=10)`。
> 3. 计算共同交易日:把三只 ETF 的索引取交集,后续所有图都用这对齐后的日期
> 4. 用 `EqualWeightOptimizer` + `Threshold` 信号(column="close", threshold=0, relationship="gt")组装策略,再平衡 `RebalanceFrequencyRule(interval_days=10)`。
> 📌 **要点**跨市场组合必须显式处理共同交易日。沪深300 走 A 股日历,纳指100 走美股日历,圣诞节美股休市但 A 股开市,反过来春节 A 股休市但美股开市。**spec 不点名,AI 大概率不会想到这一步**——画出来的净值曲线会是锯齿状。这是 q3 起跨市场章节的领域必备配置块,跟 q1 的字体三选一一样,要写进 spec
> 📌 **要点**多只资产放在一起比较时,先要把日期对齐。即使三只 ETF 都在 A 股市场交易,历史数据也可能出现个别缺失日。spec 要求先取共同交易日,是为了让三条净值曲线站在同一组日期上比较,避免图表因为日期不齐而产生误导
#### 起草结果呈现
#### 第四段:验收标准
结果呈现段把权重检查、对比表、净值曲线一次锁死,让 AI 输出可以直接对照书里的图表。
验收标准段把权重检查、对比表、净值曲线一次锁死,让 AI 输出可以直接对照书里的图表。
> **结果呈现**
> **验收标准**
>
> 1. **权重合法性检查**`weights = ew_weights_df.iloc[-1]; assert abs(weights.sum() - 1.0) < 1e-6, f"权重和应为 1.0,实际 {weights.sum()}"; assert (weights >= 0).all(), "等权权重不应为负"`。
> 2. 打印权重分配 + 10 万元换算(每只约 33,333 元)。
> 3. 打印 4 行对比表:沪深300 / 纳指100 / 黄金 / 等权组合,三列指标(累计收益率、年化波动率、最大回撤)。
> 4. 净值曲线图:3 条灰色线(用 `--` / `:` / `-.` 三种线型区分单只持有)+ 1 条蓝色实线加粗(等权组合),归一化到 100,标题「各买三分之一:等权组合 vs 单只持有」。
> 3. 打印 4 行对比表:沪深 300 / 纳指 100 / 黄金 / 等权组合,三列指标(累计收益率、年化波动率、最大回撤)。
> 4. 净值曲线图:3 条灰色线(用 `--` / `:` / `-.` 三种线型区分单只持有)+ 1 条蓝色实线加粗(等权组合),统一从 100 开始,标题「各买三分之一:等权组合 vs 单只持有」。
> 📌 **要点**仓位分配 spec 的**必查**断言是「权重和 = 1.0 ± 1e-6」。这条 assert 在 q1 单标的策略里不需要只有一个标的,要么买要么不买),但只要进入“分钱”场景,这条就必须有。**没有这条断言,AI 输出 0.998 或 1.003 你都会以为正常**——但下游回测会按这个权重直接乘资金,误差会一路传到最后的收益率。三个 spec 都要复用这条模板。
> 📌 **要点**权重分配 spec 里必须写清一个验收标准:「权重和 = 1.0 ± 1e-6」。这在第 1 章那种单资产策略里不需要只有一个资产时,要么买要么不买但只要进入“分钱”场景,这条就必须有。没有这条断言,AI 输出 0.998 或 1.003 你可能都会以为正常下游回测会按这个权重直接乘资金,误差会一路传到最后的收益率。三个 spec 都要复用这条模板。
完整 spec 在 [`specs/spec-01-equal-weight.md`](https://github.com/xingwudao/xquant-learning/blob/main/q3-how-much/specs/spec-01-equal-weight.md)——复制给 AI,弹窗选「允许」
完整示例 spec 在配套仓库的 [`q3-how-much/specs/spec-01-equal-weight.md`](https://github.com/xingwudao/xquant-learning/blob/main/q3-how-much/specs/spec-01-equal-weight.md)。参考它确认自己的 spec 后,再复制给 AI,按提示允许执行
AI 助手执行完毕后,你的 notebook 里应该出现了一组权重数字、一张对比表和一张净值图。我们先认识两个新概念。
AI 执行完毕后,你的 notebook 里应该出现了一组权重数字、一张对比表和一张净值图。我们先认识两个新概念。
**权重(Weight** ——“这笔钱怎么分”,每只标的分到总资金的百分之多少。你有 10 万元,三只 ETF 各 1/3 权重,就是每只买 33,333 元。权重就像分蛋糕——蛋糕总共 100%,每人分多少取决于权重。
**权重(Weight**:回答“每个标的分总资金的多少比例”。每个标的分到总资金的百分之多少,就是它的权重。你有 10 万元,三只 ETF 各 1/3 权重,就是每只买 33,333 元。
**信号(Signal** ——根据指标对市场做出的判断:要不要动、怎么动。信号只表达意愿,不负责执行。第一章的 Crossover 信号说的是“买还是不买”——价格上穿均线就买、下穿就卖。这里的 EqualWeightOptimizer 说的是“各买多少”——三只 ETF 各 1/3。判断的内容升级了,但本质都是信号:观察市场、做出判断。至于判断之后怎么执行——下多少单、什么价格成交——那是后面的事。
**权重分配方法**:回答“按照什么逻辑分配资金”。等权分配就是一种最简单的权重分配方法:不看涨跌,不看波动,三只 ETF 各 1/3。权重分配方法有很多,后面也可以看到不同的分配方式。至于目标权重之后怎么变成真实订单、什么价格成交,那是第 7 章要处理的事。
回测中设定了每 10 个交易日(大约两周)重新调整一次持仓,让实际权重回到目标权重。为什么需要再平衡?因为三只 ETF 涨跌幅不同,持有一段时间后,涨得多的那只实际占比会变大,偏离了最初的 1/3。再平衡就是定期“拨乱反正”
在量化领域,在一起参与分配资金的一组标的,叫做**组合(Portfolio)**。组合不是简单的候选名单。第 2 章选出的标的池,是策略允许考虑的范围,是候选大名单;第 3 章要做的,是从这个大名单里给每只标的分配资金。按规则算出来的配置资金比例,叫**目标权重(Target Weight**
目标权重只是理想资金比例。账户里真正持有的标的和份额数量,叫**持仓(Position)**;这些持仓按市值算出来的比例,才是**实际权重**。即使一开始完全按目标权重买入,后面标的价格也会涨跌,实际权重会慢慢偏离目标权重。因此,过一段时间就要重新调整持仓,让实际权重重新接近目标权重。这个过程叫**再平衡(Rebalancing**。
标的池里的标的,不是每次都一定能分到钱。有些标的的权重可能是 0,极端情况下,所有标的的权重都可能是 0。这时可以把现金(CASH)也视为组合成员,现金获得 100% 权重,意味着账户里暂时不持有任何标的。
### 实验结果
等权就是等,三只各占三分之一,每只买 33,333 元。但等分钱之后跑出来的效果如何?三只 ETF 单独持有与等权组合的对比如表 3-2 所示。
等权就是强制让资产的权重相等,三只各占三分之一,每只买 33,333 元。这种平均分资金的方式,效果如何?三只 ETF 单独持有与等权组合的对比如表 3-2 所示。
**表 3-2 三只 ETF 单独持有 vs 等权组合表现**
| 标的 | 累计收益率 | 年化波动率 | 最大回撤 |
| ETF | 累计收益率 | 年化波动率 | 最大回撤 |
|------|-----------|-----------|---------|
| 沪深300ETF | -1.78% | 18.11% | -42.16% |
| 纳指100ETF | 106.09% | 22.66% | -27.50% |
@@ -103,87 +101,85 @@ AI 助手执行完毕后,你的 notebook 里应该出现了一组权重数字
### 读懂这些结果
先看图 3-1 的大趋势:等权组合那条蓝色实线,稳稳地走在三条灰色线之间——不是最好的,也不是最差的。黄金一路领涨,纳指100先跌后涨、波折不断,沪深300整体低迷。组合把三者的表现“平均”了一下,走出了一条居中的路线。
先看图 3-1 的大趋势:等权组合那条蓝色实线,走在三条灰色线之间。它不是最好的,也不是最差的。黄金一路领涨,纳指 100 先跌后涨、波折不断,沪深 300 整体低迷。组合把三者的表现“平均”了一下,走出了一条居中的路线。
但你可能已经注意到了:黄金单独拿的累计收益率是 188.54%,比等权组合的 80.75% 高了一倍多。那为什么不全买黄金?
看波动率那列。**年化波动率(Annualized Volatility** 衡量的是价格上下波动的剧烈程度——第二章我们认识过这个指标。波动率大意味着你的账户大起大落:今天涨 3%、明天跌 4%,反复折腾。现实中大部分人受不了这种颠簸——涨的时候开心,连跌几天就开始怀疑“是不是该卖了”,一卖可能就错过后面的反弹。**波动率小,意味着你能在低点不慌、在涨中不慌——账户里看着一时少了 5%、10%,你不会马上卖掉。** 不慌,才能真正拿到那段收益。
看波动率那列。**年化波动率(Annualized Volatility** 衡量的是价格上下波动的剧烈程度。第 2 章我们认识过这个指标。波动率大意味着你的账户大起大落:今天涨 3%、明天跌 4%,反复折腾。现实中大部分人受不了这种颠簸涨的时候开心,连跌几天就开始怀疑“是不是该卖了”,一卖可能就错过后面的反弹。**波动率小,意味着你能在低点不慌、在涨中不慌。** 账户里一时少了 5%、10%,你不会马上卖掉。不慌,才能真正拿到那段收益。
再看一个更关键的问题。三只 ETF 的年化波动率从 15.83%(黄金)到 22.66%(纳指100),差了好几个百分点。但等权信号说“不管你多颠簸,都买一样多的钱”。想想这意味着什么波动最大的纳指100,虽然只花了 1/3 的钱,但它每天的涨跌幅度最大,对组合整体的影响也最大——它一跌,组合就被拖着跌;它一涨,组合的涨幅也主要靠它撑着。**平均分钱,并不等于平均分影响力。** 波动大的那只,用同样的钱产生了更大的影响力,**拉着整个组合的涨跌走**
再看一个更关键的问题。三只 ETF 的年化波动率从 15.83%(黄金)到 22.66%(纳指 100),差了好几个百分点。但等权方法说:“不管你多颠簸,都买一样多的钱”这意味着什么波动最大的纳指 100,虽然只花了 1/3 的钱,但它每天的涨跌幅度最大,对组合整体的影响也最大它一跌,组合就被拖着跌;它一涨,组合的涨幅也主要靠它撑着。**每个标的拿一样多的资金,并不等于它造成的波动也一样。** 波动大的那只,用同样的钱产生了更大的影响力,拉着整个组合的涨跌走。
有没有更聪明的分法?比如,波动大的少买点,波动小的多买点——让每只 ETF 对组合的“影响力”真正平均
有没有更合理的分法?比如,波动大的少买点,波动小的多买点让每只 ETF 对组合的“影响力”更接近
---
## 3.2 波动大的少买点,波动小的多买点
上一节的结论很清楚:平均分钱,并不等于平均分影响力。波动大的纳指100,用同样的钱却产生了更大的影响力,把整个组合的涨跌拉着走。那反过来想——既然波动大的影响力太大,能不能给它少分点钱?波动小的那只影响力不够,多分点钱给它?这样三只 ETF 对组合的“拉扯力度”应该更均匀。
上一节的结论很清楚:平均分钱,并不等于平均分影响力。波动大的纳指 100,用同样的钱却产生了更大的影响力,把整个组合的涨跌拉着走。那反过来想既然波动大的影响力太大,能不能给它少分点钱?波动小的那只影响力不够,能不能多分点钱给它?这样三只 ETF 对组合的“拉扯力度”应该更均匀。
这种“按波动率倒数分配权重、让每个资产对组合波动的贡献相等”的方法,有一个正式的名字:**风险平价(Risk Parity** ——“风险”指的是波动率,“平价”指的是让每个资产的风险贡献相等。让每个资产对组合波动的贡献相等——就像把三个发动机的功率调到一样大,整个组合不会被某一个拖着走。桥水基金的“全天候策略”用的就是这个思路。下面我们用一个生活化的类比直接走进它。
这种“按波动率倒数分配权重”的方法,有一个正式的名字:**风险平价(Risk Parity**。本章用的是简化版风险平价:波动大的少买,波动小的多买,让每只标的对组合的影响更均匀。你可以把它想成把三个发动机的功率调到接近,整个组合就不容易被某一个拖着走。
想象你要把一笔钱交给三个人帮你打理。第一个人成熟稳重,赚了不炫亏了不慌,你看着他的账户心里很踏实;第二个人喜怒无常,今天信心爆棚明天就想清仓,你的心跟着他上上下下;第三个人介于两者之间。你会怎么分钱?肯定是稳重的那个多管点,情绪的那个少管点。三只 ETF 也一样——波动率就是它们的“情绪起伏程度”。波动小的稳重,多买;波动大的情绪化,少买。
想象你要把一笔钱交给三个人帮你打理。第一个人成熟稳重,赚了不炫耀,亏了不慌,你看着他的账户心里很踏实;第二个人情绪起伏大,今天信心很足,明天就想清仓;第三个人介于两者之间。你会怎么分钱?大概率会让稳重的那个多管点,情绪起伏大的那个少管点。三只 ETF 也一样波动率就是它们的“情绪起伏程度”。波动小的稳重,多买;波动大的起伏大,少买。
### 动手实验 2:风险平价组合回测
我们一起把这份 spec 写出来。这次重点看两件新东西:**signal.required_indicators 在信号上挂指标**、**差量式 spec 让差异点单点暴露**。
我们一起把这份 spec 写出来。这次重点看两件新东西:**`signal.required_indicators` 在信号上挂指标**、**公共配置复用,只改差异点**。
#### 起草上下文 + 任务
#### 第一、二段:上下文和任务描述
这是 q3 的第二份 spec,接续 spec-01 的等权回测结果。上下文一句话承接,任务一句话点明:
> **上下文**:在 `q3-how-much.ipynb` 中已有等权组合回测结果。学员已看到三只 ETF 波动率差异很大,等权分配让波动大的 ETF 主导了组合涨跌。当前问题:能不能按波动来分——波动大的少买,波动小的多买?
> **上下文**:在 `q3-how-much.ipynb` 中已有等权组合回测结果。读者已看到三只 ETF 波动率差异很大,等权分配让波动大的 ETF 主导了组合涨跌。当前问题:能不能按波动来分波动大的少买,波动小的多买?
>
> **任务**:在 notebook 中新建代码单元格,用风险平价信号运行回测,对比等权组合。
> **任务描述**:在 notebook 中新建代码单元格,用风险平价权重分配方法运行回测,对比等权组合。
#### 起草要求
#### 第三段:任务要求
风险平价要用波动率,但波动率是怎么传给优化器的?oxq 的做法是**在信号上挂指标依赖**——这是 oxq 框架的关键模式,把指标声明和信号绑在一起,再把公共配置抽出做成对照实验:
风险平价要用波动率,这就要定义波动率指标,并且要使用 oxq 提供的接口告诉风险平价这个权重分配模块,使用这个指标。
> **要求**
> **任务要求**
>
> 1. 阅读 `oxq.portfolio.optimizers.RiskParityOptimizer`(若 spec-01 未读 `Threshold`,补一下)。
> 2. 在 `Threshold` 信号上注册 vol 指标:`signal_rp.required_indicators = {"vol": (RollingVolatility(), {"column": "close", "period": 20})}`。这样回测引擎跑到信号时会自动算 vol 列,优化器再读这一列分配权重。
> 3. 用 `RiskParityOptimizer(volatility_col="vol")` 装配优化器,打印最新一天与等权权重的对比 + 10 万元换算。
> 4. 抽出公共配置 `COMMON = dict(universe=universe, ...)`,让等权和风险平价两个策略只在 `portfolio` 一行不同——`Strategy(name="equal-weight", **COMMON, portfolio=EqualWeightOptimizer())` vs `Strategy(name="risk-parity", **COMMON, portfolio=RiskParityOptimizer(...))`。
> 4. 抽出公共配置 `COMMON = dict(universe=universe, ...)`,让等权和风险平价两个策略只在 `portfolio` 一行不同`Strategy(name="equal-weight", **COMMON, portfolio=EqualWeightOptimizer())` vs `Strategy(name="risk-parity", **COMMON, portfolio=RiskParityOptimizer(...))`。
> 📌 **要点**oxq 用 `signal.required_indicators` 把“信号需要哪些指标”声明在信号本身上——q3 三个 spec 都依赖这条语法。**spec 要给到具体写法**(“在信号上注册”+ 字典字面量),AI 才能照抄;只写描述,它要么抄到 strategy 上,要么挂到 universe 上,接口对不上就报错。同样的精确度还体现在 COMMON 字典的设计上:把公共部分抽出来,让等权与风险平价的唯一差异落在 portfolio 一行——这是仓位分配章三联 spec 的主线设计,**写了 COMMON 就要兑现**,否则这条教学就失效
> 📌 **要点**这里的 `signal.required_indicators` 是 open-xquant 的代码入口,用来告诉回测引擎:先算出 vol 指标,再让风险平价方法读取 vol 来分配权重。读者不需要记接口细节,但 spec 要把“风险平价依赖波动率”这件事写清楚
#### 起草结果呈现
#### 第四段:验收标准
这一段把“权重检查 + 视觉契约”两件事一起锁——分析话术按实际数据走向描述,避免提前替结果下定义
这一段把“权重检查 + 图表要求”两件事一起
> **结果呈现**
> **验收标准**
>
> 1. **权重检查**:复用 spec-01 的 assert 模板,加一条`assert rp_w.nunique() > 1, "风险平价权重不应全相等(否则退化为等权)"`。
> 2. 权重对比表 + 10 万元换算 + 指标对比表。
> 3. 净值曲线对比图(figsize 12×6,等权灰虚 + 风险平价蓝实) + 权重历史堆叠面积图(figsize 12×4,展示三只 ETF 权重随时间变化)。
> 4. 末尾分析话术按数据动态描述方向(若波动率反升说明 vol 估计期偏短,不要硬写“降到”)。
> 4. 末尾分析文字按数据动态描述方向(若波动率反升说明 vol 估计期偏短,不要硬写“降到”)。
> 📌 **要点**仓位分配章的标志可视化是**权重历史堆叠面积图**——它让学员一眼看到“权重不是一成不变的”。等权下三条带等宽,风险平价下面积带宽随时间变化。spec 必须明确画这张图,figsize 12×4,堆叠面积,y 轴 0-1。这是 q3 起会反复出现的视觉模板。
> 📌 **要点**权重分配可视化采用了**权重历史堆叠面积图**。它让人一眼看到“权重不是一成不变的”。等权下三条带等宽,风险平价下面积带宽随时间变化。
完整 spec 在 [`specs/spec-02-risk-parity.md`](https://github.com/xingwudao/xquant-learning/blob/main/q3-how-much/specs/spec-02-risk-parity.md)——复制给 AI,弹窗选「允许」
完整示例 spec 在配套仓库的 [`q3-how-much/specs/spec-02-risk-parity.md`](https://github.com/xingwudao/xquant-learning/blob/main/q3-how-much/specs/spec-02-risk-parity.md)。参考它确认自己的 spec 后,再复制给 AI,按提示允许执行
AI 助手执行完毕后,你的 notebook 里应该出现了新的权重数字、一张对比表、两张图。
AI 执行完毕后,你的 notebook 里应该出现了新的权重数字、一张对比表、两张图。
风险平价信号的用法和 3.1 的等权信号完全一样——只是换了一个信号类,其余不变。但钱真的分得不一样了:等权是三等分,风险平价则是波动小的多分、波动大的少分。同样 10 万元,沪深300ETF 从 33,333 元涨到了 45,510 元,黄金ETF 从 33,333 元降到了 11,239 元。
风险平价法和 3.1 的等权方法用法相似,只是换了 `portfolio` 里的权重分配方法,其余不变。但钱真的分得不一样了:等权是三等分,风险平价则是波动小的多分、波动大的少分。同样 10 万元,沪深 300ETF 从 33,333 元涨到了 45,510 元,黄金 ETF 从 33,333 元降到了 11,239 元。
策略组装和上一节几乎一模一样——整个策略定义只有组合优化器那一行不同,从 `EqualWeightOptimizer()` 换成 `RiskParityOptimizer()`。其余的投资宇宙、信号、指标、再平衡频率、回测引擎全部复用。当框架搭好之后,换一种“分钱方式”就只是换一个优化器
策略组装和上一节几乎一模一样整个策略定义只有 `portfolio` 那一行不同,从 `EqualWeightOptimizer()` 换成 `RiskParityOptimizer()`。其余的全部复用。当框架搭好之后,换一种“分钱方式”就只是换一个权重分配方法
### 实验结果
两种方案的权重对比如表 3-3 所示。
一个细节先点透:表 3-3 的权重按**最近 20 天的滚动波动率**算,与表 3-2 那行**全期年化波动率**不是同一组数字——短期与长期波动可以差很多。
两种方案的权重对比如表 3-3 所示。这里有一个细节:表 3-3 的权重按**最近 20 天的滚动波动率**算,与表 3-2 那行**全期年化波动率**不是同一组数字。这两个指标反映的是短期波动与长期波动。
**表 3-3 等权 vs 风险平价权重对比**
| 标的 | 等权权重 | 风险平价权重 |
| ETF | 等权权重 | 风险平价权重 |
|------|---------|------------|
| 沪深300ETF | 33.3% | 45.5% |
| 纳指100ETF | 33.3% | 43.3% |
| 黄金ETF | 33.3% | 11.2% |
指标层面,两种方案的差异如表 3-4 所示。
指标,两种方案的差异如表 3-4 所示。
**表 3-4 等权 vs 风险平价指标对比**
@@ -201,100 +197,98 @@ AI 助手执行完毕后,你的 notebook 里应该出现了新的权重数字
### 读懂这些结果
先看图 3-2 的净值曲线。蓝色实线(风险平价)走得比灰色虚线(等权)更平滑,而且终点更高——风险平价不仅更稳,还赚得更多。
先看图 3-2 的净值曲线。蓝色实线(风险平价)走得比灰色虚线(等权)更平滑,而且终点更高。这说明,风险平价不仅更稳,还赚得更多。
再看指标表里的数字。波动率从 11.73% 降到 10.81%,最大回撤从 -16.79% 收窄到 -12.26%——最惨的时候少跌了 4.5 个百分点。收益率反而更高了(80.75% → 99.67%——波动小了,收益没丢,甚至更好。这不是巧合:波动小意味着你更容易在低点不慌,不会在大跌时恐慌卖出,反而能享受到后面的反弹
再看指标表里的数字。波动率从 11.73% 降到 10.81%,最大回撤从 -16.79% 收窄到 -12.26%最惨的时候少跌了 4.5 个百分点。收益率反而更高了(80.75% → 99.67%。在这段数据里,按波动调整不仅降低了波动,也保住了收益。对真实投资者来说,波动小还有一个好处:更容易坐得住,因此也许更能享受到后面的涨势
最后看图 3-3 的权重历史。你会发现一个有意思的现象:三只 ETF 的权重不是固定的,而是随时间在动态调整。某段时间黄金ETF 波动率飙升,它分到的钱就自动减少;某段时间沪深300ETF 变得平稳了,它分到的钱就自动增加。这就是节首讲的“按波动率倒数分配”在跑——市场自己在告诉你谁该多买谁该少买,你不用做任何主观判断。
最后看图 3-3 的权重历史。你会发现一个有意思的现象:三只 ETF 的权重不是固定的,而是随时间在动态调整。某段时间黄金 ETF 波动率飙升,它分到的钱就自动减少;某段时间沪深 300ETF 变得平稳了,它分到的钱就自动增加。这就是节首讲的“按波动率倒数分配”在跑。市场数据在告诉你谁该多买谁该少买,你不用做主观判断。
风险平价比等权更稳了。但你有没有注意到,它只看波动率,完全不看涨跌。如果一只 ETF 正在涨,风险平价不会多买它;如果一只正在跌,也不会少买它。能不能更贪心一点——让涨得好的多买点?
风险平价比等权更稳了。但你有没有注意到,它只看波动率,完全不看涨跌。如果一只 ETF 正在快速上涨,风险平价不会多买它;如果一只正在跌,也不会少买它。能不能更强调上涨趋势,让涨得好的多买点?
---
## 3.3 涨得好的多买点,跌的别买
风险平价让组合更稳了,但回头想想,它的判断标准只有一个——波动率。波动大的少买,波动小的多买,仅此而已。至于一只 ETF 是在涨还是在跌?它完全不关心。黄金如果正在涨,风险平价不会因此多买一分钱;沪深300如果正在跌,它也不会少买一分钱。它只看颠簸程度,不看方向。
风险平价让组合更稳了,但回头想想,它的判断标准只有一个波动率。波动大的少买,波动小的多买,仅此而已。至于一只 ETF 是在涨还是在跌?它完全不关心。黄金如果正在快速上涨,风险平价不会因此多买一分钱;沪深 300 如果正在明显下跌,它也不会少买一分钱。它只看颠簸程度,不看方向。
那能不能更进一点:涨得好的多买,跌的干脆不买?
还记得第二章我们提过几种交易方式吗?其中一种叫趋势交易——跟着涨势走。动量排名就是趋势交易思想的量化表达:过去一段时间涨得猛的,我认为它还会继续涨,多买;跌的,我认为它还会继续跌,不买。简单粗暴,但逻辑清晰。
那能不能更进一点:涨得好的多买,跌的干脆不买?我们可以借鉴一种交易思想:趋势交易。顾名思义,也就是跟着涨势走。动量排名就是趋势交易思想的量化表达:过去一段时间涨得好的,我认为它可能继续上涨,多买;过去一段时间下跌的,我认为它可能继续走弱,不买。
### 动手实验 3:动量排名组合回测
我们一起把这份 spec 写出来。这次重点看两件新东西:**多指标依赖链mom + vol → ram**、**排序型 spec 的过滤后归一化**。
我们一起把这份 spec 写出来。这次重点看两件新东西:**多指标依赖链**、**过滤后重新把权重分到 100%**。
#### 起草上下文 + 任务
#### 第一、二段:上下文和任务描述
这是 q3 三联 spec 的最后一份,从“加权(永远全持有)”跃迁到“排序(动量为负的不买”。上下文 + 任务一气呵成:
这是 q3 三联 spec 的最后一份,从“始终持有全部 ETF”走到“动量为负的不买”。上下文 + 任务一气呵成:
> **上下文**:在 `q3-how-much.ipynb` 中已有等权组合和风险平价组合的回测结果。学员已理解:等权不看任何指标,风险平价只看波动率。当前问题:风险平价更稳了,但它完全不看涨跌。能不能让涨得好的多买点?
> **上下文**:在 `q3-how-much.ipynb` 中已有等权组合和风险平价组合的回测结果。读者已理解:等权不看任何指标,风险平价只看波动率。当前问题:风险平价更稳了,但它完全不看涨跌。能不能让涨得好的多买点?
>
> **任务**:在 notebook 中新建代码单元格,用动量排名信号运行回测,与前两种方案三方对比。
> **任务描述**:在 notebook 中新建代码单元格,用动量排名权重分配方法运行回测,与前两种方案对比。
#### 起草要求
#### 第三段:任务要求
动量排名比风险平价多一层——它要算 ram = mom / vol**ram 依赖 mom 和 vol 两个指标**。oxq 的 required_indicators 支持这种链式依赖,再加一个排序型优化器收尾:
动量排名比风险平价多一步:它要先计算“动量 / 波动率”,作为权重分配要依赖的指标。而这个指标又依赖动量和波动率两个指标。oxq 支持这种链式指标依赖,也支持这种排序型权重分配。
> **要求**
> **任务要求**
>
> 1. 阅读 `TopNRankingOptimizer` / `Momentum` / `Ratio` 三个 oxq 模块。
> 2. 在信号上注册三个指标(指标依赖链):
> ```python
> signal_tn.required_indicators = {
> mom: (Momentum(), {column: close, period: 20}),
> vol: (RollingVolatility(), {column: close, period: 20}),
> ram: (Ratio(), {col_a: mom, col_b: vol}),
> "mom": (Momentum(), {"column": "close", "period": 20}),
> "vol": (RollingVolatility(), {"column": "close", "period": 20}),
> "ram": (Ratio(), {"col_a": "mom", "col_b": "vol"}),
> }
> ```
> 顺序很重要——ram 依赖 mom 和 vol,所以 mom 和 vol 要先注册。
> 3. 用 `TopNRankingOptimizer(score_col="ram", n=3, filter_negative=True)` 装配优化器。`n=3` 是因为候选池就 3 只 ETF,这里等于“全选 + 过滤负值”;`filter_negative=True` 是动量排名的硬规则——**正在跌的不买**。
> 顺序很重要ram(风险调整后的动量指标)依赖 mom(动量)和 vol(波动率,代表风险),所以 mom 和 vol 要先注册。
> 3. 用 `TopNRankingOptimizer(score_col="ram", n=3, filter_negative=True)` 装配优化器。`n=3` 是因为标的池里就 3 只 ETF,这里等于“全选 + 过滤负值”;`filter_negative=True` 是动量排名的硬规则**正在跌的不买**。
> 4. 复用 spec-02 的 COMMON 字典,只把 portfolio 换成 `TopNRankingOptimizer(...)`。
> 📌 **要点**:多指标依赖链是 oxq 信号系统的关键能力。spec-02 注册 1 个指标(vol),spec-03 注册 3 个且 ram 依赖前两个——**spec 必须把注册顺序写清楚**,而不是只列指标名。AI 写代码时如果先注册 ram 再注册 mom/vol,运行时 ram 算不出来就直接 NaN——你看不到报错,但权重全错。
> 📌 **要点**:多指标依赖链是 oxq 的关键能力。spec-02 注册 1 个指标(vol),spec-03 注册 3 个指标,而且 ram 依赖前两个spec 必须把注册顺序写清楚,而不是只列指标名。
> 📌 **要点**:排序型 spec(动量排名)与加权型 spec(等权、风险平价)的本质区别是:可以**放弃部分标的**。所以“权重和=1.0”的断言要改成“未被过滤的活跃权重和=1.0”——`active_w = tn_w[tn_w > 1e-6]; assert abs(active_w.sum() - 1.0) < 1e-6`。这是排序型 spec 的活跃权重检查,加权型 spec 不需要这一步。
> 📌 **要点**:排序型 spec(动量排名)与加权型 spec(等权、风险平价)的本质区别是:可以**放弃部分 ETF**。所以“权重和 = 1.0”的断言要改成“未被过滤的活跃权重和 = 1.0”`active_w = tn_w[tn_w > 1e-6]; assert abs(active_w.sum() - 1.0) < 1e-6`。这一步是在检查:被留下来的 ETF,权重是否重新分满 100%。加权型 spec 不需要这一步。
#### 起草结果呈现
#### 第四段:验收标准
这一段的两个着力点:用排序型断言代替原来的“权重和=1.0”硬话术,并把“动量为负时面积图出空白”这个特殊视觉点写进 spec。
这一段有个交付细节:把“动量为负时面积图出空白”,这是一个特殊图表要求,写进 spec。
> **结果呈现**
> **验收标准**
>
> 1. **权重检查**:用排序型断言(过滤后归一化)。
> 2. 三权重对比表 + 三指标对比表(三种信号同台 PK
> 1. **权重检查**:用排序型断言(过滤后重新分到 100%)。
> 2. 三种方法权重对比表 + 三种方法指标对比表。
> 3. 三条净值曲线图(等权灰虚 + 风险平价蓝实 + 动量排名橙实)。
> 4. 动量排名权重历史堆叠面积图,**注意:动量为负时权重为 0,面积会出现空白**——把这个视觉特征预先写进 spec。
> 5. 分析话术按实际数据动态描述方向,**不要硬写“更大”或“更深”**——市场不可预测,spec 不应假设结果方向。
> 4. 动量排名权重历史堆叠面积图,**注意:动量为负时权重为 0,面积会出现空白**把这个视觉特征预先写进 spec。
> 5. 分析文字按实际数据动态描述方向,不要硬写“更大”或“更深”市场不可预测,spec 不应假设结果方向。
> 📌 **要点**:可视化 spec 不仅要描述要画什么,还要把**特殊视觉点**预先点出——动量为负时面积图会出空白,这种“反常”的视觉如果 spec 不预告,AI 可能用 `fillna(0.33)` 把空白补上,反而抹掉了排序型策略最重要的视觉信号。这是仓位分配章的高级 spec 写法:**视觉契约不只规定颜色形状,还要规定“该出现的空白也要出现”**
> 📌 **要点**:可视化 spec 不仅要描述要画什么,还要把特殊图表现象预先点出,比如这里的:动量为负时面积图会出空白
完整 spec 在 [`specs/spec-03-momentum-ranking.md`](https://github.com/xingwudao/xquant-learning/blob/main/q3-how-much/specs/spec-03-momentum-ranking.md)——复制给 AI,弹窗选「允许」
完整示例 spec 在配套仓库的 [`q3-how-much/specs/spec-03-momentum-ranking.md`](https://github.com/xingwudao/xquant-learning/blob/main/q3-how-much/specs/spec-03-momentum-ranking.md)。参考它确认自己的 spec 后,再复制给 AI,按提示允许执行
AI 助手执行完毕后,你的 notebook 里应该出现了新的权重对比、一张三指标表、两张图。这个实验引入了两个新概念。
AI 执行完毕后,你的 notebook 里应该出现了新的权重对比、一张三种方法的指标表、两张图。这个实验引入了两个新概念。
**动量(Momentum** ——过去 N 天的涨跌趋势。正数 = 涨势,负数 = 跌势。就像看一辆车的速度表——动量为正说明车在加速前进,为负说明在倒退。这里用的是 20 日动量,也就是看过去一个月的涨跌方向。
**动量(Momentum**过去 N 天的涨跌趋势。正数代表上涨,负数代表下跌。就像看一辆车的速度表动量为正说明车在向前,动量为负说明车在后退。这里用的是 20 日动量,也就是看过去一个月的涨跌方向。
但单看动量有个问题:波动大的标的天然动量值更大——它涨 5%波动小的标的涨 2%,可能只是因为它“脾气大”,不一定代表趋势更强。所以我们把动量除以波动率,得到**风险调整动量(ram = mom / vol** ——每份波动带来的动量。这样不同脾气的标的之间才能公平比较。
但单看动量有个问题:波动大的标的天然动量值更大它涨 5%波动小的标的涨 2%,可能只是因为它“脾气大”,不一定代表趋势更强。所以我们把动量除以波动率,得到**风险调整动量(ram = mom / vol**。你可以把它理解成每份波动带来的动量。这样不同波动程度的标的之间才能公平比较。
**TopNRankingOptimizer** ——按 ram 值排名分配权重。ram 为负的标的直接权重设为 0——不买。剩下的按 ram 大小归一化分配权重。涨得越且波动越小,分到的钱越多。如果三只 ETF 里有两只 ram 为负,那所有的钱就全部集中到唯一 ram 为正的那只上。
**动量归一化权重分配方法**按 ram 值排名分配权重。ram 为负的 ETF 直接权重设为 0,也就是不买。剩下的 ETF 再按 ram 大小重新分配到 100%。涨得越且波动越小,分到的钱越多。如果三只 ETF 里有两只 ram 为负,那所有的钱就全部到唯一 ram 为正的那只上。
### 实验结果
三种信号的权重对比(最新一天)如表 3-5 所示。
三种权重分配方法的权重对比(最新一天)如表 3-5 所示。
**表 3-5 三种信号最新一天权重对比**
**表 3-5 三种权重分配方法最新一天权重对比**
| 标的 | 等权 | 风险平价 | 动量排名 |
| ETF | 等权 | 风险平价 | 动量排名 |
|------|------|---------|---------|
| 沪深300ETF | 33.3% | 45.5% | 0.0% |
| 纳指100ETF | 33.3% | 43.3% | 0.0% |
| 黄金ETF | 33.3% | 11.2% | 100.0% |
差异一目了然。等权三等分,风险平价按波动调整,而动量排名直接把沪深300和纳指100的权重归零——近期它们在跌,不买。所有的钱全部涌向唯一在涨的黄金ETF。
差异一目了然。等权三等分,风险平价按波动调整,而动量排名直接把沪深 300 和纳指 100 的权重归零。策略运行时,它们在跌,所以不买。所有的钱全部分到唯一在涨的黄金 ETF。
三种信号的指标对比如表 3-6 所示。
三种权重分配方法的指标对比如表 3-6 所示。
**表 3-6 三种信号指标对比**
**表 3-6 三种权重分配方法指标对比**
| 指标 | 等权 | 风险平价 | 动量排名 |
|------|------|---------|---------|
@@ -304,129 +298,119 @@ AI 助手执行完毕后,你的 notebook 里应该出现了新的权重对比
三条净值曲线同框对比如图 3-4 所示,动量排名的权重历史如图 3-5 所示。
![三种信号对比:等权 vs 风险平价 vs 动量排名](images/q3-how-much/04-three-signals-nav.png)
![三种权重分配方法对比:等权 vs 风险平价 vs 动量排名](images/q3-how-much/04-three-signals-nav.png)
![动量排名:涨的多买,跌的不买](images/q3-how-much/05-momentum-weight-history.png)
### 读懂这些结果
先看图 3-4 的净值曲线,三条线同框对比。橙色实线(动量排名)终点最高——累计收益 179.96%,远超风险平价的 99.67% 和等权的 80.75%。但这笔超额收益不是白来的:动量排名的波动率是 15.54%,高于风险平价的 10.81%;最大回撤 -15.77%,也深于风险平价的 -12.26%。**收益更高,但颠簸更大、回撤更深——这就是激进策略的代价。**
先看图 3-4 的净值曲线,三条线同框对比。橙色实线(动量排名)终点最高累计收益 179.96%,远超风险平价的 99.67% 和等权的 80.75%。但这笔更高收益不是白来的:动量排名的波动率是 15.54%,高于风险平价的 10.81%;最大回撤 -15.77%,也深于风险平价的 -12.26%。**收益更高,但颠簸更大、回撤更深这就是更进取方法的代价。**
别急着下结论。记得第章的教训吗?同一个策略换个时间段,结果可能完全不同。动量排名在这几年的数据上表现优异,是因为市场恰好有几段清晰的趋势——比如黄金从 2023 年开始的持续上涨。**换段时间,动量排名的判断可能跟不上市场反转的节奏——这种"数据上看着好、换个时段就出问题"的现象,第章会专门讨论,本章先不下结论。** 没有完美的分法——风险平价更稳,动量排名更激进——哪个更适合你,要看你打算拿多久、能承受多大波动、能不能扛得住一段时间的回撤。第章我们会用更系统的方法判断“一个策略到底好不好”。
别急着下结论。记得第 1 章的教训吗?同一个策略换个时间段,结果可能完全不同。动量排名在这几年的数据上表现优异,是因为市场恰好有几段清晰的趋势比如黄金从 2023 年开始的持续上涨。换段时间,动量排名的判断可能跟不上市场反转的节奏。这种“在这段数据上好看,换一段时间就出问题的现象,第 5 章会专门讨论,本章先不下结论。没有完美的分法风险平价更稳,动量排名更进取。哪个更适合你,要看你打算拿多久、能承受多大波动、能不能扛得住一段时间的回撤。第 5 章我们会用更系统的方法判断“一个策略到底好不好”。
再看图 3-5 的权重历史。对比 3.2 的风险平价权重图,动量排名的变化剧烈得多——某只 ETF 动量转负,权重直接从几十个百分点归零,所有钱涌向其他标的;等它动量转正,权重又突然拉满。你还会发现图中有些时段出现了空白——三只 ETF 的权重加起来不到 100%,甚至全部归零。这说明那段时间三只 ETF 的动量全是负的,没有一只在涨,信号的判断是“都别买”。风险平价的权重变化则平缓得多,三只 ETF 始终都持有,只是比例在缓慢调整。两种信号的性格完全不同:一个求稳,一个求进。风险平价像一个谨慎的管家,均匀分配、避免偏科;动量排名像一个激进的赌徒,押注赢家、果断弃子
再看图 3-5 的权重历史。对比 3.2 的风险平价权重图,动量排名的变化剧烈得多。某只标的动量转负,权重直接从几十个百分点归零,钱转向其他标的;等它动量转正,权重又突然变高。你还会发现图中有些时段出现了空白:三只标的的权重加起来不到 100%,甚至全部归零。这说明那段时间三只 ETF 的动量全是负的,没有一只在涨,这种权重分配方法给出的决策是“都别买”。风险平价的权重变化则平缓得多,三只 ETF 始终都持有,只是比例在缓慢调整。两种权重分配方法的特点完全不同:一个求稳,一个求进。风险平价像一个谨慎的管家,均匀分配、避免偏科;动量排名像一个进取的交易者,押注走势更好的资产,果断放弃走弱的资产
三种信号,三种结果。到这里,你可能已经有了一个模糊的感觉:刚才做的事情好像不简单——选信号、跑回测、比指标,这不就是在做量化研究吗?
回头看:前言里说量化第一步是“**做**”——把动作写成可重复执行的规则。三次实验里,你已经做了三次:等权、风险平价、动量排名,每一次都是把“怎么分钱”从凭感觉变成了一段 spec 能让 AI 重跑的规则。这就是“做”。具体每一种规则做了什么?我们回头看看。
三种方法,三种结果。到这里,你可能已经有了一个模糊的感觉:刚才做的事情好像不简单。选权重分配方法、跑回测、比指标,这不就是在做量化研究吗?
---
## 3.4 回头看:你刚才做了什么?
三次实验,你只换了一样东西——信号。数据、标的、回测引擎、再平衡频率全部一样,只有信号不同,结果就完全不同。
三次实验,你只换了一样东西:权重分配方法。数据、标的、回测引擎、再平衡频率全部一样,只有“钱怎么分”不同,结果就完全不同。
你刚才做的事情,在量化交易的框架里有一个正式的名字:**信号对比(Signal Comparison** ——保持其他条件不变,只切换信号,观察结果差异。这是量化研究中最基础、也最重要的操作之一。信号只管判断,不管执行——但判断之后,谁来动手?这是规则(Rules)的事,第四章会讲
你刚才做的事情,可以叫**权重分配方法对比**保持其他条件不变,只切换“钱怎么分”,观察结果差异。这是量化研究中最基础、也最重要的操作之一。权重分配方法只给出目标权重,不负责决定什么时候调整持仓。什么时候调整、什么条件下卖出,这是规则(Rules)的事,第 4 章会讲。怎么把目标权重变成真实订单、按什么价格成交,是第 7 章会讲的执行交易问题
我们来看看你现在走到了哪里:第章解决了“买什么”(Universe),第三章解决了“买多少”(Signal),第四章将解决“什么时候”(Rules)。
我们来看看你现在走到了哪里:第 2 章解决了“买什么”(标的池),第 3 章解决了“买多少”(权重分配),第 4 章将解决“什么时候动手”(Rules)。
章里的 Crossover 信号说的是“买还是不买”——价格上穿均线就买、下穿就卖,要么买要么不买。第章的三种信号说的是“每只买百分之多少”——从 0% 到 100%,可以精确到小数点。判断的粒度更细了,但本质没变:都是信号,都是观察市场之后做出的判断。三种信号、三种性格,对照如表 3-7 所示。
1 章里的 Crossover 信号说的是“买还是不买”价格上穿均线就买、下穿就卖,要么买要么不买。第 3 章的三种权重分配方法说的是“每只买百分之多少”从 0% 到 100%,可以精确到小数点。这两类东西不要混在一起。信号负责判断市场状态,权重分配方法负责把钱分到资产上。三种权重分配方法的特点如表 3-7 所示。
**表 3-7 三种信号的性格对照**
**表 3-7 三种权重分配方法的特点对照**
| 信号 | 看什么 | 性格 |
| 方法 | 看什么 | 特点 |
|------|--------|------|
| EqualWeightOptimizer | 什么都不看 | 佛系 |
| RiskParityOptimizer | 波动率 | 稳 |
| TopNRankingOptimizer | 涨跌趋势 | 激进 |
| 等权 | 什么都不看 | 简单平均 |
| 风险平价 | 波动率 | 更重视平稳 |
| 动量排名 | 涨跌趋势 | 更重视上涨 |
“性价比”这个问题——三种信号收益和波动都不同,能不能用一个数字综合衡量?这是下一节要回答的事。
“性价比”这个问题来了。三种方法的收益和波动都不同,能不能用一个数字综合衡量?这是下一节要回答的事。
---
## 3.5 夏普比率:一个数字概括“性价比”
三种信号的收益率和波动率都不同。等权收益最低,风险平价更稳且收益更高,动量排名收益最高但波动也最大。有没有一个数字能把收益和波动综合起来,告诉你“每承受一份颠簸,能赚多少收益”?
三种权重分配方法的收益率和波动率都不同。等权收益最低,风险平价更稳且收益更高,动量排名收益最高但波动也最大。有没有一个数字能把收益和波动综合起来,告诉你“每承受一份颠簸,能赚多少收益”?
有。**夏普比率(Sharpe Ratio** ——年化收益率除以年化波动率衡量的是“性价比”。就像买东西看“每块钱能买到多少克”,夏普比率看的是“每承一份颠簸能赚到多少收益”。数字越大,说明你承受的颠簸越值得。三种信号的夏普比率对比如表 3-8 所示
有。**夏普比率(Sharpe Ratio** 的标准定义是:(年化收益率 - 无风险收益率)/ 年化波动率。它衡量的是每承一份波动,能比无风险资产多获得多少额外收益
**表 3-8 三种信号的夏普比率**
本章先让你理解“收益 / 波动”的关系,所以暂时采用简化口径:年化收益率 / 年化波动率。严格说,这不是标准夏普值,而是一个近似的收益波动比。等你真正比较策略时,应该使用扣除无风险收益后的标准夏普比率。三种方法的简化夏普对比如表 3-8 所示。
**表 3-8 三种权重分配方法的简化夏普对比**
| 指标 | 等权 | 风险平价 | 动量排名 |
|------|------|---------|---------|
| 年化收益率 | 11.96% | 13.97% | 20.80% |
| 年化波动率 | 11.73% | 10.81% | 15.54% |
| 夏普比率 | 1.08 | 1.35 | 1.42 |
| 简化夏普 | 1.08 | 1.35 | 1.42 |
看最后一行。三种方案的夏普比率依次递增:等权 1.08,风险平价 1.35,动量排名 1.42。风险平价比等权高出不少,说明按波动调整确实提升了性价比。动量排名最高,但优势不如收益率差距那么大——因为它的波动率也更高,部分抵消了收益优势。不过,夏普比率有三个你需要知道的局限:
看最后一行。三种方案的简化夏普依次递增:等权 1.08,风险平价 1.35,动量排名 1.42。风险平价比等权高出不少,说明按波动调整确实提升了性价比。动量排名最高,但优势不如收益率差距那么大因为它的波动率也更高,部分抵消了收益优势。不过,夏普比率有三个你需要知道的局限:
1. 它把上涨和下跌的波动一视同仁——但你可能根本不介意往上的颠簸。
2. 同一个策略换个时间段,夏普比率可能完全不同——它只反映特定历史区间的表现。
3. 当波动率为 0 时它会失效——持有现金的夏普比率无穷大,但显然不是好策略。
1. 它把上涨和下跌的波动一视同仁但你可能根本不介意往上的颠簸。
2. 同一个策略换个时间段,夏普比率可能完全不同它只反映特定历史区间的表现。
3. 当波动率为 0 时它会失效持有现金的夏普比率可能被算成无穷大,但显然不是好策略。
结论:夏普比率适合在相同条件下横向对比几种方案的性价比,但别把决策押在这一个数字上。怎么综合多个指标来判断一个策略到底好不好?这是第章的主题。
结论:夏普比率适合在相同条件下横向对比几种方案的性价比,但别把决策押在这一个数字上。本章表格里的数字只是简化夏普,更不能当作最终结论。怎么综合多个指标来判断一个策略到底好不好?这是第 5 章的主题。
---
## 3.6 本章总结
三次实验,三种信号,从“各买三分之一”到“按波动调整”再到“按涨势分配”——你一步步把“买多少”这个问题从拍脑袋变成了有据可依。信号就是策略的大脑,换一个大脑,整个策略的表现就完全不同
还有一个细节值得带走:本章三种信号下回测都设定了每 10 个交易日重算权重——这叫**再平衡(Rebalancing)**,又名**调仓**。“多久重算一次 / 多久调一次”是另一个独立的设计选择,第四章会专门讲。
三次实验,三种权重分配方法,从“各买三分之一”到“按波动调整”再到“按涨势分配”你一步步把“买多少”这个问题从拍脑袋变成了有据可依。买多少不是小问题。权重一变,每个资产对账户的影响就会变,整个策略的表现也会跟着变
### 概念速查表
本章涉及的核心概念汇总如表 3-9 所示,方便随时回查。
**表 3-9 第章核心概念速查**
**表 3-9 第 3 章核心概念速查**
| 概念 | 含义 | 类比 |
|------|------|------|
| 权重(Weight | 每只标的分到总资金的百分之多少 | 一笔钱怎么分 |
| 信号(Signal) | 根据指标对市场做出的判断——要不要动、怎么动。只表达意愿,不负责执行 | 你看完天气预报后的判断:“带伞”。带不带是另一回事 |
| 风险平价(Risk Parity) | 按波动率倒数分配权重,让每只影响力均匀 | 成熟稳重的多管钱,情绪化的少管钱 |
| 权重(Weight | 每只资产分到总资金的百分之多少 | 一笔钱怎么分 |
| 权重分配方法 | 回答每只资产各买多少,在 open-xquant 里通常由 `PortfolioOptimizer` 实现 | 分蛋糕的方法 |
| 组合(Portfolio) | 实际拿来配置资金的一组资产,不是候选名单 | 购物车里真正放进去的商品 |
| 目标权重(Target Weight) | 按规则算出来的理想资金比例 | 预算表 |
| 持仓(Position) | 账户里实际持有的资产和数量 | 手里真正拿着的份额 |
| 实际权重 | 按持仓市值算出来的真实比例 | 结账后每样东西实际占了多少预算 |
| 风险平价(Risk Parity) | 按波动率倒数分配权重,让每只资产的影响更均匀 | 成熟稳重的多管钱,起伏大的少管钱 |
| 动量(Momentum) | 过去 N 天的涨跌趋势,正=涨势,负=跌势 | 最近的势头 |
| 动量排名(TopNRankingOptimizer | 按涨势强弱分配权重,跌的不买 | 趋势交易的量化表达 |
| 夏普比率(Sharpe Ratio | 年化收益 / 年化波动,衡量性价比 | 每份颠簸赚多少 |
| 再平衡/调仓Rebalancing) | 定期重新计算权重并调整仓位 | 定期重新分工 |
| 夏普比率(Sharpe Ratio | 标准定义是(年化收益率 - 无风险收益率)/ 年化波动率;本章暂用简化夏普理解收益和波动的关系 | 每份颠簸赚多少 |
| 再平衡(Rebalancing) | 定期重新计算权重并调整持仓比例 | 定期重新分工 |
### 策略进化路径
章产出了投资宇宙(沪深300、纳指100、黄金)。本章在此基础上探索了三种分钱方式Step 1 各买 1/3EqualWeightOptimizer)——简单,但波动大的把组合拉着走Step 2 按波动调整RiskParityOptimizer)——更稳,每只影响均匀Step 3 按涨势调整TopNRankingOptimizer)——趋势交易的量化表达。第三章产出:三种信号对比 + 信号就是策略的大脑
2 章产出了标的池(沪深 300、纳指 100、黄金)。本章在此基础上探索了三种分钱方式。第 1 步,各买 1/3,也就是等权,简单,但波动大的资产会把组合拉着走。第 2 步,按波动调整,也就是风险平价,更稳,每只资产的影响均匀。第 3 步,按涨势调整,也就是动量排名,这是趋势交易思想在“买多少”问题上的表达。第 3 章的产出:三种权重分配方法对比
### 本章最重要的收获
走完三个实验后,本章最值得带走的五条认知如表 3-10 所示。
**表 3-10 第章主线认知**
**表 3-10 第 3 章主线认知**
| 认知 | 来源 |
|------|------|
| 平均分钱 ≠ 平均分影响力 | 3.1 |
| 波动率小 = 你能在低点不慌 | 3.1 |
| 按波动调整让组合更稳 | 3.2 |
| 同样的策略,只换信号,结果完全不同 | 3.3 |
| 夏普比率适合对比,但别只看一个指标 | 3.4 |
| 同样的策略,只换权重分配方法,结果完全不同 | 3.3 |
| 简化夏普适合对比,但别只看一个指标 | 3.5 |
### 带走的问题
做完本章,你应该带着两个问题进入后续章节——它们将在下两章被一一回答:
做完本章,你应该带着两个问题进入后续章节它们将在下两章被一一回答:
- 信号只负责判断“想怎么分”,但**判断完了谁来执行?按什么规则下单** → 第
- 动量排名在这段数据上全面胜出,但**换一段时间还行吗?怎么区分真本事和运气?** → 第
- 权重分配方法只负责给出目标权重,但**什么时候调整持仓、什么条件下卖出** → 第 4
- 动量排名在这段数据上全面胜出,但**换一段时间还行吗?怎么区分真本事和运气?** → 第 5
第二个问题正是本书口号“**做要规则、看要指标、还要怀疑你的指标**”中“疑”的入口——动量排名的累计 179.96% 看起来很漂亮,但你已经隐隐感到不对劲:换段时间还能不能这样?这种警觉,是后面章要反复训练的主线动作
第二个问题正是本书口号“**做要规则、看要指标、还要怀疑你的指标**”中“疑”的入口动量排名的累计 179.96% 看起来很漂亮,但你已经隐隐感到不对劲:换段时间还能不能这样?这种警觉,是后面章要反复训练的主线。
> 本章所有代码的可运行版本见 `notebooks/q3-how-much.ipynb`
---
## 反馈与读者群
如果你发现本章有错别字、概念不清或实验结果不一致,欢迎
[提交 GitHub Issue](https://github.com/xingwudao/xquant-beginner/issues/new/choose)。
课程、正式书和后续更新见
[xquant.shop/courses](https://xquant.shop/courses)。
添加作者微信 `xquanter` 进入读者群。请备注:`XQuant 读者`
> 本章所有代码的可运行版本见配套仓库的 [`q3-how-much/notebooks/q3-how-much.ipynb`](https://github.com/xingwudao/xquant-learning/blob/main/q3-how-much/notebooks/q3-how-much.ipynb)