三、波动率计算
波动率计算
历史波动率:自行采用不同算法,包括 c2c 、parkinson 、garmanklass 、rsy 、yz
隐含波动率:自行采用QuantLib/Mibian 计算实时隐含波动率
波动率VIX(恐慌指数):自行编码模块实时计算VIX指数(分钟/日级别)
# 计算历史某一天的iVIX
# Based on http://www.cboe.com/micro/vix/vixwhite.pdf
def calDayVIX(self,vixDate):
# concat某一日行情和期权基本信息,得到所需数据
opt = self.getOPT(vixDate)
flag_month_expire=opt.flag_month_expire.unique()
if len(flag_month_expire)<2:
vix30=-99.
else:
#opt=self.getRealOPT()
# 由于50etf分红加挂合约,导致使用strikePrice并不能唯一确定合约(存在行权价相同的情况)
# 通联的secID中,加挂合约会设置为尾缀为XSHG2,所以用通联的合约最后几位最为唯一识别码
# 510050P1706M02250.XSHG2
# 510050P1706M02250.XSHG
# 通联相同行权价的put合约代码如上,前者为因为分红加挂
#date=dt.datetime.strptime(date,'%Y-%m-%d')
opt.loc[:,'strikeMark'] = [x[12:] for x in opt.tickerSymbol]
opt.loc[:,'price']= opt['settlePrice']
exp_dates = TD.expDateNp[TD.expDateNp>vixDate]
exp_periods = {}
for epd in exp_dates:
exp_periods[epd] = xtool.deltaDays(vixDate,epd)*1.0/365.0
risk_free = 0.04
sigma_square = {}
for date in exp_dates:
# 计算某一日的vix
opt_date = opt[opt.expDate==date]
if len(opt_date)==0:
continue
rf = risk_free
#rf = 0.05
opt_call = opt_date[opt_date.contractType == 'C'].set_index(['strikeMark','strikePrice'])
opt_put = opt_date[opt_date.contractType == 'P'].set_index(['strikeMark','strikePrice'])
opt_call_price = opt_call[[u'price']].sort_index()
opt_put_price = opt_put[[u'price']].sort_index()
opt_call_price.columns = [u'callPrice']
opt_put_price.columns = [u'putPrice']
opt_call_put_price = pd.concat([opt_call_price, opt_put_price], axis=1, join='inner').sort_index()
opt_call_put_price['diffCallPut'] = opt_call_put_price.callPrice - opt_call_put_price.putPrice
strike_mark = abs(opt_call_put_price['diffCallPut']).idxmin()
price_diff = opt_call_put_price['diffCallPut'][strike_mark]
ttm = exp_periods[date]
# 如上,strike_mark为一tuple,('strikeMark','strikePrice')
fw = strike_mark[1] + np.exp(ttm*rf) * price_diff
# 计算delta K
opt_call_put_price = opt_call_put_price.sort_index(level='strikePrice')
strike_price = opt_call_put_price.reset_index(level='strikePrice').sort_values('strikePrice')['strikePrice']
delta_strike = strike_price.rolling(window=3).apply(lambda x: (x[-1] - x[0])/2.0).shift(-1).values
delta_strike = np.concatenate((delta_strike[1:2], delta_strike[1:-1], delta_strike[-2:-1]))
opt_call_put_price['deltaStrike'] = delta_strike
# opt_otm = opt_out_of_money
opt_otm = pd.concat([opt_call.loc[[x for x in opt_call.index if x[1] > fw], :],opt_put.loc[[x for x in opt_put.index if x[1] < fw], :]], axis=0, join='inner')
opt_otm['deltaStrike'] = opt_call_put_price['deltaStrike']
opt_otm = opt_otm.sort_index()
# 计算VIX时,比forward price低的第一个行权价被设置为参考行权价,参考值以上
# 的call和以下的put均为虚值期权,所有的虚值期权被用来计算VIX,然而计算中发
# 现,有时候没有比forward price更低的行权价,例如2015-07-08,故有以下关于
# 参考行权价的设置
strike_marks_idx = opt_otm.index
strike_marks_low = [x for x in strike_marks_idx if x[1] < fw]
if len(strike_marks_low) > 0:
strike_mark_ref = strike_marks_low[-1]
#opt_otm['price'][strike_mark_ref] = (opt_call['price'][strike_mark_ref] + opt_put['price'][strike_mark_ref])/2.0
if strike_mark_ref in opt_call.index and strike_mark_ref in opt_put.index:
opt_otm.loc[strike_mark_ref,'price']=(opt_call.loc[strike_mark_ref,'price'] + opt_put.loc[strike_mark_ref,'price'])/2.0
else:
opt_otm.loc[strike_mark_ref,'price']=(opt_call.query('strikeMark=="%s"'%(strike_mark_ref[0]))['price'].values[0]+\
opt_put.query('strikeMark=="%s"'%(strike_mark_ref[0]))['price'].values[0])/2.0
strike_price_ref = strike_mark_ref[1]
else:
strike_price_ref = fw
opt_otm = opt_otm.reset_index(level='strikeMark')
exp_rt = np.exp(rf*ttm)
opt_otm['sigmaTerm'] = opt_otm.deltaStrike*opt_otm.price/opt_otm.index/opt_otm.index
sigma = opt_otm.sigmaTerm.sum()
sigma = (sigma*2.0*exp_rt - (fw*1.0/strike_price_ref - 1.0)**2)/ttm
sigma_square[date] = sigma
#差值计算
try:
# d_one, d_two 将被用来计算VIX(30):
if exp_periods[exp_dates[0]] >= 1.0/365.0:
d_one = exp_dates[0]
d_two = exp_dates[1]
w = (exp_periods[d_two] - 30.0/365.0)/(exp_periods[d_two] - exp_periods[d_one])
vix30 = exp_periods[d_one]*w*sigma_square[d_one] + exp_periods[d_two]*(1 - w)*sigma_square[d_two]
vix30 = 100*np.sqrt(vix30*365.0/30.0)
else:
d_one = exp_dates[1]
vix30 = sigma_square[d_one]
vix30 = 100*np.sqrt(vix30)
except Exception,e:
vix30=-99.
'''
# d_one, d_two 将被用来计算VIX(60):
d_one = exp_dates[1]
d_two = exp_dates[2]
w = (exp_periods[d_two] - 60.0/365.0)/(exp_periods[d_two] - exp_periods[d_one])
vix60 = exp_periods[d_one]*w*sigma_square[d_one] + exp_periods[d_two]*(1 - w)*sigma_square[d_two]
vix60 = 100*np.sqrt(vix60*365.0/60.0)
'''
vix30=round(vix30, 2)
print('%s: %0.2f %s'%(vixDate,vix30,flag_month_expire))
return vix30
实时日内分钟级别隐含波动率及VIX
http://adog.net.cn
公众号:期权量化ADOG