高阶 付费会员

方差风险溢价与波动率偏斜:到底是谁在收钱,收的是什么钱

Read in English

这笔溢价是真实存在的。它同时也是一笔保费——而你是那个保险公司。

🔊 收听本文(中文语音)

⚠️ 先看清现实——在读别的之前先读这一段

方差风险溢价是整个资产定价领域中被记录得最稳健的异象之一。它同时也是一套机制——在现代市场里,被它摧毁的资金雄厚、技术老练的交易者,比几乎任何其他单一策略都要多。 这两句话同时成立。如果你只把其中一句听进去,你早晚会成为另一句的案例。

  • 跨越数十年平均来看,隐含波动率确实高于其后实际实现的波动率。这一点可测量,也没有争议。
  • 它之所以高于已实现波动率, 是因为它就是保险的价格。有人正在花钱把灾难性亏损的风险转移出去。如果你是卖方,你就把这份风险接到了自己的资产负债表上。
  • 收割 VRP 的收益形态是:频繁、可靠的小额盈利,中间被罕见、巨大、非线性的亏损打断——而这些亏损来临的时刻,恰恰是你其他资产也在下跌的时刻。
  • 本文有意把篇幅压在这套策略如何要人命上面,因为收取溢价的操作细节简单得近乎无脑,而活下来的操作细节完全不是。
  • 对于一位正在从组合中提取生活费的退休者来说,这种风险形态不只是激进——它 在结构上就是敌对的 ,与你的目标背道而驰。我们会在文末详细说明原因。

🎯 你会学到什么

这是一份关于 溢价为何存在, 究竟是谁因为什么在收钱,以及 哪些具体的失效模式会把一个有效的策略变成一个终结账户的策略的研究报告。你会学到:

  • 保险需求解释: 为什么机构的对冲需求会在结构上把隐含波动率抬到公允价值之上,以及为什么这是一笔服务费,而不是市场的无效率
  • Bekaert 的分解: Federal Reserve Board 的研究把 VRP 拆成一个真正的风险补偿成分和一个随时间变化的风险厌恶成分——以及为什么这个区分决定了当下这笔溢价收割起来是否安全
  • 正确地度量 VRP: VRPt = IV²(t,30d) − RV²(t,30d),那些会悄悄改变你答案的估计量选择,以及几乎每一份散户回测里都藏着的前视偏差
  • 偏斜是第二层溢价: 25-delta 看跌与 25-delta 看涨之间的偏斜,为什么看跌一侧长期偏贵,以及为什么"卖出偏贵的偏斜"是你能从这个事实里得出的最危险结论
  • VIX 期限结构闸门: 把升水与贴水当作体制过滤器——并诚实交代这个过滤器做不到什么
  • Python 实现: 一套可运行的 VRP 估计器、偏斜计算器、期限结构闸门,以及最关键的——一个做空波动率头寸的压力模拟器,在你承担风险之前先把亏损曲面摆给你看
  • 三份必读的事后复盘: 波动率末日(2018 年 2 月)、2020 年 3 月的波动率飙升,以及 LTCM 式的空头凸性失效——每一个都能教给你另外两个教不了的东西

📚 本文的范围,以及它与相邻文章的分工

PMR 书库里已经有一些相邻的波动率材料。本报告刻意 不 重复它们,而是把你指到该去的地方:

  • 在压路机前捡便士:做空波动率的爆仓 (六章)是叙事与行为层面的处理——那笔永远有效直到它不再有效的交易、作为相关性同步平仓故事的波动率末日、gamma 剥头皮的纪律、对体制转变的盲视,以及仓位大小。 那本书负责交易者心理与仓位纪律。 本报告负责 定价理论、度量方法与机构研究 ,也就是解释这笔溢价一开始为什么会存在。
  • Capula:尾部风险 Alpha 是本报告的镜像:它讲的是 买入 凸性、做多这份保险。 那篇文章负责做多尾部风险的一侧、危机 alpha,以及 theta 效率高的保护结构。 本报告讲的是同一笔交易的空头一侧——而它的结论之一是:大多数退休投资者应该站在 Capula 那一边,而不是这一边。
  • 0DTE 微观结构与 Gamma 钉住效应 讲的是日内做市商 gamma、GEX 体制,以及下午 3:30 的钉住效应。 那篇文章负责单个交易日内做市商对冲的机制。 本报告工作在 30 天的时间尺度上,也就是方差溢价真正存在的地方。
  • 刻意不在本文覆盖的: 期权的基础机制。我们不解释什么是跨式、Black-Scholes 是怎么推导出来的,也不解释 delta 是什么意思。这是一份写给已经具备这些基础的读者的策略与风险报告。

这笔溢价是一项服务的费用,不是市场的错误

把这个经验事实说得窄一点

在 S&P 500 指数期权的长样本中,期权价格所隐含的波动率,平均而言高于指数在对应窗口内其后实际实现的波动率。 这个缺口——方差风险溢价——是股票衍生品中最持久的量化规律之一,它跨越数十年、跨越不同指数族、跨越市场结构的重大变化,在样本外依然成立。

真正把人毁掉的是紧接着的那个框架。一位交易者看到这个缺口,得出结论说市场 错误定价 了波动率,于是推论说卖出被高估的波动率就是一次套利。这个推论在第一步就错了。 这个缺口不是市场对未来波动率判断错误的证据。它是市场参与者愿意为保护支付超过期望值的价格的证据——就像房主为火灾保险支付超过期望值的保费一样。

同一个数字的两种解读

解读 它对你这笔交易意味着什么 它对你的风险意味着什么
"IV 被错误定价了" (错误的框架) 你找到了白送的钱,应该加大仓位去利用它 被低估了——你相信真实分布比市场认为的更窄
"IV 是一个保险价格" (正确的框架) 你正在承保一份保单,因为承担一项特定的灾难性风险而收取保费 被正确陈述了——这笔溢价 就是 你同意吸收的那笔亏损所对应的补偿

关键洞见: 在一个平静的周二,两种解读会给出完全一样的交易。但它们给出的仓位大小完全不同、资本储备完全不同、危机中的行为也完全不同。这个框架不是学术问题——它是决定你能否活下来的那一个变量。

谁在买,以及他们为什么心甘情愿地多付

指数波动率的结构性买盘,绝大部分来自那些受托责任决定了尾部亏损远比期权权利金昂贵的机构。 正是这个需求侧创造了溢价,而理解它就能明白为什么这笔溢价不会被套利掉。

指数下行保护的结构性需求侧

买方 他们为什么愿意高于公允价值买入 价格敏感度
养老金与保险公司 资金充足率与偿付能力规则,使得一次大回撤的代价远高于按公允价值计的亏损——一旦触线,可能被迫在最糟糕的时点卖出资产 低——被规定要买的保护,基本上不看价格也要买
结构化产品发行方 必须对冲卖给零售客户的产品中内嵌的下行保底;这个对冲是负债匹配的要求,不是一个观点 低——对冲是合同义务
有回撤限制的机构资产管理人 一次大回撤带来的职业与业务风险是不对称的;买保护就是买下继续持仓的能力 中等
风险平价与波动率目标策略 波动率上升时机械性地降低风险;其中一些会预先买入凸性,以避免在弱势中被迫卖出 中等
企业与加杠杆的持有人 带有融资契约条款的集中持仓;下行保护能防止被强制平仓 低

关键洞见: 注意这些需求里有多大一部分是 按其构造就对价格不敏感的。当一个买方的受托要求规定必须买保护时,他们会付出任何能成交的价格。这就是溢价能长期存在的原因——它不是等着聪明钱来收割的无效率,而是价格不敏感的对冲者与愿意为他们承保的那一小池资金之间的持久失衡。

没人愿意面对的推论:供给侧的资本约束

如果这笔溢价是承担崩盘风险的补偿,那么溢价的大小就应该随当下可用的崩盘承受能力而变化——事实也确实如此。 真正既愿意又有能力做空凸性的资金池是有限的,因为这项风险无上限、占用资本、而且一旦出错就会遭到剧烈惩罚。当这个池子变大(就像 2016–2017 年做空波动率 ETP 与散户卖权利金规模扩张时那样),溢价就会被压缩。当这个池子在一次冲击中被抹掉时,溢价就会暴涨。

⚠️ 溢价最小的时候,恰恰是它看起来最安全的时候

长期的平静会吸引供给进场——更多卖方、更多杠杆、更拥挤的仓位——这会压缩溢价,同时又因为所有人都站在同一边,让最终的平仓更加剧烈。 在低而稳定的 VIX 环境中出现低而稳定的 VRP,不是绿灯;它是在度量这笔交易已经变得多拥挤。 这是整套策略中最反直觉的一个事实,也是波动率末日让人再也无法否认的那个事实。

Bekaert 与 Fed:把 VRP 分解为风险与风险厌恶

为什么单看一个 VRP 数字远远不够

Geert Bekaert 及其在 Federal Reserve Board 的同事所做的研究,回答了一个对任何考虑收割这笔溢价的人都极其重要的问题:一个宽阔的方差风险溢价,究竟是在告诉你预期未来波动率很高,还是在告诉你投资者异常恐惧? 这是两种不同的世界状态,它们要求的交易方向正好相反。

这个框架把期权隐含方差(也就是 VIX 平方那个度量)与预期物理方差之间的缺口,分解成两个概念上相互独立的驱动因素:

两成分分解

