期权的隐含波动率微笑、斜偏

论坛 期权论坛 期权     
欧晨的金学智库   2020-12-19 13:06   3776   0
一、隐含波动率
隐含波动率(Implied Volatility)是将市场上的期权或权证交易价格代入权证理论价格模型——Black-Scholes-Merton模型,反推出来的波动率数值。
由于期权定价模型(如BSM模型)给出了期权价格与五个基本参数(标的股价S、执行价格K、利率r、到期时间T、波动率σ)之间的定量关系,只要将其中前4个基本参数及期权的实际市场价格作为已知量代入定价公式,就可以从中解出惟一的未知量,其大小就是隐含波动率。
本篇给出两种求解隐含波动率的方法:非线性优化方法求解期权的隐含波动率与二分法求解期权的隐含波动率。【案例分析1】看涨期权的市场价格P=0.16, 基础资产的价格S=5.3, 期权的执行价格K=6, 无风险收益率r=0.03,期权合约的剩余期限T=0.5.计算看涨期权的隐含波动率。
【案例分析2】看跌期权的市场价格P=0.72, 基础资产的价格S=5.3, 期权的执行价格K=6, 无风险收益率r=0.03,期权合约的剩余期限T=0.5.计算看跌期权的隐含波动率。
Python实现:
1. 非线性优化方法求解期权的隐含波动率
  1. #非线性优化方法求解期权的隐含波动率
复制代码
  1. from scipy.stats import norm
复制代码
  1. import numpy as np
复制代码
  1. import scipy.optimize as so
复制代码
  1. def BSM_imply_vo(P,S,K,r,T,op_type):
复制代码
  1.     '''非线性优化方法求解期权的隐含波动率
复制代码
  1.     P:期权的市场价格;
复制代码
  1.     S:基础资产的价格;
复制代码
  1.     K:期权的执行价格;
复制代码
  1.     r:无风险收益率;
复制代码
  1.     T:期权合约的剩余期限;
复制代码
  1.     op_type:输入'call'表示看涨期权;输入'put'表示看跌期权。'''
复制代码
  1.     def f(sigma):
复制代码
  1.         d1=(np.log(S/K)+(r+0.5*sigma**2)*T)/(sigma*np.sqrt(T))
复制代码
  1.         d2=d1-sigma*np.sqrt(T)
复制代码
  1.         bscall=S*norm.cdf(d1)-K*np.exp(-r*T)*norm.cdf(d2)
复制代码
  1.         bsput=-S*norm.cdf(-d1)+K*np.exp(-r*T)*norm.cdf(-d2)   
复制代码
  1.         if op_type=='call':
复制代码
  1.             return bscall-P
复制代码
  1.         else:
复制代码
  1.             return bsput-P
复制代码
  1.     return so.fsolve(f,0.2)
复制代码
  1.         
复制代码
  1. print('非线性优化方法计算看涨期权的隐含波动率',np.round(BSM_imply_vo(0.16,5.3,6,0.03,0.5,'call'),6))
复制代码
  1. print('非线性优化方法计算看跌期权的隐含波动率',np.round(BSM_imply_vo(0.72,5.3,6,0.03,0.5,'put'),6))
复制代码


2. 二分法求解期权的隐含波动率

  1. #二分法求解期权的隐含波动率
复制代码
  1. def binary_imply_vo(P,S,K,r,T,op_type):
复制代码
  1.     '''二分法求解期权的隐含波动率
复制代码
  1.     P:期权的市场价格;
复制代码
  1.     S:基础资产的价格;
复制代码
  1.     K:期权的执行价格;
复制代码
  1.     r:无风险收益率;
复制代码
  1.     T:期权合约的剩余期限;
复制代码
  1.     op_type:输入'call'表示看涨期权;输入'put'表示看跌期权。'''        
复制代码
  1.     def BSM_model(S,K,sigma,r,T,op_type):
复制代码
  1.         import numpy as np
复制代码
  1.         from scipy.stats import norm
复制代码
  1.         d1=(np.log(S/K)+(r+0.5*sigma**2)*T)/(sigma*np.sqrt(T))
复制代码
  1.         d2=d1-sigma*np.sqrt(T)
复制代码
  1.         if op_type=='call':
复制代码
  1.             BSM_model=S*norm.cdf(d1)-K*np.exp(-r*T)*norm.cdf(d2)
复制代码
  1.         else:
复制代码
  1.             BSM_model=-S*norm.cdf(-d1)+K*np.exp(-r*T)*norm.cdf(-d2)
