「IV 是 28%,该卖期权吗?」——这个问题没法回答。28% 对一只平时 15% 的股票是天价,对一只危机里 60% 的指数却是地板价。脱离了历史分布,单个 IV 数字毫无意义。
波动率锥(Volatility Cone)要解决的正是这件事:它把「在每一个特定期限下,滚动已实现波动率历史上落在什么区间」画成一组随期限展开的喇叭形分位带。你再看当前 IV / 当前已实现波动落在喇叭的哪个位置,就能回答:现在波动算贵还是算便宜?该卖溢价还是该买翅膀?要不要先降仓避险?
下面用一段模拟的随机波动率指数序列(含偶发崩盘冲击)从零把整套方法跑通,所有图表均为真实计算、非占位图。

一、波动率锥是怎么画出来的#
核心就三步:
- 对每个特定期限
w(10/20/30/60/90/120/180 日),算全样本上「滚动w日年化已实现波动」这条时间序列; - 对每条序列取历史分位(5 / 25 / 50 / 75 / 95);
- 把不同
w的分位点在图上连起来——短期限波动聚集在窄带、长期限被更多样本平均、带子更宽,于是自然形成「喇叭」。
import numpy as np
def rolling_ann_vol(ret, w):
"""ret: 日收益(%);返回年化滚动已实现波动序列(前 w-1 个为 NaN)。"""
n = len(ret)
rv = np.full(n, np.nan)
for i in range(w, n):
rv[i] = np.std(ret[i - w + 1:i + 1], ddof=1) * np.sqrt(252)
return rv
windows = [10, 20, 30, 60, 90, 120, 180]
pcts = [5, 25, 50, 75, 95]
cone = {w: rolling_ann_vol(ret, w) for w in windows}
band = {p: [] for p in pcts}
for w in windows:
valid = cone[w][~np.isnan(cone[w])]
for p in pcts:
band[p].append(np.percentile(valid, p))
# band[50] 即各期限中位数;band[5]/band[95] 即「常态区间」上下沿python读图要点:中位数(蓝线)是「公平值」,25–75 分位(浅蓝填充)是「常态区」,5/95 分位是极端边界。 当某个期限的当前波动戳到 95 分位以上,说明它处在该期限自身历史上的「最慌」那 5%。
二、把当前 IV 放进锥里:它是贵还是便宜#
波动率锥最直白的用途是相对定价。假设你交易的是 30 日期限期权,拿到一个 IV=35% 的报价:
- 查锥上 30 日那一点:中位数可能是 22%、95 分位是 33%;
- IV=35% > 95 分位 → 这个期权相对于「该标的自身历史波动」明显偏贵 → 倾向卖出(收溢价);
- 反过来 IV 跌破 5 分位 → 便宜 → 倾向买入(买翅膀/买跨式)。
注意一个常见坑:比较要在「同一期限」上做。用 30 日 IV 去对标 10 日锥是错位;IV 与已实现波动的期限结构本来就不平。
三、分位时序:把「现在慌不慌」做成信号#
单看某一日的分位还不够,把它沿时间画成序列,就得到一张「波动率温度计」:
def vol_percentile_series(ret, w=60, look=252):
"""每日 60 日已实现波动,在过去 1 年分布中的历史分位(0-100)。"""
rv = rolling_ann_vol(ret, w)
n = len(rv)
pct = np.full(n, np.nan)
for i in range(w + look, n):
hist = rv[i - look:i + 1]
hist = hist[~np.isnan(hist)]
pct[i] = (hist < rv[i]).mean() * 100.0
return pct
pct_series = vol_percentile_series(ret, w=60, look=252)python
图上 90 分位(红虚线)以上标「卖波动区」、10 分位(绿虚线)以下标「买波动区」。它能干两件事:
- 择时信号:分位突破 90 → 波动进入自身历史极端高位,通常对应恐慌/急跌,此时卖溢价最危险(IV 可能继续飙、或 realized 随后反扑),应谨慎;分位跌破 10 → 波动被压到地板上,期权极便宜,是买权布局的好窗口。
- 状态识别:不是预测方向,而是回答「我现在处于什么波动状态」——这是后面所有期权结构选择的前提。
四、定价视角:隐含 vs 已实现(期限结构对照)#
波动率锥给的是「已实现」的历史分布;期权交易的是「隐含」。把两者摆在一起,才能做真正的相对价值。