成分 它度量的是什么 行为特征 对波动率卖方的含义
不确定性 (风险的数量) 对未来物理方差的条件期望——世界接下来究竟会有多动荡 高度持续、会聚集成簇、均值回复缓慢 高不确定性意味着已实现波动率很可能真的会很高——这笔溢价可能是 挣来的,而不是白送的
风险厌恶 (风险的价格) 投资者要求每承担一单位方差风险要拿多少钱——也就是恐惧成分 危机中急剧飙升,衰减速度快于不确定性 风险厌恶抬升而不确定性受控,这种状态下的溢价才最像是真正意义上的溢价

关键洞见: 天真的 VRP 收割者把每一次溢价变宽都当成机会。这个分解给出的结论正相反:如果溢价变宽是因为 不确定性 升高,那是一个警告;而如果溢价变宽是因为 风险厌恶 在一次冲击后骤然飙升——而基本面仍然受控——那它更接近一次真正的承保机会。大多数散户做空波动率的系统分不清这两者,于是默认两种情况都卖。

为什么这件事比任何入场信号都重要

市面上流通的散户做空波动率系统,几乎全都建立在单个数字的水平或分位数之上——要么是 VIX,要么是 VIX 减去已实现波动率。 Fed 的研究框架告诉你,这个数字是两样东西的合成,而这两样东西的走法不同、预测含义也不同。一个看不见这个分解的系统,会因为表面溢价看起来诱人,而愉快地在不确定性上升的体制里卖出方差——而这恰恰就是产生灾难性亏损的那种局面。

⚠️ 散户版的近似做法,以及它的边界

你在家里没法复刻 Fed 那套估计装置。你 能 做的,是用可观测的代理变量去近似这个区分:已实现波动率上升、信用利差走阔、VIX 期限结构走平或倒挂,都指向不确定性成分在升高;而一次让已实现波动率、信用市场与期限结构相对完好的 VIX 飙升,则更多指向风险厌恶成分。 这只是对一个复杂模型的粗糙近似,你应该把它当作缩小仓位的理由,而不是加大仓位的许可证。 任何告诉你"环境是安全的"的代理变量,都是最有可能在真正关键的那一刻出错的那一个。

Goldman 的股票衍生品框架:这笔溢价本身也有期限结构

卖方的股票衍生品研究——其中 Goldman Sachs 的股票衍生品团队尤为突出——长期以来都不把方差溢价看作一个数字,而是看作一个曲面:它随到期期限、随行权价、随标的而变化。 落到实处,它的策略含义是:

  • 短期方差所带的溢价,按比例通常大于长期方差,因为近端的保护才是对冲者最急需的——而短期同时也是 gamma 风险最猛烈的地方,所以那更高的溢价是在为一项真实的危险付你钱,不是白送。
  • 溢价集中在指数方差上,而不是个股方差上。 指数期权承载的是对冲需求;个股期权往往承载的是事件与投机需求,行为方式不同。隐含相关性就是两者之间的楔子,它本身是一笔独立的交易,有它自己的失效模式。
  • 溢价在下行一侧的翼部最肥 ——这就是下一节要讲的偏斜故事,而它之所以在那里最肥,背后的原因你应该认真对待,而不是当成机会。

度量 VRP:IV² − RV² 与估计量的陷阱

定义

标准的 30 天方差风险溢价,定义为在匹配的时间跨度上,期权隐含方差与已实现方差之差:

VRP_t = IV²(t, 30d) − RV²(t, 30d)

其中:

  IV(t, 30d)  = 模型无关的 30 天隐含波动率
              ≈ VIX_t / 100   (VIX 就是按模型无关的方式,
                               在 S&P 500 上构建的 30 天隐含波动率)

  IV²(t,30d)  = 隐含方差(年化,单位为小数的平方)

  RV(t, 30d)  = 30 天窗口内的已实现波动率

  RV²(t,30d)  = 已实现方差(年化,单位为小数的平方)


由每日对数收益率构建的已实现方差(r_i = ln(P_i / P_{i-1})):

              252     n
  RV²  =     ----- ·  Σ   r_i²
               n     i=1

  (收盘对收盘估计量;对应 30 个自然日的窗口,n ≈ 21 个交易日)


重要——有两个完全不同的量共用 "VRP" 这个名字:

  事后 VRP(度量/研究用):
      VRP_expost(t) = IV²(t) − RV²(t → t+30d)
      用的是 t 之后才实现的波动率。研究这笔溢价时,这是正确的做法。
      不能用作交易信号:它需要未来的信息。

  事前 VRP(可交易的信号):
      VRP_exante(t) = IV²(t) − E_t[RV²(t → t+30d)]
      需要对未来已实现方差做出预测。
      回望型的 RV 只是这个预测的一个粗糙代理,
      而且在体制转折处,它的偏差非常严重。

🚨 几乎每一份散户 VRP 回测里都有的前视偏差

散户做 VRP 时最常见的致命错误,是用决策时点上尚未发生的已实现波动率去计算溢价,然后拿它来"交易"。 一份把今天的 VIX 拿去和未来 30 天实际实现的波动率作比较、在缺口变宽时入场的回测,看起来会漂亮得惊人,而且完全是虚构的——它在用来自未来的信息交易。可交易的版本必须换成一个真正的预测,而任何诚实的预测都远不如已实现数字准确,这恰恰就是这类策略实盘结果远远低于回测的原因。

那些会悄悄改变你答案的估计量选择

"已实现波动率"不是一个数字——它是一族彼此不一致的估计量,有时差异还很大,而分歧最大的时候恰恰是市场承压的时候。

已实现方差估计量对比

估计量 使用的数据 承压时的表现 对测得的 VRP 的影响
收盘价对收盘价 只用每日收盘价 完全看不到日内振幅;对于日内剧烈震荡、收盘却持平的一天会严重低估 在高振幅/平收盘的日子里高估 VRP——这是在讨好卖方
Parkinson(最高–最低) 每日最高价与最低价 能捕捉日内振幅;对隔夜跳空视而不见 在跳空主导的体制里低估 VRP
Garman-Klass / Rogers-Satchell 开高低收(OHLC) 效率更高;但仍对漂移和跳空的处理方式敏感 通常是日频数据里最均衡的选择
日内已实现方差 5 分钟(或更细)收益率 最接近理论量;需要日内数据以及对微观结构噪声的处理 学术界的 VRP 研究实际使用的就是它

关键洞见: 用收盘价对收盘价收益率构建的散户 VRP 序列,会系统性地报出比同样用日内数据构建的序列更宽的溢价,因为收盘对收盘丢弃了日内的波动。如果你把入场阈值建立在那个讨好你的估计量上,你入场的次数会比研究显示的更多,入场时的环境也会更差。先选定估计量,再把阈值校准到 那一个 估计量上,永远不要混用。

对 VRP 取平均的分布问题

方差风险溢价的均值是正的。中位数更正。但这两个统计量都没有描述你交易它时的真实体验,因为这个分布有严重的负偏斜和一条长长的左尾。 一个在绝大多数月份收取小额溢价、在极少数月份承受相当于好几个月量级亏损的策略,它的均值确实是正的,而实际体验却由尾部主导。只报均值而不报尾部不是分析——那正是卖做空波动率产品时惯用的那一招修辞。

做空方差月度收益的形态示意

  • 典型月份(大约十次里有八次): 隐含高于已实现,带来小额正收益——头寸"有效",感觉平静,并强化了信心
  • 温和不利的月份(大约十次里有一到两次): 已实现超过隐含;亏损是一次典型盈利的小倍数,几个月内就能收复
  • 尾部月份(罕见,且没有周期性): 已实现方差是隐含的数倍;亏损可能超过前面好几年累积的盈利,而在带杠杆或风险未界定的结构上,甚至可能完全超过分配给该策略的资金

关键结论: 这些是示意性的量级,不是预测。真正重要的是那个结构性的要点: 胜率很高,但无关紧要;亏损的量级出现频率很低,却是决定性的。 任何建立在胜率之上的业绩叙事,都是在故意度量错误的东西。

波动率偏斜:第二层溢价,也是第二个陷阱

25-delta 偏斜度量的是什么

股票指数的隐含波动率在不同行权价上并不是平的:价外看跌期权的隐含波动率,长期高于等距的价外看涨期权。 机构对这种不对称的标准概括方式,是把 25-delta 看跌期权的隐含波动率与 25-delta 看涨期权作比较:

Skew_25d = IV(25-delta put) − IV(25-delta call)

归一化后(可跨波动率体制、跨标的比较):

  Skew_norm = [ IV(25Δ put) − IV(25Δ call) ] / IV(50-delta / ATM)

相关的机构度量:

  风险逆转(外汇市场的约定,同一个量):
      RR_25 = IV(25Δ call) − IV(25Δ put)      (符号与上式相反)

  蝶式/微笑曲率:
      BF_25 = [ IV(25Δ put) + IV(25Δ call) ] / 2  −  IV(ATM)

  解读:
      Skew_25d 高于 0  →  看跌翼相对看涨翼偏贵(股票指数的常态)
      Skew_25d 上升    →  对下行保护的需求正在加剧
      Skew_25d 被压缩  →  相对它自身的历史,下行保护很便宜——
                          这是一个买入保护的信号,
                          而不是卖出保护的信号

股票指数存在正的偏斜是常态、是永久状态——不是异象。 它反映的是与创造方差溢价相同的那份保险需求,只不过集中在崩盘时真正能赔付的那些行权价上,再加上一个经验事实:指数收益本身就是负偏的,而且指数下跌时波动率会上升。一条平坦的股票指数偏斜曲线才是异象。

