# 第 3 章：决定各买多少：3 种分法实测

> 最新书稿已更新至 [XQuant 量化课堂页](https://xquant.shop/courses)。
> 想阅读最新版官方书稿，请前往图书页。

第 2 章我们从全市场几千个标的中，一步步筛选出了三只 ETF：沪深 300、纳指 100、黄金，构建了自己的标的池。选资产的问题解决了，但紧接着一个新问题摆在面前：三只 ETF，各买多少？

这听起来像个分钱小问题：平均分一下不就完了吗？别急着下这个结论。同样三只 ETF、同一段历史，只是分法不同，本章这段历史数据里的累计收益确实差出 1 倍以上。买什么，决定你参与哪些市场；买多少，决定每个市场对账户的影响有多大。这就是为什么一整章都要解决这个问题。

### 路线图

本章进入四个阶段里的**制定规则**阶段。本章分三步探索三种分钱方式，每节做 1 次实验，最后你来判断哪种更合理。全章一共要动手做 3 次实验。

**表 3-1 第 3 章路线图**

| 节 | 内容 | 实验 |
|----|------|------|
| 3.1 | 最简单的回答：各买三分之一 | 1 |
| 3.2 | 波动大的少买点，波动小的多买点 | 1 |
| 3.3 | 涨得好的多买点，跌的别买 | 1 |

---

## 3.1 最简单的回答：各买三分之一

三只 ETF，各买多少？最自然的回答：平均分，每只买三分之一。不偏不倚，公平合理。毕竟，如果你不确定哪只会涨得更好，平均分至少不会犯大错。对吧？

我们来验证一下这个直觉。

### 动手实验 1：等权组合回测

这个实验用到 open-xquant 的几个模块：`EqualWeightOptimizer`（把钱平均分的组合优化器）、`Engine`（回测引擎，模拟历史买卖）、`SimBroker`（模拟券商）。你不需要了解它们的代码，spec 会告诉 AI 怎么用。

我们一起把这份 spec 写出来。这次重点看三件新东西：**oxq 模块的“先读后写”**、**权重和 = 1.0 的关键断言**、**将多只资产的交易日对齐**。

#### 第一、二段：上下文和任务描述

这是 q3 的第一份 spec，直接接续第 2 章。三只 ETF 已经选好了，现在只关心权重。上下文说前提，任务描述说要做什么，两段都很短：

> **上下文**：第 2 章选好了 3 只 ETF（沪深 300、纳指 100、黄金），现在要回答：每只各买多少？
>
> **任务描述**：在 notebook `q3-how-much.ipynb` 中创建代码，跑等权组合回测，并展示三只 ETF 各自的表现差异。

#### 第三段：任务要求

spec 主体的第一件事不是写代码，而是要求 AI 先读源码。这样它调的是真实接口，不会用过时或编造的写法。

> **任务要求**：
>
> 1. 阅读以下 oxq 模块的源码（按用途分四组）：
>    - 引擎与策略：`oxq.core.Engine` / `Strategy`
>    - 数据：`oxq.data.YFinanceDownloader` / `LocalMarketDataProvider`
>    - 权重分配：`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)`。

> 📌 **要点**：多只资产放在一起比较时，先要把日期对齐。即使三只 ETF 都在 A 股市场交易，历史数据也可能出现个别缺失日。spec 要求先取共同交易日，是为了让三条净值曲线站在同一组日期上比较，避免图表因为日期不齐而产生误导。

#### 第四段：验收标准

验收标准段把权重检查、对比表、净值曲线一次锁死，让 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 单只持有」。

> 📌 **要点**：权重分配 spec 里必须写清一个验收标准：「权重和 = 1.0 ± 1e-6」。这在第 1 章那种单资产策略里不需要。只有一个资产时，要么买，要么不买。但只要进入“分钱”场景，这条就必须有。没有这条断言，AI 输出 0.998 或 1.003 你可能都会以为正常。下游回测会按这个权重直接乘资金，误差会一路传到最后的收益率。三个 spec 都要复用这条模板。

完整示例 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 里应该出现了一组权重数字、一张对比表和一张净值图。我们先认识两个新概念。

**权重（Weight）**：回答“每个标的分总资金的多少比例”。每个标的分到总资金的百分之多少，就是它的权重。你有 10 万元，三只 ETF 各 1/3 权重，就是每只买 33,333 元。

**权重分配方法**：回答“按照什么逻辑分配资金”。等权分配就是一种最简单的权重分配方法：不看涨跌，不看波动，三只 ETF 各 1/3。权重分配方法有很多，后面也可以看到不同的分配方式。至于目标权重之后怎么变成真实订单、按什么价格成交，那是第 7 章要处理的事。

在量化领域，在一起参与分配资金的一组标的，叫做**组合（Portfolio）**。组合不是简单的候选名单。第 2 章选出的标的池，是策略允许考虑的范围，是候选大名单；第 3 章要做的，是从这个大名单里给每只标的分配资金。按规则算出来的配置资金比例，叫**目标权重（Target Weight）**。

目标权重只是理想资金比例。账户里真正持有的标的和份额数量，叫**持仓（Position）**；这些持仓按市值算出来的比例，才是**实际权重**。即使一开始完全按目标权重买入，后面标的价格也会涨跌，实际权重会慢慢偏离目标权重。因此，过一段时间就要重新调整持仓，让实际权重重新接近目标权重。这个过程叫**再平衡（Rebalancing）**。

标的池里的标的，不是每次都一定能分到钱。有些标的的权重可能是 0，极端情况下，所有标的的权重都可能是 0。这时可以把现金（CASH）也视为组合成员，现金获得 100% 权重，意味着账户里暂时不持有任何标的。

### 实验结果

等权就是强制让资产的权重相等，三只各占三分之一，每只买 33,333 元。这种平均分资金的方式，效果如何呢？三只 ETF 单独持有与等权组合的对比如表 3-2 所示。

**表 3-2 三只 ETF 单独持有 vs 等权组合表现**

| ETF | 累计收益率 | 年化波动率 | 最大回撤 |
|------|-----------|-----------|---------|
| 沪深300ETF | -1.78% | 18.11% | -42.16% |
| 纳指100ETF | 106.09% | 22.66% | -27.50% |
| 黄金ETF | 188.54% | 15.83% | -16.77% |
| **等权组合** | **80.75%** | **11.73%** | **-16.79%** |

净值曲线对比如图 3-1 所示。

![各买三分之一：等权组合 vs 单只持有](images/q3-how-much/01-equal-weight-nav.png)

### 读懂这些结果

先看图 3-1 的大趋势：等权组合那条蓝色实线，走在三条灰色线之间。它不是最好的，也不是最差的。黄金一路领涨，纳指 100 先跌后涨、波折不断，沪深 300 整体低迷。组合把三者的表现“平均”了一下，走出了一条居中的路线。

但你可能已经注意到了：黄金单独拿的累计收益率是 188.54%，比等权组合的 80.75% 高了一倍多。那为什么不全买黄金？

看波动率那列。**年化波动率（Annualized Volatility）** 衡量的是价格上下波动的剧烈程度。第 2 章我们认识过这个指标。波动率大，意味着你的账户大起大落：今天涨 3%、明天跌 4%，反复折腾。现实中大部分人受不了这种颠簸。涨的时候开心，连跌几天就开始怀疑“是不是该卖了”，一卖可能就错过后面的反弹。**波动率小，意味着你能在低点不慌、在上涨中不慌。** 账户里一时少了 5%、10%，你不会马上卖掉。不慌，才能真正拿到那段收益。

再看一个更关键的问题。三只 ETF 的年化波动率从 15.83%（黄金）到 22.66%（纳指 100），差了好几个百分点。但等权方法说：“不管你多颠簸，都买一样多的钱。”这意味着什么？波动最大的纳指 100，虽然只花了 1/3 的钱，但它每天的涨跌幅度最大，对组合整体的影响也最大。它一跌，组合就被拖着跌；它一涨，组合的涨幅也主要靠它撑着。**每个标的拿一样多的资金，并不等于它造成的波动也一样。** 波动大的那只，用同样的钱产生了更大的影响力，拉着整个组合的涨跌走。

有没有更合理的分法？比如，波动大的少买点，波动小的多买点，让每只 ETF 对组合的“影响力”更接近？

---

## 3.2 波动大的少买点，波动小的多买点

上一节的结论很清楚：平均分钱，并不等于平均分影响力。波动大的纳指 100，用同样的钱却产生了更大的影响力，把整个组合的涨跌拉着走。那反过来想：既然波动大的影响力太大，能不能给它少分点钱？波动小的那只影响力不够，能不能多分点钱给它？这样三只 ETF 对组合的“拉扯力度”应该更均匀。

这种“按波动率倒数分配权重”的方法，有一个正式的名字：**风险平价（Risk Parity）**。本章用的是简化版风险平价：波动大的少买，波动小的多买，让每只标的对组合的影响更均匀。你可以把它想成把三个发动机的功率调到接近，整个组合就不容易被某一个拖着走。

想象你要把一笔钱交给三个人帮你打理。第一个人成熟稳重，赚了不炫耀，亏了不慌张，你看着他的账户心里很踏实；第二个人情绪起伏大，今天信心很足，明天就想清仓；第三个人介于两者之间。你会怎么分钱？大概率会让稳重的那个多管点，让情绪起伏大的那个少管点。三只 ETF 也一样。波动率就是它们的“情绪起伏程度”。波动小的稳重，多买；波动大的起伏大，少买。

### 动手实验 2：风险平价组合回测

我们一起把这份 spec 写出来。这次重点看两件新东西：**`signal.required_indicators` 在信号上挂指标**、**公共配置复用，只改差异点**。

#### 第一、二段：上下文和任务描述

这是 q3 的第二份 spec，接续 spec-01 的等权回测结果。上下文一句话承接，任务一句话点明：

> **上下文**：在 `q3-how-much.ipynb` 中已有等权组合回测结果。读者已看到三只 ETF 波动率差异很大，等权分配让波动大的 ETF 主导了组合涨跌。当前问题：能不能按波动来分：波动大的少买，波动小的多买？
>
> **任务描述**：在 notebook 中新建代码单元格，用风险平价权重分配方法运行回测，对比等权组合。

#### 第三段：任务要求

风险平价要用波动率，这就要定义波动率指标，并且要使用 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(...))`。

> 📌 **要点**：这里的 `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 估计期偏短，不要硬写“降到”）。