经验规律:IV 通常系统性高于 RV,这部分价差叫波动率风险溢价(VRP)——投资者愿意为「保险」付费,所以期权卖方便能有正的预期 carry。但 VRP 不是常数:
- 当 IV 相对 RV 的溢价处于自身历史高位(锥的上沿)→ 卖溢价更划算;
- 当溢价被压缩甚至倒挂(IV < RV,常发生在剧烈真实波动中)→ 卖溢价吃亏,应转向买方策略。
所以定价 = 看 IV 相对「锥上的 RV 分布」贵不贵;方向 = 看 VRP 处在自身历史的哪个分位。两个维度交叉,才构成完整的期权相对价值判断。
五、择时视角:把锥当成风险叠加层(vol overlay)#
波动率锥最稳妥的实战用法,不是去赌「波动一定会回归」,而是当风险叠加层:当当前波动处于历史高位(>90 分位)时,降低风险敞口。
下面用底层资产的「波动率择时叠加层」来演示这一逻辑——高波动区往往对应崩盘与剧烈回撤,锥把「现在是否危险」量化出来:
def vol_overlay_backtest(ret, pct_series, threshold=90):
"""波动分位 > threshold 时降仓至 0(现金),否则满仓。"""
r = ret / 100.0
strat, bench = [1.0], [1.0]
start = np.where(~np.isnan(pct_series))[0][0]
for t in range(len(r)):
danger = (t >= start) and (pct_series[t] >= threshold)
x = 0.0 if danger else 1.0
strat.append(strat[-1] * (1 + x * r[t]))
bench.append(bench[-1] * (1 + r[t]))
return np.array(strat), np.array(bench)python
在我们这段含偶发崩盘冲击的模拟路径上,效果非常直接:
| 方案 | 年化收益 | 夏普 | 最大回撤 |
|---|---|---|---|
| 始终满仓基准 | −7.84% | −0.23 | −68.93% |
| 波动率锥叠加层(>90 分位降仓) | +0.31% | +0.11 | −41.11% |
叠加层没让收益飞起,但做对了一件事:在风暴区把仓位的「致命回撤」砍掉约 40%,并把夏普从负拉正。这正是波动率锥作为择时工具该有的样子——不追求多赚,而追求「别在最容易死的地方满仓」。
六、不同波动状态,该用哪类期权结构#
把锥的读数翻译成期权动作,是这篇文章的落脚点:
- 分位 > 90(恐慌/高波动):IV 贵、realized 可能反扑。慎卖裸溢价;若一定要卖,用价差(定义好最大亏损)而非裸卖;可小仓买虚值认沽做尾部保险。
- 分位 50–90(正常偏热):VRP 通常丰厚,卖出期权收割溢价(铁秃鹰 / 看跌价差贷方)的甜蜜区,但严控仓位、做好对冲。
- 分位 10–50(正常偏冷):方向性波动率不高,卖溢价收益薄,适合价差组合或轻仓趋势结构。
- 分位 < 10(极致压抑):期权极便宜,是买入跨式 / 买翅膀布局「波动醒来」的窗口;成本极低,赔率极佳。
七、三大实战陷阱#
- 前视偏差(最致命):分位必须用「截至当日的过去数据」算。若不小心把「未来波动」混进历史分布,分位信号会偷偷看到答案,回测虚高。严格滚动、滚动窗口内只向前看。
- 非平稳与结构突变:一段大牛市的「常态波动」和危机后的「新常态」天差地别。固定全样本分位会严重滞后。实务上用滚动窗口(如过去 1–2 年)而非全样本,并定期重置。
- IV ≠ RV 的瞬时错位:锥讲的是 realized 的历史,但交易的是 implied。极端行情里 IV 会滞后、会跳变,单看 realized 分位会误判「IV 已便宜」。务必把第四节的 IV/RV 期限结构对照一起看。
八、小结#
波动率锥的价值,不在于预测波动往哪走,而在于给「贵贱」和「状态」一个可量化的标尺:
- 对定价:它让 IV 的贵贱变成「相对自身历史分位的相对值」,而不是一个孤立数字;
- 对择时:它把「现在慌不慌」量化成 0–100 的分位,直接驱动卖/买期权与降仓决策;
- 对风控:它是最朴素也最稳健的风险叠加层——在波动率自身历史的极端区,先活下来。
从卡尔曼滤波的在线估计,到波动率锥的历史分位,量化里真正难的从来不是写出公式,而是给每一个数字找到它在「分布中的位置」。锥,就是波动率的那个位置标尺。