失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > python量化策略——改进的美林时钟轮动策略(三)

python量化策略——改进的美林时钟轮动策略(三)

时间:2020-03-24 13:56:19

相关推荐

python量化策略——改进的美林时钟轮动策略(三)

策略实现

前面,有了统计的的结果改进的美林一/二,现在用历史的数据进行回测

1.所需的库

# coding=utf-8import mathimport tushare as tsimport pandas as pdimport matplotlibimport matplotlib.pyplot as pltimport numpy as npimport talibimport pandas as pdfrom datetime import datetime, datematplotlib.rcParams['axes.unicode_minus']=Falseplt.rcParams['font.sans-serif']=['SimHei']ts.set_token(' token码 ')pro = ts.pro_api()

2.数据读取和数据的处理,和前面一样python量化策略——改进的美林时钟(二)

若想直接运行此代码,需获取Tushare pro 金融数据的token码,这里获取token码

############################读取数据类###################################class readData:def read_index_daily(self,code,star,end):#指数数据dsb = pro.index_daily(ts_code=code, start_date=star, end_date=end,fields='ts_code,trade_date,close,change')#默认读取三个数据return dsbdef read_daily(self,code,star,end):dsc1 = pro.daily(ts_code=code, start_date=star, end_date=end,fields='ts_code,trade_date,close,change')return dsc1def read_CPI(self,star,end):#时间格式start_cpi='09'dc=_cpi(start_m=star, end_m=end,fields='month,nt_yoy')return dcdef read_GDP(self,star,end):#时间格式star='Q4'df1 = _gdp(start_q=star, end_q=end,fields='quarter,gdp_yoy')return df1def read_bond(self,code,star,end):df=pro.cb_daily(ts_code=code,start_date=star,end_date=end)return df##################################################################### start_time='20000430'#发布GDP需要时间,我们延迟1个月,即第一季度的GDP4月份才发布。end_time="2031"star_GDP='Q1'#延后一年,因为我们找的是差分 end_GDP='Q1'#不是以3 4季度结尾star_CPI='01'end_CPI='20'df1=readData()#读取dc=readData()dsc1=readData()dsp=readData()dsb=readData()df1=df1.read_GDP(star_GDP,end_GDP)dc=dc.read_CPI(star_CPI,end_CPI)dsc1=dsc1.read_index_daily('000300.SH',start_time,end_time) dsb=dsb.read_index_daily('000012.SH',start_time,end_time)dsp=dsp.read_index_daily('NHCI.NH',start_time,end_time) ##########################GDP信号处理################################def GDP_fun(df1):df1.set_index('quarter',inplace=True)#设置日期索引df2=(df1.shift(4)-df1).shift(-4)df2=df2.dropna()G=pd.Series(0,index=df2.gdp_yoy.index)for i in range(len(df2.gdp_yoy)):if df2.gdp_yoy[i]>0:G[i]=1elif df2.gdp_yoy[i]<0:G[i]=0else:G[i]=G[i-1]return GG=GDP_fun(df1)###############################################################################################CPI信号函数##############################def CPI_fun(dc):dc=dc.sort_index()dc.set_index('month',inplace=True)dc2=(dc.shift(12)-dc.shift()).shift(-12).dropna()C=pd.Series(0,index=dc2.nt_yoy.index)for j in range(len(dc2.nt_yoy)-3):if (3+j)%3==0:if dc2.nt_yoy[j]>0:C[j]=1elif dc2.nt_yoy[j]<0:C[j]=0else:C[j]=C[j-1] else:pass return CC=CPI_fun(dc)########################################################################

3.收益计算函数

############################计算收益率+索引函数##########################class ZC_fun:def ret_function(self,ds):#standard_base=pro.index_daily( ts_code='000300.SH', start_date='1031', end_date="2030")standard_base=ds.sort_index()standard_base.index=pd.to_datetime(standard_base.trade_date,format='%Y-%m-%d')#设置日期索引close_base= standard_base.closestandard_ret=standard_base.change/standard_base.close.shift(-1)ret=standard_ret.sort_index(axis=0,ascending=True)ret=ret.dropna()return retdef bsc_fun(self,ds):dsc=ds.drop(['ts_code'],axis=1)dsc=dsc.sort_index()dsc.index=pd.to_datetime(dsc.trade_date,format='%Y-%m-%d')#设置日期索引dsc=dsc.drop(['trade_date'],axis=1)return dsc######################################################################### gc=ZC_fun()R_c=gc.ret_function(dsc1)#股票的利率gb=ZC_fun()R_b=gb.ret_function(dsb)#债券的利率gp=ZC_fun()R_p=gp.ret_function(dsp)#商品的利率

