牛顿迭代法
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.2
while abs(bscall(S,K,r,sigma,t)-P)>0.0001:
if bscall(S,K,r,sigma,t)>P:
sigma-=0.001
else:
sigma+=0.001
return sigma
def newton_put(P,S,K,r,t):
#print('put')
sigma=0.2
while abs(bsput(S,K,r,sigma,t)-P)>0.0001:
if bsput(S,K,r,sigma,t)>P:
sigma-=0.0001
else:
sigma+=0.0001
return sigma
二分法
#二分法
def binary_call(P,S,K,r,t):
sigma_up=1
sigma_down=0.001
sigma_mid=(sigma_up+sigma_down)/2
while 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_mid
sigma_mid=(sigma_mid+sigma_down)/2
elif bscall(S,K,r,sigma_up,t)>P>bscall(S,K,r,sigma_mid,t):
sigma_down=sigma_mid
sigma_mid=(sigma_up+sigma_down)/2
else:
print('error!')
break
return sigma_mid
def binary_put(P,S,K,r,t):
sigma_up=1
sigma_down=0.001
sigma_mid=(sigma_up+sigma_down)/2
while 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_mid
sigma_mid=(sigma_mid+sigma_down)/2
elif bsput(S,K,r,sigma_up,t)>P>bsput(S,K,r,sigma_mid,t):
sigma_down=sigma_mid
sigma_mid=(sigma_up+sigma_down)/2
else:
print('error!')
break
return 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/365
S=2.859;r=0.032
K=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']=False
plt.plot(K,volcall,label='50ETF认购期权')
plt.plot(K,volput,label='50ETF认沽期权')
plt.xlabel('执行价格')
plt.ylabel('隐含波动率')
plt.title('50ETF期权的波动率微笑(偏斜)')
plt.legend()
plt.grid()
smile()