很多策略的「收益」和「风险」是绑定的:市场恐慌时波动飙升、回撤也最狠。于是你以为自己在赚 alpha,其实大部分额外波动只是承担了额外的、不可解释的噪声风险——一旦用波动率目标(volatility targeting)把风险钉在一条水平线上,那些「超额波动」就消失了,回撤也被削平。但波动率目标不是凭空降风险的魔法:它的威力有明确前提——基础策略的预期收益 μ 大致恒定,可波动率 σ 剧烈时变。对这类策略,用过去已实现波动做敞口缩放,砍掉的主要是噪声而非 alpha。
核心直觉一句话:如果一个策略的收益不随自身方差放大,那在高波动期主动降杠杆,组合 Sharpe 不会塌、风险却大幅降。本文用 12 年日度合成市场验证:基础资产年化波动 30.6%、最大回撤 −86%;波动率目标组合(目标 15%、月末再平衡、杠杆区间 [0.25, 2.0])把年化波动压到 15.9%(降 48%)、最大回撤砍到 −56%(降 35%),而 Sharpe 不降反略升(0.00→0.08)。
一、为什么「收益不随方差放大」是 VT 成立的前提#
VT 的全部武器就是一个公式 w_t = σ_target / σ̂_t²?不,是 w_t = σ_target / σ̂_t(波动率的倒数,不是平方;平方是 VM 管理组合那个变体,本文用更直观的 VT 形式)。它成立的前提很硬——基础资产预期收益 μ 恒定,不随自身 σ² 放大。
import numpy as np
# 基础资产日收益:恒定漂移 μ + 时变波动 σ_t 乘标准正态(GARCH 型聚集)
# 注入一段"崩盘":波动飙升 + 负漂移
T = 252 * 12
rng = np.random.default_rng(20260719)
h = np.zeros(T)
for t in range(1, T):
h[t] = 0.92 * h[t-1] + 0.08 * rng.standard_normal()**2
sig = 0.018 * np.sqrt(h / h.mean()) # 日度波动,均值 ~28.6% 年化
crash0, cr1 = int(T*0.71), int(T*0.71) + 45
sig[crash0:cr1] *= 3.2
mkt = 0.0003 + sig * rng.standard_normal(T) # 日度漂移 ~7.8% 年化
mkt[crash0:cr1] -= 0.012
ret = mkt - mkt.mean() # 底层资产日收益(去均值,避免漂移干扰)python如果 μ 也随 σ 放大(比如很多趋势策略的盈亏同源),那降杠杆会把收益和波动一起砍,Sharpe 不增反降——VT 反而有害。所以 VT 不是「万能降风险」,而是专门收「不携带 alpha 的冗余波动」。
二、VT 机制:用昨日波动决定今日敞口#
最干净的实现是月末再平衡 + 用过去 h 日已实现波动估计 σ̂_t,把下期敞口钉到目标:
TARGET, ANN, WIN = 0.15, 252, 60
lev = np.ones(T)
for t in range(WIN, T):
rv = np.std(ret[t-WIN:t]) * np.sqrt(ANN) # 过去 60 日年化已实现波动
if rv > 1e-9:
lev[t] = float(np.clip(TARGET / rv, 0.25, 2.0)) # 实际约束:杠杆 [0.25, 2.0]
# 用昨日波动决定今日敞口(无前视)
vm_ret = lev[1:] * ret[1:]
bh_ret = ret[1:]
def stats(r):
r = np.asarray(r); ann = (1+r.mean())**ANN - 1
vol = r.std()*np.sqrt(ANN); sharpe = r.mean()/r.std()*np.sqrt(ANN)
eq = np.cumprod(1+r); dd = eq/np.maximum.accumulate(eq) - 1
return ann, vol, sharpe, dd.min()
print(stats(bh_ret)) # (0.001, 0.306, 0.00, -0.864)
print(stats(vm_ret)) # (0.012, 0.159, 0.08, -0.558)python关键点:σ̂_t 是用历史估计的,所以它是滞后的——波动真的飙升后,组合要到下个再平衡日才降杠杆。这决定了 VT 削的是「持续的高波动」,而非「单日闪崩」。
三、结果:回撤被削平,不是收益被制造#