复制代码
  1.         return BSM_model
复制代码
  1.     sigma_down=0.000001
复制代码
  1.     sigma_up=1
复制代码
  1.     sigma_mid=(sigma_down+sigma_up)/2
复制代码
  1.     op_min=BSM_model(S,K,sigma_down,r,T,op_type)
复制代码
  1.     op_max=BSM_model(S,K,sigma_up,r,T,op_type)
复制代码
  1.     op_mid=BSM_model(S,K,sigma_mid,r,T,op_type)
复制代码
  1.     diff=P-op_mid
复制代码
  1.     if Pop_max:
复制代码
  1.         print('错误')
复制代码
  1.     while abs(diff)>1e-6:
复制代码
  1.         diff=P-BSM_model(S,K,sigma_mid,r,T,op_type)
复制代码
  1.         sigma_mid=(sigma_down+sigma_up)/2
复制代码
  1.         op_mid=BSM_model(S,K,sigma_mid,r,T,op_type)
复制代码
  1.         if P>op_mid:
复制代码
  1.             sigma_down=sigma_mid
复制代码
  1.         else:
复制代码
  1.             sigma_up=sigma_mid
复制代码
  1.     return sigma_mid
复制代码
复制代码
  1. print('二分法计算看涨期权的隐含波动率',np.round(binary_imply_vo(0.16,5.3,6,0.03,0.5,'call'),6))   
复制代码
  1. print('二分法计算看跌期权的隐含波动率',np.round(binary_imply_vo(0.72,5.3,6,0.03,0.5,'put'),6))
复制代码


可见,两种算法的结果基本一致,考虑到精度设置以及计算速度等问题,建议采用二分法计算。



二、波动率微笑
波动率微笑(smile)描述了期权隐含波动率和执行价格之间的关系,即针对相同的到期日和基础资产、但不同执行价格的期权,当执行价格偏离基础资产现货的价格越远时,期权的隐含波动率就越大,类似于微笑曲线。
广义的波动率斜偏泛指不满足微笑形状的各种波动率曲线,狭义的波动率斜偏则是指当期权的执行价格由小变大时,期权的隐含波动率则是由大变小,即隐含波动率是执行价格的减函数。


【案例分析3】例如当前日期为2020/5/26,求取并绘制期权隐含波动率图像。


【注】认购期权对应看涨期权;认沽期权对应看跌期权。
Python实现:
  1. import datetime as dt
复制代码
  1. T1=dt.datetime(2020,5,26)     #当前日
复制代码
  1. T2=dt.datetime(2020,12,23)
复制代码
  1. T3=dt.datetime(2020,9,23)
复制代码
  1. T_left_12=(T2-T1).days/366   #12月到期的剩余时间
复制代码
  1. T_left_9=(T3-T1).days/366    #9月到期的剩余时间
复制代码
  1. S0=2.79
复制代码
  1. Call_list_12=np.array([0.2661,0.2327,0.2005,0.1730,0.1469,0.1235,0.1038,0.0869,0.0719,0.0594,0.0400])
复制代码
  1. Call_list_9=np.array([0.4248,0.3794,0.3336,0.2891,0.2478,0.21,0.1746,0.1427,
复制代码
  1.                       0.1145,0.0907,0.0714,0.0554,0.0421,0.0326,0.0197,0.0124,0.0083,0.0063])
复制代码
  1. Put_list_12=np.array([0.0705,0.0853,0.1042,0.1250,0.1486,0.1748,0.2051,0.2363,0.2711,0.3051,0.3841])
复制代码
  1. Put_list_9=np.array([0.0173,0.0206,0.025,0.0315,0.0396,0.0506,0.0647,0.0826,
复制代码
  1.                      0.1036,0.1288,0.159,0.1922,0.2305,0.2697,0.3549,0.4486,0.5415,0.641])
复制代码
  1. K_list_12=np.array([2.5500,2.6000,2.6500,2.7000,2.7500,2.8000,2.8500,2.9000,2.9500,3.0000,3.1000])
复制代码
  1. K_list_9=np.array([2.35,2.4,2.45,2.5,2.55,2.6,2.65,2.7,2.75,2.8,2.85,2.9,2.95,3,3.1,3.2,3.3,3.4])
复制代码
  1. shibor_12=0.015030
复制代码
  1. shibor_9=0.014050
复制代码
复制代码
  1. sigma_clist_9=np.zeros_like(Call_list_9)    #9月到期的看涨隐含波动率求解
复制代码
  1. for i in np.arange(len(Call_list_9)):
