# 第 5 章：判断策略好不好：4 个关键视角

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

第 4 章我们给策略加上了规则：再平衡频率、止损、止盈，也学会了“不是所有合理的规则都有效”。现在手上有一个“看起来不错”的配置：风险平价 + 5% 止损。它的年化收益接近 15%，简化夏普也不低。

但“看起来不错”到底是什么意思？年化 15% 好不好？简化夏普 1.4 左右够不够？**跟什么比？**

更关键的问题：**这些数字是好几年平均出来的。如果某一年亏了 20%，你扛得住吗？**

### 路线图

本章进入四个阶段里的**评估归因**阶段。前面几章主要在训练“做”：把想法写成规则，让程序跑起来。本章开始训练“看”：拿到一组回测结果后，知道先看什么、再看什么、每个数字说明什么。

本章给策略做一次“全面体检”，分四个角度检查结果。全章一共要动手做 4 次实验，路线如表 5-1 所示。

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

| 节 | 内容 | 实验 |
|----|------|------|
| 5.1 | 跟什么比？ | 1 |
| 5.2 | 每年都有收益吗？ | 1 |
| 5.3 | 收益结构什么样？ | 1 |
| 5.4 | 参数动一动，结果还稳吗？ | 1 |

铁律不变：**先猜后验，数据说了算。**

本章用第 3 章和第 4 章的四个策略配置作为“被检查对象”。四个候选配置对照如表 5-2 所示。

**表 5-2 第 5 章评估的四个候选配置**

| 策略 | 来源 | 特点 |
|------|------|------|
| EqualWeight | 第 3 章等权 | 最简单，无参数 |
| RiskParity | 第 3 章风险平价 | 波动相对低 |
| TopNRanking | 第 3 章动量排名 | 收益高，但波动也高 |
| RP+止损5% | 第 4 章规则配置 | 风险平价 + 5% 止损 |

> 提示：本章的要点段会比前几章更长，因为本章开始处理指标口径、图表约定和同一种方法的不同用途。读到要点段时不用赶，重点是看清楚：为什么要这样写，不这样写会怎样。

---

## 5.1 跟什么比？

第 4 章的策略年化收益接近 15%，简化夏普也不低，好不好？

直觉告诉我们：收益高就是好，简化夏普越大越好。但“好”是跟什么比？如果同期简单买入并持有也涨了很多，你忙活半天可能并没有占到便宜。

本章要做的第一件事，就是把第 3 章、第 4 章产出的策略配置放到“跟谁比”的语境里。一个策略自己涨了，不代表它好。只有它比一个简单可行的参照做法更好，才说明这套规则可能有价值。

在开始之前，先复习四个你已经见过的“基础体检指标”。它们在第 1 章、第 2 章、第 3 章都已经登场过。如果一时忘了，回来看表 5-3 就好。

**表 5-3 四个基础体检指标速查（第 1 章、第 2 章、第 3 章已登场）**

| 指标 | 白话含义 |
|------|---------|
| 累计收益率 | 从头到尾总共赚了多少 |
| 年化收益率 | 平均每年赚多少 |
| 年化波动率 | 价格上下波动的程度，数字越大越颠簸 |
| 最大回撤 | 最惨时从最高点跌了多少，用来衡量“最坏情况有多坏” |

这四个指标已经能看出策略“赚没赚、颠不颠、跌得深不深”。但它们各自只看一面。你还需要几把“综合尺”，把收益和风险放在一起看。第 3 章已经介绍过夏普比率，也说明本书表格里暂时使用的是简化口径：年化收益率 / 年化波动率。本章实验跑完后，我们会把简化夏普和另外两把尺子放在一起看：卡玛比、索提诺比。先做实验，再解释。

### 动手实验 1：策略对比买入持有基准

我们一起把这份 spec 写出来。这次重点看三件新东西：**金融指标的年化口径必须显式**、**open-xquant 评估与构造模块都要白话点名**、以及**防止 AI 写出错误分析的标准句**。

> 先看完下面的 spec 拆解，再回到运行结果。这一节信息会比前面密一些，因为 5.1 是本章信息量最大的一节。

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

第 5 章是“看”的一章，把前几章产出的策略配置放进体检台。上下文不引入新的策略，只把第 3 章、第 4 章的产物集合起来：

> **上下文**：本章评估策略是否真的好。第 3 章和第 4 章产出了 EqualWeight、RiskParity、TopNRanking、RiskParity+5% 止损四个策略配置，回测指标看起来不错。但“不错”是跟什么比？年化 15% 好不好，取决于同期一个简单参照做法赚了多少。
>
> **任务描述**：在 notebook `q5-how-to-validate.ipynb` 中，把四个策略配置和“等权买入持有”基准放在一起比较，引入多种风险调整指标。

> 📌 **要点**：第 5 章不引入新策略，只把前几章的产物集中送进体检台。spec 的上下文段要把“被检查对象”明确点名。这种“集合体检”型 spec 的好处是：读者只需要学习评估方法，不必再消化新的策略逻辑。

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

任务要求段做两件硬约束。第一件，点名 open-xquant 评估端和构造端要用哪几个模块，接口细节让 AI 自己去查。第二件，指标的年化方法必须写清楚，否则不同工具、不同时间跑出来的数字可能对不上。

> **任务要求**：
>
> 1. 评估端使用 oxq 的 `RunResult`，指标的计算口径显式锁定：
>    - 年化方法：**252 个交易日**（非 365 自然日）
>    - 简化夏普：`annualized_return / annualized_volatility`，不扣无风险收益
>    - 卡玛比：`annualized_return / abs(max_drawdown)`
>    - 索提诺比：`annualized_return / downside_volatility`（下行 = 收益 < 0 的标准差）
>    - 基准的简化夏普也要用同一口径
> 2. 构造端使用 oxq 的三个权重分配方法：等权（`EqualWeightOptimizer`）、风险平价（`RiskParityOptimizer`）、动量排名（`TopNRankingOptimizer`），按各自的构造参数和所需指标实例化
> 3. 数据快照固定：`START = "2021-01-01"`，`END = "2026-03-18"`（本章数字以此为基准，不要用 `today`）
> 4. 定义辅助函数 `run_strategy(portfolio, indicators=None, freq=10, stop_loss=None)` 供后续 spec 复用
> 5. 运行四个策略 + 构造“等权买入持有”基准（每只 ETF 归一化到 1，等权平均，之后不交易）

> 📌 **要点**：金融指标的年化口径（252 个交易日还是 365 个自然日、是否扣无风险收益、下行波动怎么定义）必须写明。零基础读者不知道这些约定，同一个指标在不同资料里口径可能不同。如果 spec 不锁定口径，你跑出 1.43，别人跑出 1.27，谁也不知道差在哪。指标 spec 的“精度”，恰恰落在这些看不见的小字上。