4.季度收益函数

############################对应季度的收益####################################def RET_sig(sig_c,i):#输入利率,输出i对应的时间段利率#####截取利率段if G.index[i][5:6] =='1':a=G.index[i][0:4]+'0501'b=G.index[i][0:4]+'0731'at1=pd.to_datetime(a,format='%Y-%m-%d')bt1=pd.to_datetime(b,format='%Y-%m-%d')sig_c=sig_c[ sig_c.index<=bt1] sig_c=sig_c[ sig_c.index>=at1]elif G.index[i][5:6] =='2':a=G.index[i][0:4]+'0801'b=G.index[i][0:4]+'1031'at1=pd.to_datetime(a,format='%Y-%m-%d')bt1=pd.to_datetime(b,format='%Y-%m-%d')sig_c=sig_c[ sig_c.index<=bt1] sig_c=sig_c[ sig_c.index>=at1]elif G.index[i][5:6] =='3':a=G.index[i][0:4]+'1101'a1=G.index[i][0:4]+'1231'at1=pd.to_datetime(a,format='%Y-%m-%d')bt1=pd.to_datetime(a1,format='%Y-%m-%d')sig_c1=sig_csig_c1=sig_c1[ sig_c1.index<=bt1] sig_c1=sig_c1[ sig_c1.index>=at1]sig_c1=sig_c1b=G.index[i-2][0:4]+'0101'b1=G.index[i-2][0:4]+'0131'at11=pd.to_datetime(b,format='%Y-%m-%d')bt11=pd.to_datetime(b1,format='%Y-%m-%d')sig_c=sig_c[ sig_c.index<=bt11] sig_c=sig_c[ sig_c.index>=at11]sig_c=sig_c1.append(sig_c)else:a=G.index[i-1][0:4]+'0201'b=G.index[i-1][0:4]+'0430'at1=pd.to_datetime(a,format='%Y-%m-%d')bt1=pd.to_datetime(b,format='%Y-%m-%d')sig_c=sig_c[ sig_c.index<=bt1] sig_c=sig_c[ sig_c.index>=at1]return sig_c###########################################################################

5.策略判断信号函数

#################################策略条件##################################RETT=Nonefor i in range(len(G)):if G[i]>0 and CP(i)>0:RETT=( 0*RET_sig(R_c,i)+1*RET_sig(R_p,i) +0*RET_sig(R_b,i) ).append(RETT)elif G[i]==0 and CP(i)>0:RETT=( 0*RET_sig(R_c,i)+0*RET_sig(R_p,i)+1*RET_sig(R_b,i) ).append(RETT)elif G[i]>0 and CP(i)==0:RETT=( 1*RET_sig(R_c,i)+0*RET_sig(R_p,i) +0*RET_sig(R_b,i) ).append(RETT)else:RETT=( 1*RET_sig(R_c,i)+0*RET_sig(R_p,i)+0*RET_sig(R_b,i) ).append(RETT)RETT=RETT.sort_index(axis=0)cum=np.cumprod(1+RETT)-1cum=cum.dropna()

6.基准函数(直接调用)