> 📌 **要点**：权重分配可视化采用了**权重历史堆叠面积图**。它让人一眼看到“权重不是一成不变的”。等权下三条带等宽，风险平价下面积带宽随时间变化。

完整示例 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 里应该出现了新的权重数字、一张对比表、两张图。

风险平价方法和 3.1 的等权方法用法相似，只是换了 `portfolio` 里的权重分配方法，其余不变。但钱真的分得不一样了：等权是三等分，风险平价则是波动小的多分、波动大的少分。同样 10 万元，沪深 300ETF 从 33,333 元涨到了 45,510 元，黄金 ETF 从 33,333 元降到了 11,239 元。

策略组装和上一节几乎一模一样。整个策略定义只有 `portfolio` 那一行不同，从 `EqualWeightOptimizer()` 换成 `RiskParityOptimizer()`。其余的全部复用。当框架搭好之后，换一种“分钱方式”就只是换一个权重分配方法。

### 实验结果

两种方案的权重对比如表 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 等权 vs 风险平价指标对比**

| 指标 | 等权组合 | 风险平价组合 |
|------|---------|------------|
| 累计收益率 | 80.75% | 99.67% |
| 年化波动率 | 11.73% | 10.81% |
| 最大回撤 | -16.79% | -12.26% |

净值曲线对比如图 3-2 所示，权重随波动率变化的历史轨迹如图 3-3 所示。