> 📌 **要点**：评估端和构造端要分别点名。第 1 条锁定评估端，也就是 `RunResult` 的指标计算；第 2 条列出构造端，也就是三个权重分配方法。零基础读者只需要知道“用哪些模块”，AI 会自己去查接口。spec 把模块点清楚，剩下的对照工作交给 AI。

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

最后一段最关键的不是“画几张图”，而是怎么让 AI 在不知道结果方向的情况下写出准确的分析文字：

> **验收标准**：
>
> 1. 策略与基准对比表（5 行 × 8 列）：策略名 / 累计收益 / 年化收益 / 波动率 / 最大回撤 / 简化夏普 / 卡玛比 / 索提诺比；最后一行是等权买入持有基准
> 2. 相对基准收益差表
> 3. 净值曲线对比图（figsize 12×6，4 实线 + 1 灰虚线，归一化到 100）
> 4. 分析文字（**根据实际数据动态描述方向，不要硬写“更高”或“更低”**）：哪些策略跑赢了基准？三把尺子的冠军是不是同一个？

> 📌 **要点**：「根据实际数据动态描述方向，不要硬写“更高”或“更低”」是第 5 章四份 spec 的标准句。AI 容易写出听上去合理、但和数据对不上的结论。把这句话当成第 5 章的标配，任何要 AI 写“分析文字”的 spec 都该带上。