############################指数基准图#########################################start_time_jz=str(RETT.index[0])[:4]+str(RETT.index[0])[5:7]+str(RETT.index[0])[8:10]#获取开始时间end_time_jz=str(RETT.index[-1])[:4]+str(RETT.index[-1])[5:7]+str(RETT.index[-1])[8:10]#计算函数def bj_standard(code,lab='沪深300',col='k'):#针对沪深股票,直接画出比较基准(收益情况)standard_base = pro.index_daily( ts_code=code, start_date=start_time_jz, end_date=end_time_jz)standard_base=standard_base.sort_index()standard_base.index=pd.to_datetime(standard_base.trade_date,format='%Y-%m-%d')#设置日期索引close_base= standard_base.closestandard_ret=standard_base.change/standard_base.close.shift(-1)standard_sig=pd.Series(0,index=close_base.index) standard_trade=standard_sig.shift(1).dropna()/100#shift(1)整体下移一行standard_SmaRet=standard_ret*standard_trade.dropna()standard_cum=np.cumprod(1+standard_ret[standard_SmaRet.index[0:]])-1plt.plot(standard_cum,label=lab,color=col)return standard_cum###########################################################################

7.结果统计函数(最大回撤、波动率等信息)

#############################策略的年化统计######################################def Tongji(RET,cum):RET1 = RET*100 - (4/252)NH=cum[-2]*100*252/len(RET.index)BD=np.std(RET)*100*np.sqrt(252)SR=(NH-400/252)/BDClose=Nonefor i in range(len(G)):Close=RET_sig( gc.ret_function(dsc1)[1] ,i).append(Close)for i in range(len(cum)):if Close[Close.index[i]]==Close.max():MHC=(Close.max()-Close[Close.index[i:]].min())*100/Close.max()print("年化收益率:{:.2f}%:,年化夏普率:{:.2f},波动率为:{:.2f}%,最大回撤:{:.2f}%".format( NH,SR,BD,MHC))############################################################################

8.调用函数

if __name__=="__main__":bj_standard('000300.SH')#比较基准函数(图)bj_standard('000012.SH',lab='上证国债',col='b')bj_standard('NHCI.NH',lab='南华商品指数',col='y')Tongji(RETT,cum)plt.plot(cum,label="组合策略",color='r',linestyle='-')plt.title("策略收益率")plt.legend()

9输出结果:

-回测结果:

年化收益率:28.01%:,年化夏普率:1.31,波动率为:20.13%,最大回撤:72.30%

看看其他年份的结果

-

年化收益率:9.78%:,夏普率:0.44,波动率为:18.77%,最大回撤:72.30%

-

结果:

年化收益率:26.73%:,夏普率:1.20,波动率为:20.92%,最大回撤:37.91%

可以看出单资产策略抓住06-08年的行情,总体还是不错的收益率。

如果不选择单资产配置,采用组合配置呢,每次配2-3个大类资产。

下面来看下

只要平均收益率大于0,就选择它,权重根据平均收益的大小按比例配置。

-

年化收益率:42.01%:,年化夏普率:1.80,波动率为:22.45%,最大回撤:36.23%

07年的那一波行情没抓住。

下面看下最近十年的情况(-今)

年化收益率:6.71%:,夏普率:0.33,波动率为:17.78%

效果也不是很夸张,但是最后都跑赢了三个基准,但是波动确实相对较大。

完整代码:

注:若想直接运行此代码,需获取Tushare pro 金融数据的token码,这里获取token码