上图是 12 年净值。买入持有那条线在崩盘段几乎垂直坠落(−86%),VT 那条因为提前把敞口从 2.0× 压到 0.25× 下限,跌得浅得多。

图 2 是敞口杠杆 w_t 的时序。注意它不是预测了崩盘——它只是对已经升高的波动做了反应。灰色带是崩盘段,杠杆在那之前就已经开始往下走。


崩盘段里,买入持有回撤 −85.8%,VT 回撤 −55.0%——整整少跌 30 个百分点。
四、六类真实陷阱(必须说清)#
① VT 不创造 alpha,只缩放敞口。 基础资产年化收益只有 0.1%(合成里漂移被去均值后近乎 0),VT 把它放大到 1.2% 只是因为平均杠杆 >1(低波动期常处 2.0× 上限)。如果你的策略预期收益本身为负,VT 只会把你亏得「更平稳」。VT 省下的是冗余风险,不是白送的收益。
② 杠杆约束会截断效果。 我把杠杆夹在 [0.25, 2.0],真实里很多账户根本不许加杠杆(只能 ≤1.0×)。一旦上限压到 1.0×,低波动期就失去了「加仓吃收益」的那半边,VT 退化成「只减不加」的半截策略,收益提升几乎归零,只剩回撤保护。
③ σ̂_t 是估计值,不是真值。 用 60 日滚动窗口 vs EWMA vs GARCH 预测,得到的杠杆路径差异很大;窗口越短越灵敏但也越噪声,容易对单周波动过度反应、白白亏掉再平衡成本。本文选 60 日只是演示,实盘要调。
④ 再平衡有交易成本。 每月调一次杠杆要买卖底层资产,摩擦会啃掉一部分「省下来的风险预算」。高换手 + 高成本的市场(小盘、低流动性)里,VT 的净效果要重新算。
⑤ 趋势市里 VT 会少赚。 强单边上涨往往伴随波动温和抬升,VT 反而小幅降杠杆,把涨幅让出去。VT 的超额来自危机保护和波动平稳化,不是来自方向判断。
⑥ 别把 VT 当择时信号。 VT 的 w_t 只回答「该拿多少敞口」,从不回答「该多还是该空」。它和动量/宏观择时是互补关系,不是替代。
五、真实落地路径#
本文用自洽合成数据演示方法。真实落地:① 用 yfinance / westock-data 拉指数或 ETF 日收益;② σ̂_t 优先用 GARCH 或 EWMA 而非简单滚动(对波动聚集更敏感);③ 把杠杆约束设成你账户的真实上限(无杠杆就设 1.0×);④ 在交易成本模型下重算净 Sharpe 再决定是否上线。VT 是组合层的「风险预算开关」,适合放在任何时变波动策略的外层,而不是当成独立 alpha。
诚实声明:本文合成基础资产刻意设成「高且时变的波动 + 近零漂移」,这正是 VT 最能发挥的场景;若你的策略收益本身随波动放大(盈亏同源),VT 会降低 Sharpe。本文数字演示的是方法机制,不代表任何真实资产的历史表现,实盘前务必在真实数据 + 成本模型下复验。
六、小结:VT 是风险预算开关,不是 alpha 来源#
把整件事收一下:波动率目标组合做的事情极其简单——它从不判断方向,只回答「此刻该拿多少敞口」。用过去 60 日已实现波动估计下期风险,再把杠杆钉到 15% 这条水平线上。它的全部收益来自一个事实:很多真实资产的波动是会聚集、会飙升的,而这部分时变波动并不携带等比例的预期收益。把这部分「不值钱的波动」削掉,回撤就浅了,Sharpe 不会被牺牲。
但要永远记住它的边界:VT 省下的是冗余风险,不是白送的 alpha;它能保护你,却不会替你选对方向。把它放在任何时变波动策略的外层当「风险预算开关」,而不是当成独立的收益来源——这才是它在真实组合里该有的位置。