利用BS模型计算欧式看涨期权价格——基于中国沪深300ETF看涨期权验证,结果发现当期权虚值程度较深时,理论价格与现实价格差异极大。比如,在近年来沪深300很少能到4600点以上,因此理论价格几乎为零,但是现实市场中仍有投机者在够买
作者:袁江磊
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import datetime
import math
from scipy.stats import norm
plt.rcParams['font.sans-serif']=['simhei']#用于正常显示中文标签
plt.rcParams['axes.unicode_minus']=False#用于正常显示负号
import tushare as ts
pro=ts.pro_api()
pd.set_option('display.max_columns', None)# 显示所有列
pd.set_option('display.max_rows', None)# 显示所有行
class BlackScholes():
"""通过BS模型计算欧式看涨期权价格"""
def __init__(self,ts_code):
self.data_ = pro.index_daily(ts_code=ts_code) # 获得指定标的资产的日行情数据
def init_info(self,S_0,X,r):
"""S_0为股票初始价格,X为行权价格,r为无风险利率"""
self.S_0=S_0
self.X=X
self.r=r
def time_through(self):
"""计算期权到期所剩时间,以年为单位"""
time1 = datetime.datetime.strptime(self.start_date, '%Y%m%d')
time2 = datetime.datetime.strptime(self.end_date, '%Y%m%d')
time_ = time2 - time1 # 作差
days=time_.days
return days/365
def cost(self):
"""计算期权费用"""
d_1 = (math.log(self.S_0 /self.X) + (self.sigma ** 2 / 2 * self.time_)) / (self.sigma * (math.sqrt(self.time_)))
d_2 = d_1 - self.sigma * math.sqrt(self.time_)
C = math.exp(-1 * self.r * self.time_) * (self.S_0 * norm.cdf(d_1) - self.X * norm.cdf(d_2))
return C/1000
def stock_miu_sigma(self,start_date,end_date):
"""计算股票价格漂移率miu和波动率sigma,,start_date为现在日期(格式'20200305'),end_date为到期日期,sigma为股票价格波动率(标准差)"""
#ts_code = '000300.SH'
self.start_date = start_date
self.end_date = end_date
self.time_ = self.time_through()
data_ = self.data_
data_ = pd.DataFrame(data_[['close','trade_date']]) # 获得其中的收盘价
data_.sort_values(['trade_date'], ascending=True,inplace=True)
data_['ratio'] = [0.0000000000000000000] * len(data_)
data_.index = range(data_.shape[0])
# 计算股价比率
for i in range(data_.shape[0] - 1):
data_['ratio'][i + 1] = np.log(data_['close'][i + 1] / data_['close'][i])
# 计算基础参数
T = self.time_*365 # 使用过去T天的数据计算漂移率和波动率,本处使用期权到期所剩时间
data_train = data_.ix[(len(data_['ratio'])-T):len(data_['ratio']), :] # 选取过去一月的时间作为训练集
mean = data_train['ratio'].sum() / T # 计算样本均值
S_2 = ((data_train['ratio'] - mean) ** 2).sum() / (T - 1) # 计算样本方差
miu = (mean + S_2 / 2) / self.time_ # 股价漂移率
sigma = np.sqrt(S_2)/np.sqrt(self.time_) # 股价波动率
self.miu=miu
self.sigma = sigma
#300ETF看涨期权日线行情
if __name__=='__main__':
data_300opt=pd.read_excel('300ETF购.xlsx')
data_300opt=data_300opt[['最新','行权','到期日']]
data_300opt['行权']=data_300opt['行权']*1000
data_300opt.columns=['最新价格','行权','到期日']
cols=data_300opt.columns
# 300指数日线行情
ts_code = '000300.SH'
close_300=pro.index_daily(ts_code=ts_code)[['trade_date','close']]#沪深300最新收盘价
#df = pro.index_daily(ts_code=ts_code)
BS=BlackScholes()
S_0=close_300['close'][0]#初始股价,不变值
X=data_300opt['行权'][0]#行权价格
start_date=close_300['trade_date'][0]#今日日期
end_date=str(data_300opt['到期日'][0])#行权日期
BS.stock_miu_sigma(ts_code,start_date,end_date)#波动率
r = 0.05#无风险收益率
#print(BS.sigma)
BS.init_info(S_0,X,r)
BS.cost()
if __name__=='__main__':
data_300opt=pd.read_excel('300ETF购.xlsx')#从东方财富下载沪深300指数所有看涨期权的日行情数据
data_300opt=data_300opt[['最新','行权','到期日']]
data_300opt['行权']=data_300opt['行权']*1000
data_300opt.columns=['最新价格','行权','到期日']
data_300opt['BS价格']=0.0000000
cols=data_300opt.columns
# 300指数日线行情
ts_code = '000300.SH'
close_300=pro.index_daily(ts_code=ts_code)[['trade_date','close']]#获得标的资产指数沪深300日行情数据
#df = pro.index_daily(ts_code=ts_code)
BS=BlackScholes(ts_code)
for i in range(len(data_300opt['行权'])):
S_0=close_300['close'][0]#初始股价,不变值
X=data_300opt['行权'][i]#行权价格
start_date=close_300['trade_date'][0]#今日日期
end_date=str(data_300opt['到期日'][i])#行权日期
BS.stock_miu_sigma(start_date,end_date)#波动率
r = 0.05#无风险收益率
#print(BS.sigma)
BS.init_info(S_0,X,r)
data_300opt['BS价格'][i]=BS.cost()#将通过BS模型计算的期权理论价格并入
print('已经完成'+str(round(i/len(data_300opt['行权']),2)*100)+'%')
data_300opt