# coding=utf-8import mathimport tushare as tsimport pandas as pdimport matplotlibimport matplotlib.pyplot as pltimport numpy as npimport talibimport pandas as pdfrom datetime import datetime, datematplotlib.rcParams['axes.unicode_minus']=Falseplt.rcParams['font.sans-serif']=['SimHei']ts.set_token('填入token码')###填入token码pro = ts.pro_api()def CP(x):#转换CPI为季度数据return C[3*x]############################读取数据类###################################class readData:def read_index_daily(self,code,star,end):#指数数据dsb = pro.index_daily(ts_code=code, start_date=star, end_date=end,fields='ts_code,trade_date,close,change')#默认读取三个数据return dsbdef read_daily(self,code,star,end):dsc1 = pro.daily(ts_code=code, start_date=star, end_date=end,fields='ts_code,trade_date,close,change')return dsc1def read_CPI(self,star,end):#时间格式start_cpi='09'dc=_cpi(start_m=star, end_m=end,fields='month,nt_yoy')return dcdef read_GDP(self,star,end):#时间格式star='Q4'df1 = _gdp(start_q=star, end_q=end,fields='quarter,gdp_yoy')return df1def read_bond(self,code,star,end):df=pro.cb_daily(ts_code=code,start_date=star,end_date=end)return df##################################################################### start_time='20000430'#发布GDP需要时间,我们延迟1个月,即第一季度的GDP4月份才发布。end_time="2031"star_GDP='Q1'#延后一年,因为我们找的是差分 end_GDP='Q1'#不是以3 4季度结尾star_CPI='01'end_CPI='03'df1=readData()#读取dc=readData()dsc1=readData()dsp=readData()dsb=readData()df1=df1.read_GDP(star_GDP,end_GDP)dc=dc.read_CPI(star_CPI,end_CPI)dsc1=dsc1.read_index_daily('000300.SH',start_time,end_time) dsb=dsb.read_index_daily('000012.SH',start_time,end_time)dsp=dsp.read_index_daily('NHCI.NH',start_time,end_time) ##########################GDP信号处理################################def GDP_fun(df1):df1.set_index('quarter',inplace=True)#设置日期索引df2=(df1.shift(4)-df1).shift(-4)df2=df2.dropna()G=pd.Series(0,index=df2.gdp_yoy.index)for i in range(len(df2.gdp_yoy)):if df2.gdp_yoy[i]>0:G[i]=1elif df2.gdp_yoy[i]<0:G[i]=0else:G[i]=G[i-1]return GG=GDP_fun(df1)###############################################################################################CPI信号函数##############################def CPI_fun(dc):dc=dc.sort_index()dc.set_index('month',inplace=True)dc2=(dc.shift(12)-dc.shift()).shift(-12).dropna()C=pd.Series(0,index=dc2.nt_yoy.index)for j in range(len(dc2.nt_yoy)-3):if (3+j)%3==0:if dc2.nt_yoy[j]>0:C[j]=1elif dc2.nt_yoy[j]<0:C[j]=0else:C[j]=C[j-1] else:pass return CC=CPI_fun(dc)####################################################################################################计算收益率+索引函数##########################class ZC_fun:def ret_function(self,ds):#standard_base=pro.index_daily( ts_code='000300.SH', start_date='1031', end_date="2030")standard_base=ds.sort_index()standard_base.index=pd.to_datetime(standard_base.trade_date,format='%Y-%m-%d')#设置日期索引close_base= standard_base.closestandard_ret=standard_base.change/standard_base.close.shift(-1)ret=standard_ret.sort_index(axis=0,ascending=True)ret=ret.dropna()return retdef bsc_fun(self,ds):dsc=ds.drop(['ts_code'],axis=1)dsc=dsc.sort_index()dsc.index=pd.to_datetime(dsc.trade_date,format='%Y-%m-%d')#设置日期索引dsc=dsc.drop(['trade_date'],axis=1)return dsc######################################################################### gc=ZC_fun()R_c=gc.ret_function(dsc1)#股票的利率gb=ZC_fun()R_b=gb.ret_function(dsb)#债券的利率gp=ZC_fun()R_p=gp.ret_function(dsp)#商品的利率############################对应季度的收益####################################def RET_sig(sig_c,i):#输入利率,输出i对应的时间段利率#####截取利率段if G.index[i][5:6] =='1':a=G.index[i][0:4]+'0501'b=G.index[i][0:4]+'0731'at1=pd.to_datetime(a,format='%Y-%m-%d')bt1=pd.to_datetime(b,format='%Y-%m-%d')sig_c=sig_c[ sig_c.index<=bt1] sig_c=sig_c[ sig_c.index>=at1]elif G.index[i][5:6] =='2':a=G.index[i][0:4]+'0801'b=G.index[i][0:4]+'1031'at1=pd.to_datetime(a,format='%Y-%m-%d')bt1=pd.to_datetime(b,format='%Y-%m-%d')sig_c=sig_c[ sig_c.index<=bt1] sig_c=sig_c[ sig_c.index>=at1]elif G.index[i][5:6] =='3':a=G.index[i][0:4]+'1101'a1=G.index[i][0:4]+'1231'at1=pd.to_datetime(a,format='%Y-%m-%d')bt1=pd.to_datetime(a1,format='%Y-%m-%d')sig_c1=sig_csig_c1=sig_c1[ sig_c1.index<=bt1] sig_c1=sig_c1[ sig_c1.index>=at1]sig_c1=sig_c1b=G.index[i-2][0:4]+'0101'b1=G.index[i-2][0:4]+'0131'at11=pd.to_datetime(b,format='%Y-%m-%d')bt11=pd.to_datetime(b1,format='%Y-%m-%d')sig_c=sig_c[ sig_c.index<=bt11] sig_c=sig_c[ sig_c.index>=at11]sig_c=sig_c1.append(sig_c)else:a=G.index[i-1][0:4]+'0201'b=G.index[i-1][0:4]+'0430'at1=pd.to_datetime(a,format='%Y-%m-%d')bt1=pd.to_datetime(b,format='%Y-%m-%d')sig_c=sig_c[ sig_c.index<=bt1] sig_c=sig_c[ sig_c.index>=at1]return sig_c############################################################################################################策略条件##################################RETT=Nonefor i in range(len(G)):if G[i]>0 and CP(i)>0:RETT=( 0*RET_sig(R_c,i)+1*RET_sig(R_p,i) +0*RET_sig(R_b,i) ).append(RETT)elif G[i]==0 and CP(i)>0:RETT=( 0*RET_sig(R_c,i)+0*RET_sig(R_p,i)+1*RET_sig(R_b,i) ).append(RETT)elif G[i]>0 and CP(i)==0:RETT=( 1*RET_sig(R_c,i)+0*RET_sig(R_p,i) +0*RET_sig(R_b,i) ).append(RETT)else:RETT=( 1*RET_sig(R_c,i)+0*RET_sig(R_p,i)+0*RET_sig(R_b,i) ).append(RETT)RETT=RETT.sort_index(axis=0)cum=np.cumprod(1+RETT)-1cum=cum.dropna()############################指数基准图#########################################start_time_jz=str(RETT.index[0])[:4]+str(RETT.index[0])[5:7]+str(RETT.index[0])[8:10]end_time_jz=str(RETT.index[-1])[:4]+str(RETT.index[-1])[5:7]+str(RETT.index[-1])[8:10]def bj_standard(code,lab='沪深300',col='k'):#针对沪深股票,直接画出比较基准(收益情况)standard_base = pro.index_daily( ts_code=code, start_date=start_time_jz, end_date=end_time_jz)standard_base=standard_base.sort_index()standard_base.index=pd.to_datetime(standard_base.trade_date,format='%Y-%m-%d')#设置日期索引close_base= standard_base.closestandard_ret=standard_base.change/standard_base.close.shift(-1)standard_sig=pd.Series(0,index=close_base.index) standard_trade=standard_sig.shift(1).dropna()/100#shift(1)整体下移一行standard_SmaRet=standard_ret*standard_trade.dropna()standard_cum=np.cumprod(1+standard_ret[standard_SmaRet.index[0:]])-1plt.plot(standard_cum,label=lab,color=col)return standard_cum########################################################################### #############################策略的年化统计######################################def Tongji(RET,cum):RET1 = RET*100 - (4/252)NH=cum[-2]*100*252/len(RET.index)BD=np.std(RET)*100*np.sqrt(252)SR=(NH-400/252)/BDfor i in range(len(cum)):if cum[cum.index[i]]==cum.max():MHC=(cum.max()-cum[cum.index[i:]].min())*100/cum.max()print("年化收益率:{:.2f}%:,年化夏普率:{:.2f},波动率为:{:.2f}%,最大回撤:{:.2f}%".format( NH,SR,BD,MHC))############################################################################if __name__=="__main__":bj_standard('000300.SH')#比较基准函数(图)bj_standard('000012.SH',lab='上证国债',col='b')bj_standard('NHCI.NH',lab='南华商品指数',col='y')Tongji(RETT,cum)plt.plot(cum,label="组合策略",color='r',linestyle='-')plt.title("策略收益率")plt.legend()

其他策略

1.python量化——alpha股票-指数期货对冲策略

2.多因子选股策略

3.海龟交易策略

4.移动平均策略——单/双均线策略

5.改进的美林时钟策略(一)

5.改进的美林时钟策略(二)

如果觉得《python量化策略——改进的美林时钟轮动策略(三)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。