投资小课堂由开课啦????本篇是最后一章
1、期权类型与到期盈亏
2、定价模型与平价关系式
3、期权价格和相关变量的关系
4、期权的希腊字母(上)
5、期权的希腊字母(下)
在布B-S模型中,可以直接观察到基础资产的当前价格S、期权的执行价格K、期权合约期限T以及无风险收益率r,唯一不能直接观察到的变量就是基础资产的波动率σ。当然,可以通过基础资产的历史价格来估计波动率。
但在实践中,通常会使用所谓的隐含波动率( implied volatility),该波动率是指通过期权的市场价格、运用B-S模型计算得到的波动率。但比较棘手的问题是,无法直接通过反解看涨期权定价式子或看跌期权定价式子将σ表示为变量c(或p)、S、K、r、T的函数,只能运用迭代方法求解出隐含的σ值。常用的迭代方法包括牛顿迭代法和二分查找法。
牛顿迭代法计算隐含波动率
牛顿迭代法( Newton' s Method),也称为牛顿拉弗森方法,在利用该方法计算期权的隐含波动率时,需要做好以下3个方面的工作:一是需要输入一个初始的隐含波动率;二是建立一种迭代关系式,如果由初始的隐含波动率得到的期权价格高于市场价格,则需要减去一个标量(比如0.0001),相反则加上一个标量;三是需要对迭代过程进行控制,也就是针对隐含波动率得到的期权价格与期权的市场价格之间的差额设置一个可接受的临界值。
利用牛顿迭代法并运用 Python自定义分别计算欧式看涨、看跌期权隐含波动率的函数用python实现代码如下:
import numpy as np
from scipy.stats import norm
# 首先要先定义好 BS 模型计算期权价格的函数公式
def call_BS(S,K,sigma,r,T):
'''用bs模型计算欧式看涨期权价格
S 期权基础资产价格
K 期权执行价格
sigma 基础资产价格百分比变化(收益率)的年化波动率
r 无风险收益率
T 期权合约剩余年限
'''
d1 = (np.log(S/K) + (r + pow(sigma,2)/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 put_BS(S,K,sigma,r,T):
'''用bs模型计算欧式看跌期权价格
S 期权基础资产价格
K 期权执行价格
sigma 基础资产价格百分比变化(收益率)的年化波动率
r 无风险收益率
T 期权合约剩余年限
'''
d1 = (np.log(S/K) + (r + pow(sigma,2)/2)*T) / (sigma*np.sqrt(T))
d2 = d1 - sigma*np.sqrt(T)
return K*np.exp(-r*T)*norm.cdf(-d2) - S*norm.cdf(-d1)
牛顿迭代法计算隐含波动率
# BS 模型计算期权价格
def call_BS(S,K,sigma,r,T):
'''用bs模型计算欧式看涨期权价格
S 期权基础资产价格
K 期权执行价格
sigma 基础资产价格百分比变化(收益率)的年化波动率
r 无风险收益率
T 期权合约剩余年限
'''
d1 = (np.log(S/K) + (r + pow(sigma,2)/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 put_BS(S,K,sigma,r,T):
'''用bs模型计算欧式看跌期权价格
S 期权基础资产价格
K 期权执行价格
sigma 基础资产价格百分比变化(收益率)的年化波动率
r 无风险收益率
T 期权合约剩余年限
'''
d1 = (np.log(S/K) + (r + pow(sigma,2)/2)*T) / (sigma*np.sqrt(T))
d2 = d1 - sigma*np.sqrt(T)
return K*np.exp(-r*T)*norm.cdf(-d2) - S*norm.cdf(-d1)
def impvol_call_Newton(C,S,K,r,T): # 初始sigma是0.2
'''运用BS模型计算看涨期权的隐含波动率,使用的是牛顿迭代法。
C 看涨期权市场价格
S 基础资产价格
K 行权价格
r 无风险收益率
T 期权剩余时间(年)
'''
sigma0 = 0.2 #设置一个初始波动率
diff = C - call_BS(S,K,sigma0,r,T)
i = 0.0001 #设置一个标量
while abs(diff) > 0.0001:
diff = C - call_BS(S,K,sigma0,r,T)
if diff > 0:
sigma0 = sigma0 + i
else:
sigma0 = sigma0 - i
return sigma0
def impvol_put_Newton(P,S,K,r,T): # 初始sigma是0.2
'''运用BS模型计算看跌期权的隐含波动率,使用的是牛顿迭代法。
P 看跌期权市场价格
S 基础资产价格
K 行权价格
r 无风险收益率
T 期权剩余时间(年)
'''
sigma0 = 0.2 #设置一个初始波动率
diff = P - put_BS(S,K,sigma0,r,T)
i = 0.0001 #设置一个标量
while abs(diff) > 0.0001:
diff = P - put_BS(S,K,sigma0,r,T)
if diff > 0:
sigma0 = sigma0 + i
else:
sigma0 = sigma0 - i
return sigma0
仍然以某股票作为例子,设置看涨期权市场价格为0.1566元,看跌期权的市场价格为0.7503,元,其他参数市场价格5.29,执行价格6,无风险收益率4%,剩余期限6个月
impvol_call_Newton(C=0.1566, S=5.29, K=6, r=0.04, T=0.5)
# 输出
>>> 0.2426999999999953
impvol_put_Newton(P=0.7503, S=5.29, K=6, r=0.04, T=0.5)
# 输出
>>> 0.24450000000006122
通过以上的计算结果可以得到看涨期权的隐含波动率是24.27%,看跌期权的隐含波动率是24.45%。需要注意的是,由于计算的步骤会比较多,因此牛顿迭代法的效率往往是比较低的,如 果将结果的精确度进一步提高,则需要花费比较长的时间进行运算。
二分查找法计算隐含波动率
为了提高运算速度,可以采用二分查找法( binary search,也称“折半查找法”) 作为迭代的方法。
可以通过举一个简单的例子更好地理解这种方法。用前面牛顿迭代的股票的例子,初始猜测的波动率是20%,对应该波动率数值估计得到的欧式看涨期权价格是0.1035元,显然,比市场价格0.1566元更小。由于期权价格是波动率的增函数,因此合理地估计正确的波动率应该会比20%更大。然后假定波动率是30%,对应的期权价格0.2336元,这个结果又比0.1566元高,则可以肯定波动率是介于20%~30%的区间中。接下来,取上两次波动率值的均值,也就是波动率25%,对应的期权价格为0.1662元,这个值又比0.1566元高,但是合理的波动率所处的区间范围收窄至20%与25%之间,然后取均值22.5%继续计算,每次迭代都使波动率所处的区间减半,最终就可以计算出满足较高精确度的隐含波动率近似值。
利用二分查找法并运用 Python构建分别计算欧式看涨、看跌期权隐含波动率的python实现函数,具体的代码如下:(同样也是需要先定义期权的计算公式函数)
def impvol_call_Binary(C,S,K,r,T): #从0.001 - 1.000进行二分查找
'''运用BS模型计算看涨期权的隐含波动率,使用的迭代方法是二分查找法。
C 看跌期权市场价格
S 基础资产价格
K 行权价格
r 无风险收益率
T 期权剩余时间(年)
'''
sigma_min = 0.001 # 设定波动率初始最小值
sigma_max = 1.000 # 设定波动率初始最大值
sigma_mid = (sigma_min + sigma_max) / 2
call_min = call_BS(S,K,sigma_min,r,T)
call_max = call_BS(S,K,sigma_max,r,T)
call_mid = call_BS(S,K,sigma_mid,r,T)
diff = C - call_mid
if C < call_min or C > call_max:
print('Error')
while abs(diff) > 0.000001:
diff = C - call_BS(S,K,sigma_mid,r,T)
sigma_mid = (sigma_min + sigma_max) / 2
call_mid = call_BS(S,K,sigma_mid,r,T)
if C > call_mid:
sigma_min = sigma_mid
else:
sigma_max = sigma_mid
return sigma_mid
def impvol_put_Binary(P,S,K,r,T): #从0.001 - 1.000进行二分查找
'''运用BS模型计算看跌期权的隐含波动率,使用的迭代方法是二分查找法。
P 看跌期权市场价格
S 基础资产价格
K 行权价格
r 无风险收益率
T 期权剩余时间(年)
'''
sigma_min = 0.001 # 设定波动率初始最小值
sigma_max = 1.000 # 设定波动率初始最大值
sigma_mid = (sigma_min + sigma_max) / 2
put_min = put_BS(S,K,sigma_min,r,T)
put_max = put_BS(S,K,sigma_max,r,T)
put_mid = put_BS(S,K,sigma_mid,r,T)
diff = P - put_mid
if P < put_min or P > put_max:
print('Error')
while abs(diff) > 0.000001:
diff = P - put_BS(S,K,sigma_mid,r,T)
sigma_mid = (sigma_min + sigma_max) / 2
put_mid = put_BS(S,K,sigma_mid,r,T)
if P > put_mid:
sigma_min = sigma_mid
else:
sigma_max = sigma_mid
return sigma_mid
沿用牛顿迭代的例子,设置看涨期权市场价格为0.1566元,看跌期权的市场价格为0.7503,元,其他参数市场价格5.29,执行价格6,无风险收益率4%,剩余期限6个月。
impvol_call_Binary(C=0.1566, S=5.29, K=6, r=0.04, T=0.5)
# 输出
>>> 0.2426642599105835
impvol_put_Binary(P=0.7503, S=5.29, K=6, r=0.04, T=0.5)
# 输出
>>> 0.2445982828140259
两种方法计算的结果是一样的,但是二分法的运算效率会更高一些。
End!期权系列文章最后一篇结束了。
前文链接????
1、期权类型与到期盈亏
2、定价模型与平价关系式
3、期权价格和相关变量的关系
4、期权的希腊字母(上)
5、期权的希腊字母(下)