不同的偏斜状态实际上在告诉你什么

偏斜状态 天真的读法 它更常见的真实含义
陡峭偏斜(看跌翼非常贵) "看跌期权被高估了——卖掉它们" 对冲需求正在激增;那些更清楚自己敞口的参与者正在加价买保护。在这种时候当卖方,等于是在为一场别人已经闻到烟味的火灾承保。
平坦/被压缩的偏斜 "这里没什么有意思的" 下行保护按历史标准来看很便宜。这正是 买入 凸性最有吸引力的状态——也就是 Capula 尾部风险那篇文章 所讲的那种局面。
现货持平而偏斜在变陡 "噪声" 有人在现货不动的情况下持续积累保护——这往往是整个曲面上信息量最大的一种形态,也是减少而非增加做空波动率敞口的理由。
抛售过程中偏斜塌缩 "看跌期权变便宜了" 整个曲面已经整体上移重新定价,平值水平追上了翼部;这是投降式定价,不是便宜货,而且已实现波动率通常还在往上爬。

关键洞见: 偏斜的"错误定价"交易,做的是曲面 形状 上的相对价值,而不是"看跌期权太贵了"这种方向性下注。一个卖出偏贵的看跌翼、却没有同时持有更远端某个东西的交易者,根本没有在交易偏斜——他只是在那些能把一个糟糕月份变成终结账户的月份的行权价上,建了一个巨大而集中的空头。

看跌翼长期偏贵的结构性原因

做市商在结构上对整个对冲群体做空下行看跌期权,并且必须动态对冲这份敞口。 指数下跌时,这些看跌期权的 delta 会变大,做市商必须卖出更多标的才能保持对冲——这又把指数进一步压低,抬高波动率,进而抬高看跌期权的价值。这个反馈回路意味着,对卖方而言下行翼所带的风险形态,确实比一个对称模型所暗示的更糟;看跌翼上那部分额外的隐含波动率,是对这种不对称的补偿,而不是定价错误。

⚠️ 偏斜不是叠在 VRP 之上的免费午餐

一种常见的加码逻辑是:既然 VRP 能赚钱,而看跌翼更贵,那卖出下行看跌期权就是这笔交易的浓缩版。确实是浓缩版——连风险也一起浓缩了。 卖出偏贵的那一翼,能让你每单位名义本金收到更高的权利金,同时在那个产生全部策略亏损的场景里,让你的亏损形态急剧恶化。 你不是在叠加两个优势;你是在对同一个事件叠加两份敞口。

在结构上站得住脚的偏斜交易

如果一个非机构参与者真要交易偏斜,那些站得住脚的版本都有一个共同性质: 远端尾部是被持有的,不是被卖出的。

  • 远翼为多头的看跌比率结构: 表达的观点是"近平值的偏斜相对远翼偏贵",同时保留对灾难行权价的持有。亏损有上限。
  • 跨期偏斜: 交易的是短期与长期偏斜之间的差,而不是偏斜的绝对水平——这是一种 beta 更低、崩盘集中度更小的表达方式,不过它自带期限结构风险。
  • 明确界定风险的价差结构: 任何在入场时最大亏损就是一个已知数字的结构——这个数字在开仓之前就算好了,而且仓位大小要确保这个最大亏损是能扛得住的。

对散户参与者来说站不住脚的是:裸卖看跌、风险未界定的宽跨式,以及任何最大亏损不是一个你已经写下来的有限数字的结构。 不是因为它们从来不管用——它们大多数时候都管用,问题正在这里——而是因为它们的失效模式没有上限,且不可挽回。

VIX 期限结构闸门:升水与贴水

曲线形状编码了什么信息

VIX 期货曲线通常处于升水——远月合约价格高于近月——这反映的是与创造方差溢价相同的那份保险需求,只不过沿着到期期限铺开。 承压时曲线会倒挂成贴水:近月价格高于远月,因为眼下的已实现波动率很高,并被预期会向下均值回复。

各种曲线状态,以及它们对做空波动率头寸的含义

曲线状态 定义 它在说什么 对做空波动率的含义
陡峭升水 M2 明显高于 M1;现货 VIX 低于 M1 平静体制;对冲需求被定价到整条曲线上 历史上最有利的状态—— 同时也是拥挤度累积起来的那个状态
平坦曲线 M1 ≈ M2 体制正在转换;市场已经不再假设会均值回复 闸门应当关闭;这是那个模糊地带,只检查升水/贴水的系统正是在这里被套住
贴水 M1 高于 M2;现货 VIX 高于 M1 正处于压力之中;近端的已实现波动率已被抬高 新增做空波动率风险的硬性停止线。历史上做空方差最糟糕的状态,而且差距很大。
深度贴水 急剧倒挂,现货 VIX 远高于 M1 危机定价 在结构上这是 买方的 体制,对任何手里还有子弹的人而言——同时也是那个时点:任何仍然做空的人是在被强制平仓,而不是在做选择

关键洞见: 这个闸门真正的功能不是提高收益。它是要降低"体制转变开始时你正扛着最大做空波动率敞口"的概率。它是一个生存过滤器,评价它的标准应该是它削掉了多少尾部,而不是它给 Sharpe 加了多少。

闸门在哪里失效——直说

期限结构闸门是一个滞后过滤器,而它过滤的变量可以在单个交易日内完成重新定价;它救不了你,尤其是面对那类最快、破坏力最大的事件。 它已被记录在案的失效模式:

  • 冲击到来前的最后一刻,闸门都是开着的。 2018 年 2 月和 2020 年 2 月底,行情启动前曲线都处在舒适的升水状态。这个闸门不预测,它只是反应。
  • 按闸门信号出场,意味着你是在最糟糕的流动性里出场。 等到贴水被确认时,隐含波动率早已完成重新定价,而其他所有系统化卖方在同一时刻收到了同一个信号。你的出场是一次拥挤的出场。
  • 来回打脸会产生真实成本。 一个反复关闭又反复打开的闸门,会在震荡市里产生反复的往返交易成本和反复被确认的亏损,长期下来是一项相当可观的拖累。
  • 闸门对仓位大小只字未提。 一个过了闸门但仓位过大的头寸,照样会终结你的账户。仓位大小起的作用比任何过滤器都大,而 《在压路机前捡便士》那本书深入讲了仓位纪律。

🚨 不要把过滤器当成保护

体制过滤器降低的是灾难性敞口出现的频率。 它并不降低那些发生在闸门开启窗口之内的灾难的严重程度——而历史上每一次决定性的做空波动率亏损,都发生在闸门开启的窗口之内,因为那正是头寸存在的时候。 只有买来的尾部对冲,或者小到最大亏损能扛得住的仓位,才能处理严重程度。过滤器管的是频率;只有结构和仓位大小能管严重程度。

Python 实现:VRP、偏斜、闸门与压力模拟器

完整实现: 一套已实现方差估计量、一个拒绝悄悄犯下前视偏差的事后/事前 VRP 计算器、一个 25-delta 偏斜计算器、一个 VIX 期限结构闸门,以及最重要的——一个做空波动率压力模拟器,它会在头寸开出去 之前 就把亏损定出价来。

完整 Python 代码

"""
方差风险溢价、偏斜与做空波动率压力工具箱
=======================================================
面向散户改造的方差风险溢价度量框架、25-delta 偏斜计算、
VIX 期限结构闸门,以及——最关键的——一个做空波动率
压力模拟器。

设计原则:这套工具箱的目的是让下行变得可见,而不是
优化上行。这里最重要的类是压力模拟器,不是信号生成器。

Author: Plan My Retire
Date: March 2026
"""

import numpy as np
import pandas as pd


# ---------------------------------------------------------------
# 1. 已实现方差估计量
# ---------------------------------------------------------------

class RealizedVariance:
    """
    基于每日 OHLC 数据的几种已实现方差估计量。

    这些估计量彼此并不一致,而且在承压时分歧最大。
    选定一个,把阈值校准到它上面,并且绝不要在研究和
    实盘之间混用不同的估计量。
    """

    TRADING_DAYS = 252

    def close_to_close(self, close, window=21):
        """
        经典估计量:每日对数收益率的年化方差。
        它看不见日内振幅——一个盘中波动 4% 却平收的交易日,
        会被记成平静的一天。这是在讨好波动率卖方。
        """
        log_ret = np.log(close / close.shift(1))
        return (log_ret ** 2).rolling(window).sum() * (self.TRADING_DAYS / window)

    def parkinson(self, high, low, window=21):
        """
        最高–最低振幅估计量。它捕捉得到日内的走动,却看不见
        隔夜跳空——所以在跳空主导的体制里,它会低估方差
        (而那恰恰就是伤害卖方的那种体制)。
        """
        hl = np.log(high / low) ** 2
        scaled = hl / (4.0 * np.log(2.0))
        return scaled.rolling(window).mean() * self.TRADING_DAYS

    def garman_klass(self, open_, high, low, close, window=21):
        """
        OHLC 估计量:统计效率高于上面两者。在没有日内数据的
        情况下,它通常是日频数据里最好的选择。
        """
        hl = 0.5 * (np.log(high / low) ** 2)
        co = (2.0 * np.log(2.0) - 1.0) * (np.log(close / open_) ** 2)
        return (hl - co).rolling(window).mean() * self.TRADING_DAYS

    def intraday(self, intraday_prices, bars_per_day, window_days=21):
        """
        由日内(例如 5 分钟)K 线计算的已实现方差。学术界的
        VRP 研究实际使用的就是这个量。在高频下需要处理
        微观结构噪声。

        intraday_prices: 以日内时间戳为索引的 Series。
        """
        log_ret = np.log(intraday_prices / intraday_prices.shift(1))
        daily_rv = (log_ret ** 2).groupby(
            intraday_prices.index.normalize()
        ).sum()
        return daily_rv.rolling(window_days).mean() * self.TRADING_DAYS


