halo 的技术博客

返回

传统多因子模型里,「因子」通常是价值、动量、规模这些横截面上的异常。但有一个因子一直站在棋盘之外、却在每个危机里决定你的生死——恐慌本身。VIX 不是新闻,它是一个可以被定价、被交易、被做成组合一块的资产。本文的论点只有一句:把「波动率风险溢价(VRP)」当成和风险资产同等地位的一个因子,它的收益来源、风险来源、与股票的相关结构,都清清楚楚。

我们用一个 Bates 型 SVJ(随机波动率+跳跃) 模型把整条逻辑跑通:先生成带崩盘跳的随机波动路径,再据此给 VIX 与 VIX 期货定价,最后把「恐慌」拆成一个可多可空的因子。在 20 年(5040 个交易日)模拟里,模型隐含 VIX 中枢 ≈20、峰值 45,共发生 11 次崩盘跳;由此定出的 VIX 期货在平静日呈 Contango(升水)、恐慌日呈 Backwardation(贴水),全样本 67% 的交易日期货高于即期、VRP 均值 +0.74 vol 点——一个真实存在、长期为正的溢价。把它做成「做空 VIX 期货」因子,年化 7.2%、波动 15%、Sharpe 0.48,比同期股票(Sharpe 0.12)还高;它顺周期(与股票相关 +0.54),危机关头和你同跌,这正是它被定价的本质。

SVJ 模拟:指数价格带崩盘跳,模型 VIX 在恐慌期飙升

一、SVJ:让波动自己随机、让崩盘自己跳#

普通 BS 模型把波动当成常数,但 2020 年 3 月的 VIX 从 15 飙到 80,绝不是「常数波动」能解释的。SVJ 做两件事:用 Heston 随机方差 v_t 让波动连续地随机游走,用复合泊松跳给收益周期性地来一记崩盘。

  • 方差服从 CIR:dv = κ(θ−v)dt + σ_v√v dW
  • 收益:d lnS = (μ − ½v − λm_J)dt + √v dZ + J_t,其中 J_t 是跳,强度 λ、单跳对数收益 ∼N(μ_J, σ_J²)
  • ρ(J,Z)=−0.7:跳往往伴随波动飙升(崩盘日 VIX 暴涨)
  • m_J = E[e^{J}−1] 是跳的漂移补偿,保证风险中性下股价是鞅

代码如下(纯 numpy,无外部定价库):

跑 5040 天,VIX 隐含中枢 ≈20、样本均值 18.6、峰值 45.1,全样本 11 次跳空(占比 0.22%)——和真实市场「低波动是常态、崩盘是尖刺」的画像一致。

二、VIX 是怎么被「定价」的:30 日远期方差#

VIX 的数学定义是 30 天方差互换远期率的平方根。关键好处:在 Heston 模型下,远期方差对当前方差 v_t仿射的,有闭式解,不用蒙特卡洛就能算即期公允 VIX。

远期方差 E^Q[∫_t^{t+T} v_s ds | v_t] = θT + (v_t−θ)(1−e^{−κT})/κ,令 T=30/252,则:

T30 = 30.0 / 252.0
def fair_vix(v):
    vs = (theta * T30 + (v - theta) * (1.0 - np.exp(-kappa * T30)) / kappa) / T30
    return 100.0 * np.sqrt(np.maximum(vs, 1e-6))
python

这一步的意义:VIX 不是外生给定的数字,而是模型内部状态 v_t 的确定性函数。波动状态高了,VIX 自动高;状态低了,VIX 自动低。这就把「恐慌」从新闻还原成了可计算的模型变量

三、VIX 期货定价:E^Q[VIX_T] 与期限结构#

VIX 期货在 T 时刻交割的,是那时的 VIX 水平。风险中性价格就是 F_t(τ) = E^Q[VIX_{t+τ}]。因为每个未来时点的 VIX 仍仿射依赖于那时的方差 v_{t+τ},我们只需在 Q 测度下模拟 CIR 方差、取终态 VIX 平均即可:

def mc_expected_vix(v0_scalar, tau_days, n_paths=1500, seed=7):
    n_steps = max(1, int(round(tau_days)))
    dts = tau_days / n_steps / 252.0
    rng = np.random.default_rng(seed)
    vv = np.full(n_paths, v0_scalar)
    Z = rng.standard_normal((n_steps, n_paths))
    for s in range(n_steps):
        vs = np.maximum(vv, 0.0)
        vv = np.maximum(vv + kappa * (theta - vs) * dts + sigma_v * np.sqrt(vs) * np.sqrt(dts) * Z[s], 1e-6)
    return float(np.mean(fair_vix(vv)))
python

把不同到期 τ 的期货价连起来,就是 VIX 期限结构。模拟里两个典型快照:

  • 平静日(VIX=11.8):期货 1M→6M = 14.2→19.1,整体向上——近端低、远端高,典型的 Contango(升水)
  • 恐慌日(VIX=45.1):期货 1M→6M = 41.1→27.8,整体向下——近端极高、远端回落,典型的 Backwardation(贴水)

VIX 期货期限结构:平静日整体升水,恐慌日整体贴水

同一标的、不同时点,曲线整体翻转——这正是 VIX 期货最核心的可交易结构。

四、VRP:恐慌被明码标价#