![等权 vs 风险平价](images/q3-how-much/02-ew-vs-rp-nav.png)

![风险平价：权重如何随波动率调整](images/q3-how-much/03-rp-weight-history.png)

### 读懂这些结果

先看图 3-2 的净值曲线。蓝色实线（风险平价）走得比灰色虚线（等权）更平滑，而且终点更高。这说明，风险平价不仅更稳，还赚得更多。

再看指标表里的数字。波动率从 11.73% 降到 10.81%，最大回撤从 -16.79% 收窄到 -12.26%。最惨的时候少跌了 4.5 个百分点。收益率反而更高了（80.75% → 99.67%）。在这段数据里，按波动调整不仅降低了波动，也保住了收益。对真实投资者来说，波动小还有一个好处：更容易坐得住，因此也许更能享受到后面的涨势。

最后看图 3-3 的权重历史。你会发现一个有意思的现象：三只 ETF 的权重不是固定的，而是随时间在动态调整。某段时间黄金 ETF 波动率飙升，它分到的钱就自动减少；某段时间沪深 300ETF 变得平稳了，它分到的钱就自动增加。这就是节首讲的“按波动率倒数分配”在跑。市场数据在告诉你谁该多买、谁该少买，你不用做主观判断。

风险平价比等权更稳了。但你有没有注意到，它只看波动率，完全不看涨跌。如果一只 ETF 正在快速上涨，风险平价不会多买它；如果一只正在下跌，也不会少买它。能不能更强调上涨趋势，让涨得好的多买点？