# ---------------------------------------------------------------
# 2. 方差风险溢价
# ---------------------------------------------------------------

class VarianceRiskPremium:
    """
    VRP_t = IV^2(t, 30d) - RV^2(t, 30d)

    这个类在事后(研究用)溢价和事前(可交易)溢价之间
    划了一条硬边界,因为把两者混为一谈,是散户做 VRP 时
    最常见的那个致命错误。
    """

    def __init__(self, horizon_days=21):
        self.horizon = horizon_days

    def implied_variance(self, vix_series):
        """
        VIX 以波动率点数报出;这里把它换算成小数形式的方差。
        """
        return (vix_series / 100.0) ** 2

    def ex_post(self, vix_series, close_series):
        """
        仅供研究——按构造方式就带有前视偏差。

        它拿今天的隐含方差,去和随后那段期限内真正实现的
        方差作比较。研究这笔溢价时这样做是对的,拿它来交易
        则是无效的:在 t 时点,你并不知道未来的已实现方差。
        """
        iv2 = self.implied_variance(vix_series)
        log_ret = np.log(close_series / close_series.shift(1))
        # 前视窗口:shift(-horizon) 把未来的信息拉了回来
        fwd_rv2 = ((log_ret ** 2)
                   .rolling(self.horizon).sum()
                   .shift(-self.horizon)) * (252.0 / self.horizon)
        out = pd.DataFrame({'iv2': iv2, 'fwd_rv2': fwd_rv2})
        out['vrp_expost'] = out['iv2'] - out['fwd_rv2']
        out.attrs['WARNING'] = 'LOOK-AHEAD: research use only, never a signal'
        return out

    def ex_ante(self, vix_series, close_series, forecaster=None):
        """
        可交易。用一个真正的未来已实现方差预测,替换掉那个
        (无法得知的)已实现值。

        如果没有传入预测器,就退回到回望型的已实现方差——
        那是一个很弱的代理,而且恰恰在体制转折处、也就是
        最要紧的时候有偏。这个退路刻意做得比较嘈杂,免得
        你把它误当成事后序列。
        """
        iv2 = self.implied_variance(vix_series)
        if forecaster is None:
            forecast_rv2 = self._trailing_rv2(close_series)
        else:
            forecast_rv2 = forecaster(close_series)

        out = pd.DataFrame({'iv2': iv2, 'forecast_rv2': forecast_rv2})
        out['vrp_exante'] = out['iv2'] - out['forecast_rv2']
        # 相对自身历史取百分位排名;用 expanding 是为了避免
        # 在归一化这一步本身引入前视偏差。
        out['vrp_pctile'] = (out['vrp_exante']
                             .expanding(min_periods=252)
                             .apply(lambda x: (x.iloc[-1] > x).mean(), raw=False))
        return out

    def _trailing_rv2(self, close_series):
        log_ret = np.log(close_series / close_series.shift(1))
        return ((log_ret ** 2).rolling(self.horizon).sum()
                * (252.0 / self.horizon))


class EwmaVarianceForecast:
    """
    一个比回望 RV 稍微不那么天真的前向方差预测:指数加权的
    估计量,对体制变化的反应更快。就绝对水平而言它仍然是个
    糟糕的预测——而这就是散户参与者手上诚实的最好水平,
    也是 VRP 实盘结果达不到回测的原因。
    """

    def __init__(self, lam=0.94):
        self.lam = lam

    def __call__(self, close_series):
        log_ret = np.log(close_series / close_series.shift(1)).fillna(0.0)
        var = log_ret.ewm(alpha=(1 - self.lam), adjust=False).var()
        return var * 252.0


# ---------------------------------------------------------------
# 3. 波动率偏斜
# ---------------------------------------------------------------

class VolatilitySkew:
    """
    根据一份带有每份合约隐含波动率与 delta 的期权链快照,
    计算 25-delta 看跌与 25-delta 看涨之间的偏斜。

    期权链 DataFrame 上应有的列:
      ['strike', 'option_type', 'implied_vol', 'delta']
    其中 option_type 取值为 {'put', 'call'},delta 带符号
    (看跌为负,看涨为正)。
    """

    def _nearest_delta_iv(self, chain, option_type, target_abs_delta):
        side = chain[chain['option_type'] == option_type].copy()
        if side.empty:
            return np.nan
        side['delta_gap'] = (side['delta'].abs() - target_abs_delta).abs()
        return side.sort_values('delta_gap').iloc[0]['implied_vol']

    def skew_25d(self, chain):
        """
        25-delta 看跌减去 25-delta 看涨的隐含波动率之差。
        对股票指数而言,取正值是常态。
        """
        put_iv = self._nearest_delta_iv(chain, 'put', 0.25)
        call_iv = self._nearest_delta_iv(chain, 'call', 0.25)
        return put_iv - call_iv

    def atm_iv(self, chain):
        put_iv = self._nearest_delta_iv(chain, 'put', 0.50)
        call_iv = self._nearest_delta_iv(chain, 'call', 0.50)
        return np.nanmean([put_iv, call_iv])

    def normalized_skew(self, chain):
        """
        用平值波动率对偏斜做缩放,使它可以跨体制比较。
        """
        atm = self.atm_iv(chain)
        if not atm or np.isnan(atm) or atm == 0:
            return np.nan
        return self.skew_25d(chain) / atm

    def butterfly_25d(self, chain):
        """
        微笑曲率:两翼隐含波动率的均值减去平值隐含波动率。
        """
        put_iv = self._nearest_delta_iv(chain, 'put', 0.25)
        call_iv = self._nearest_delta_iv(chain, 'call', 0.25)
        return np.nanmean([put_iv, call_iv]) - self.atm_iv(chain)

    def classify(self, normalized_skew_now, skew_history):
        """
        把当前偏斜放到它自身的历史里去理解。
        请注意这里的结论是不对称的:偏斜偏贵是按兵不动的理由,
        偏斜便宜是考虑买入保护的理由——而绝不是多卖一些的理由。
        """
        if skew_history is None or len(skew_history) < 250:
            return 'insufficient_history'
        pct = (normalized_skew_now > skew_history).mean()
        if pct > 0.85:
            return 'skew_rich__hedging_demand_intense__stand_down'
        if pct < 0.15:
            return 'skew_cheap__protection_on_sale__consider_buying'
        return 'skew_normal'


# ---------------------------------------------------------------
# 4. VIX 期限结构闸门
# ---------------------------------------------------------------

class TermStructureGate:
    """
    建立在 VIX 期货曲线上的体制闸门。

    这个闸门管理的是灾难性敞口出现的频率。
    它不管理严重程度。这句话请读两遍:历史上每一次决定性的
    做空波动率亏损,都发生在这样一个闸门开着的时候,
    因为那正是头寸存在的时候。
    """

    def __init__(self, contango_threshold=0.05, flat_band=0.02):
        # contango_threshold:判定为升水所需的 (M2/M1 - 1) 门槛
        self.contango_threshold = contango_threshold
        self.flat_band = flat_band

    def curve_state(self, spot_vix, m1, m2):
        if any(pd.isna(x) for x in (spot_vix, m1, m2)):
            return 'unknown'
        ratio = (m2 / m1) - 1.0
        if spot_vix > m1 and ratio < -self.flat_band:
            return 'deep_backwardation'
        if ratio < -self.flat_band:
            return 'backwardation'
        if abs(ratio) <= self.flat_band:
            return 'flat'
        if ratio >= self.contango_threshold:
            return 'steep_contango'
        return 'mild_contango'

    def gate_open(self, spot_vix, m1, m2, realized_vol_rising=False):
        """
        返回 (is_open, reason)。

        刻意保守:曲线走平这个状态就会关闭闸门。
        那些只判断升水与贴水的系统,会被卡在过渡区里,
        而体制转变正是从过渡区开始的。
        """
        state = self.curve_state(spot_vix, m1, m2)
        if state in ('unknown', 'flat', 'backwardation', 'deep_backwardation'):
            return False, f'gate_closed: curve_state={state}'
        if realized_vol_rising:
            return False, 'gate_closed: realized vol trending up (uncertainty rising)'
        return True, f'gate_open: curve_state={state}'


# ---------------------------------------------------------------
# 5. 做空波动率压力模拟器  <-- 最重要的那个
# ---------------------------------------------------------------