复制代码
  1.     sigma_clist_9[i]=BSM_imply_vo(P=Call_list_9[i],S=S0,K=K_list_9[i],r=shibor_9,T=T_left_9,op_type='call')
复制代码
复制代码
  1. sigma_clist_12=np.zeros_like(Call_list_12)  #12月到期的看涨期权隐含波动率求解
复制代码
  1. for i in np.arange(len(Call_list_12)):
复制代码
  1.     sigma_clist_12[i]=BSM_imply_vo(P=Call_list_12[i],S=S0,K=K_list_12[i],r=shibor_12,T=T_left_12,op_type='call')
复制代码
复制代码
  1. sigma_plist_9=np.zeros_like(Put_list_9)     #9月到期的看跌期权隐含波动率求解
复制代码
  1. for i in np.arange(len(Put_list_9)):
复制代码
  1.     sigma_plist_9[i]=BSM_imply_vo(P=Put_list_9[i],S=S0,K=K_list_9[i],r=shibor_9,T=T_left_9,op_type='put')
复制代码
复制代码
  1. sigma_plist_12=np.zeros_like(Put_list_12)     #12月到期的看跌期权隐含波动率求解
复制代码
  1. for i in np.arange(len(Put_list_12)):
复制代码
  1.     sigma_plist_12[i]=BSM_imply_vo(P=Put_list_12[i],S=S0,K=K_list_12[i],r=shibor_12,T=T_left_12,op_type='put')
复制代码
  1.    
复制代码
  1. import matplotlib.pyplot as plt
复制代码
  1. from pylab import mpl
复制代码
  1. mpl.rcParams['font.sans-serif']=['SimHei']
复制代码
  1. mpl.rcParams['axes.unicode_minus']=False   
复制代码
  1. plt.figure(figsize=(8,6))
复制代码
  1. plt.plot(K_list_9,sigma_clist_9,'b-',label=u'9月到期的50ETF看涨期权',lw=2.5)
复制代码
  1. plt.plot(K_list_9,sigma_plist_9,'r-',label=u'9月到期的50ETF看跌期权',lw=2.5)
复制代码
  1. plt.plot(K_list_12,sigma_clist_12,'g-',label=u'12月到期的50ETF看涨期权',lw=2.5)
复制代码
  1. plt.plot(K_list_12,sigma_plist_12,'k-',label=u'12月到期的50ETF看跌期权',lw=2.5)
复制代码
  1. plt.xlabel(u'期权的执行价格',fontsize=13)
复制代码
  1. plt.ylabel(u'隐含波动率',fontsize=13)
复制代码
  1. plt.xticks(fontsize=13)
复制代码
  1. plt.yticks(fontsize=13)
复制代码
  1. plt.title(u'期权的执行价格与期权隐含波动率的关系',fontsize=13)
复制代码
  1. plt.legend(fontsize=13)
复制代码
  1. plt.grid('True')
复制代码
  1. plt.show()
复制代码


【结论】波动率微笑/偏斜现象的解释
①关于波动率微笑的形成,主要是因为BS公式假定资产价格服从对数正态分布,而事实上该资产服从一个更加尖峰厚尾的分布,两边尾部的风险更高,因此隐含波动率更大;同时资产价格有跳跃现象(比如外汇期权的外汇受到央行管制),期权价值的不确定性增大,这也会导致两边变成肥尾。
②波动率偏斜现象(左高右低)在股票期权中更为常见,因为股票价格也不是完全服从对数正态分布,而是一种尖峰、左肥尾、右瘦尾的分布(股票涨得少跌得多),因此左尾更加肥厚,表明隐含波动率更高。
③还有一种较为可靠的解释是崩盘恐惧症(crashophobia):低执行价格区域对应的虚值看跌期权按照BS模型定价很低,但是实际上没这么低(股灾不少见),导致市面上定价有溢价,因此高的价格形成了高的σ。


【拓展】关于隐含波动率曲面的构建方法可参考:
1.https://www.baidu.com/link?url=473mY0KtgHYbMs0X_G5JmBa7T2n3Cwsce7A9-cKDPMvETOxjhRQAV97dgj_lq-7b&wd=&eqid=88c1d5f700039c0a000000065eccc355
2.https://zhuanlan.zhihu.com/p/142685333?from_voters_page=true


附录:欢迎大家关注!


所有python案例分析的数据地址:

链接:https://pan.baidu.com/s/1ds35rhd5yf-BSmzc-fxvzw
提取码:je4a
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:
帖子:
精华:
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP