先说结论:把”最小化最大回撤”直接写成优化目标在技术上完全可行——非复利口径下 MaxDD 约束是线性的,加一组辅助变量就是标准 LP。但我这次实验的主角不是这个技巧,而是它的翻车现场:单路径 min-MaxDD 解在 100 次块自助重抽样下权重 IQR 高达 0.27/0.39(方差目标只有 0.13/0.12,稳定性差 2-3 倍),样本外 200 条路径的中位 MaxDD 12.8%,反而输给了它声称要打败的最小方差组合(10.6%)。原因不复杂:MaxDD 是路径泛函,由一条历史上的一个点决定,对着它优化等于对着噪声做精确制导。补救方案是把优化从”一条路径”升级到”多条情景的 worst-case”——20 情景鲁棒解把训练集最差回撤从 23.9% 压到 21.8%,样本外中位 MaxDD 也从 12.8% 收回到 11.5%。回撤优化不是不能做,是不能对一条路径做。
这篇接在 CDaR 之后:那篇讲的是把回撤尾部的平均写进目标(CDaR₉₅),这篇走到光谱最极端的一端——直接优化 MaxDD 本身,然后眼睁睁看它过拟合,再用多情景把它救回来。
MaxDD 也能写成线性规划#
沿用 CDaR 篇的非复利口径。给定权重 ,组合累计收益 ( 是资产 的累计简单收益),回撤是 。
MaxDD 的麻烦在 这个 running max——它不是 的光滑函数。但有个经典技巧:引入辅助变量 代表 running max,用两组不等式把它”夹”出来:
最小化 。在最优解处 会被压到恰好等于 running max(多余的松弛只会让 变大),于是 就是最大回撤。全部约束对 线性——这就是一个 LP:
from scipy.optimize import linprog
from scipy import sparse
import numpy as np
def solve_min_maxdd(R_cum, mu_d, target):
"""min u s.t. m_t >= W_t, m_t >= m_{t-1}, m_t - W_t <= u,
mu'w >= target, sum(w)=1, w>=0. R_cum: (T,K) 累计简单收益"""
T, K = R_cum.shape
nv = K + T + 1 # 变量: w, m, u
iw, im, iu = 0, K, K + T
rows, cols, vals, rhs = [], [], [], []
rc = 0
for t in range(T):
# W_t - m_t <= 0
for k in range(K):
rows += [rc]; cols += [iw + k]; vals += [R_cum[t, k]]
rows += [rc]; cols += [im + t]; vals += [-1.0]; rhs += [0.0]; rc += 1
if t > 0: # m_{t-1} - m_t <= 0
rows += [rc, rc]; cols += [im + t - 1, im + t]
vals += [1.0, -1.0]; rhs += [0.0]; rc += 1
# m_t - W_t - u <= 0
rows += [rc]; cols += [im + t]; vals += [1.0]
for k in range(K):
rows += [rc]; cols += [iw + k]; vals += [-R_cum[t, k]]
rows += [rc]; cols += [iu]; vals += [-1.0]; rhs += [0.0]; rc += 1
# 收益约束 -mu'w <= -target
for k in range(K):
rows += [rc]; cols += [iw + k]; vals += [-mu_d[k]]
rhs += [-target]; rc += 1
A = sparse.coo_matrix((vals, (rows, cols)), shape=(rc, nv)).tocsr()
Aeq = sparse.coo_matrix((np.ones(K), (np.zeros(K), np.arange(K))),
shape=(1, nv)).tocsr()
c = np.zeros(nv); c[iu] = 1.0
res = linprog(c, A_ub=A, b_ub=rhs, A_eq=Aeq, b_eq=[1.0],
bounds=[(0, 1)] * K + [(0, None)] * T + [(0, None)],
method="highs")
return res.x[:K], res.x[iu]python顺带一提,这个骨架和 CDaR 的 LP 只差最后一组约束:CDaR 把 超过门槛 的部分收集起来取平均,MaxDD 直接压最大值。CDaR 的 极限就是 MaxDD——它们是同一个家族的两端。
实验设定:三资产两状态#
沿用回撤系列的模拟世界:股票(平时年化 +12%/15%,危机 −35%/30%)、债券(+3%/5%,危机 +6%/7%)、趋势(平时 +2%/13%,危机 +60%/26%),两状态马尔可夫切换,危机平均持续约 20 天。样本内一条 10 年路径(2500 天),实现的年化均值:股票 5.8%、债券 4.7%、趋势 14.4%(这条路径趋势资产运气很好——记住这一点,后面要用)。
先看一眼三个目标在同一条路径、同一收益约束(年化 9.7%)下给出的权重:
| 目标 | 股票 | 债券 | 趋势 |
|---|---|---|---|
| min 方差 | 27.3% | 24.7% | 48.0% |
| min CDaR₉₅ | 0% | 49.0% | 51.0% |
| min MaxDD | 0% | 49.0% | 51.0% |
CDaR 和 MaxDD 给出了完全相同的解,而且都把股票清零。这不是巧合:这条路径上的深回撤全部由股票的危机段贡献,任何盯着回撤尾部的目标都会做同一件事——扔掉股票,用债券+趋势填收益约束。