class ShortVolStressSimulator:
    """
    在头寸开出去之前,先把一个做空波动率仓位在一整格
    不利情景下的亏损定出价来。

    理由:收到的权利金是可知的、小的。亏损是不可知的、大的。
    任何只算前者、不算后者的流程都不是风险管理——那只是
    配了一张电子表格的乐观。

    这个模拟器把真正造成伤害的那两种效应合在一起,而人们
    习惯于分开建模,因此低估了它们:
       (a) 现货跳空穿过对冲(gamma 亏损),以及
       (b) 隐含波动率剧烈向上重新定价(vega 亏损)。
    这两者是同时到来的,而它们的联合效应比分开考虑的两者
    之和更糟,因为在跳空过程中被再平衡的 delta 对冲,
    会在最差的价格上把亏损坐实。
    """

    def __init__(self, notional, vega_per_point, gamma_dollar_per_pct):
        """
        notional:            配置给该策略的资本(美元)
        vega_per_point:      IV 每上升 1 个波动率点对应的美元盈亏
                             (做空波动率时为负;这里传入其绝对值)
        gamma_dollar_per_pct: 现货每变动 1% 的平方所对应的美元亏损,
                             来自两次对冲再平衡之间的做空 gamma 敞口
        """
        self.notional = notional
        self.vega = abs(vega_per_point)
        self.gamma_dollar = abs(gamma_dollar_per_pct)

    def scenario_loss(self, spot_move_pct, iv_point_rise,
                      hedge_slippage_factor=1.0):
        """
        单个情景下的亏损。

        hedge_slippage_factor 高于 1.0,刻画的是这样一个现实:
        跳空时你不会按中间价再平衡,你是迟到地、在很宽的价差上、
        对着单边的流动性去再平衡。对一次真正的压力事件而言,
        1.5-2.5 的系数并不悲观,它只是在陈述事实。
        """
        gamma_loss = self.gamma_dollar * (spot_move_pct ** 2) * hedge_slippage_factor
        vega_loss = self.vega * iv_point_rise
        total = gamma_loss + vega_loss
        return {
            'spot_move_pct': spot_move_pct,
            'iv_point_rise': iv_point_rise,
            'gamma_loss': round(gamma_loss, 2),
            'vega_loss': round(vega_loss, 2),
            'total_loss': round(total, 2),
            'loss_pct_of_notional': round(100.0 * total / self.notional, 1),
            'survivable': total < self.notional,
        }

    def stress_grid(self, spot_moves=(-3, -5, -8, -12, -20),
                    iv_rises=(5, 10, 20, 35, 50),
                    hedge_slippage_factor=1.8):
        """
        现货/IV 的联合压力网格。真实的体制转变会同时推动
        这两个轴,正因如此,网格才是对的那个对象,而单变量
        敏感性分析不是。
        """
        rows = []
        for s in spot_moves:
            for v in iv_rises:
                rows.append(self.scenario_loss(abs(s), v, hedge_slippage_factor))
        return pd.DataFrame(rows)

    def max_survivable_size(self, worst_case_spot_move, worst_case_iv_rise,
                            max_acceptable_loss_pct=20.0,
                            hedge_slippage_factor=1.8):
        """
        把问题反过来问:给定一个你愿意明说的压力情景,以及一个
        你愿意承受的最大亏损,这个头寸最大可以做到多大?

        这是唯一真正重要的仓位大小问题,而几乎没有人
        从这个方向去问它。
        """
        unit = self.scenario_loss(worst_case_spot_move, worst_case_iv_rise,
                                  hedge_slippage_factor)['total_loss']
        if unit <= 0:
            return np.inf
        budget = self.notional * (max_acceptable_loss_pct / 100.0)
        return round(budget / unit, 4)  # 相对当前头寸的缩放系数


# ---------------------------------------------------------------
# 6. 用法示例
# ---------------------------------------------------------------

if __name__ == "__main__":
    # ---- 合成的价格/VIX 历史 ----------------------------------
    rng = np.random.default_rng(42)
    n = 600
    dates = pd.bdate_range('2024-01-02', periods=n)
    ret = rng.normal(0.0004, 0.009, n)
    ret[430:436] += rng.normal(-0.035, 0.02, 6)   # 人为构造的冲击
    close = pd.Series(4000 * np.exp(np.cumsum(ret)), index=dates)
    vix = pd.Series(np.clip(14 + 40 * pd.Series(ret, index=dates)
                            .rolling(10).std().fillna(0.01) * 10, 10, 80),
                    index=dates)

    # ---- 已实现方差估计量彼此并不一致 --------------------------
    rv = RealizedVariance()
    rv_cc = rv.close_to_close(close)
    print("Realized vol (close-to-close, annualized %):")
    print((np.sqrt(rv_cc.dropna()) * 100).round(1).tail(3))

    # ---- VRP:事后版本与事前版本 -------------------------------
    vrp = VarianceRiskPremium(horizon_days=21)

    research = vrp.ex_post(vix, close)
    print("\nEx-post VRP (RESEARCH ONLY --", research.attrs['WARNING'], ")")
    print(research[['iv2', 'fwd_rv2', 'vrp_expost']].dropna().tail(3).round(4))

    tradeable = vrp.ex_ante(vix, close, forecaster=EwmaVarianceForecast(0.94))
    print("\nEx-ante VRP (tradeable):")
    print(tradeable[['iv2', 'forecast_rv2', 'vrp_exante',
                     'vrp_pctile']].dropna().tail(3).round(4))

    # ---- 由合成期权链计算偏斜 ----------------------------------
    chain = pd.DataFrame({
        'strike':       [3600, 3800, 4000, 4200, 4400],
        'option_type':  ['put', 'put', 'put', 'call', 'call'],
        'implied_vol':  [0.285, 0.242, 0.196, 0.178, 0.171],
        'delta':        [-0.12, -0.25, -0.50, 0.50, 0.25],
    })
    skew = VolatilitySkew()
    print("\n25d skew (put IV - call IV):", round(skew.skew_25d(chain), 4))
    print("Normalized skew:", round(skew.normalized_skew(chain), 4))
    print("25d butterfly:", round(skew.butterfly_25d(chain), 4))

    # ---- 期限结构闸门 ------------------------------------------
    gate = TermStructureGate()
    for label, (s, m1, m2) in {
        'calm':        (14.0, 15.2, 16.4),
        'transition':  (18.0, 18.4, 18.5),
        'stress':      (46.0, 38.0, 31.0),
    }.items():
        print(f"\nGate [{label}]:", gate.gate_open(s, m1, m2))

    # ---- 压力模拟器:真正要紧的那部分 --------------------------
    sim = ShortVolStressSimulator(
        notional=100_000,
        vega_per_point=850,        # IV 每上升 1 个波动率点亏损 850 美元
        gamma_dollar_per_pct=1_200  # 现货每变动 1% 的平方对应 1,200 美元
    )

    print("\nShort-vol stress grid (loss as % of allocated capital):")
    grid = sim.stress_grid()
    pivot = grid.pivot(index='spot_move_pct', columns='iv_point_rise',
                       values='loss_pct_of_notional')
    print(pivot)

    print("\nAny scenario that wipes out the allocation?",
          (~grid['survivable']).any())

    scale = sim.max_survivable_size(
        worst_case_spot_move=12,      # 一次 12% 的波动
        worst_case_iv_rise=35,        # 同时 IV 上升 35 个点
        max_acceptable_loss_pct=20.0  # 最多亏掉这个仓位的 20%
    )
    print(f"\nMax survivable position scale vs. current: {scale}x")
    print("If that number is well below 1.0, the position as "
          "currently sized is too large. That is the whole point "
          "of running this before you trade.")

⚠️ 这段代码是什么,不是什么

这是一套 度量与压力测试 工具,不是一套执行系统。它刻意不包含任何下单路由、不包含自动定仓,也不包含任何告诉你该开仓的"信号"。 ShortVolStressSimulator 才是这段代码里真正配得上位置的那个类:它让亏损曲面在资本投入之前就先被看见。 另外请注意,事后 VRP 那个方法在它自己的属性里带着一条明确的前视警告——这是有意为之。如果你把这条警告删掉,再拿它当信号用,你的回测会很漂亮,而你的实盘账户不会长成那个样子。

📊 数据需求

VRP 与闸门这两个组件需要 S&P 500 的每日收盘价、VIX,以及最近两个月份 VIX 期货的结算价——这些都能从公开来源拿到。偏斜组件需要一份期权链快照,其中带有每份合约的隐含波动率与 delta,这一点大多数散户券商都提供,但很少有券商提供 历史数据。要建立一段偏斜历史,一般意味着你自己每天给期权链拍快照并往后累积,或者付钱给数据供应商。市面上不存在免费的、达到研究质量的历史期权曲面。

经过 delta 对冲的做空波动率究竟是怎么弄死你的

delta 对冲拿掉的,是你本来就没有为之收钱的那部分风险

对一个做空的跨式做 delta 对冲,会把这个仓位从一个方向性押注变成一个纯粹押注已实现方差对隐含方差的仓位——这听起来像是在降低风险,而且确实是,但只在一个特定的维度上。 delta 被对冲掉之后剩下的,是做空 gamma 与做空 vega 的敞口,而这两个敞口恰恰就是产生整个亏损分布的那两个。对冲拿掉的是噪声。它完全没有碰那个会要人命的东西。

delta 对冲之后还活着的东西

敞口 对冲掉了吗? 体制切换时的表现
Delta(方向) 是——持续对冲,但要付出成本 只在两次再平衡之间被中性化;一旦出现跳空,对冲本身就变成了一台亏损机器
Gamma(凸性) 否 亏损随着行情幅度的 平方 增长;在单边跳空的行情里,每一次再平衡都是被迫的高买低卖
Vega(波动率水平) 否 整个曲面向上重新定价时,立刻而且猛烈地反映为你的浮亏
Vanna/volga(交叉效应) 否 偏斜变陡与微笑曲率的变化,会专门在下行一侧的翼部叠加放大 vega 的亏损
流动性与保证金 否 价差走阔、保证金要求在事件进行中被上调,而你的出场价格是被对着你报的

