改进美林时钟代码
1.python量化——alpha股票-指数期货对冲策略
2.多因子选股策略
3.海龟交易策略
4.移动平均策略——单/双均线策略
5.改进的美林时钟策略(一)
5.改进的美林时钟策略(二)
6.改进的美林时钟策略(三)
这里获取token码
""" 2020.08.28 9:57
zp
宏观经济指标和大类资产收益的相关性
"""
# coding=utf-8
import math
import tushare as ts
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import talib
import pandas as pd
from datetime import datetime, date
import pymysql
import threading
from queue import Queue
matplotlib.rcParams['axes.unicode_minus']=False
plt.rcParams['font.sans-serif']=['SimHei']
ts.set_token('19fbtoken码5e0')
pro = ts.pro_api()
class read_data:
def fetchData(self, query, q, name, db, host='192.168.0.153', user='jcyj', password='jcyjQwer'):
'get data from mysql database'
conn = pymysql.connect(host, user, password, database=db, charset='utf8', cursorclass=pymysql.cursors.DictCursor)
cursor = conn.cursor()
res = cursor.execute(query)
fetch = cursor.fetchall()
data = pd.DataFrame(fetch)
q.put((name, data))
def multithread(self, dataList, db):
threads = []
q = Queue()
for key, value in dataList.items():
t = threading.Thread(target=self.fetchData, args=(value, q, key, db)) # initiate a thread
t.start() # activate a thread
threads.append(t) # collect threads list
for thread in threads:
thread.join()
result = []
for _ in range(len(threads)):
result.append(q.get())
result = {i[0]: i[1] for i in result}
return result
def readhgyz(self, db='py_daziguan_2_1'):
baseQuery = "select report_date , shibor_1w "\
" from py_hgyz_pbc_shanghai_shibor_statistics_month where DATE(report_date) > '2005-12-01' and DATE(report_date) < '2020-04-01' "
data = self.multithread({'base': baseQuery},db)
return data
def readetl1(self, db='py_etl'):
baseQuery = "select trading_date , bond_1y "\
" from py_etl_risk_free_rate_daily_2_1 where DATE(trading_date) > '2006-04-30' and DATE(trading_date) < '2020-08-01' "
data = self.multithread({'base2': baseQuery},db)
return data
BO1=read_data()
BO1=BO1.readetl1()["base2"]
BO1.set_index('trading_date',inplace=True)
BO1.index = pd.to_datetime(BO1.index)
BO1.bond_1y
R_B=BO1.bond_1y
#############################七天回购利率###############################
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 dsb
def 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 dsc1
def read_CPI(self,star,end):#时间格式start_cpi='201609'
dc=pro.cn_ppi(start_m=star, end_m=end,fields='month,ppi_yoy')
return dc
def read_GDP(self,star,end):#时间格式star='2016Q4'
df1 = pro.cn_gdp(start_q=star, end_q=end,fields='quarter,gdp_yoy')
return df1
def read_bond(self,code,star,end):
df=pro.cb_daily(ts_code=code,start_date=star,end_date=end)
return df
def readshibor(self,star,end):
return pro.shibor(start_date=star, end_date=end)
#####################################################################
start_time='20000430'#发布GDP需要时间,我们延迟1个月,即第一季度的GDP4月份才发布。
end_time="20200731"
star_GDP='2005Q1'#延后一年,因为我们找的是差分
end_GDP='2020Q1'#不是以3 4季度结尾
star_CPI='200501'
end_CPI='202003'
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]=1
elif df2.gdp_yoy[i]<0:
G[i]=0
else:
G[i]=G[i-1]
return G
G=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.ppi_yoy.index)
for j in range(len(dc2.ppi_yoy)):
if (3+j)%3==0:
if dc2.ppi_yoy[j]>0:
C[j]=1
elif dc2.ppi_yoy[j]<0:
C[j]=0
else:
C[j]=C[j-1]
else:
pass
return C
C=CPI_fun(dc)
########################################################################
##############################利率处理##################################
DF=read_data()
DF2=DF.readhgyz()
DF=DF2['base']
def LV_fun(dc):
dc=dc.sort_index()
dc.set_index('report_date',inplace=True)
dc2=(dc.shift(12)-dc.shift()).shift(-12).dropna()
C=pd.Series(0,index=G.index)
for j in range(len(dc2.shibor_1w)):
if (3+j)%3==0:
for i in range(int(j/3),int((3+j)/3)):
if dc2.shibor_1w[j]+dc2.shibor_1w[j+1]+dc2.shibor_1w[j+2] >0:
C[i]=1
elif dc2.shibor_1w[j]+dc2.shibor_1w[j+1]+dc2.shibor_1w[j+2]<0:
C[i]=0
else:
C[i]=C[i-1]
else:
pass
return C
LV=LV_fun(DF)
#########################################################################
############################计算收益率+索引函数##########################
class ZC_fun:
def ret_function(self,ds):
#standard_base=pro.index_daily( ts_code='000300.SH', start_date='20081031', end_date="20200430")
standard_base=ds.sort_index()
standard_base.index=pd.to_datetime(standard_base.trade_date,format='%Y-%m-%d')#设置日期索引
close_base= standard_base.close
standard_ret=standard_base.change/standard_base.close.shift(-1)
ret=standard_ret.sort_index(axis=0,ascending=True)
ret=ret.dropna()
return ret#,close_base/close_base[start_time_jz].values#=str(RETT.index[0])[:4]+str(RETT.index[0])[5:7]+str(RETT.index[0])[8:10]###############
#有点问题,上面一行
def 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)#商品的利
R_B=pd.DataFrame(R_B,dtype=np.float).bond_1y/100#无风险利率 ###########
#R_B=R_B[start_time_jz:]
#Close_c=gc.ret_function(dsc1)[1]#股票的利
#Close_b=gb.ret_function(dsb)[1]#债券的利
#Close_p=gp.ret_function(dsp)[1]#商品的利
#Close_B=np.cumprod(R_B+1)
############################对应季度的收益####################################
def RET_sig(sig_c,i):#输入ret,输出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_c
sig_c1=sig_c1[ sig_c1.index<=bt1]
sig_c1=sig_c1[ sig_c1.index>=at1]
sig_c1=sig_c1
b=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
###########################################################################
#################################策略条件##################################
def quanzhong_fun(R_c,R_p,R_b,R_B):
RETT=None
for i in range(len(G)):
if G[i]>0 and CP(i)>0 and LV[i]>0:
RETT=( 1*RET_sig(R_c,i)+0*RET_sig(R_p,i) +0*RET_sig(R_b,i)+0*RET_sig(R_B,i) ).append(RETT)
elif G[i]==0 and CP(i)>0 and LV[i]>0:
RETT=( 0*RET_sig(R_c,i)+0*RET_sig(R_p,i)+1*RET_sig(R_b,i) +0*RET_sig(R_B,i) ).append(RETT)
#elif G[i]>0 and CP(i)==0 and LV[i]>0:
# RETT=( 0*RET_sig(R_c,i)+0.9*RET_sig(R_p,i) +0*RET_sig(R_b,i)+0.1*RET_sig(R_B,i) ).append(RETT)
elif G[i]==0 and CP(i)==0 and LV[i]>0:
RETT=( 1*RET_sig(R_c,i)+0*RET_sig(R_p,i)+0*RET_sig(R_b,i)+0*RET_sig(R_B,i) ).append(RETT)
elif G[i]>0 and CP(i)>0 and LV[i]==0:
RETT=( 1*RET_sig(R_c,i)+0*RET_sig(R_p,i) +0*RET_sig(R_b,i)+0*RET_sig(R_B,i) ).append(RETT)
elif G[i]==0 and CP(i)>0 and LV[i]==0:
RETT=( 1*RET_sig(R_c,i)+0*RET_sig(R_p,i)+0*RET_sig(R_b,i) +0*RET_sig(R_B,i) ).append(RETT)
elif G[i]>0 and CP(i)==0 and LV[i]==0:
RETT=( 1*RET_sig(R_c,i)+0*RET_sig(R_p,i) +0*RET_sig(R_b,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)+0*RET_sig(R_B,i) ).append(RETT)
return RETT
RETT=quanzhong_fun(R_c,R_p,R_b,R_B)
RETT=RETT.sort_index(axis=0)
cum=np.cumprod(1+RETT)
cum=cum.dropna()
#################################策略条件##################################
def quanzhong_fun1(R_c,R_p,R_b,R_B):
RETT=None
for i in range(len(G)):
if G[i]>0 and CP(i)>0 and LV[i]>0:
RETT=( 0.4*RET_sig(R_c,i)+0.3*RET_sig(R_p,i) +0.1*RET_sig(R_b,i)+0.2*RET_sig(R_B,i) ).append(RETT)
elif G[i]==0 and CP(i)>0 and LV[i]>0:
RETT=( 0.1*RET_sig(R_c,i)+0.2*RET_sig(R_p,i)+0.4*RET_sig(R_b,i) +0.3*RET_sig(R_B,i) ).append(RETT)
#elif G[i]>0 and CP(i)==0 and LV[i]>0:
# RETT=( 0*RET_sig(R_c,i)+0.9*RET_sig(R_p,i) +0*RET_sig(R_b,i)+0.1*RET_sig(R_B,i) ).append(RETT)
elif G[i]==0 and CP(i)==0 and LV[i]>0:
RETT=( 0.4*RET_sig(R_c,i)+0.3*RET_sig(R_p,i)+0.2*RET_sig(R_b,i)+0.1*RET_sig(R_B,i) ).append(RETT)
elif G[i]>0 and CP(i)>0 and LV[i]==0:
RETT=( 0.4*RET_sig(R_c,i)+0.1*RET_sig(R_p,i) +0.2*RET_sig(R_b,i)+0.3*RET_sig(R_B,i) ).append(RETT)
elif G[i]==0 and CP(i)>0 and LV[i]==0:
RETT=( 0.4*RET_sig(R_c,i)+0.2*RET_sig(R_p,i)+0.3*RET_sig(R_b,i) +0.1*RET_sig(R_B,i) ).append(RETT)
elif G[i]>0 and CP(i)==0 and LV[i]==0:
RETT=( 0.4*RET_sig(R_c,i)+0.3*RET_sig(R_p,i) +0.1*RET_sig(R_b,i)+0.2*RET_sig(R_B,i) ).append(RETT)
else:
RETT=( 0.4*RET_sig(R_c,i)+0.3*RET_sig(R_p,i)+0.2*RET_sig(R_b,i)+0.1*RET_sig(R_B,i) ).append(RETT)
return RETT
RETT1=quanzhong_fun1(R_c,R_p,R_b,R_B)
RETT1=RETT1.sort_index(axis=0)
cum1=np.cumprod(1+RETT1)
cum1=cum1.dropna()
def quanzhong_fun11(R_c,R_p,R_b,R_B):
RETT=None
for i in range(len(G)):
if G[i]>0 and CP(i)>0 and LV[i]>0:
RETT=( 0.5*RET_sig(R_c,i)+0.3*RET_sig(R_p,i) +0*RET_sig(R_b,i)+0.2*RET_sig(R_B,i) ).append(RETT)
elif G[i]==0 and CP(i)>0 and LV[i]>0:
RETT=( 0*RET_sig(R_c,i)+0.2*RET_sig(R_p,i)+0.5*RET_sig(R_b,i) +0.3*RET_sig(R_B,i) ).append(RETT)
#elif G[i]>0 and CP(i)==0 and LV[i]>0:
# RETT=( 0*RET_sig(R_c,i)+0.9*RET_sig(R_p,i) +0*RET_sig(R_b,i)+0.1*RET_sig(R_B,i) ).append(RETT)
elif G[i]==0 and CP(i)==0 and LV[i]>0:
RETT=( 0.5*RET_sig(R_c,i)+0.3*RET_sig(R_p,i)+0.2*RET_sig(R_b,i)+0*RET_sig(R_B,i) ).append(RETT)
elif G[i]>0 and CP(i)>0 and LV[i]==0:
RETT=( 0.5*RET_sig(R_c,i)+0*RET_sig(R_p,i) +0.2*RET_sig(R_b,i)+0.3*RET_sig(R_B,i) ).append(RETT)
elif G[i]==0 and CP(i)>0 and LV[i]==0:
RETT=( 0.5*RET_sig(R_c,i)+0.2*RET_sig(R_p,i)+0.3*RET_sig(R_b,i) +0*RET_sig(R_B,i) ).append(RETT)
elif G[i]>0 and CP(i)==0 and LV[i]==0:
RETT=( 0.5*RET_sig(R_c,i)+0.3*RET_sig(R_p,i) +0*RET_sig(R_b,i)+0.2*RET_sig(R_B,i) ).append(RETT)
else:
RETT=( 0.5*RET_sig(R_c,i)+0.3*RET_sig(R_p,i)+0.2*RET_sig(R_b,i)+0*RET_sig(R_B,i) ).append(RETT)
return RETT
RETT11=quanzhong_fun11(R_c,R_p,R_b,R_B)
RETT11=RETT11.sort_index(axis=0)
cum11=np.cumprod(1+RETT11)
cum11=cum11.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.close
standard_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:]])-1
plt.plot(close_base/close_base[-1],label=lab,color=col)
return close_base/close_base[-1] #standard_cum
###########################################################################
#############################策略的年化统计######################################
def Tongji(RET,cum):
RET1 = RET*100 - (4/252)
NH=(cum[-2]-1)*100*252/len(RET.index)
BD=np.std(RET)*100*np.sqrt(252)
SR=(NH-400/252)/BD
return_list=cum
MHC=((np.maximum.accumulate(return_list) - return_list) / np.maximum.accumulate(return_list)).max()*100
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( np.cumprod(1+R_B),label="一年期国债",color='g',linestyle='-')
plt.plot(cum1,label="多资产策略",color='c',linestyle='-')
plt.plot(cum11,label="避险策略",color='r',linestyle='-')
plt.plot(cum,label="单资产策略",color='m',linestyle='-')
plt.title("利率+GDP+CPI下各个策略净值走势对比图")
plt.legend()
年化收益率:66.71%:,年化夏普率:2.57,波动率为:25.30%,最大回撤:46.70%
净值走势图: