第三章 基础数据和技术指标 | 波动率计算

三、波动率计算

波动率计算

历史波动率:自行采用不同算法,包括 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

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿岛格

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值