完整示例 spec 在配套仓库的 [`q5-how-to-validate/specs/spec-01-benchmark-and-metrics.md`](https://github.com/xingwudao/xquant-learning/blob/main/q5-how-to-validate/specs/spec-01-benchmark-and-metrics.md)。参考它确认自己的 spec 后，再复制给 AI，按提示允许执行。

AI 执行完毕后，你的 notebook 里应该出现一张对比表、一张相对基准收益差表和一张净值曲线图。

这个实验做了什么？把第 3 章、第 4 章产出的四个策略配置（等权、风险平价、动量排名、风险平价 + 止损）全部重新跑一遍含成本的回测，同时构造一个“买入持有”基准：等权买入三只 ETF 后不再做任何交易，代表“什么都不做”的结果。然后把五条净值曲线画在一起，用七个指标（累计收益、年化收益、波动率、最大回撤、简化夏普、卡玛比、索提诺比）逐一比较，算出每个策略相对基准多赚或少赚了多少。

### 实验结果

四个策略与基准的指标对比如表 5-4 所示。

**表 5-4 四个策略与等权买入持有基准的指标对比**

| 策略 | 累计收益 | 年化收益 | 波动率 | 最大回撤 | 简化夏普 | 卡玛比 | 索提诺比 |
|------|---------|---------|--------|---------|--------|--------|---------|
| EqualWeight | 84.37% | 12.33% | 12.49% | -16.86% | 1.05 | 0.73 | 0.92 |
| RiskParity | 98.01% | 13.77% | 11.16% | -12.81% | 1.29 | 1.08 | 1.16 |
| TopNRanking | 153.03% | 18.71% | 15.77% | -17.77% | 1.27 | 1.05 | 1.11 |
| RP+止损5% | 106.23% | 14.59% | 10.61% | -13.07% | 1.43 | 1.12 | 1.33 |
| 等权买入持有 | 94.82% | 14.39% | 13.00% | -17.24% | 1.10 | — | — |

相对基准收益差（策略累计收益 - 基准累计收益 94.82%）如表 5-5 所示。

**表 5-5 四个策略相对等权买入持有基准的收益差**

| 策略 | 相对基准收益差 |
|------|-------|
| EqualWeight | -10.45% |
| RiskParity | +3.18% |
| TopNRanking | +58.20% |
| RP+止损5% | +11.41% |

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

![策略对比买入持有基准](images/q5-how-to-validate/01-strategy-vs-benchmark-nav.png)

### 结果解读

第一个认知升级：**“好不好”必须有参照物。**

**基准（Benchmark）**：用来做比较的参照物。这里的基准是“什么都不做”：等权买入三只 ETF 后不再交易。它就像考试的“及格线”。不跟基准比，你根本不知道自己的策略是好还是坏。

年化 14% 听起来不错，但等权买入持有同期也赚了 14.39%。EqualWeight 做了很多次交易，累计收益 84.37%，反而没跑赢“什么都不做”的 94.82%。这说明：多做事不一定带来更好结果。

表 5-5 看的就是“比基准多赚或少赚了多少”。EqualWeight 的相对基准收益差是 -10.45%，说明它不但没有跑赢简单基准，反而可能被频繁调整持仓带来的交易成本拖累了。TopNRanking 的相对基准收益差最高（+58.20%），但先别急着下结论。还要看其他指标怎么说。

第二个发现：**不同的尺子量出不同的结论。**

实验跑完了，正式介绍三把“综合尺”。它们各自把收益和风险放在一起，但对“风险”的定义不同：

- **简化夏普**：年化收益除以年化波动率。把“收益高”和“波动大”折成一个数字。注意，这里仍然沿用本书前面章节的简化口径，不扣无风险收益。
- **卡玛比（Calmar Ratio）**：年化收益除以最大回撤。每承受 1% 的最大回撤，能换来多少年化收益。如果你最怕“一次跌太深”，卡玛比是最直接的尺子。
- **索提诺比（Sortino Ratio）**：只用下行波动率做分母。上涨波动不是风险，涨得猛不应该被惩罚，所以索提诺比只关注亏损方向的波动。

简单记忆：**夏普看“颠不颠”，卡玛看“摔多惨”，索提诺只关心“亏的部分”。**

把这三把尺子放进表 5-4 之后回头看。三把尺子的冠军都是 RP+止损5%：简化夏普 1.43、卡玛比 1.12、索提诺比 1.33。TopNRanking 虽然收益最高，但三把尺子都不是冠军。这次三把尺子碰巧给出了同一个冠军，但不是每次都这么巧。不同的尺子关注不同的风险维度，完全可能给出不同答案。你最怕什么风险，就优先看对应的尺子。

但这些都是好几年平均出来的数字。**平均年化 14% 听着不错，但如果其中一年亏了 20%，你扛得住吗？**

---

## 5.2 每年都有收益吗？

刚才的指标覆盖了 2021 年初到 2026 年 3 月，整整 5 年多、1250 多个交易日。这么长时间的平均值，可能掩盖某些年份的亏损。就像考试平均 80 分，但其中一科考了 30 分。

直觉告诉我们：平均好就是好吧，哪年赚哪年亏不重要？

真的吗？拆开看看。

### 动手实验 2：逐年收益拆解

我们一起把这份 spec 写出来。这次重点看两件新东西：**接续型 spec 共享 notebook 状态**、以及**时间维度切片要避免重复回测**。

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

spec-02 不需要重新介绍策略。它直接接着 spec-01 在同一个 notebook 里跑。上下文段把“已经有什么”列清楚就够了：

> **上下文**：在 `q5-how-to-validate.ipynb` 中已有四个策略和基准的整体指标对比、`results` 字典、`run_strategy` 辅助函数、`TNR_PORTFOLIO` 等变量。读者已了解基准、相对基准收益差、卡玛比、索提诺比等概念。
>
> **任务描述**：按年度拆解策略表现，并深挖 TopNRanking 在负收益年份的异常。

> 📌 **要点**：第 5 章四份 spec 共享同一个 notebook 状态。spec-02 直接读 spec-01 留下的 `results` / `run_strategy` / `TNR_PORTFOLIO`。接续型 spec 的上下文段不必从头说明，只列“已经有什么”。这样 AI 不会重新下载数据、不会重新构建策略、不会假设一个不存在的变量。

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

任务要求段做两件事：按年度切片计算指标；深挖 TopNRanking 在负收益年份。这是最容易出现重复计算和口径不一致的地方。

> **任务要求**：
>
> 1. 用 oxq `RunResult` 的日收益序列（`daily_returns()`）和净值曲线（`equity_curve`）做时间切片
> 2. 按年度拆解四策略 + 基准：用 `daily_returns()` 按年分组，计算年收益率（累乘）、年波动率、年简化夏普、年内最大回撤。跳过样本不足的年份（`if len(year_data) < 20: continue`，避开新年初只有几个交易日的边界）
> 3. 打印逐年对比表（pandas DataFrame，存入变量 `annual_df` 供后续 spec 复用）
> 4. 画逐年收益柱状图（figsize 14×6，每年一组 5 根柱子，与 spec-01 颜色一致）
> 5. 深挖 TopNRanking 负收益年份：扫描 `mom_periods = [5, 10, 15, 20, 25, 30]`，每个窗口只跑一次回测，结果存入 `deep_dive[period]`，从字典里直接读，不要重新调用 `run_strategy` 做“是否所有窗口都亏”的二次判断

> 📌 **要点**：时间维度切片不要重复回测。“按年度拆”听起来像每年都要跑一遍，其实不需要。整段时间只跑一次，得到日收益序列后按 `index.year` 分组算指标。深挖也一样：6 个动量窗口跑 6 次，不要因为后面要二次判断又跑 6 次。spec 不点名“结果存 dict 复用”，AI 写出的代码大概率会重复回测。

> 📌 **要点**：最小样本过滤必须写清楚。年内少于 20 个交易日不进表，是为了避免样本太少导致年化数字失真。spec 不写明，AI 可能用 1 月份的 5 天数据计算“年化”，得出离谱数字。表上突然多出一行“2026 年化 +800%”，读者很难看出哪里错了。

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

> **验收标准**：
>
> 1. 逐年收益对比表（DataFrame，行=年份，列=4 策略+基准，负收益用 `*` 标注）
> 2. 逐年收益柱状图
> 3. TopNRanking 异常年份深挖表（行=动量窗口，列=负收益年份）
> 4. 分析文字（**根据实际数据动态描述方向**）：哪些策略“每年都赚”？深挖结论是“参数没选对”还是“策略结构性问题”？

完整示例 spec 在配套仓库的 [`q5-how-to-validate/specs/spec-02-annual-breakdown.md`](https://github.com/xingwudao/xquant-learning/blob/main/q5-how-to-validate/specs/spec-02-annual-breakdown.md)。参考它确认自己的 spec 后，再复制给 AI，按提示允许执行。

AI 执行完毕后，你的 notebook 里应该出现逐年对比表、柱状图和一份 TopNRanking 深挖分析。

这个实验做了什么？把第 1 个实验的整体指标拆成逐年成绩单。按年份分组计算每个策略和基准的年收益率、年波动率、年内最大回撤，看看哪些策略“每年都赚”，哪些有负收益年份。然后针对 TopNRanking 在负收益年份做深挖：换遍 6 种动量窗口（5 / 10 / 15 / 20 / 25 / 30 天）重新跑回测，看这一年的亏损是参数选错了，还是策略本身的结构性问题。

### 实验结果

四个策略 + 基准的逐年收益拆解如表 5-6 所示（`*` 标注负收益年份）。

**表 5-6 四策略与基准逐年收益对比**

| 年份 | EqualWeight | RiskParity | TopNRanking | RP+止损5% | 基准 |
|------|------------|------------|-------------|----------|------|
| 2021 | 3.76% | 1.03% | -10.09% * | 3.04% | 4.09% |
| 2022 | -12.72% * | -8.55% * | 3.04% | -8.63% * | -13.44% * |
| 2023 | 17.04% | 15.03% | 23.48% | 15.67% | 21.21% |
| 2024 | 27.55% | 30.12% | 24.50% | 30.65% | 28.31% |
| 2025 | 31.29% | 39.01% | 62.02% | 40.74% | 32.10% |
| 2026 | 3.88% | 3.00% | 9.65% | 3.00% | 5.24% |

逐年收益的柱状对比如图 5-2 所示。

![逐年收益对比](images/q5-how-to-validate/02-annual-return-comparison.png)

深挖 TopNRanking 在 2021 年的负收益。把动量窗口换遍，结果如表 5-7 所示。

**表 5-7 TopNRanking 2021 年不同动量窗口的年收益**

| 窗口 | 2021 |
|------|------|
| period=5 | -9.48% |
| period=10 | -7.97% |
| period=15 | -5.08% |
| period=20 | -10.09% |
| period=25 | -11.09% |
| period=30 | -9.14% |

所有动量窗口在 2021 年都亏钱。

### 结果解读

**分段检验（Segment Analysis）**：把回测结果按时间段拆开检查。整体指标是“平均分”，逐年拆开才是“每科成绩单”。整体及格不等于每科都及格。

拆开后两个重要发现：

**第一，没有哪个策略“年年赚钱”。** EqualWeight、RiskParity 和 RP+止损5% 在 2022 年都出现了负收益，同期基准也亏了 -13.44%。策略和基准一起亏，说明策略并没有真正提供“下跌保护”。这是资产配置策略的特点：它能分散风险，但不能消除市场整体下跌带来的损失。

**第二，TopNRanking 的负收益不是参数问题。** 2021 年，TopNRanking 是唯一亏钱的策略（-10.09%），而其他三个策略和基准都是正收益。换遍所有动量窗口（5 天到 30 天），在 2021 年全部亏钱。这是**动量策略的结构性弱点**。

**动量滞后性**：动量指标基于“过去涨了多少”来判断买什么。但当市场反复上下波动、没有明确方向时，过去涨得好的恰恰可能是“已经涨到头了”的那个。动量指标看的是后视镜，它有天然的滞后性。2021 年的市场就是典型的来回波动环境，动量策略在这种环境下容易吃亏，换什么参数都不一定能解决。

**数据说了算：逐年拆开，才能看到整体指标掩盖的问题。不同策略类型有不同的市场环境偏好。**

但年度还是太粗了。知道了哪年亏钱还不够。赚钱的年份里，是每月稳稳地赚，还是靠某几个月的大涨覆盖其他月份的亏损？

---

## 5.3 收益结构什么样？

年度表现解释了“什么时候赚、什么时候亏”，但没解释“怎么赚的”：是每个月稳稳地赚一点，还是靠几次大赚覆盖很多次小亏？

同样赚钱的两个策略，赚法可能完全不同。你能接受“一年中 8 个月亏钱、靠 4 个月大赚拉回来”的策略吗？

另外，回撤不只是一个数字。最大回撤 -15% 但 3 个月恢复，和最大回撤 -10% 但 1 年没恢复，哪个更痛苦？

### 动手实验 3：月度分布 + 回撤深度

我们一起把这份 spec 写出来。这次重点看两件新东西：**图表约定要写到颜色与子图布局**，以及**关键阈值（包括看似微小的 -0.001）必须显式**。

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

接续 spec-02 的发现：胜率全时段都差不多，但 2021 年有人亏 10% 有人赚 3%。这一份 spec 把“为什么差距这么大”拆开看：

> **上下文**：notebook 里已有四个策略和基准的整体对比、逐年拆解、TopNRanking 在反复波动市场中的结构性弱点。
>
> **任务描述**：分析月度收益分布和历史回撤事件。同样赚钱的策略，赚法可能完全不同。

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

第一组要求做月度分布。第二组做回撤事件。回撤事件的“什么算事件”阈值，是这份 spec 最容易被遗漏的精度点。

> **任务要求**：
>
> 1. 用 oxq `RunResult` 的月度收益（`monthly_returns()`）和回撤序列（`drawdown_series()`）做收益结构分析
> 2. 月度分布分析（四策略）：胜率、平均盈利月、平均亏损月、盈亏比、盈亏因子、最长连赢/连亏（**月收益 = 0 算亏损**）
> 3. 打印月度统计对比表 + 画月度收益分布直方图（figsize 14×8，2×2 子图，20 bins，x=0 处红色虚线）
> 4. 回撤深度分析：识别每次回撤事件，阈值锁定 `THRESHOLD = -0.001`（即跌幅 ≥ 0.1% 才算事件，避开数值噪声生成假事件）：起点 = dd 跌穿阈值的那天，恢复 = dd 反弹回阈值之上的那天，未恢复则标“—”
> 5. 打印每个策略前 5 大回撤事件 + 回撤汇总
> 6. 画水下曲线（figsize 14×10，4 子图垂直，**与 spec-01 同色继承**：EW=#4472C4 / RP=#ED7D31 / TNR=#70AD47 / RP+止损=#FFC000）
> 7. 拆解 TopNRanking 2021 年月度，说明为什么胜率 50% 但盈亏比 0.47 仍然会亏钱

> 📌 **要点**：图表和事件识别里的“阈值”包括看不见的数字。回撤事件的 `THRESHOLD = -0.001` 看似微不足道，但它直接决定有多少行进表。`-0.001` 可能给你 50 个事件，`-0.01` 可能只剩 10 个。spec 不锁阈值，AI 选不同值就会得出完全不同的“前 5 大回撤”，读者两次跑结果对不上，根本不知道差在哪。任何“看起来微小”的阈值，都应该写进 spec。

> 📌 **要点**：跨 spec 的颜色要继承。spec-01 的净值曲线用了 4 个颜色，spec-03 的水下曲线也要沿用。否则读者刚记住“绿色 = TNR 净值线”，下一张图又变成全蓝色，就很难对应。第 5 章一开始锁定的图表约定（颜色、figsize、布局），要在每份后续 spec 显式继承，不能假设 AI 会自动记住。

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

> **验收标准**：月度统计表（4 行）+ 月度直方图（2×2）+ TopNRanking 2021 年逐月明细 + 四策略 2021 月度对比 + 前 5 大回撤事件表 + 回撤汇总表 + 水下曲线图（4 子图）+ 分析文字（根据实际数据动态描述方向）

完整示例 spec 在配套仓库的 [`q5-how-to-validate/specs/spec-03-return-distribution-and-drawdown.md`](https://github.com/xingwudao/xquant-learning/blob/main/q5-how-to-validate/specs/spec-03-return-distribution-and-drawdown.md)。参考它确认自己的 spec 后，再复制给 AI，按提示允许执行。

AI 执行完毕后，你的 notebook 里应该出现月度统计表、分布直方图、2021 年胜率陷阱分析、回撤事件表和水下曲线图。

这个实验做了什么？从两个维度拆解“怎么赚的钱”。第一个维度是月度收益分布：把每个策略的日收益按月汇总，统计胜率（赚钱月占比）、盈亏比（平均赚多少、平均亏多少）、最长连赢/连亏月数等。还专门拆解了 TopNRanking 2021 年的逐月明细，和其他三个策略对比同年的胜率和盈亏比，解释为什么胜率差不多、结局却完全不同。第二个维度是回撤深度：识别每次从高点下跌到恢复的完整事件，记录深度、下跌天数、恢复天数，画出水下曲线。

内容比较多，我们分两个维度来看。

**维度一：月度收益分布**

四个策略的月度统计指标如表 5-8 所示。

**表 5-8 四策略月度收益统计对比**

| 策略 | 胜率 | 平均盈利月 | 平均亏损月 | 盈亏比 | 盈亏因子 | 最好月 | 最差月 | 连赢 | 连亏 |
|------|------|----------|----------|--------|---------|--------|--------|------|------|
| EqualWeight | 63.5% | 2.54% | -1.63% | 1.55 | 2.70 | 9.52% | -7.82% | 8 | 3 |
| RiskParity | 61.9% | 2.79% | -1.56% | 1.79 | 2.91 | 11.29% | -6.09% | 11 | 4 |
| TopNRanking | 61.9% | 3.88% | -2.21% | 1.75 | 2.85 | 9.88% | -8.36% | 11 | 4 |
| RP+止损5% | 63.5% | 2.77% | -1.55% | 1.79 | 3.12 | 11.74% | -5.52% | 11 | 4 |

四个策略的月度收益分布直方图如图 5-3 所示。

![月度收益分布](images/q5-how-to-validate/03-monthly-return-distribution.png)

乍一看，四个策略的胜率都差不多，都是 62% 左右。但第 2 个实验告诉我们，TopNRanking 在 2021 年亏了 10%，而其他策略同年都是正收益。胜率差不多，为什么结局完全不同？拆解 2021 年的月度数据就能看清原因。

**拆解 TopNRanking 2021 年：胜率的陷阱**

TopNRanking 在 2021 年的逐月收益如表 5-9 所示。

**表 5-9 TopNRanking 2021 年逐月明细**

| 月份 | 收益 |
|------|------|
| 2021-01 | 0.00% |
| 2021-02 | -7.29% |
| 2021-03 | -1.44% |
| 2021-04 | +1.93% |
| 2021-05 | +1.54% |
| 2021-06 | -1.78% |
| 2021-07 | +1.17% |
| 2021-08 | +2.28% |
| 2021-09 | -4.30% |
| 2021-10 | +1.12% |
| 2021-11 | +0.75% |
| 2021-12 | -4.05% |

把四个策略放在 2021 这一年同一张表里对比，胜率与盈亏比的差异如表 5-10 所示。

**表 5-10 四策略 2021 年月度胜率与盈亏比对比**

| 策略 | 胜率 | 平均盈利月 | 平均亏损月 | 盈亏比 | 年收益 |
|------|------|----------|----------|--------|--------|
| EqualWeight | 50% | 2.03% | -1.37% | 1.48 | 3.76% |
| RiskParity | 58% | 1.76% | -2.20% | 0.80 | 1.03% |
| TopNRanking | 50% | 1.46% | -3.14% | 0.47 | -10.09% |
| RP+止损5% | 58% | 1.77% | -1.82% | 0.97 | 3.04% |

看上面的 2021 年对比。TopNRanking 的胜率 50%，跟 EqualWeight 一样。但它赚的月份平均只赚 1.46%，亏的月份平均亏 3.14%，盈亏比只有 0.47。翻译一下：赚的时候赚得少，亏的时候亏得多。结果是，虽然一半的月份赚钱，但亏损月把所有利润全吃掉还倒贴了，全年 -10.09%。

同年的 EqualWeight 胜率也是 50%，但盈亏比 1.48。赚的月份平均赚 2.03%，亏的月份平均只亏 1.37%。同样的胜率，完全不同的结局。

这就是**胜率的陷阱**：大多数人天然觉得“赢的次数越多越好”，但胜率本身意义不大。胜率 90%，每次赚 1 元；亏的那 10% 每次亏 20 元。10 次交易赚 9 元、亏 20 元，净亏 11 元。高胜率，也可能亏钱。

真正决定收益的是**盈亏比（Win/Loss Ratio）**：平均每次赚多少除以平均每次亏多少。优秀策略的关键是“小亏大赚”：亏的时候尽量控制亏损幅度，赚的时候让利润继续增长。只追求高胜率，可能会忽略亏损幅度。

**盈亏因子（Profit Factor）**：总盈利除以总亏损的绝对值。大于 1 说明赚的比亏的多，大于 2 通常已经不错。四个策略的盈亏因子都在 2.7 到 3.1 之间，整体看都不错。但注意，这是全时段的数字。拆到具体年份，比如 2021 年，TopNRanking 的盈亏因子会远低于 1。

**维度二：回撤深度**

**前 5 大回撤事件**

EqualWeight 的前 5 大回撤事件如表 5-11 所示。

**表 5-11 EqualWeight 前 5 大回撤事件**

| # | 开始 | 最低点 | 恢复 | 深度 | 下跌天数 | 恢复天数 |
|---|------|--------|------|------|---------|---------|
| 1 | 2021-11-22 | 2022-10-28 | 2023-06-16 | -16.86% | 340 | 231 |
| 2 | 2021-02-18 | 2021-03-09 | 2021-11-15 | -9.88% | 19 | 251 |
| 3 | 2025-02-20 | 2025-04-07 | 2025-05-06 | -9.22% | 46 | 29 |
| 4 | 2026-01-30 | 2026-02-02 | 未恢复 | -7.95% | 3 | — |
| 5 | 2024-07-18 | 2024-08-05 | 2024-09-26 | -7.82% | 18 | 52 |

最大回撤：-16.86% / 平均恢复：17 天 / 最长恢复：251 天

RiskParity 的前 5 大回撤事件如表 5-12 所示。

**表 5-12 RiskParity 前 5 大回撤事件**

| # | 开始 | 最低点 | 恢复 | 深度 | 下跌天数 | 恢复天数 |
|---|------|--------|------|------|---------|---------|
| 1 | 2021-11-22 | 2022-10-28 | 2023-05-19 | -12.81% | 340 | 203 |
| 2 | 2021-02-22 | 2021-03-09 | 2021-07-15 | -7.98% | 15 | 128 |
| 3 | 2025-02-20 | 2025-04-07 | 2025-04-16 | -6.72% | 46 | 9 |
| 4 | 2026-01-30 | 2026-02-02 | 未恢复 | -6.02% | 3 | — |
| 5 | 2024-07-19 | 2024-08-05 | 2024-09-26 | -5.94% | 17 | 52 |

最大回撤：-12.81% / 平均恢复：15 天 / 最长恢复：203 天

TopNRanking 的前 5 大回撤事件如表 5-13 所示。

**表 5-13 TopNRanking 前 5 大回撤事件**

| # | 开始 | 最低点 | 恢复 | 深度 | 下跌天数 | 恢复天数 |
|---|------|--------|------|------|---------|---------|
| 1 | 2021-02-22 | 2022-06-01 | 2023-03-20 | -17.77% | 464 | 292 |
| 2 | 2026-01-30 | 2026-02-02 | 未恢复 | -14.39% | 3 | — |
| 3 | 2024-07-10 | 2024-09-04 | 2024-12-17 | -14.02% | 56 | 104 |
| 4 | 2023-07-20 | 2023-12-05 | 2024-02-23 | -9.34% | 138 | 80 |
| 5 | 2025-04-23 | 2025-04-28 | 2025-06-30 | -6.48% | 5 | 63 |

最大回撤：-17.77% / 平均恢复：14 天 / 最长恢复：292 天

RP+止损5% 的前 5 大回撤事件如表 5-14 所示。

**表 5-14 RP+止损5% 前 5 大回撤事件**

| # | 开始 | 最低点 | 恢复 | 深度 | 下跌天数 | 恢复天数 |
|---|------|--------|------|------|---------|---------|
| 1 | 2021-11-22 | 2022-10-21 | 2023-05-19 | -13.07% | 333 | 210 |
| 2 | 2021-02-22 | 2021-03-09 | 2021-05-18 | -6.06% | 15 | 70 |
| 3 | 2026-01-30 | 2026-02-02 | 未恢复 | -6.02% | 3 | — |
| 4 | 2024-07-19 | 2024-08-05 | 2024-09-26 | -5.94% | 17 | 52 |
| 5 | 2025-02-20 | 2025-04-07 | 2025-04-11 | -5.57% | 46 | 4 |

最大回撤：-13.07% / 平均恢复：13 天 / 最长恢复：210 天

四个策略的水下曲线如图 5-4 所示，可以直观看到“在水下度过的时间”。

![水下曲线](images/q5-how-to-validate/04-underwater-curves.png)

### 结果解读

收益结构揭示了“怎么赚的钱”，这里有两个关键维度。

**胜率是陷阱，盈亏比才是关键。** 四个策略全时段的胜率都在 62% 左右，看不出差别。但拆到 2021 年，TopNRanking 的盈亏比只有 0.47。每赚 1 块钱，对应要亏 2 块多。同年 EqualWeight 盈亏比 1.48，赚的月份能覆盖亏的月份。同样的胜率，截然不同的结局。真正决定收益的不是赢的次数，而是赢的时候赚多少、亏的时候亏多少。

**回撤不只是深度，还有恢复时间。** TopNRanking 的最大回撤 -17.77%，从 2021 年 2 月开始下跌，直到 2023 年 3 月才恢复，整整两年都没有回到前高。RiskParity 最大回撤 -12.81%，恢复用了 203 天。RP+止损5% 最大回撤 -13.07%，恢复用了 210 天。

**水下曲线（Underwater Curve）**：每天距离历史最高点跌了多少。它直观展示一个残酷的事实：你有多少时间是在“还没回本”的状态中度过的。回撤不只是一个数字，它是一段真实的持有体验。深度和恢复时间同样重要。

**回撤恢复时间**：从最低点爬回前高需要多久。回撤 -15% 但 3 个月恢复，和回撤 -10% 但 1 年没恢复相比，后者对实际持有体验的伤害可能更大。比起回撤深度，恢复时间更影响你能不能拿得住。

**数据说了算：赚钱的方式和赚钱一样重要。** 别被高胜率迷惑，关注盈亏比；别只看回撤深度，还要看恢复时间。

评估够全面了吗？其实还有一个隐藏问题：你用的参数（动量窗口 20 天、波动率窗口 20 天、止损阈值 5%）是在历史数据里选出来的。但如果把 20 天前后扰动一下，比如改成 15 天或 25 天，结果还差不多吗？如果稍微一动就差很多，那这个“最优”在未来的数据上恐怕也靠不住。

---

## 5.4 参数动一动，结果还稳吗？

前面三个实验的评估都基于特定参数：动量窗口 20 天、波动率窗口 20 天、止损阈值 5%。这些参数是在历史数据里选出来的，至少在这段数据上表现不错。

但问题是：在最优参数附近前后扰动一下，比如动量窗口从 20 天改成 15 天或 25 天，结果是差不多，还是会差很多？如果附近的参数表现都还行，说明这个“最优”相对稳定；如果稍微一动，简化夏普就从 1.27 跌到 0.85，那历史上的“最优”很可能在未来数据上不再最优。

直觉告诉我们：找到最优参数就行了。真的吗？

### 动手实验 4：参数敏感性扫描

我们一起把这份 spec 写出来。这次重点看两件新东西：同样是参数扫描，这次目的不同；要让“高原型”和“山峰型”的视觉对比成立，y 轴范围必须统一。

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

这是读者第二次见到参数扫描。上次在第 1 章，是用来“找最优参数”；这次在第 5 章，是用来“判断结果是否稳定”。同样的技术，不同的目的。这个区别必须在上下文段就讲清楚，否则读者会困惑为什么又来一次：

> **上下文**：notebook 里已有四策略的整体指标、逐年收益、月度分布、回撤分析。所有分析都基于特定参数（period=20, freq=10, threshold=0.05）。
>
> 当前问题：如果参数稍微变一下，结论还成立吗？
>
> **注意**：这里的参数扫描和第 1 章 spec-06 不同。第 1 章是“用扫描找最优参数”，目的是挑值；本章是“用扫描判稳健性”，目的是看形状。同样的技术，完全不同的目的。本章不是要找出比 20 更好的窗口，而是要判断“在 20 附近的所有值，结果是不是都差不多”。
>
> **任务描述**：扫描 RiskParity 波动率窗口、TopNRanking 动量窗口、止损阈值三个维度，对比“高原型”和“山峰型”。

> 📌 **要点**：同方法不同目的，必须在 spec 里显式区分。参数扫描在第 1 章是过拟合的诱因，因为它容易让你挑出漂亮数字；在第 5 章则是检查稳健性的方法，因为它用来观察附近参数是不是都差不多。如果 spec 不点名“这次不是为了找最优”，读者会以为又是一次找最优，下一章讲过拟合时就接不上。工具的意义会随章节变化，spec 必须写出当前章节用它干什么。

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

> **任务要求**：
>
> 1. RiskParity 波动率窗口扫描 `vol_period = [10, 15, 20, 25, 30, 40]`：中心 20 是 spec-01 选定值，左右对称展开 ±10/±15，加 40 看远端外推；不试 5（5 天太短无法稳定估计波动率）
> 2. TopNRanking 动量窗口扫描 `mom_period = [10, 15, 20, 25, 30, 40]`（波动率窗口固定 20）
> 3. 止损阈值扫描 `thresholds = [0.02, 0.03, 0.05, 0.07, 0.10, 0.15, 0.20]` + 无止损（共 8 行表，无止损作为最后一行，“止损阈值”列填“无”）
> 4. 计算每组的简化夏普极差（max - min），打印对比 + 标注“高原型”（极差小）和“山峰型”（极差大）
> 5. 画三子图折线（figsize 15×5，1×3 布局），y 轴范围统一，这样 RP 的“平”和 TNR 的“尖”才能立刻可见
> 6. 输出“山顶营地”隐喻：高原型像一片平坦的高原（站在哪都差不多高），山峰型像一座尖峰（偏一步就掉下去）

> 📌 **要点**：参数列表的设计必须能解释。`[10, 15, 20, 25, 30, 40]` 不是随便挑。中心 20 是当前选定值，左右展开看附近，加远端 40 看外推。spec 不解释扫描点的来历，读者仿写时只会照抄数字，遇到自己的策略就不知道该挑哪些值扫。

> 📌 **要点**：y 轴统一，是“高原型”和“山峰型”对比能不能看出来的关键。三个子图如果各自缩放，看起来都会“波动很大”，因为每个图都填满了画布。统一 ylim 后，RP 是平的，TNR 是尖的，差异会立刻出现。参数敏感性对比图，坐标轴要尽量共享。

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

> **验收标准**：RiskParity 波动率窗口表（6×5）+ TopNRanking 动量窗口表（6×5）+ 止损阈值表（8×5）+ 简化夏普极差对比 + 折线敏感性图（1×3）+ 分析文字（根据实际数据动态描述方向），用“山顶营地”隐喻收束

完整示例 spec 在配套仓库的 [`q5-how-to-validate/specs/spec-04-parameter-sensitivity.md`](https://github.com/xingwudao/xquant-learning/blob/main/q5-how-to-validate/specs/spec-04-parameter-sensitivity.md)。参考它确认自己的 spec 后，再复制给 AI，按提示允许执行。

AI 执行完毕后，你的 notebook 里应该出现三组参数敏感性表和一张折线对比图。

这个实验做了什么？分三组做参数扰动测试。第一组：保持其他参数不变，把 RiskParity 的波动率窗口从 10 天到 40 天逐个试一遍，看简化夏普变化多大。第二组：对 TopNRanking 做同样的事，把动量窗口从 10 天到 40 天逐个试。第三组：固定 RiskParity 策略，把止损阈值从 2% 到 20% 逐个试（外加无止损对照）。然后算出每组的简化夏普极差（最高减最低），判断策略是“高原型”（参数怎么调都差不多）还是“山峰型”（偏一点结果就明显变差）。

### 实验结果

RiskParity 波动率窗口扫描结果如表 5-15 所示。

**表 5-15 RiskParity 波动率窗口敏感性**

| 窗口（天） | 累计收益 | 简化夏普 | 卡玛比 | 回撤 |
|----------|---------|--------|--------|------|
| 10 | 104.32% | 1.33 | 1.13 | -12.80% |
| 15 | 102.65% | 1.33 | 1.13 | -12.64% |
| 20 | 98.01% | 1.29 | 1.08 | -12.81% |
| 25 | 96.76% | 1.28 | 1.06 | -12.93% |
| 30 | 109.29% | 1.39 | 1.10 | -13.49% |
| 40 | 111.45% | 1.40 | 1.05 | -14.37% |

简化夏普极差：0.13

TopNRanking 动量窗口扫描结果如表 5-16 所示。

**表 5-16 TopNRanking 动量窗口敏感性**

| 窗口（天） | 累计收益 | 简化夏普 | 卡玛比 | 回撤 |
|----------|---------|--------|--------|------|
| 10 | 104.21% | 1.00 | 0.72 | -19.91% |
| 15 | 83.31% | 0.85 | 0.73 | -16.78% |
| 20 | 153.03% | 1.27 | 1.05 | -17.77% |
| 25 | 144.73% | 1.21 | 1.10 | -16.46% |
| 30 | 105.42% | 1.02 | 0.87 | -16.64% |
| 40 | 101.54% | 1.00 | 0.74 | -19.03% |

简化夏普极差：0.42

止损阈值的扫描结果如表 5-17 所示（基于 RiskParity 策略，再平衡频率 10 天）。

**表 5-17 止损阈值敏感性**

| 止损阈值 | 累计收益 | 简化夏普 | 最大回撤 | 交易次数 |
|---------|---------|--------|---------|---------|
| 2% | 125.87% | 1.63 | -9.65% | 402 |
| 3% | 118.80% | 1.56 | -11.62% | 394 |
| 5% | 106.23% | 1.43 | -13.07% | 387 |
| 7% | 100.90% | 1.36 | -13.26% | 382 |
| 10% | 106.16% | 1.40 | -12.02% | 375 |
| 15% | 99.30% | 1.32 | -12.51% | 371 |
| 20% | 97.04% | 1.29 | -13.23% | 370 |
| 无止损 | 98.01% | 1.29 | -12.81% | 369 |

简化夏普极差：0.35

三组参数的简化夏普极差汇总如表 5-18 所示。

**表 5-18 参数敏感性极差对比**

| 参数组 | 简化夏普极差 | 类型 |
|--------|----------|------|
| RiskParity | 0.13 | 高原型（参数不敏感） |
| TopNRanking | 0.42 | 山峰型（参数敏感） |
| 止损阈值 | 0.35 | 山峰型（参数敏感） |

三组参数的简化夏普折线对比如图 5-5 所示。

![参数敏感性对比](images/q5-how-to-validate/05-parameter-sensitivity.png)

### 结果解读

最后一个认知升级：**好策略不怕参数变。**

**参数敏感性（Parameter Sensitivity）**：改一个参数值，策略表现变化有多大。这是策略体检中不可或缺的一项。

看 RiskParity：波动率窗口从 10 天调到 40 天，简化夏普在 1.28 到 1.40 之间，极差只有 0.13。不管你选哪个窗口，结果都差不多。这叫**高原型（Plateau）**：像一片平坦的高原，站在哪里都差不多高。

再看 TopNRanking：动量窗口从 10 天调到 40 天，简化夏普在 0.85 到 1.27 之间，极差 0.42，是 RiskParity 的 3 倍多。窗口选 20 天时简化夏普 1.27，选 15 天时只有 0.85，掉了 1/3。这叫**山峰型（Peak）**：像一座尖峰，只有山尖上最高，稍微偏一步就掉下去。

想象你在山上找营地。高原型策略像一片平坦的高原，站在哪里都差不多高。山峰型策略像一座尖峰，只有山尖上最高，稍微偏一步就掉下去。你选哪个？

**好策略不应该依赖某一个特殊参数。** 如果换一个参数值，简化夏普就从 1.27 跌到 0.85（掉了 1/3），说明你可能只是运气好选对了那个值。RiskParity 的有效性来自基本逻辑：“波动大的少买”。不管你用 10 天还是 40 天窗口来衡量波动，排序关系不会剧烈变化。TopNRanking 的高收益则部分依赖于“恰好选对了参数 20”。

这也呼应了第 2 个实验的发现：TopNRanking 在某些年份负收益、对参数敏感，它的高收益可能有运气成分。RiskParity 虽然收益不如 TopNRanking 高，但参数更稳、年度一致性更好，这才是更可靠的策略。

**选策略就像选营地：要选高原，不选尖峰。**

回头看：还记得第 1 章末尾你亲眼看到的那次“参数扫描里冠军在样本外掉到了水下”吗？那就是山峰型在参数和时间两个维度上同时暴露的问题。你当时亲手看到一次漂亮回测失效，从此对回测多一份警觉。

**这一章的高原型和山峰型，是从“看”走向“疑”的桥梁。下一章，你会专门训练“疑”：检查回测本身是否可信。**

---

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

这一节是“看”的操作流程总图，把四个实验铺成一条以后可以复用的检查路径：

- **第 1 个实验：跟什么比？** 基准 + 相对基准收益差 + 多维指标（简化夏普 / 卡玛比 / 索提诺比）
- **第 2 个实验：每年都有收益吗？** 分段检验 + 策略类型弱点（动量滞后性）
- **第 3 个实验：收益结构什么样？** 胜率陷阱 / 盈亏比 / 盈亏因子 + 回撤深度 / 恢复时间
- **第 4 个实验：参数动一动，结果还稳吗？** 参数敏感性 + 高原型和山峰型

从今以后，拿到任何策略的回测结果，你都可以用这四步做一次“全面体检”。这四步会拆出五个具体检查问题，如表 5-19 所示。

**表 5-19 策略体检维度速查**

| 维度 | 问题 |
|------|------|
| 基准 | 跑赢了吗？ |
| 年度 | 每年都赚吗？ |
| 分布 | 赚法健康吗？ |
| 回撤 | 最坏到什么程度？ |
| 参数 | 参数改了还行吗？ |

**从“看收益率”到“全面体检”，这是本章最重要的认知升级。**

### 五个最容易让你“被自己骗”的陷阱

每个维度对应一种最容易踩的陷阱。它们各有不同名字，但本质都是“指标好看，结果不靠谱”。下次别人（或者你自己）拿一份“漂亮”的回测来，先用这五个视角扫一遍：

1. **基准陷阱**：只看年化收益，没和“什么都不做”对比。EqualWeight 累计 84% 看着还行，等权买入持有同期 95%，你忙了半天反而落后。
2. **整体陷阱**：只看多年累计，掩盖了某些年份的大亏。TopNRanking 累计第一，但 2021 年是唯一亏钱的策略（-10.09%），其他三个策略同期都是正收益，普通人在那年可能就放弃了。
3. **胜率陷阱**：胜率 90% 不等于赚钱。一次大亏可以抹平十次小赚，真正决定结果的是盈亏比和盈亏因子。
4. **回撤陷阱**：只看最大回撤深度，不看恢复时间。跌 15% 但 3 个月恢复，和跌 10% 但 1 年不恢复，持有体验完全不同。
5. **山峰陷阱**：某个参数最优，稍微一偏简化夏普就掉一大截。这往往不是规律，是巧合，和第 1 章末尾那次样本外失效是同一种问题。

五个陷阱合起来，就是本章反复强调的事：不是指标越多越好，而是每个指标只看一面。你得把几面合起来看，才能少被自己骗。

---

## 5.6 本章总结

### 策略进化路径

**第 4 章产出：风险平价 + 止损 + 三个对比策略**

- 第 1 个实验：跟基准比，不是所有策略都跑赢了“什么都不做”
- 第 2 个实验：逐年拆，某些年份亏损，动量策略有结构性弱点
- 第 3 个实验：看分布，胜率是陷阱，盈亏比才是关键
- 第 4 个实验：动参数，高原型稳，山峰型脆

**第 5 章产出：完整的策略评估方法 + “体检清单”**

### 概念速查表

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

**表 5-20 第 5 章核心概念速查**

| 概念 | 含义 | 类比 |
|------|------|------|
| 基准（Benchmark） | 用来做比较的参照物，“什么都不做”时你能赚多少 | 考试的“及格线” |
| 相对基准收益差 | 策略收益减去基准收益 | 比及格线高多少或低多少 |
| 卡玛比（Calmar） | 年化收益 / 最大回撤 | 每承受 1% 最大回撤换多少收益 |
| 索提诺比（Sortino） | 只用下行波动率做分母 | 上涨波动不算风险 |
| 分段检验 | 把回测按年份拆开 | 整体及格不等于每科都及格 |
| 动量滞后性 | 动量指标基于“过去涨了多少” | 后视镜，过去涨不代表未来继续涨 |
| 胜率的陷阱 | 胜率本身意义不大 | 胜率 90% 也可能亏钱 |
| 盈亏比（Win/Loss Ratio） | 平均盈利 / 平均亏损 | 真正决定收益的指标 |
| 盈亏因子（Profit Factor） | 总盈利 / 总亏损 | 大于 1 赚钱，大于 2 优秀 |
| 水下曲线（Underwater） | 每天距离历史最高点跌了多少 | “你在水下待了多久” |
| 回撤恢复时间 | 从最低点爬回前高要多久 | 比深度更影响持有体验 |
| 参数敏感性 | 改参数后结果变化多大 | 好策略不怕参数变 |
| 高原型和山峰型 | 高原：参数怎么调都差不多。山峰：偏一点简化夏普极差大 | 找营地选高原不选尖峰 |

### 本章核心认知

走完四步实验，沉淀下来的认知如表 5-21 所示。

**表 5-21 第 5 章核心认知**

| 认知 | 来源 |
|------|------|
| “好不好”必须有参照物：基准 | 第 1 个实验 |
| 相对基准收益差告诉你有没有跑赢简单做法 | 第 1 个实验 |
| 简化夏普、卡玛比、索提诺比是三把不同的尺子 | 第 1 个实验 |
| 整体指标可能掩盖年度亏损：分段检验 | 第 2 个实验 |
| 动量策略在反复震荡的市场中有结构性弱点：滞后性 | 第 2 个实验 |
| 胜率是陷阱，真正决定收益的是盈亏比 | 第 3 个实验 |
| 回撤不只是深度，还有恢复时间：水下曲线 | 第 3 个实验 |
| 好策略不怕参数变：高原型优于山峰型 | 第 4 个实验 |
| 先猜后验，数据说了算 | 贯穿全章 |

### 带走的问题

- 体检工具给了你客观数据。但**回测本身可信吗？** 回测能调参数让收益翻倍，这是真的好，还是自欺欺人？这是第 6 章要回答的问题。
- 如果你在 2023 年跑回测发现某个策略 2021-2023 表现好，你怎么知道它 2024 年还会好？这也是第 6 章要回答的问题。

带着这两个问题进入下一章。它们正是“疑”这个环节要训练的核心。这一章你已经把“看”练了一遍，下一章我们专门把“疑”练成主线。

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

---

## 拓展阅读

本章正文聚焦“四步策略体检”。下面三段是主线之外的补充，读完正文后再看更容易吸收。

### 为什么“年化”用 252 这个数字

正文反复说“年化收益率”、“年化波动率”，背后都隐含一个换算系数：**252**。

A 股一年大约 250 到 252 个交易日（节假日不开盘），美股 252 个，全球主流市场都接近这个数。所以，从日收益换算成年化时，常见做法是：**年化收益率 ≈ 平均日收益率 × 252**；**年化波动率 ≈ 日收益率标准差 × √252**。注意，波动率是乘以根号 252，不是直接乘以 252。比如一个策略日波动率 1%，年化波动率 ≈ 1% × √252 ≈ 15.87%。回测里所有“年化”指标都用了这个换算。它不是定理，但是常见行业惯例。

### 夏普比率和信息比率（IR）

本书表格里用的是简化夏普：年化收益 / 年化波动。你可能在论文或基金报告里见过另一个相似的指标：**信息比率（Information Ratio, IR）**。

二者长得很像，区别在分子：简化夏普的分子是策略本身的年化收益，信息比率的分子是“策略收益减去基准收益”。也就是说，信息比率衡量的是：在扣掉简单参照做法之后，策略多赚的那一部分是否值得它承担的波动。本书默认用简化夏普，因为更直观；但你以后看到信息比率不要陌生，它只是把比较对象换成了“相对基准的收益差”。

### 索提诺比的“MAR”参数

正文说索提诺比 = 年化收益 / 下行波动率。但什么算“下行”？常见定义是：收益低于某个阈值（叫 MAR，Minimum Acceptable Return，最低可接受收益率）的那部分波动。

常见的两种 MAR 选法：第一，**MAR = 0**，把“亏损”定义为“日收益率 < 0”，最简单；第二，**MAR = 无风险利率**，把“没跑赢无风险收益”也算“下行”，更严格。本书计算时用的是 MAR = 0，更直观。你看到不同来源的索提诺比数值有差异时，先确认它们用的是哪种 MAR，否则比的不是同一个东西。