图里是最小方差组合的回撤序列:MaxDD 只看那个 13.7% 的红点,CDaR₉₅ 看整片橙色尾巴(均值 10.0%)。由一个点决定的统计量,样本噪声有多大,对它的优化就有多不稳。
翻车现场:块自助下的权重神经质#
把样本内路径做 21 天块自助重抽样 100 次,每次重新解 min-MaxDD 和 min-方差,看最优权重晃得有多厉害:

| 权重 IQR | 股票 | 债券 | 趋势 |
|---|---|---|---|
| min MaxDD | 0.27 | 0.39 | 0.09 |
| min 方差 | 0.13 | 0.12 | 0.06 |
MaxDD 目标的权重四分位距是方差目标的 2-3 倍。机制很直白:块自助改变了”哪一段危机被抽到、抽到几次”,MaxDD 由单一最深谷底决定,谷底换了位置,最优权重就大幅换仓;方差是全样本平均,对重抽样天然钝感。优化目标的统计效率直接决定了解的稳定性——这是比”哪个目标更贴近投资人偏好”更硬的约束。
补救:从一条路径到 worst-case 多情景#
既然单路径 MaxDD 是噪声,正确的问法是:在多条可能的未来路径下,最差那条的回撤最小化。这就是条件回撤优化的鲁棒版本:模拟 条情景,每条情景各自带一组 running-max 辅助变量,共享同一个 :
变量规模 ,20 条两年期情景约 1 万个变量,HiGHS 一秒出解。20 情景解 ——注意它把股票加回来了:不同情景里危机的时点和深度不同,趋势资产不再每条路径都是英雄,分散重新有了价值。

在 20 条训练情景上逐条对比:单路径解(只看情景 0)的最差情景 MaxDD 23.9%,鲁棒解压到 21.8%,平均值也从 14.8% 降到 13.4%——没有任何一条情景上鲁棒解明显更差,它买的是整个分布的保险。
样本外审判#
200 条全新路径(两年期),四个组合的 MaxDD 分布:

| 组合 | 中位 MaxDD | p95 MaxDD | 平均年化 |
|---|---|---|---|
| min 方差 | 10.6% | 21.7% | 7.5% |
| min CDaR₉₅(单路径) | 12.8% | 23.9% | 6.6% |
| min MaxDD(单路径) | 12.8% | 23.9% | 6.6% |
| worst-case(20 情景) | 11.5% | 23.1% | 6.9% |
诚实地说:这张表对回撤优化不客气。单路径的 MaxDD/CDaR 解样本外全面落后于朴素的最小方差——它们在样本内路径上学到的”扔掉股票、重仓趋势”,本质是对那条路径上趋势资产 14.4% 年化好运气的过拟合(趋势的真实无条件年化只有约 5%)。20 情景鲁棒解修复了一部分(中位 12.8%→11.5%),但仍没有反超方差目标。
这和 CDaR 篇”样本外优势缩水但方向保持”的结论并不矛盾——那篇的危机 alpha 信号强度是刻意调高的。两篇合起来的真实教训是:回撤类目标只有在”资产间存在机制性的危机对冲结构、且你有足够多情景让优化器看清这个结构”时才跑赢方差目标;只喂一条历史路径,它一定过拟合,因为 MaxDD 的有效样本量约等于 1。
A. 实现细节#
- 非复利累计收益保 LP 线性;MaxDD 用 running-max 辅助变量 + 三组不等式夹逼;多情景版每情景独立辅助变量、共享
- 收益约束按各实验样本内实现均值定标(介于第一、第二高收益资产之间),保证约束绑定、权重有分化
- 块自助:21 天块、100 次重抽样,每次按该次样本重新定收益目标(避免不可行)
- 样本外评估用复利口径 MaxDD、每日再平衡——训练口径(非复利)与评估口径(复利)故意不同,模拟真实使用场景
B. 已知偏差#
- 非复利训练口径在深回撤区高估回撤,对浅回撤区几乎无影响;训练/评估口径不一致会让最优解轻微偏保守
- 情景由与真实 DGP 相同的模型生成——真实世界里你没有这个奢侈,情景模型本身的误设是额外风险层
- 每日再平衡无成本;MaxDD 型解权重跳动大,换手惩罚会进一步压缩其相对方差目标的空间
C. 结果解读#
- MaxDD 的有效样本量约等于 1:块自助 IQR 0.27/0.39 vs 方差目标 0.13/0.12,是这篇最重要的数字——目标函数由几个点决定,解就由噪声决定
- 样本外反转:单路径回撤优化中位 MaxDD 12.8% 输给最小方差 10.6%,回撤目标不是免费午餐,它用统计效率换偏好贴合度
- 多情景是必选项不是增强项:20 情景把最差训练回撤压 2.1pp、样本外中位收回 1.3pp,且把被单路径解清零的股票权重恢复到 10.6%——分散的价值只有在多情景下才被看见
- CDaR 与 MaxDD 在尾部主导的样本里解重合:当深回撤集中来自单一资产的少数事件时,尾部平均和尾部最大值指向同一个方向,α 的选择只在回撤来源多样时才有区分度