ETF 期权隐含波动率曲面计算方法文档
朱陈毓 2025.04.30
1 隐含波动率计算公式
ETF 期权的价格公式可以由 Black-76 公式得到:
其中:
- 为看涨期权的价格
- 为无风险利率
- 为距离到期的剩余时间
- 为标准正态分布的累计概率密度 (cdf) 函数
- 为看涨期权的行权价
- 为 ETF 的远期价格
的定义为:
其中:
- 为看涨期权的隐含波动率
对于行权价 与剩余时间 相同的看涨期权价格 和看跌期权价格 ,有 put-call parity 成立:
ETF 的远期价格 定义为:
其中:
- 为 ETF 的隐含持有成本
- 为 ETF 的价格
将 公式.(3) 和公式.(4) 联立可以得到 的计算公式为:
2 ETF隐含波动率曲面计算步骤
在完成步骤 1 后,对于同一个到期日,每10s选取一个期权数据切片,每个时间切片上有 个行权价 的看涨和看跌期权对,我们会得到看涨和看跌期权一共 个隐含波动率数据点 :
t 时刻的波动率曲面的计算步骤如下:
- 计算期权当前时间的各行权价所对应的 个
Moneyness,ForwardMoneyness和LogForwardMoneyness:
- 对于看涨期权,选取
ForwardMoneyness >= 1-MoneynessCutoff的隐含波动率,对于看跌期权,选取ForwardMoneyness <= 1+MoneynessCutoff的隐含波动率,并将FwdMoneyness有交叉的数据点加权平均得到 个隐含波动率数据点:
-
重复步骤1-2,得到每一个时间点上的
Moneyness, Forwardmoneyness, LogForwardMoneyness和ImpliedVol -
计算每一个数据点的拟合的
Weight:
其中:
- 为标准正态分布的概率密度函数
- 取
min(ImpliedVol)*1.1 - 取 20.0 天
计算完 Weight 后需要将 Weight 归一化:
Weight = Weight / sum(Weight)
- 调用
QE_SVI.py中的CalibrateSVI()函数,得到当前到期日的隐含波动率曲线拟合参数:
LB_Sigma_Init = 1e-3
UB_Sigma_Init = 20
SVIPar, Resid, ATMVol = CalibrateSVI(Moneyness, ImpliedVol, R, yield_rt, Tenor, Weight, TargetRes = 1e-4, Method='SQP')
- 对每一个到期日,重复步骤1-5
注意
CalibrateSVI()进行了版本更新,需要使用最新版的API- 更新前的 API 调用格式为
def CalibrateSVI( Moneyness, ImpVol, R, Q, T, Weights, TargetRes = 1e-4, Method = 'SQP' ):
...
- 更新后的 API 在
Method后新增了两个输入变量InitialPar和grad_tol,但设有默认值,请勿更改:
def CalibrateSVI(Moneyness, ImpVol, R, Q, T, Weights, TargetRes = 1e-4, Method='SQP',
InitialPar=(1e-6, 1e-4, 0.0, 0.0, NP.sqrt(LB_Sigma_Init * UB_Sigma_Init)),
grad_tol=1e-16)
因此在调用该函数时仍然可以保持原来的格式不变:
# 保持原来的调用格式
SVIPar, Resid, ATMVol = CalibrateSVI( Moneyness, ImpVol, R, Q, T, Weights, TargetRes = 1e-4,
Method = 'SQP' )
错误处理
- 计算隐含波动率时,筛掉无法计算的行权价:
idxCalc = ( ~NP.isnan(ETFForwardPrice) & \ # ETFForwardPrice 不为 nan
~NP.isnan(OptionForwardPrice) & \ # OptionForwardPrice 不为 nan
~NP.isnan(Tenor) & \ # Tenor is not nan
# OptionForwardPrice 大于期权内在价值
(OptionForwardPrice > NP.maximum( Optiontype * ( UnderlyingForwardPrice_rt - K ), 0 )) & \
# OptionForwradPrice 大于 ETFForwradPrice
(ETFForwardPrice > OptionForwardPrice)
)
# 看涨期权 Optiontype == 1
# 看跌期权 Optiontype == 1
- 调用
CalibrateSVI()之前,检查Moneyness, ImpliedVol, R, yield_rt, Tenor, Weight,如果这些 Input 数据存在nan值,则计算失败 - 若
CalibrateSVI()返回的Resid为inf/-inf/nan,或者SVIPar,ATMVol中有nan/inf/-inf值,则说明波动率曲面计算失败,此时再调用一次CalibrateSVI()重新计算,保持其他输入变量不变,改用Method='NL'