---

## 3.3 涨得好的多买点，跌的别买

风险平价让组合更稳了，但回头想想，它的判断标准只有一个：波动率。波动大的少买，波动小的多买，仅此而已。至于一只 ETF 是在涨还是在跌？它完全不关心。黄金如果正在快速上涨，风险平价不会因此多买一分钱；沪深 300 如果正在明显下跌，它也不会少买一分钱。它只看颠簸程度，不看方向。

那能不能更进取一点：涨得好的多买，跌的干脆不买？我们可以借鉴一种交易思想：趋势交易。顾名思义，也就是跟着涨势走。动量排名就是趋势交易思想的量化表达：过去一段时间涨得好的，我认为它可能继续上涨，多买；过去一段时间下跌的，我认为它可能继续走弱，不买。

### 动手实验 3：动量排名组合回测

我们一起把这份 spec 写出来。这次重点看两件新东西：**多指标依赖链**、**过滤后重新把权重分到 100%**。

#### 第一、二段：上下文和任务描述

这是 q3 三联 spec 的最后一份，从“始终持有全部 ETF”走到“动量为负的不买”。上下文 + 任务一气呵成：

> **上下文**：在 `q3-how-much.ipynb` 中已有等权组合和风险平价组合的回测结果。读者已理解：等权不看任何指标，风险平价只看波动率。当前问题：风险平价更稳了，但它完全不看涨跌。能不能让涨得好的多买点？
>
> **任务描述**：在 notebook 中新建代码单元格，用动量排名权重分配方法运行回测，与前两种方案对比。

#### 第三段：任务要求