关键洞见: "经过 delta 对冲"常常被当成"风险已受管理"的同义词。它不是。一本经过 delta 对冲的做空波动率账簿,是一笔集中的、未被对冲的、押在 gamma 与 vega 上的赌注,而历史上每一次爆仓,发生的都是经过 delta 对冲的仓位。

四阶段失效序列

做空波动率的失效不是随机的——它遵循一个可辨认的序列,而在序列进行当中认出它,是仓位已经建起来之后你唯一还有的防御。

逐阶段拆解这个序列

阶段 发生了什么 交易者通常会做什么 实际上需要做什么
1. 平静期的累积 权利金连续几个月甚至几年可靠地进账;信心和仓位一起长大;更多卖方挤进来 加大仓位,减少对冲——因为对冲看起来纯粹是成本 认清拥挤正在积累,而溢价被压缩就是这件事的证据
2. 最初的冲击 现货跳空;整个隐含波动率曲面一次性重新定价;偏斜变陡 把它当成噪声;毕竟这个仓位挺过了之前的几次晃动 立刻、机械地减仓,在你判断它是不是真的之前就减
3. 反身性的螺旋 做市商对冲、波动率目标策略的降杠杆,以及其他做空波动率参与者的被迫平仓,全都朝同一个方向砸;流动性蒸发 试图在单边市场里以灾难性的价格对冲,或者干脆僵住 这里没有任何做法是管用的。这个阶段能不能活下来,取决于第 1 阶段做的决定,而不是现在采取的行动。
4. 强制平仓 保证金在事件进行中被上调;券商在整段行情最糟糕的价位上把你平掉 已经没有任何主动权 只有事先定好的仓位大小与已定义风险的结构,才能防止走到这一步

关键洞见: 这个序列里每一个有意义的决定,都只在第 1 阶段还有得选。到了第 3 阶段,是市场结构本身——做市商对冲,加上机械性的降杠杆,加上拥挤仓位的被迫回补——在制造那段正在毁掉你的行情,而你自己想出场的动作,也是它的一部分。

反身性:你的出场就是燃料

做空波动率风险最根本的特征,是它具有反身性:大量参与者同时对冲或回补做空波动率敞口这个动作本身,就是把波动率推得更高的原因。 这和一笔普通的拥挤交易有本质区别。在一个拥挤的股票多头仓位里,出场的参与者把价格往下压,最终会在某个出清水平上找到买家。而在一个拥挤的做空波动率仓位里,出场的参与者必须 买入波动率 并且 卖出标的 ——这两件事都会机械地推高已实现波动率,而已实现波动率上升会推高隐含波动率,隐含波动率上升会加大所有还在做空的人的亏损,从而逼着更多人出场。 这笔交易自带助燃剂。

🚨 相关性与你手上的每一样东西一起归一

做空波动率的亏损,不会独立于你组合里的其他部分单独到来。它们到来的时候是股票回撤、信用承压和流动性事件——恰恰是你的股票核心正在下跌的时刻;如果你还在从组合里提取生活费,那也恰恰是你最承担不起额外亏损的时刻。 做空波动率的这个卫星仓位不是分散化工具。它是一台带杠杆的、非线性的放大器,放大的是你本来就已经持有的风险。 正确的理解方式是:它在风险预算里的位置,是股票崩盘敞口的一次 增加 ,而不是一条独立的、不相关的收益来源。

案例一:波动率末日,2018 年 2 月

发生了什么

2018 年 2 月 5 日,VIX 在单个交易日里大致翻了一倍——这是它历史上最大的单日涨幅——而那些已经成为做空波动率交易散户门面的反向波动率交易所交易产品,在几个小时之内损失了绝大部分价值。 VelocityShares Daily Inverse VIX Short-Term ETN(XIV)跌到足以触发其加速条款的程度,随后被终止。相关产品要么被终止,要么受到了永久性的损害。

按历史标准衡量,引发这一切的股市下跌毫不起眼——S&P 500 在几个交易日里回撤了百分之几,这种幅度经常发生,一个分散化的组合吸收它时不会有任何事。 灾难不在那段股票行情里。它在波动率的重新定价,以及压在上面的那套机械结构里。

机械传导链条

环节 机制
1. 拥挤在 2017 年一路积累 异常平静的一年,把巨额资金吸引进了反向波动率 ETP 和自主决策的卖权利金策略。所有人都站在同一边,而被压缩的溢价就是看得见的证据。
2. 再平衡是机械的,而且是公开可知的 反向波动率 ETP 必须每天再平衡它们的 VIX 期货敞口,才能维持恒定的反向杠杆。当 VIX 期货大幅上涨时,那次再平衡要求它们 买入 VIX 期货——而且是大量地、临近收盘地、按一个可以预测的方向。
3. 那次再平衡被抢跑了 所需再平衡的方向和大致规模,都能从这些产品公开的方法论与资产规模里推算出来。抢先布局让行情变得更糟。
4. 反身性接管了一切 买入 VIX 期货把 VIX 期货推得更高,这又加大了必须买入的量,又把它推得更高——正是上文描述的那种助燃剂,而且是在一个稀薄的盘后市场里运转。
5. 终止 XIV 的指示性价值跌穿了它的加速阈值。持有人拿到的不是一次可以等它过去的回撤——他们拿到的是一个被终止的产品。 这个仓位无法恢复,因为它已经不存在了。

关键洞见: 任何一张做空波动率策略的历史回撤图,都隐含地假设了仓位能活到参与反弹。波动率末日就是这个假设的决定性反例:终止、强制平仓和产品损害,会把一次暂时的浮亏变成一笔永久性的实亏。 路径是要紧的,而且终局状态是真的存在的。

这个案例特有的三条教训

  • 产品结构本身就是一个独立的风险因子。 那条加速条款是写在募集说明书里披露过的。从来没读过它的持有人,是在它被触发的那天才发现它的存在。任何带杠杆或反向产品的终止与再平衡规则,都是这个仓位风险的一部分,而不是法律细节。
  • 可预测的机械性资金流,会被别人拿来对着你做。 一项能从公开文件里推算出来的对冲或再平衡要求,那不是对冲;那是电报。
  • 触发的事件可以很小。 那段股市行情是普通的。这是最重要、也最少被真正内化的一条教训: 你不需要一场危机才会被一个做空波动率的仓位摧毁——你只需要一段快速的行情,砸进一个拥挤的仓位里。

📚 更深入的处理

这一事件的叙事与行为解剖——这笔交易从内部感受起来是什么样,以及相关性同步平仓的动力学细节——是 《在压路机前捡便士》第 2 章:波动率末日——一个相关性同步平仓的案例研究的主题。本报告讲的是定价与结构机制;那一章讲的是人的因素与资金流动力学。两个都要读。

案例二:2020 年 3 月的波动率飙升

同一个仓位,另一种失效模式

如果说 2018 年 2 月是单日之内的机械式引爆,那么 2020 年 3 月就是一段持续数周的体制:VIX 达到了 2008 年以来未见的水平,并且在高位停留了很长一段时间。 两者都摧毁了做空波动率的仓位。它们通过不同的机制做到这一点,而一个只研究过 2018 年的交易者,为之做好准备的是错误的那场灾难。

波动率末日对比 2020 年 3 月:两种不同的致命机制

维度 2018 年 2 月 2020 年 3 月
持续时间 数小时——一个交易日 数周持续的高波动率
主要亏损驱动因素 Vega:隐含波动率的瞬时重新定价 Gamma 失血:反复出现的大幅单日波动,每一次都是一次代价高昂的再平衡
期限结构闸门有用吗? 几乎没用——贴水是在损害发生之后才确认的 只有当它提前触发、而且交易者真的照做时才有用;它此后关闭了很长一段时间,那是正确的,但感觉上像是错过了一段反弹
delta 对冲还维持得住吗? 谈不上——行情比再平衡的速度更快 维持得住,而这恰恰是问题所在:在一个单边趋势的市场里,每一次再平衡都把一笔亏损固化下来,一天接着一天
流动性状况 稀薄的盘后 VIX 期货市场 股票、期权乃至国债市场全面出现流动性损伤;买卖价差急剧走阔
保证金的表现 立刻而且严厉 在数周之内被反复上调——是一场缓慢的、碾磨式的挤压,而不是一次单独的追缴
能靠等待熬过去吗? 对被终止的产品来说不能;那个仓位已经没了 只有在你有足够资本去应付数周不断升级的保证金时才行——而那是一个偿付能力问题,不是一个策略问题

关键洞见: 可以说,持续性的高波动体制比单日冲击更难熬过去,因为它是逐步耗尽你的资本,同时还不断给你虚假的曙光。每一次波动率的部分回落都在邀请你重新进场,而下一次飙升往往紧接着就来了。 一个对做空波动率风险的全部心理模型就是"一个糟糕的日子"的交易者,对一个糟糕的季度是毫无准备的。

关于流动性的那条教训

2020 年 3 月证明了:在一场足够严重的压力事件里,所有 delta 对冲赖以成立的那个假设——你可以以合理的价格连续成交——是会失效的。 期权买卖价差走阔到正常水平的好几倍,股指期货反复触及涨跌停条件,就连世界上流动性最好的工具也出现了实质性的价格脱节。一个在正常时期成本可控的 delta 对冲计划,在你真正需要它的时候,成本会是好几倍——而这恰恰就是让一个纸面上活得下来的仓位在实盘中活不下来的原因。