真实市场里,VIX 期货长期高于随后的实现波动,这块价差叫 波动率风险溢价(VRP)——投资者愿意为「崩溃保险」付费,卖波动的人赚这份溢价。我们在期货里显式植入一个随期限衰减的 VRP 楔差(近端最肥),让期货 F_t(τ) = E^Q[VIX_{t+τ}] + 楔差(τ)。结果是:

  • 期货相对即期的溢价均值 +0.74 vol 点
  • 67.1% 的交易日期货高于即期(即处于 Contango,做空波动能赚溢价)。

VIX 期货相对即期长期溢价:Contango 占多数,做空波动赚确定性溢价

这证明了一件事:「恐慌」不是一个模糊的情绪词,而是一个长期为正的、可被定价的价差。既然能被定价,它就是一个因子。

五、把恐慌做成因子:做空收割 vs 做多保险#

「恐慌因子」怎么交易?最干净的做法是做空 VIX 期货——你卖出市场为崩溃恐惧付的保费,赚 VRP。月度收益定义为:

H = 21
r_short = []          # 做空 VIX 期货(收割 VRP) 月度收益
for d in range(0, NDAY - H, H):
    entry = mc_expected_vix(v[d], H) + vrp_wedge(H)   # 月初建仓的 1 月期货价
    settle = fair_vix(v[d + H])                        # 月末到期 = 即月 VIX
    r_short.append((entry - settle) / entry)
python

按 15% 年化波动缩放后(原始头寸波动极高,缩放不改变 Sharpe),这个因子:

  • 年化 7.2%、波动 15%、Sharpe 0.48、最大回撤 −37.3%;
  • 与股票相关 +0.54——它是顺周期的:股市崩、VIX 暴涨、做空者亏,所以它和你「同跌」。
  • 最惨月 −14.2%(当月股票 −6.8%),最好月 +9.5%。

Sharpe 0.48 高于本例股票本身的 0.12——「恐慌」作为一个因子,质量不输任何传统风格因子。但注意它的镜像:**做多 VIX 期货(恐慌对冲因子)**则是危机保险——年化 −6.8%、Sharpe −0.45、与股票相关 −0.54,崩盘月飙升、平静月慢慢 bleed。

把这两个「恐慌因子」接到组合里,对照清晰:

组合 (90% 股票 + 10% 恐慌因子)年化波动Sharpe最大回撤
纯股票2.8%22.2%0.12−72.1%
+10% 做空 VIX(赚溢价)3.2%20.9%0.15−68.7%
+10% 做多 VIX(买保险)1.8%19.2%0.09−66.2%

恐慌因子(做空 VIX)净值 vs 股票,配 10% 提升组合 Sharpe

两类用法都对,只是角色不同:做空 VRP 是「赚取恐慌溢价」的因子,做多 VIX 是「为组合买崩溃保险」的因子。前者提升风险调整收益,后者牺牲一点收益换回撤保护。

六、真实陷阱(诚实版)#

1. 数据是合成的:全文数字来自 SVJ 模拟,用于演示机制,不是某只真实 ETF 的回测。落地时要用真实 VIX 期货收盘价、真实指数收益替换 simulate_svj

2. VRP 是显式植入的:真实 VIX 期货长期 Contango 是经验事实,但模型本身不含风险溢价,我们用楔差把它「钉」进去。若想从纯扩散推导出正 VRP,需要引入风险厌恶(市场价格为波动风险为负),那会改动 Q 测度的漂移项。

3. 波动缩放不是魔法:原始做空 VIX 头寸月度波动可达 75%,±70% 的月份并不罕见。本文按 15% 目标波动缩放,Sharpe 不变但数字才可读。实盘必须做波动率目标化管理,否则寸头会失控。

4. 跳跃尾部是真实风险:做空 VRP 最惨月 −14%(缩放后),这是因为一次崩盘跳让 VIX 翻倍。模型里只有 11 次跳,真实市场 2008/2020 级别的跳会更狠——做空波动的尾部比你想象的更肥。

5. 期限结构会动:本文用固定楔差。真实 VRP 随 regime 变化,2008 与 2020 的贴水深度天差地别;静态做空会在危机里被反复打脸,必须配合 regime 判断或严格止损。

6. 相关结构是时变的:顺周期(+0.54)是样本均值,危机最剧烈的几周相关会冲到接近 +1,那时「赚溢价」和「持股票」会同时流血——这也是为什么纯做空 VRP 不能单独扛组合。

结语#

「把恐慌也做成因子」不是修辞。从一个 SVJ 模型出发,VIX 是内部状态的函数、VIX 期货有可计算的期限结构、VRP 是长期为正的明码标价——恐慌由此变成了一个收益可算、风险可度量、与股票相关结构清晰的因子。你可以像持有价值、动量那样,把它写进因子清单:想要溢价就做空 VIX,想要保险就做多 VIX。真正难的从来不是「有没有这个因子」,而是承认它、给它一个明确的风险预算、并为它的崩溃尾部留好退路

本文图表与全部数字均由 generate_svj_vix_futures_images.py 用 numpy 从零计算生成(SVJ 模拟 + VIX 仿射定价 + VIX 期货蒙特卡洛),非占位图。把 simulate_svj 换成真实数据,整套代码可直接复用。

随机波动率带跳跃与 VIX 期货定价:把恐慌也做成因子
https://blog.halo26812.eu.org/blog/svj-vix-futures
Author halo
Published at 2026年7月12日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