本文使用某个交易日内的上证50ETF的5分钟收盘价(原始数据:),计算该交易日的已实现波动率。日度已实现波动率的计算公式如下:
同时,周度已实现波动率和月度已实现波动率的计算公式如下:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import time
plt.rcParams['font.sans-serif']=['simhei']#用于正常显示中文标签
plt.rcParams['axes.unicode_minus']=False#用于正常显示负号
#简单处理数据
data=pd.read_csv('上证50ETF5分钟数据.csv')#读取数据
data['交易日']=data['日期'].apply(lambda x:x.split(' ')[0])
data['交易日']=data['交易日'].apply(lambda x:time.strftime('%Y%m%d',time.strptime(x,'%Y/%m/%d')))#修改日期格式
data['分时']=data['日期'].apply(lambda x:x.split(' ')[1])
#调整数据格式
data_time_date=pd.pivot_table(data,index=['分时'],columns=['交易日'],values=['收盘'])['收盘']
data_time_date=data_time_date.loc[data['分时'].unique(),:]
#定义绘图函数
def plot_cols(data,xlabel=None,ylabel=None,path_file=None,marker=True,len_xticks=10,save=False):
"""
:param data:DataFrame,数据表格--行标题为横坐标,列标题为数据列
Series,序列——行标题为横坐标,name为数据列
:param xlabel: str,横坐标名称
:param ylabel: str,纵坐标名称
:param path_file: str,保存文件路径
:param marker: bool,是否为每条线添加不同的标记
:param len_xticks:int,横坐标显示的值个数
:param save: bool,是否保存图片
example:
data=pd.DataFrame(np.random.random((100,3)),index=np.arange(100),columns=['a','b','c'])
plot_cols(data,xlabel='指标',ylabel='指数')
"""
data.index=data.index.astype(str)
plt.figure(figsize=(12,8))
markers=['.',',','o','v','^','<','>','1','2','3','4','s','p','*','h','H','+','x','D','d','|','_']#标记符号
#如果是DataFrame表格形式,则画出多列;如果是Series,则画出单列
if type(data) is pd.core.frame.DataFrame:
#是否为每条线添加不同的符号
if marker==False:
for col in data.columns:
plt.plot(data[col],marker='o',label=col)
else:
for col,marker_ in zip(data.columns,markers):
plt.plot(data[col], marker=marker_, label=col)
elif type(data) is pd.core.series.Series:
plt.plot(data, marker='o', label=data.name)
plt.legend(loc='best',fontsize='small')
xticks=np.linspace(0,len(data),(len_xticks+1)).astype(int).tolist()[:-1]#被显示的横坐标刻度值的位置
plt.xticks(data.index[xticks],rotation=270)
plt.ylabel(ylabel,fontsize=15)
plt.xlabel(xlabel,fontsize=15)
plt.grid(True,alpha=0.2)
if save==True:plt.savefig(path_file)
#计算每个交易日的日度已实现波动率并绘图
RV=((np.log(data_time_date)-np.log(data_time_date.shift())).dropna()**2).sum()#日度已实现方差
plot_cols(np.sqrt(RV),xlabel='日期',ylabel='日度已实现波动率',len_xticks=20,path_file='日度已实现波动率.png')
#计算每个交易日的指定天数已实现波动率
def RV_days_(days):
RV_days=[]
dates=[]
for i in range(days,len(RV)):
date=RV.index[i]
RV_day=RV[i-days:i].sum()
dates.append(date)
RV_days.append(RV_day)
RV_days=pd.Series(RV_days,index=dates)/days
plot_cols(np.sqrt(RV_days),xlabel='日期',ylabel='{}天度已实现波动率'.format(days),len_xticks=20,path_file='{}天度已实现波动率.png'.format(days))
RV_days_(days=5)#计算周度已实现波动率并绘图
RV_days_(days=21)#计算月度已实现波动率并绘图
三幅图如下所示,显然,从日度已实现收益率,到周度已实现收益率,再到月度已实现收益率,曲线在变得越来越平滑。