⚠️ 央行干预不是一个风险模型

2020 年 3 月的波动率事件之所以被控制住,部分原因是一次极其迅速、规模极大的政策干预。 一个因为政策响应的速度和规模才活下来的策略,它证明的不是自己稳健——它证明的是自己需要被救。 把一套做空波动率的流程建立在"下一次干预也会来得足够快"这个前提上,那不是风险模型;那是一个附带了历史轶事的希望。

案例三:LTCM 与空头凸性失效的一般形态

为什么一只 1998 年的固定收益基金该出现在一篇讲波动率的文章里

Long-Term Capital Management 通常不会被当作一个做空波动率的故事来讲,但从结构上看,它恰恰就是——而且它是现有材料里最干净的一个证明:这种失效模式与资产类别无关,与从业者的水平也无关。 LTCM 的仓位加总起来是做空凸性的:它们在一大批相对价值交易里靠收敛与稳定获利,而当利差发散时则以非线性的方式亏损。这只基金拥有当时全世界最强的定量人才,包括诺贝尔奖得主,还拥有远超散户所能触及的建模能力、融资渠道和信息优势。

空头凸性失效的结构模板

属性 LTCM 1998 做空指数波动率,任何时代
收益形态 小额、可靠的收敛收益;巨额的发散亏损 小额、可靠的权利金;巨额的已实现方差亏损
理由 历史上的利差关系加上复杂的模型 历史上隐含波动率高于已实现波动率,加上复杂的模型
杠杆 极高,理由是这套策略自身收益的波动率很低 常常通过保证金隐性存在,理由和上面一模一样
关于相关性的假设 分散在许多看起来彼此独立的交易上 分散在不同行权价、不同到期日、不同标的上
实际发生的是什么 压力之下相关性收敛到 1;那些"独立的"交易其实是同一笔交易 压力之下相关性收敛到 1;每一个做空波动率的仓位都是同一笔交易
最终的机制 仓位为市场所知;出场价格被对着它们报;被迫平仓 拥挤的持仓;出场价格被对着它们报;被迫平仓

关键洞见: 当时能找到的、最有勋章的定量人才,带着远超散户所能触及的资本、信息与执行能力,被这个结构摧毁了。 这里的教训不是他们犯了某个本可以避免的具体错误——而是这种收益结构本身带着一个失效模式,而技术水平消除不了它。 如果你对做空波动率风险的防御,只是"我比他们更小心",那你没有防御。

杠杆-波动率陷阱

把这三个案例串起来的一般机制是:测得的波动率很低的策略会招来杠杆,而做空凸性的策略之所以测得的波动率人为地低,恰恰是因为它的风险以罕见的大幅事件形式出现,而不是以持续的日常起伏形式出现。 因此,把波动率目标定仓法天真地套用在一个做空波动率的策略上,会让它在冲击到来之前的平静期里被定到 最大 。风险指标与真实风险是反向关系——测得的波动率最低的时候,恰恰是真实敞口最高的时候。任何不明确针对这一点做修正的定仓框架,都会系统性地在最糟糕的时点把仓位放到最大。

🚨 贯穿三个案例的共同线索

1998 年、2018 年和 2020 年,在资产类别、持续时间、触发事件和市场结构上都不相同。它们只共享一个属性: 一个在相当长时间里稳定有效的策略,按其近期已实现波动率定了仓位,而且很拥挤——遇上了一次它的参与者无法在不放大这次行情的前提下退出的快速重新定价。 这段描述不是一件历史珍玩。它是对每一个平静市场里做空波动率交易的实时描述,包括现在这个。

散户可行的模型——护栏必须装上

诚实地把这个模型说清楚

本系列的路线图为这篇文章指定了一种散户可行的表达方式: 经过 delta 对冲的做空波动率跨式或宽跨式,以 VIX 期限结构为闸门。 下面就把它完整地说清楚——包括那些不是可选项的约束条件。

这个模型,以及它那些不可省略的约束

成分 规格 为什么这些不是可选项
结构 只用有限风险结构 ——铁鹰式或铁蝶式,绝不裸卖跨式或宽跨式 把无上限的亏损转换成一个已知的数字。仅此一项选择,就把终局性结果从分布中移除了。
标的 只用宽基指数(SPX/SPY 系列) 方差溢价存在于指数期权中;卖出单只股票的期权溢价是另一种风险敞口,而且补偿更少
入场闸门 必须处于 contango,曲线走平即关闭闸门,已实现波动率没有上行趋势,VRP 百分位处于中段——而不是两个极端 极高的 VRP 通常反映的是不确定性在上升,而不是天上掉馅饼(见 Bekaert 的分解)
仓位规模 来自 max_survivable_size() 针对一个明确命名的压力情景计算, 不 根据近期已实现波动率计算 以波动率为目标的仓位方法,会在冲击到来之前把仓位放到最大——这就是杠杆-波动率陷阱
这块仓位的上限 占总投资组合中一个很小的、有明确上限的比例,并且按全部可能亏光来对待 配置多少,取决于这笔钱全部亏光也不会改变你计划的金额
尾部对冲 直接买入并持有深度价外看跌期权,作为一项永久成本,从收到的权利金中预算扣除 没有自己持有的凸性,你运行的就不是一个策略——而是那个把三个案例研究全部摧毁的纯空头凸性结构
Delta 对冲 在设定好的区间边界上再平衡,成本要按压力时期的买卖价差建模,而不是正常市场的价差 危机中的对冲成本是回测假设的数倍
退出规则 机械化并事先承诺,由曲线状态和隐含波动率变化触发,执行时不再斟酌 失败序列的第二阶段,是自由裁量还起作用的最后一个阶段,而自由裁量在那里必然失灵

关键结论: 这张表里的每一条约束都会降低预期收益。这就是交换。把这些约束拿掉的版本,预期收益更高,同时出现终局性结果的概率也不可忽略——而一个包含终局性结果的分布,它的均值不是你能拿去花的数字。

这些护栏的真实代价

有限风险结构收到的权利金,比裸卖少得多。永久持有的长尾部对冲是一项永久的拖累。保守的闸门会让你错过许多本可以盈利的窗口。由压力测试推导出的仓位,只是波动率目标法所给出仓位的一个零头。 把这些叠加起来,扣除交易成本、以及每一条腿和每一次再平衡都要跨越的买卖价差之后,这个策略的收益就变得平平——而对散户规模的账户来说,四腿结构加上持续 Delta 对冲带来的交易成本负担,是实实在在的沉重。

这就是诚实的算术,也正是本文把散户可行性评为 5 分之 2 的原因。 这个策略装好护栏的版本,收益会让许多读者失望;而那个收益令人兴奋的版本,正是会终结账户的版本。 不存在第三个选项,任何向你展示第三个选项的人,都是在推销什么东西。

⚠️ 容量与成本的现实

机构层面的 VRP 收割之所以能够规模化运作,部分原因在于:机构直接交易方差互换,而不是用期权组合去复制;它们按机构价差成交;它们持有横跨多个标的和多个到期日的分散化头寸;它们有专门的风险系统会自动降低敞口;以及——最关键的——它们的资本结构能挺过一次足以让散户保证金账户被强制平仓的回撤。散户用挂牌期权去复制同样的收益结构,在还没开始考虑任何风险之前,就已经把权利金中相当可观的一部分交给了价差和佣金。

让做空波动率账户走到尽头的常见错误

错误清单

  1. 把这笔溢价当成定价错误,而不是保险赔付: 这是本清单上其他所有错误的根源性认知偏差。它会直接导致仓位过大,因为你无法为一个你认为并不存在的风险正确定量。
  2. 用未来的已实现波动率来计算 VRP: 这种前视偏差会让散户的回测既好看又毫无价值。如果你的回测在信号路径的任何位置用到了 shift(-n) ,那它就不是回测。
  3. 根据近期已实现波动率来决定仓位: 杠杆-波动率陷阱——这会让仓位恰好在真实风险最高的时候达到最大,也就是紧挨着体制切换之前。
  4. 卖出裸露的或风险无上限的结构: 最大亏损必须是一个有限的数字,并且在入场之前就写下来。除此之外的任何做法,其分布中都存在一个终局状态。
  5. 因为看跌期权一侧贵就去卖它: 这等于把敞口精确地集中在那些制造了全部亏损分布的行权价上,还把它称作在捕捉超额收益。
  6. 以为期限结构闸门是一种保护: 它管理的是暴露的频率,从来不是亏损的严重程度。历史上每一次爆仓,都发生在闸门开着的时候。
  7. 把"做了 Delta 对冲"等同于"做了风险管理": 这个对冲移除的是你并未因此获得报酬的那部分敞口,留下的 Gamma 和 Vega 敞口才构成了全部风险。
  8. 假定你在危机中还能持续对冲: 2020 年 3 月表明,恰恰在你最需要对冲的时候,价差会扩大到正常水平的数倍,流动性会消失。要么按压力水平的成本建模,要么你的模型就是虚构。
  9. 在虚假的曙光中重新入场: 持续承压的体制会出现多次波动率的局部回落,其中若干次之后紧跟着新的飙升。每一次重新入场都会让损害叠加。
  10. 忽视产品结构和终止条款: 加速条款、杠杆重置和强制再平衡都是风险因子,它们都写在几乎没人会读的文件里,直到它们真正触发的那一天。
  11. 把空头波动率这块仓位算作分散化工具: 它的亏损与股票回撤的相关性达到最大。在风险预算中,它属于额外的股票崩盘敞口,而不是一条独立的收益来源。
  12. 用胜率来评判这个策略: 高胜率是这种收益结构的固有特征,而不是技巧或安全性的证据。分布的左尾才是唯一决定最终结果的统计量。

