牛顿迭代法
from scipy.stats import norm
import numpy as np
def bscall(S,K,r,sigma,t):d1=(np.log(S/K)+(r+0.5*sigma**2)*t)/(sigma*np.sqrt(t))d2=d1-sigma*np.sqrt(t)return S*norm.cdf(d1)-K*np.exp(-r*t)*norm.cdf(d2)
def bsput(S,K,r,sigma,t):d1=(np.log(S/K)+(r+0.5*sigma**2)*t)/(sigma*np.sqrt(t))d2=d1-sigma*np.sqrt(t)return -S*norm.cdf(-d1)+K*np.exp(-r*t)*norm.cdf(-d2)def newton_call(P,S,K,r,t):#print('call')sigma = 0.2while abs(bscall(S,K,r,sigma,t)-P)>0.0001:if bscall(S,K,r,sigma,t)>P:sigma-=0.001else:sigma+=0.001return sigma
def newton_put(P,S,K,r,t):#print('put')sigma=0.2while abs(bsput(S,K,r,sigma,t)-P)>0.0001:if bsput(S,K,r,sigma,t)>P:sigma-=0.0001else:sigma+=0.0001return sigma
二分法
#二分法
def binary_call(P,S,K,r,t):sigma_up=1sigma_down=0.001sigma_mid=(sigma_up+sigma_down)/2while abs(bscall(S,K,r,sigma_mid,t)-P)>0.0001:if bscall(S,K,r,sigma_down,t)<P<bscall(S,K,r,sigma_mid,t):sigma_up=sigma_midsigma_mid=(sigma_mid+sigma_down)/2elif bscall(S,K,r,sigma_up,t)>P>bscall(S,K,r,sigma_mid,t):sigma_down=sigma_midsigma_mid=(sigma_up+sigma_down)/2else:print('error!')breakreturn sigma_mid
def binary_put(P,S,K,r,t):sigma_up=1sigma_down=0.001sigma_mid=(sigma_up+sigma_down)/2while abs(bsput(S,K,r,sigma_mid,t)-P)>0.0001:if bsput(S,K,r,sigma_down,t)<P<bsput(S,K,r,sigma_mid,t):sigma_up=sigma_midsigma_mid=(sigma_mid+sigma_down)/2elif bsput(S,K,r,sigma_up,t)>P>bsput(S,K,r,sigma_mid,t):sigma_down=sigma_midsigma_mid=(sigma_up+sigma_down)/2else:print('error!')breakreturn sigma_mid
微笑曲线
'''
波动率微笑和波动率偏斜波动率微笑(smile)描述了期权隐含波动率和执行价格之间的关系,即在其他条件相同的情况下,期权的隐含波动率在平值点附近最小,在虚值和实值区域更大;
若隐含波动率在低执行价格区域高于高执行价格区域(即单调递减),那么就称为波动率偏斜(skew),对于股票期权来说这种情况更常见
'''
import numpy as np
from datetime import date
import matplotlib.pyplot as plt
from pylab import mpl
def smile(df1=0,df2=0):t=(date(2018,6,27)-date(2017,12,29)).days/365S=2.859;r=0.032K=np.arange(2.7,3.05,0.05)Pcall=np.array([0.2841,0.2486,0.2139,0.1846,0.1586,0.1369,0.1177])Pput=np.array([0.0464,0.0589,0.0750,0.0947,0.1183,0.1441,0.1756])volcall=np.zeros_like(K)for i in range(len(K)):volcall[i]=(binary_call(Pcall[i],S,K[i],r,t))volput=np.zeros_like(K)for i in range(len(K)):volput[i]=(binary_put(Pput[i],S,K[i],r,t))mpl.rcParams['font.sans-serif']=['SimHei']mpl.rcParams['axes.unicode_minus']=Falseplt.plot(K,volcall,label='50ETF认购期权')plt.plot(K,volput,label='50ETF认沽期权')plt.xlabel('执行价格')plt.ylabel('隐含波动率')plt.title('50ETF期权的波动率微笑(偏斜)')plt.legend()plt.grid()
smile()