15. 曲面外推与边界处理:尾部行为建模、极端行权价处理、期限结构外推
好了,咱们聊到曲面构建的最后一公里了。
前面我们把SVI、SSVI这些参数化模型都调教好了,插值也做得漂漂亮亮。但有个现实问题——市场上能看到的期权行权价和期限总是有限的。你拿到的数据,可能只有30天到1年,行权价也就覆盖了0.8到1.2倍标的价格。那问题来了:
- 深度虚值期权(比如行权价是标的价格的0.5倍)的隐含波动率是多少?
- 10年期的期权波动率怎么定?
- 极端行情下,尾部行为会不会崩掉?
这就是我们今天要啃的硬骨头——曲面外推与边界处理。
核心观点:外推不是瞎猜,而是基于金融逻辑和统计规律做合理延伸。尾部行为建模决定了你的期权定价在极端行情下是否靠谱,期限结构外推决定了长期限产品的估值是否合理。
15.1 尾部行为建模:为什么不能随便外推?
先说说尾部行为。我记得刚入行那会儿,有个老交易员跟我说过一句话:「你平时赚的钱,都是在市场正常波动时赚的;你亏大钱的时候,都是在尾部。」
尾部行为,说白了就是极端行权价处的波动率表现。比如标的价格100块,你要给行权价200块的call定价。这种深度虚值期权,市场上几乎没成交,但你不能不给它一个波动率。
尾部行为建模的核心问题有两个:
- 波动率微笑的斜率:随着行权价偏离标的价格,波动率是上升还是下降?上升多快?
- 尾部衰减速度:深度虚值期权的波动率会不会无限上升?还是说会收敛到某个极限?
我个人的习惯是,先看市场数据。拿S&P 500的期权数据来说,你会发现深度虚值put的波动率往往比平值高出一大截。这就是所谓的「波动率偏斜」(volatility skew)。但问题是,这个偏斜在极端行权价处会怎么走?
实战经验:我曾经用SVI模型拟合标普500期权数据,发现当行权价偏离标的价格超过30%时,SVI的尾部会变得非常不稳定。有时候波动率会突然飙升,有时候又会掉头向下。这显然不符合金融直觉。
为什么会这样?因为SVI模型本质上是一个抛物线形状,它在尾部会按照二次函数增长。但实际市场中,波动率在极端行权价处应该趋于一个常数,而不是无限增长。所以我们需要对尾部行为做特殊处理。
15.2 极端行权价处理:三种主流方法
处理极端行权价,我见过的方法不下十种。但真正在量化团队里用得多的,就下面三种:
| 方法 | 核心思想 | 优点 | 缺点 |
|---|---|---|---|
| 线性外推法 | 在已知数据边界处,用线性斜率继续延伸 | 简单、稳定 | 可能违反无套利条件 |
| 尾部平坦化 | 超过某个阈值后,波动率保持常数 | 符合金融直觉 | 阈值选择主观性强 |
| 参数化尾部模型 | 用专门的函数(如幂律函数)拟合尾部 | 灵活、可调 | 参数估计复杂 |
我个人最推荐的是第三种——参数化尾部模型。原因很简单:它给了你一个可解释的框架。
举个例子,我常用的一个尾部模型是这样的:
# 尾部波动率模型示例
def tail_volatility(K, S, sigma_atm, skew_param, tail_param):
"""
K: 行权价
S: 标的价格
sigma_atm: 平值波动率
skew_param: 偏斜参数
tail_param: 尾部衰减参数
"""
moneyness = K / S
# 使用幂律函数描述尾部行为
if moneyness < 0.8: # 深度虚值put
return sigma_atm * (1 + skew_param * (1 - moneyness)**tail_param)
elif moneyness > 1.2: # 深度虚值call
return sigma_atm * (1 + skew_param * (moneyness - 1)**tail_param)
else:
# 中间区域用插值
return None # 实际中会调用SVI或其他模型
这个模型里,tail_param控制了尾部衰减的速度。如果tail_param接近1,尾部是线性衰减;如果小于1,尾部衰减得更慢,意味着极端行权价的波动率更高。
注意:尾部参数不能随便设。我曾经见过一个团队把tail_param设成0.3,结果深度虚值期权的波动率比平值高了5倍,直接导致期权定价出现严重套利机会。嗯,后来他们被风控部门约谈了。
15.3 期限结构外推:短期和长期的处理
说完行权价方向,咱们再看看期限方向。
市场上能看到的期权期限通常是1个月到2年。但实际业务中,你可能需要给1天到期的期权定价,也可能要给10年到期的期权定价。这就涉及到期限结构的外推。
期限结构外推有两个极端:
- 短期外推(1天到1个月):波动率往往很高,因为短期内的不确定性更大。但要注意,短期波动率不能无限高,否则会出现「波动率爆发」的假象。
- 长期外推(2年到10年):波动率趋于稳定,因为长期来看,市场会回归均值。我记得有研究表明,10年期以上的隐含波动率,基本上就是历史波动率的长期均值。
我建议的做法是,用Nelson-Siegel模型来拟合期限结构。这个模型本来是做利率曲线的,但用在波动率期限结构上效果也不错。
# Nelson-Siegel模型用于波动率期限结构
def nelson_siegel_vol(T, beta0, beta1, beta2, lambda_):
"""
T: 期限(年)
beta0: 长期波动率水平
beta1: 短期波动率偏离
beta2: 中期波动率曲率
lambda_: 衰减速度
"""
term1 = beta0
term2 = beta1 * (1 - np.exp(-T/lambda_)) / (T/lambda_)
term3 = beta2 * ((1 - np.exp(-T/lambda_)) / (T/lambda_) - np.exp(-T/lambda_))
return term1 + term2 + term3
这个模型的好处是,参数有明确的金融含义:
- beta0:长期波动率,比如10年期的波动率水平
- beta1:短期波动率与长期波动率的差值
- beta2:中期波动率的曲率,控制「驼峰」形状
- lambda_:从短期到长期的衰减速度
避坑指南:我曾经用Nelson-Siegel模型拟合A股50ETF期权的期限结构,发现lambda_这个参数特别敏感。稍微调大一点,短期波动率就变得特别高;调小一点,又拟合不好中期数据。后来我改用固定lambda_,只优化beta参数,效果反而更好。
15.4 知识体系总览
说了这么多,咱们用一张图把整个外推与边界处理的逻辑串起来:
15.5 边界处理中的无套利检查
最后,我想强调一个容易被忽视的点——无套利条件。
你外推出来的波动率曲面,不能产生套利机会。具体来说,要检查:
- 日历套利:同一行权价下,长期限的波动率不能低于短期限的波动率(除非有特殊原因)
- 蝶式套利:相邻三个行权价的波动率不能形成「凹形」,否则会出现蝶式套利机会
- 箱体套利:call和put之间的波动率关系要满足put-call parity
血的教训:我曾经在构建一个外汇期权曲面时,用了简单的线性外推,结果在深度虚值区域出现了蝶式套利机会。当时没检查就直接上线了,结果被做市商盯上,一晚上亏了十几万美金。嗯,从那以后,我每次外推完都会跑一遍无套利检查脚本。
说白了,外推不是终点,而是起点。你外推出来的曲面,必须经过严格的无套利检验,才能用于实际定价和风险管理。
好了,关于曲面外推与边界处理,咱们就聊到这儿。记住一句话:外推要大胆,检查要小心。
公众号:蓝海资料掘金营,微信deep3321