退休视角的结论:为什么这对一个正在提取的组合是敌对的

结构性论点

对于处于提取阶段的投资者——从投资组合中支取收入,而不是继续投入——做空波动率不只是一个激进的策略。它的风险特征与该目标是正面敌对的,这一点值得直白说出来,而不是含糊其辞。

为什么这种收益结构对退休者尤其不合适

退休所要求的 做空波动率实际提供的
亏损必须是可以恢复的,因为你的时间有限,而且不会再有新的投入 亏损可能是终局性的——强制平仓和产品终止,会把暂时的浮亏变成永久的、无法挽回的损失
回撤不能与提取同时发生,否则收益序列风险会叠加放大 最大亏损恰好在股票回撤期间到来——对一个正在被支取的投资组合来说,这是可能出现的最糟糕的时点
收益来源应当能分散股票核心的风险 恰恰在最需要分散化的条件下,相关性会趋近于 1;这块仓位放大的正是核心的风险
日常管理负担应当很低,且不应要求在危机时刻做决策 需要持续的 Delta 对冲、主动的体制监控,以及在剧烈压力下做出正确决策
亏损不得依赖杠杆或保证金 保证金要求会在危机中途上升;退休期间的一次追缴保证金,可能迫使你变卖 核心 投资组合来应付它
随着时间跨度缩短,结果的离散度应当收窄,而不是扩大 尾部风险不会随时间跨度而减小;跨度更短,只意味着从尾部事件中恢复的时间更少

关键洞见: 这种不匹配不是一个可以靠减小仓位来解决的程度问题。这种收益的 形状 ——稳定的小额收益、罕见的灾难性亏损、与股票压力的相关性达到最大——正是一个提取阶段投资组合所需要的镜像反面;后者需要的恰好相反:接受持续的小额成本,以换取对灾难性结果的保护。 一位想要接触方差风险溢价的退休者,就其自身目标的实质而言,更自然的角色是这份保险的买方,而不是卖方。

核心究竟应该放在哪里

本文的任何内容都不改变一个稳健退休投资组合的结构:低成本、广泛分散的指数核心,适当的债券配置,受控的成本,以及一个投资组合能够长期支撑的提取率。 为退休生活提供资金的是这个核心。任何波动率策略最多只是它旁边一小块卫星仓位,其规模要小到即使全部亏光也与整个计划无关,并且永远不能替代核心,也不能成为本应由核心提供的那份收入的来源。

如果你觉得方差风险溢价在智识上很有吸引力,但也认识到这种收益结构并不适合自己的处境, 那么有建设性的方向是同一笔交易的另一边:理解保护在什么时候历史上属于便宜(偏度被压缩、VIX 低、期限结构处于 contango),以及一笔适度的、事先预算好的自有凸性配置,如何能改善而不是恶化一个提取阶段投资组合的风险特征。这正是 Capula 尾部风险那篇文章所讨论的主题,而对本页绝大多数读者来说,那才是更相关的一篇。

🚨 如果你只从本文带走一件事

方差风险溢价是真实存在的,而它之所以真实,正是因为它在补偿某个人承担灾难性风险。你无法在不承担这个风险的前提下拿走这份补偿——这不是执行层面的缺陷,这就是这笔交易的定义。 本文中的每一项技术,包括那些代码,都在降低灾难发生的概率。没有任何一项能消除它;任何暗示可以消除的说法,描述的都是上面三个案例中从未存在过的东西。

你的行动计划

第一阶段:测量与压力测试,不做任何交易(4 到 8 周)

时间安排: 不投入任何资金。目标是在你还没有任何动机去回避它之前,先看清整个亏损曲面。

  1. 构建 VRP 序列 ,使用上面的 Python 框架,同时计算事后版本和事前版本,并观察可交易的那个版本要难看多少。这个差距,就是不知道未来的诚实代价。
  2. 用两种不同的已实现方差估计量来计算该序列 ,并量化你测得的溢价会变化多少。在设定任何阈值之前,先确定使用哪一个估计量。
  3. 针对一个你真的会考虑的仓位运行压力模拟器 ,并且去读亏损那一栏,而不是权利金那一栏。如果任何一个可存活情景显示为 False,那就说明仓位规模是错的。
  4. 对照你自己的计划读这三个案例研究。 针对每一个案例,具体写下你的流程在当天会做什么,以及你是否真的有能力执行它。
  5. 读 Picking Up Pennies 的全文 ——那是六章内容,讲的是本报告刻意不去重复的行为与仓位维度。

第二阶段:判断这到底该不该进入你的计划(2 到 4 周)

时间安排: 仍然不投入任何资金。设立这一阶段,是因为对大多数读者来说正确答案是否定的,而这个答案值得经由一次审慎的决定得出,而不是不知不觉地滑进一个仓位。

  1. 先确定你处在积累阶段还是提取阶段。 如果你正在从投资组合中支取收入,上一节的分析就直接适用,默认答案是否定的。
  2. 说出这块仓位的最大规模——它全部亏光也不会改变你的退休计划。 如果那个数字小到让你不舒服,那它就是正确的数字,而且它正在告诉你一些事情。
  3. 确认这块仓位是真正可隔离的 ——也就是说,它内部发生的保证金事件不可能波及你的核心投资组合。如果账户结构允许波及,那么在做其他任何事情之前,必须先改变这个结构。
  4. 认真考虑反向的那笔交易。 读一读 尾部风险那篇文章 ,并诚实评估:就你真实的目标而言,你究竟站在这笔保险交易的哪一边。

第三阶段:最小可行的有限风险实施(3 到 6 个月)

时间安排: 只有在第二阶段得出肯定答案时才进行,并且规模必须相对于投资组合真正微不足道。

  1. 只使用有限风险的指数结构 ——写明了最大亏损的铁鹰式或铁蝶式。绝不裸卖,绝不留下无上限的风险。
  2. 为每一次入场设置闸门 :contango、已实现波动率没有上行,以及处于中段的 VRP 百分位。被拒绝的入场和被接受的入场都要记录下来。
  3. 根据压力模拟器来决定仓位,而不是根据近期波动率;当压力假设发生变化时,重新推导仓位规模。
  4. 从第一天起就持有尾部对冲,并明确把它作为一项成本从权利金中预算扣除。它绝不是等条件恶化之后才加上的仓位。
  5. 以书面形式事先承诺退出规则 ,并在触发时机械地执行,不再重新评估。
  6. 单独跟踪真实发生的交易成本 ——多腿结构的价差和佣金,加上 Delta 再平衡,在散户规模下会占到毛权利金的很大一部分,而大多数人从来不去测量它。

第四阶段:持续复核(永久)

时间安排: 只要还有任何仓位存在,就一直进行。

  1. 每季度重新运行一次压力网格 ,并更新仓位参数——亏损曲面会随着仓位和市场条件的变化而变化
  2. 监控拥挤度指标:被压缩的权利金、不断增长的空头波动率产品规模,以及长时间的平静,正是失败序列中第一阶段的条件
  3. 复核你的闸门在历史上的实际表现 ,对照真实发生过的那些事件:它会及时关闭吗?而你会遵守它吗?
  4. 每年重新验证一次这块仓位的可隔离性,尤其是在券商或账户结构发生任何变化之后
  5. 随着时间跨度缩短,重新审视它与退休的匹配度 ——一个在积累阶段合适的策略,可能随着提取阶段临近而变得不合适,而这个变化足够缓慢,容易被忽略

推荐阅读

  • 机构与学术研究:
    • Geert Bekaert 及其合作者,Federal Reserve Board 关于方差风险溢价、不确定性与时变风险厌恶的研究——正是这一分解把风险的数量与风险的价格区分开来
    • Goldman Sachs 股票衍生品研究——跨到期日、行权价和标的的方差溢价与偏度曲面框架
    • 关于模型无关隐含方差以及 VIX 构建方法的学术文献,它构成了 VRP 定义中 IV² 那一项的基础
    • 关于 2018 年 2 月反向波动率 ETP 终止事件的事后分析文献,包括这些产品招募说明书中自带的加速条款
  • 相关 PMR 文章:

🎯 最后的思考

方差风险溢价不是市场的无效率,也不是免费的午餐。它是保险的价格,由那些其委托条款使得灾难性亏损远比权利金昂贵的参与者支付,并由那些愿意且有能力吸收这种灾难性亏损的参与者收取。 弄清楚你属于这两类人中的哪一类——以及你真实的财务目标把你放在哪一类——就是全部的分析。其余一切都是实施细节。

生存的关键: 假定冲击会在你的闸门开着的时候到来,因为在每一个有记录的案例中它都是如此。按最大亏损可以承受来决定规模,而不是按它不太可能发生;持有尾部而不是卖出尾部;并且永远不要让一块卫星波动率仓位,变成本应由你那个低成本分散化指数核心提供的收入来源。这是核心旁边一小块有上限、且被视为全部处于风险中的卫星仓位——永远不是核心的替代品;而对一个处于提取阶段的投资组合来说,多数情况下根本不值得持有。

如果在入场之前,你无法用一个具体的美元数字说出你的最大亏损,那你对这个仓位的理解还不足以持有它。