动量排名比风险平价多一步：它要先计算“动量 / 波动率”，作为权重分配要依赖的指标。而这个指标又依赖动量和波动率两个指标。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"}),
>    }
>    ```
>    顺序很重要。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 必须把注册顺序写清楚，而不是只列指标名。

> 📌 **要点**：排序型 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 不需要这一步。

#### 第四段：验收标准

这一段有个交付细节：把“动量为负时面积图留出空白”，这是一个特殊图表要求，写进 spec。

> **验收标准**：
>
> 1. **权重检查**：用排序型断言（过滤后重新分到 100%）。
> 2. 三种方法权重对比表 + 三种方法指标对比表。
> 3. 三条净值曲线图（等权灰虚 + 风险平价蓝实 + 动量排名橙实）。
> 4. 动量排名权重历史堆叠面积图，**注意：动量为负时权重为 0，面积会出现空白**。把这个视觉特征预先写进 spec。
> 5. 分析文字按实际数据动态描述方向，不要硬写“更大”或“更深”。市场不可预测，spec 不应假设结果方向。

> 📌 **要点**：可视化 spec 不仅要描述要画什么，还要把特殊图表现象预先点出，比如这里的：动量为负时面积图会出空白。

完整示例 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 里应该出现了新的权重对比、一张三种方法的指标表、两张图。这个实验引入了两个新概念。

**动量（Momentum）**：过去 N 天的涨跌趋势。正数代表上涨，负数代表下跌。就像看一辆车的速度表，动量为正说明车在向前，动量为负说明车在后退。这里用的是 20 日动量，也就是看过去一个月的涨跌方向。

但单看动量有个问题：波动大的标的天然动量值更大。它涨 5%，波动小的标的涨 2%，可能只是因为它“脾气大”，不一定代表趋势更强。所以我们把动量除以波动率，得到**风险调整动量（ram = mom / vol）**。你可以把它理解成每份波动带来的动量。这样不同波动程度的标的之间才能公平比较。

**动量归一化权重分配方法**：按 ram 值排名分配权重。ram 为负的 ETF 直接权重设为 0，也就是不买。剩下的 ETF 再按 ram 大小重新分配到 100%。涨得越好且波动越小，分到的钱越多。如果三只 ETF 里有两只 ram 为负，那所有的钱就全部分到唯一 ram 为正的那只上。

### 实验结果

三种权重分配方法的权重对比（最新一天）如表 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。

三种权重分配方法的指标对比如表 3-6 所示。

**表 3-6 三种权重分配方法指标对比**

| 指标 | 等权 | 风险平价 | 动量排名 |
|------|------|---------|---------|
| 累计收益率 | 80.75% | 99.67% | 179.96% |
| 年化波动率 | 11.73% | 10.81% | 15.54% |
| 最大回撤 | -16.79% | -12.26% | -15.77% |

三条净值曲线同框对比如图 3-4 所示，动量排名的权重历史如图 3-5 所示。

![三种权重分配方法对比：等权 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%。**收益更高，但颠簸更大、回撤更深，这就是更进取方法的代价。**

别急着下结论。记得第 1 章的教训吗？同一个策略换个时间段，结果可能完全不同。动量排名在这几年的数据上表现优异，是因为市场恰好有几段清晰的趋势，比如黄金从 2023 年开始的持续上涨。换段时间，动量排名的判断可能跟不上市场反转的节奏。这种“在这段数据上好看，换一段时间就出问题”的现象，第 5 章会专门讨论，本章先不下结论。没有完美的分法。风险平价更稳，动量排名更进取。哪个更适合你，要看你打算拿多久、能承受多大波动、能不能扛得住一段时间的回撤。第 5 章我们会用更系统的方法判断“一个策略到底好不好”。

再看图 3-5 的权重历史。对比 3.2 的风险平价权重图，动量排名的变化剧烈得多。某只标的动量转负，权重直接从几十个百分点归零，钱转向其他标的；等它动量转正，权重又突然变高。你还会发现图中有些时段出现了空白：三只标的的权重加起来不到 100%，甚至全部归零。这说明那段时间三只 ETF 的动量全是负的，没有一只在涨，这种权重分配方法给出的决策是“都别买”。风险平价的权重变化则平缓得多，三只 ETF 始终都持有，只是比例在缓慢调整。两种权重分配方法的特点完全不同：一个求稳，一个求进。风险平价像一个谨慎的管家，均匀分配、避免偏科；动量排名像一个进取的交易者，押注走势更好的资产，果断放弃走弱的资产。

三种方法，三种结果。到这里，你可能已经有了一个模糊的感觉：刚才做的事情好像不简单。选权重分配方法、跑回测、比指标，这不就是在做量化研究吗？

---

## 3.4 回头看：你刚才做了什么？

三次实验，你只换了一样东西：权重分配方法。数据、标的池、回测引擎、再平衡频率全部一样，只有“钱怎么分”不同，结果就完全不同。

你刚才做的事情，可以叫**权重分配方法对比**：保持其他条件不变，只切换“钱怎么分”，观察结果差异。这是量化研究中最基础、也最重要的操作之一。权重分配方法只给出目标权重，不负责决定什么时候调整持仓。什么时候调整、什么条件下卖出，这是规则（Rules）的事，第 4 章会讲。怎么把目标权重变成真实订单、按什么价格成交，是第 7 章会讲的执行交易问题。

我们来看看你现在走到了哪里：第 2 章解决了“买什么”（标的池），第 3 章解决了“买多少”（权重分配），第 4 章将解决“什么时候动手”（Rules）。

第 1 章里的 Crossover 信号说的是“买还是不买”：价格上穿均线就买、下穿就卖，要么买，要么不买。第 3 章的三种权重分配方法说的是“每只买百分之多少”：从 0% 到 100%，可以精确到小数点。这两类东西不要混在一起。信号负责判断市场状态，权重分配方法负责把钱分到资产上。三种权重分配方法的特点如表 3-7 所示。

**表 3-7 三种权重分配方法的特点对照**

| 方法 | 看什么 | 特点 |
|------|--------|------|
| 等权 | 什么都不看 | 简单平均 |
| 风险平价 | 波动率 | 更重视平稳 |
| 动量排名 | 涨跌趋势 | 更重视上涨 |

“性价比”这个问题来了。三种方法的收益和波动都不同，能不能用一个数字综合衡量？这是下一节要回答的事。

---

## 3.5 夏普比率：一个数字概括“性价比”

三种权重分配方法的收益率和波动率都不同。等权收益最低，风险平价更稳且收益更高，动量排名收益最高但波动也最大。有没有一个数字能把收益和波动综合起来，告诉你“每承受一份颠簸，能赚多少收益”？

有。**夏普比率（Sharpe Ratio）** 的标准定义是：（年化收益率 - 无风险收益率）/ 年化波动率。它衡量的是：每承担一份波动，能比无风险资产多获得多少额外收益。

本章先让你理解“收益 / 波动”的关系，所以暂时采用简化口径：年化收益率 / 年化波动率。严格说，这不是标准夏普值，而是一个近似的收益波动比。等你真正比较策略时，应该使用扣除无风险收益后的标准夏普比率。三种方法的简化夏普对比如表 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. 它把上涨和下跌的波动一视同仁，但你可能根本不介意往上的颠簸。
2. 同一个策略换个时间段，夏普比率可能完全不同。它只反映特定历史区间的表现。
3. 当波动率为 0 时它会失效。持有现金的夏普比率可能被算成无穷大，但显然不是好策略。

结论：夏普比率适合在相同条件下横向对比几种方案的性价比，但别把决策押在这一个数字上。本章表格里的数字只是简化夏普，更不能当作最终结论。怎么综合多个指标来判断一个策略到底好不好？这是第 5 章的主题。

---

## 3.6 本章总结

三次实验，三种权重分配方法，从“各买三分之一”到“按波动调整”再到“按涨势分配”，你一步步把“买多少”这个问题从拍脑袋变成了有据可依。买多少不是小问题。权重一变，每个资产对账户的影响就会变，整个策略的表现也会跟着变。

### 概念速查表

本章涉及的核心概念汇总如表 3-9 所示，方便随时回查。

**表 3-9 第 3 章核心概念速查**

| 概念 | 含义 | 类比 |
|------|------|------|
| 权重（Weight） | 每只资产分到总资金的百分之多少 | 一笔钱怎么分 |
| 权重分配方法 | 回答每只资产各买多少，在 open-xquant 里通常由 `PortfolioOptimizer` 实现 | 分蛋糕的方法 |
| 组合（Portfolio） | 实际拿来配置资金的一组资产，不是候选名单 | 购物车里真正放进去的商品 |
| 目标权重（Target Weight） | 按规则算出来的理想资金比例 | 预算表 |
| 持仓（Position） | 账户里实际持有的资产和数量 | 手里真正拿着的份额 |
| 实际权重 | 按持仓市值算出来的真实比例 | 结账后每样东西实际占了多少预算 |
| 风险平价（Risk Parity） | 按波动率倒数分配权重，让每只资产的影响更均匀 | 成熟稳重的多管钱，起伏大的少管钱 |
| 动量（Momentum） | 过去 N 天的涨跌趋势，正=涨势，负=跌势 | 最近的势头 |
| 动量排名（TopNRankingOptimizer） | 按涨势强弱分配权重，跌的不买 | 趋势交易的量化表达 |
| 夏普比率（Sharpe Ratio） | 标准定义是（年化收益率 - 无风险收益率）/ 年化波动率；本章暂用简化夏普理解收益和波动的关系 | 每份颠簸赚多少 |
| 再平衡（Rebalancing） | 定期重新计算权重并调整持仓比例 | 定期重新分工 |

### 策略进化路径

第 2 章产出了标的池（沪深 300、纳指 100、黄金）。本章在此基础上探索了三种分钱方式。第 1 步，各买 1/3，也就是等权，简单，但波动大的资产会把组合拉着走。第 2 步，按波动调整，也就是风险平价，更稳，每只资产的影响更均匀。第 3 步，按涨势调整，也就是动量排名，这是趋势交易思想在“买多少”问题上的表达。第 3 章的产出是：三种权重分配方法对比。

### 本章最重要的收获

走完三个实验后，本章最值得带走的五条认知如表 3-10 所示。

**表 3-10 第 3 章主线认知**

| 认知 | 来源 |
|------|------|
| 平均分钱 ≠ 平均分影响力 | 3.1 |
| 波动率小 = 你能在低点不慌 | 3.1 |
| 按波动调整让组合更稳 | 3.2 |
| 同样的策略，只换权重分配方法，结果完全不同 | 3.3 |
| 简化夏普适合对比，但别只看一个指标 | 3.5 |

### 带走的问题

做完本章，你应该带着两个问题进入后续章节。它们将在下两章被一一回答：

- 权重分配方法只负责给出目标权重，但**什么时候调整持仓、什么条件下卖出？** → 第 4 章
- 动量排名在这段数据上全面胜出，但**换一段时间还行吗？怎么区分真本事和运气？** → 第 5 章

第二个问题正是本书口号“**做要规则、看要指标、还要怀疑你的指标**”中“疑”的入口。动量排名的累计 179.96% 看起来很漂亮，但你已经隐隐感到不对劲：换段时间还能不能这样？这种警觉，是后面几章要反复训练的主线。

> 本章所有代码的可运行版本见配套仓库的 [`q3-how-much/notebooks/q3-how-much.ipynb`](https://github.com/xingwudao/xquant-learning/blob/main/q3-how-much/notebooks/q3-how-much.ipynb)
