最近实习开始算期权隐含波动率。期权隐含波动率的算法写的人不多,分享几种计算方法。
1. 根据BS公式用二分法计算
从WIND里面取数之后算会出现的实际问题是有些价格的期权并没有价格(没人买),所以显示p=0。
def BSM(F0,k,T,r,sigma):
d1=(np.log(F0/k)+(r+0.5*sigma**2)*T)/sigma/np.sqrt(T)
d2=d1-sigma*np.sqrt(T)
c=F0*norm.cdf(d1)-k*np.exp(-r*T)*norm.cdf(d2)
p=k*np.exp(-r*T)*norm.cdf(-d2)-F0*norm.cdf(-d1)
return c,p
#二分法求隐含波动率
def bisection(P,F0,k,r,T,c): #c=0,call;c=1,put.
value0=0#迭代初始值
top=100
floor=0
sigma=(floor+top)/2
i=0
while abs(P-value0)>1e-2:
value0=BSM(F0,k,T,r,sigma)[c]
if (P-value0)>0:
floor=sigma
sigma=(sigma+top)/2
else:
top=sigma
sigma=(sigma+floor)/2
#print(sigma)
i+=1
if i>100:
sigma=''
print('Too many iterations')
break
return sigma
def bisection_sigma(P,F0,k,r,T,c):
if P==0:
return 0
else:
return bisection(P,F0,k,r,T,c)
2. 用vega算
在stackflow上看到有人是用vega算,缺点用vega算需要符合一些条件,优点是不需要迭代,可以直接计算。附上一段代码。
N = norm.cdf
def bs_call(S, K, T, r, vol):
d1 = (np.log(S/K) + (r + 0.5*vol**2)*T) / (vol*np.sqrt(T))
d2 = d1 - vol * np.sqrt(T)
return S * norm.cdf(d1) - np.exp(-r * T) * K * norm.cdf(d2)
def bs_vega(S, K, T, r, sigma):
d1 = (np.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
return S * norm.pdf(d1) * np.sqrt(T)
def find_vol(target_value, S, K, T, r, *args):
MAX_ITERATIONS = 200
PRECISION = 1.0e-5
sigma = 0.5
for i in range(0, MAX_ITERATIONS):
price = bs_call(S, K, T, r, sigma)
vega = bs_vega(S, K, T, r, sigma)
diff = target_value - price # our root
if (abs(diff) < PRECISION):
return sigma
sigma = sigma + diff/vega # f(x) / f'(x)
return sigma # value wasn't found, return best guess so far
3. 很多金融界人士其实是用excel(VBA)算的,这里推荐用Hull大神的DerivaGem,人大经济论坛上有各种版本的这个软件。优点是简单容易用,缺点的话,主要就是不适合需要算很多数据,拿来练练教材的课后习题还是好的。