请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  量化平台 帖子:3364737 新帖:1

股票指数的宏观择时

我太难了发表于:5 月 10 日 16:04回复(1)

引言

二级市场投资的本质实际上是在于择时。例如CTA策略中的趋势交易、经典的股债轮动,更进一步的,多因子选股实际上也可以看作是对驱动股票价格运动的alpha因子和风险因子进行择时。随着市场有效性的逐步增加,择时变得越来越困难。当各类技术择时指标不再好用的时候,不妨回过头来看看宏观择时指标。技术指标通常反映投资者的情绪面因素,而宏观指标反映了整个经济体系的基本面因素。宏观择时策略本质是市场对宏观层面趋势性信息的反应长期不足,使得基于经济趋势判断的择时能够显著获取超额收益。 尤其是对于较多采用量价指标的量化投资者,宏观择时指标是一个重要的辅助判断工具,可以有效提升策略的信息广度。

本文以几类常见的宏观因子为例,介绍几种A股指数的宏观择时方法,给大家提供一些思路。一般而言,股价波动与经济增长、利率、信贷、通货膨胀、汇率等密切相关。本文主要从这五个方面指标进行择时研究。

1)PMI(经济增长)

PMI (Purchasing Managers‘ Index)采购经理人指数,是全球性的采购经理人协会通过每个月对各个国家的采购经理人发放调查问卷,了解他们对货物以及服务的需求,也就了解企业对货物和服务的需求,进而能够了解每个国家的实体经济的发展状况。PMI是一个综合指数,按照国际上通用的做法,由五个扩散指数即新订单指数(简称订单)、生产指数(简称生产)、从业PMI人员指数(简称雇员)、供应商配送时间指数(简称配送)、主要原材料库存指数(简称存货)加权而成。一般来说,PMI计算出来之后,可以与上月进行比较。如果PMI大于50,表示经济上升,反之则趋向下降。PMI指数体系在经济预测和商业分析方面都有重要的意义,已成为世界经济运行活动的重要评价指标和世界经济变化的晴雨表。

1ef6d177f37ffd15f30379a1e1e643f0

上图为我国2005年以来的PMI指数变化图,可见2018年中以来PMI逐步下行有跌破荣枯线的趋势,这正是今年宏观经济下行的写照。

每个月末会公布当月的PMI指数,可以据此对下个月的投资进行决策。

标的指数:沪深300
交易规则:PMI三月均线上行时买入指数,PMI三月均线下行时卖出指数
择时周期:月频

1ef6d177f37ffd15f30379a1e1e643f0

2)Shibor:1M(货币:利率)

上海银行间同业拆放利率(Shanghai Interbank Offered Rate,简称Shibor),从2007年1月4日开始正式运行,是由信用等级较高的银行组成报价团自主报出的人民币同业拆出利率计算确定的算术平均利率。相比反应较慢的长期利率,Shibor:1M反映了中短端利率定价,又不会像隔夜或周度利率噪音较大,是一个合适的利率指标。当资金成本过高时,股票所需资金受到压制,市场资金供给降低,大概率下跌,反之上涨。

1ef6d177f37ffd15f30379a1e1e643f0

上图为一个月Shibor走势图,与PMI走势图有一定的相似性,当PMI上行时经济逐步增长,利率水平较高;当PMI下行时经济开始衰退,利率水平较低。

标的指数:沪深300
交易规则:当Shibor:1M向下突破自己的布林带下轨时买入指数,当Shibor:1M上穿自己的布林带中轨时卖出指数
择时周期:日频

1ef6d177f37ffd15f30379a1e1e643f0

3)国债10年-国债1个月到期收益率(货币:利率-期限利差)

利率期限结构是指在某一时点上,不同期限资金的收益率与到期期限之间的关系。利率的期限结构反映了不同期限的资金供求关系。该指标与利率类似,但又不完全相同,期限利差指标反映的是相对利率,而利率指标反映的是绝对利率。

如果国债利率近似代表无风险收益率的话,那么不同期限的国债利率,其实就代表的是相应期限的实际收益率和预期的通胀率。理论上,期限长的国债可以看成是滚动持有多个短期国债,但实际上,持有长债并不完全等价于持有短债的组合,投资者的偏好和债券的供需都会带来影响,因而长债比短债收益率又多隐含了一个期限溢价。长端利率的上行放缓甚至回落反映了对未来经济增速预期的降低,是市场对于一系列经济数据综合判断的结果,自然也就和未来的衰退相关;另外,曲线趋于扁平意味着金融机构进行借短放长的收益会降低,使得银行在信贷上趋紧,抑制经济进一步扩张,从而形成了股市的利空信号。

1ef6d177f37ffd15f30379a1e1e643f0

标的指数:沪深300
交易规则:当期限利差向上突破自己的布林带上轨时买入指数,当期限利差下穿自己的布林带中轨时卖出指数
择时周期:日频

1ef6d177f37ffd15f30379a1e1e643f0

4)AAA企业债-国债到期收益率:1个月(货币:利率-信用利差)

信用利差是用以向投资者补偿基础资产违约风险的、高于无风险利率的利差。与期限利差类似,信用利差反映的也是相对利率。

我们简单的介绍一下信用利差。信用利差反映了对经济前景的预期,信用利差是总体经济状况的一个函数。信用利差在经济扩张期会下降,而在经济收缩期增加。这是因为在经济收缩期,投资者信心不足,更愿投资于高信用等级债券以回避风险,而公司由于收入下降,现金流减少,为了吸引投资者购买公司债券,发行人必须提供较高的利率,因此会产生较高的信用利差。相反,在经济扩张时期,投资者对未来发展有信心,愿意投资于信用等级较低的证券以获得较高的收益,而公司收入增加,现金流充裕,不需要通过很高的成本来吸引来自外部资金,这样就导致较低的信用利差。鉴于此,可以将信用利差作为预测经济周期活动的一个指标。

1ef6d177f37ffd15f30379a1e1e643f0

标的指数:沪深300
交易规则:当期限利差向上突破自己的布林带上轨时买入指数,当期限利差下穿自己的布林带中轨时卖出指数
择时周期:日频

1ef6d177f37ffd15f30379a1e1e643f0

5)M1与M2同比的剪刀差(货币:信贷)

事先,必须要理清相关概念。
M0:流通中现金,即在银行体系以外流通的现金;
M1:狭义货币供应量,即M0+企事业单位活期存款;
M2:广义货币供应量,即M1+企事业单位定期存款+居民储蓄存款。

在这三个层次中,M0与消费变动密切相关,是最活跃的货币;M1反映居民和企业资金松紧变化,是经济周期波动的先行指标,流动性仅次于M0;M2流动性偏弱,但反映的是社会总需求的变化和未来通货膨胀的压力状况,通常所说的货币供应量,主要指M2。

N1主要反映经济中的显示购买力,而M2不仅反映显示购买力,还反映潜在购买力。在一般情况下,M1和M2增速应当保持平衡。如果M1增速过快,则消费和终端市场活跃,就有可能从需求方角度导致商品和劳务市场的价格上涨。如果M2增速较快,则表明储蓄理财情绪较浓。当M1过高M2过低时,说明企业活期存款多,投资意愿强烈,经济扩张较快。此时企业愿意以更高的成本融资,储蓄存款之外的其他类型资产收益较高,人们往往将储蓄存款提出进行其他投资或者购买股票。

1ef6d177f37ffd15f30379a1e1e643f0

M1,M2一般在次月中上旬发布,例如2018年12月11日发布了2018年11月的数据,因此当月的择时需参考上上个月的指标。

标的指数:沪深300
交易规则:当M1-M2的三月均线上行时买入指数;当M1-M2的三月均线下行时卖出指数
择时周期:月频

1ef6d177f37ffd15f30379a1e1e643f0

6)社会融资规模:当月值(货币:信贷)

社会融资规模是指一定时期内(每月、每季或每年)实体经济从金融体系获得的全部资金总额,既包括银行体系的间接融资,又包括资本市场的债券、股票等市场的直接融资。社会融资规模是全面反映金融与经济关系,以及金融对实体经济资金支持的总量指标。社会融资总量与经济增长存在明显的相互作用、相互影响的关系。
国内信用类宏观指标,具备明显的非平滑性与季节性。(原因是国内银行通常为了季度信贷考核,将平常季中的信贷匀至季度末发放;使得部分月份的信贷冲量数据不稳定。)因此,在信贷类数据上按三月平均进行处理。

1ef6d177f37ffd15f30379a1e1e643f0

与M1,M2类似,社融数据一般也在次月中上旬发布。

标的指数:沪深300
交易规则:当社会融资规模:当月值的三月均线上行时买入指数;当社会融资规模:当月值的三月均线上行时卖出指数
择时周期:月频

1ef6d177f37ffd15f30379a1e1e643f0

7)金融机构存款准备金率(货币:信贷)

存款准备金,是指金融机构为保证客户提取存款和资金清算需要而准备的在中央银行的存款,中央银行要求的存款准备金占其存款总额的比例就是存款准备金率。存款准备金制度设置的最初目的是出于风险控制角度考虑,为了确保商业银行在遇到突然大量提取银行存款时,能有相当充足的清偿能力。后来,存款准备金制度还成为国家调节经济的重要手段。如果存款准备金率提高,就意味着吸纳的存款能够放贷出去的越少,间接性的减少了货币的供应量,反之,则意味着能够放贷出去的钱变多,间接增加货币供应量。

下图是大型机构存款准备金率与沪深300指数的关系,可见存款准备金率的变化与沪深300指数的走势的关系并非确定的。多数情况下,存款准备金率的走势与股市走势相反,例如2008年底存款准备金率下降后股市开启一番上涨,2010年底存款准备金率连番上升后,股市进入了两年多的慢熊市。而2006年底开始的存款准备金率上涨并没有阻碍2007年股市牛市的发生,2018年4月的降准也没有阻止2018年一年的不断下挫。通过单独的存款准备金率变化是难以对股市走势做出判断的,但总的来说降准对A股市场是一个积极的信号。

1ef6d177f37ffd15f30379a1e1e643f0

标的指数:沪深300
交易规则:当大型机构存款准备金率小于半年前时持有指数,否则空仓。
择时周期:日频

1ef6d177f37ffd15f30379a1e1e643f0

8)USDCNH:即期汇率(汇率)

对于发达经济体而言,汇率与股市在多数情况下呈现出了负相关的关系。一般而言,汇率贬值反而容易刺激股市上涨。这背后的逻辑可能在于,发达市场大多数企业有大量的海外收入,汇率贬值有利于企业盈利改善,此外这些市场大多存在大量的海外投资者参与,汇率贬值意味着外币可以获取更多的本币资产,有利于吸引海外资金继续进入本国市场。

对于多数新兴经济体而言,汇率波动往往与国内资产价格呈现出正相关关系,也就是说汇率贬值对于国内股市而言并不是一件好事。对于海外投资者而言,新兴经济体股市往往是一种风险更高的资产,因此对其投资意愿在一定程度上取决于其国内经济与金融体系的稳健性,而汇率预期也体现出了市场对于经济体稳健性的预期。如果国内外经济条件发生变化,导致汇率贬值,一方面会影响市场风险偏好,另一方面可能引起货币政策的收紧,造成国内证券市场的下跌。

1ef6d177f37ffd15f30379a1e1e643f0

标的指数:沪深300
交易规则:当M1-M2的三月均线上行时买入指数;当M1-M2的三月均线下行时卖出指数并买入无风险资产(无风险收益年化3%)
择时周期:日频

1ef6d177f37ffd15f30379a1e1e643f0

9)PPI与CPI同比的剪刀差(通货膨胀)

CPI:消费者物价指数(Consumer Price Index,简称CPI)反映与居民生活有关的产品及劳务价格统计出来的物价变动指标,通常作为观察通货膨胀水平的重要指标。
PPI:生产者物价指数(Producer Price Index, PPI)是用来衡量生产者在生产过程中,所需采购品的物价状况,是CPI的先声。
通胀与经济的关系较为复杂,温和的通胀水平(通常在2%~3%)可以刺激经济的发展;过高的通胀水平(通常在5%以上),会使人们对货币的信心产生动摇,经济社会产生动荡;而过低的通胀甚至通缩又会抑制经济的发展。单独的通胀指数与股市走势并非一个线性的关系,对于预测股市而言,PPI与CPI同比的剪刀差是一个相对合适的指标。PPI与CPI同比剪刀差的含义是上游工业品与下游消费品的价格差。对于上游企业来说(上游工业品是上游企业的产出),PPI-CPI的扩大意味着利润增加,而对于下游企业来说(上游工业品是下游企业的原材料),PPI-CPI的扩大意味着利润减少,从这个角度来看,PPI-CPI对股市的影响是模糊的。根据郭于玮(兴业研究)的研究表明,PPI与CPI剪刀差收窄后可能触发货币政策调整,进而带来无风险利率的下行和风险偏好的改善,从而使得PPI与CPI剪刀差对利率和信用利差具有一定的领先型。

1ef6d177f37ffd15f30379a1e1e643f0

进一步的,无风险利率的下行和风险偏好的改善对于股市的复苏带来利好。因此,可以尝试基于PPI与CPI剪刀差的走势对A股的走势做出预测信号。

CPI、PPI指标在次月中上旬发布,因此当月的择时需参考上上个月的指标。

标的指数:沪深300
交易规则:当PPI-CPI的三月均线下行时买入指数;当PPI-CPI的三月均线上行时卖出指数(注:当CPI三月均线大于5时认为通胀较高,直接卖出指数,当CPI三月均线小于0时认为处于通缩,也直接卖出指数)
择时周期:月频

1ef6d177f37ffd15f30379a1e1e643f0

指标汇总

前文从宏观经济的五大角度(经济增长、利率、信贷、通货膨胀、汇率),九个细分指标对A股进行了择时策略的研究。总的来看,单个指标的择时效果并不是太理想。而且对单个指标进行过度调参很容易陷入到过拟合的陷阱中。我们参考宏观分析领域交叉验证的思想,对五类择时指标进行汇总打分(初步的,我们认为这五个角度的分值占比相同,均占比20%),然后根据总得分做出具体的仓位决策。其中利率类和信贷类的打分,按照细分指标等权相加得到。
前文中利率类指标及存款准备金率的择时周期为日频,其余指标的择时周期均为月频,为方便起见,我们统一为月频调仓,利率类指标及存款准备金率的月度择时信号均参照上月最后一天的日度信号。

当大多数指标发出看多信号,即可进行买入操作,大部分指标发出看空信号,即可进行卖出操作。因此,我们进行了如下划分,当汇总得分小于0.45时仓位为0%,当汇总得分大于0.55时仓位为100%,中间状态的仓位为50%,2007.1-2018.11回测效果如下。

1ef6d177f37ffd15f30379a1e1e643f0

宏观综合择时策略的夏普率为0.74,年化收益率为15.69%,相比各单类择时指标有着显著提升。

回顾十多年来我国经济的发展,可以发现国内经济显著受信贷周期驱动,另外信贷体量(M1,M2,社融等指标)也是国内特殊的数量型货币政策色彩背景下非常重要的中介目标变量,对未来经济发展与货币政策制定有着重要参考意义。因此,我们尝试在汇总指标中调节了信贷指标的权重,将其增大一倍,回测效果如下。

1ef6d177f37ffd15f30379a1e1e643f0

加大信贷系数权重之后的宏观择时策略夏普率为0.82,年化收益为17.68%,相比等权重宏观指标择时策略,在收益率与风险调整收益上均有一定提升。

2019年1月4日央行再一次发布了降准公告,金融机构存款准备金率将于2019年1月15日和1月25日分别下调0.5个百分点,为了估计降准对宏观择时的影响,我们将降准指标纳入到上面的指标体系中。由于存款准备金率的变动是一个低频信号,不能作为常规的信号源,因此我们将该指标作为一个额外加分项合并到信贷类指标中(权重暂定为0.3分,当信贷指标总分值超过1分时设置为1分)。考虑降准指标后,策略夏普率从0.82增加到0.86,年化收益从17.68%上升到18.87%,可见总的来说降准对A股未来几个月的行情是一个积极信号。

df_credit_loan = ((df_credit_loan_1['position']*1 df_credit_loan_2['position']*1)/2.)*1
df_credit_loan = df_credit_loan   df_reserves_M*0.3
df_credit_loan[df_credit_loan>1] = 1
#信贷择时指标=M1,M2剪刀差 社融指标 降准

1ef6d177f37ffd15f30379a1e1e643f0

附:数据与代码相关

宏观数据下载地址为:链接: https://pan.baidu.com/s/1-bUK1_ek3ZFBbIWL-RYtHA 提取码: 6xij
下载后将数据与代码放在研究环境中Macro文件夹中即可运行。

from jqdata import *
import numpy as np
import pandas as pd
import datetime as dt
from six import StringIO
from dateutil.parser import parse
import cPickle as pickle
import seaborn as sns
import matplotlib as mpl
import os
import statsmodels.api as sm
import scipy
import talib as tl


mpl.rcParams['font.family']='serif'
mpl.rcParams['axes.unicode_minus']=False # 处理负号

load_data={}

path = '/home/jquser/Macro'

class backtest_result():
    def __init__(self,data):
        self.data = data
        self.total_returns = data.iloc[-1]-1
        self.annualized_returns = data.iloc[-1]**(12./len(data))-1
        self.annualized_volatility = data.pct_change().std()*(12.**0.5)
    def Max_Drawback(self):
        net_value=self.data
        max_value=0
        df_tmp=pd.DataFrame(net_value)
        df_tmp.columns=['value']
        for j in range(0,len(net_value),1):
            max_value=max(max_value,df_tmp.ix[j,'value'])
            df_tmp.ix[j,'drawback']=1-df_tmp.ix[j,'value']/max_value
            drawback=df_tmp['drawback'].max()
        return drawback
    def Sharpe(self):
        net_value=self.data
        bench_pct=0.03
        df_tmp=pd.DataFrame(net_value)
        df_tmp.columns=['value']
        df_tmp['pct']=df_tmp['value'].pct_change()
        annual_pct = df_tmp.ix[-1,'value']**(12./len(df_tmp))-1
        sharpe = (annual_pct-bench_pct)/(df_tmp['pct'].std()*12**0.5)
        return sharpe
    def Calmar(self):
        clamar = self.annualized_returns/self.Max_Drawback()
        return clamar
#PMI择时
body=read_file(path+'/PMI组合.xls')
df_boom=pd.read_excel(StringIO(body))
print df_boom.columns
col =u'PMI'
df_boom=df_boom.set_index(u'日期')
df_boom.plot(figsize=(15,6),title='PMI')
n=3
df_boom['position']=(pd.rolling_mean(df_boom[col],n).shift(1)>pd.rolling_mean(df_boom[col],n).shift(2))*1.
prices = get_price('000300.XSHG',start_date='2006-01-01',end_date='2018-11-30',fields='close')['close']
prices_M = prices.resample('M',how='last')
rate_riskfree = 0
df_pct=pd.DataFrame()
df_pct['pct']=prices_M.pct_change()
df_pct['position']=df_boom['position']
df_pct['net_value'] =(df_pct['pct']+1).cumprod()
df_pct['net_value_timing'] = (df_pct['pct']*df_pct['position']+rate_riskfree*(1-df_pct['position'])+1).cumprod()
df_pct[['net_value','net_value_timing']].plot(figsize=(15,6),title='PMI择时')
Index([u'日期', u'PMI', u'PMI:生产', u'PMI:新订单', u'PMI:新出口订单', u'PMI:进口'], dtype='object')
<matplotlib.axes._subplots.AxesSubplot at 0x7f609328a210>
#利率择时
body=read_file(path+'/SHIBOR数据.xls')
df_interest=pd.read_excel(StringIO(body))
col = u'SHIBOR:1个月'
df_interest=df_interest.set_index(u'日期')

df_interest.iloc[:,1:2].plot(figsize=(15,6),title='SHIBOR')
df_interest=df_interest[[col]]
upperband,middleband,lowerband = (tl.BBANDS(df_interest[col].values, timeperiod=12, nbdevup=1.8, nbdevdn=1.8))
# print df_1

df_interest['BBAND_upper']=upperband
df_interest['BBAND_middle']=middleband
df_interest['BBAND_lower']=lowerband

pre_position = 0
for date in df_interest.index:
    if df_interest.loc[date,col]>df_interest.loc[date,'BBAND_middle']:
        df_interest.loc[date,'position']=0
    elif df_interest.loc[date,col]<df_interest.loc[date,'BBAND_lower']:
        df_interest.loc[date,'position']=1.0
    else:
        df_interest.loc[date,'position']=pre_position
    pre_position=df_interest.loc[date,'position']
df_interest['position']=df_interest['position'].shift(1)

df_pct=pd.DataFrame()
prices = get_price('000300.XSHG',start_date='2005-01-01',end_date='2018-11-30',fields='close')['close']
df_pct['pct']=prices.pct_change()

rate_riskfree = 0
df_pct = pd.concat([df_pct,df_interest],axis=1)['2006-01-01':'2018-11-30'].dropna()
df_pct['net_value'] =(df_pct['pct']+1).cumprod()
df_pct['net_value_timing'] = (df_pct['pct']*df_pct['position']+rate_riskfree*(1-df_pct['position'])+1).cumprod()
df_pct[['net_value','net_value_timing']].plot(figsize=(15,6),title='SHIBOR:1M择时')
# df_pct
# df_1['2007-01-01':'2018-11-30'].iloc[:1000].plot(figsize=(15,10))
# print backtest_result(df_pct['net_value_timing']).Sharpe()
<matplotlib.axes._subplots.AxesSubplot at 0x7f6092e64fd0>
#获取国债期限利差数据
body=read_file(path+'/国债到期收益率.xls')
df_gz=pd.read_excel(StringIO(body))
df_gz.set_index(u'日期',inplace=True)
print df_gz.columns
df_gz=df_gz.fillna(method='ffill')
term_spread_gz = df_gz[u'中债国债到期收益率:10年']-df_gz[u'中债国债到期收益率:1个月']
term_spread_gz_diff = term_spread_gz.diff(21)
term_spread_gz=pd.rolling_mean(term_spread_gz,1)
term_spread_gz.plot(figsize=(15,6),title='10年-1年国债期限利差')
Index([u'中债国债到期收益率:1个月', u'中债国债到期收益率:3个月', u'中债国债到期收益率:6个月',  u'中债国债到期收益率:3年',
        u'中债国债到期收益率:5年', u'中债国债到期收益率:10年'],
      dtype='object')
<matplotlib.axes._subplots.AxesSubplot at 0x7f6091d180d0>
#期限利差择时
df_termspread=pd.DataFrame()
col='termspread'
df_termspread=term_spread_gz.to_frame('termspread')
upperband,middleband,lowerband = (tl.BBANDS(df_termspread[col].values, timeperiod=25, nbdevup=1.8, nbdevdn=1.8))
# print df_termspread

df_termspread['BBAND_upper']=upperband
df_termspread['BBAND_middle']=middleband
df_termspread['BBAND_lower']=lowerband
# df_termspread
df_termspread.head()
pre_position = 0
for date in df_termspread.index:
    if df_termspread.loc[date,col]<df_termspread.loc[date,'BBAND_middle']:
        df_termspread.loc[date,'position']=0
    elif df_termspread.loc[date,col]>df_termspread.loc[date,'BBAND_upper']:
        df_termspread.loc[date,'position']=1.0
    else:
        df_termspread.loc[date,'position']=pre_position
    pre_position=df_termspread.loc[date,'position']
df_termspread['position']=df_termspread['position'].shift(1)
df_termspread.head().append(df_termspread.tail())

df_pct=pd.DataFrame()
prices = get_price('000300.XSHG',start_date='2005-01-01',end_date='2018-11-30',fields='close')['close']
df_pct['pct']=prices.pct_change()

rate_riskfree = 0
df_pct = pd.concat([df_pct,df_termspread],axis=1)['2007-01-01':'2018-11-30'].dropna()
df_pct['net_value'] =(df_pct['pct']+1).cumprod()
df_pct['net_value_timing'] = (df_pct['pct']*df_pct['position']+rate_riskfree*(1-df_pct['position'])+1).cumprod()
df_pct[['net_value','net_value_timing']].plot(figsize=(15,6),title='国债期限利差择时')
<matplotlib.axes._subplots.AxesSubplot at 0x7f6092926f90>
#获取信用利差数据
body=read_file(path+'/企业债到期收益率(AAA).xls')
df_qyz=pd.read_excel(StringIO(body))
df_qyz.set_index(u'日期',inplace=True)
df_qyz=df_qyz.fillna(method='ffill')

credit_spread = df_qyz[u'中债企业债到期收益率(AAA):1个月']-df_gz[u'中债国债到期收益率:1个月']

credit_spread=pd.rolling_mean(credit_spread,1)
credit_spread['2006-01-01':].plot(figsize=(15,6),title='AAA企业债信用利差:1个月')
<matplotlib.axes._subplots.AxesSubplot at 0x7f607e806b90>
#信用利差择时
df_creditspread=pd.DataFrame()
col='creditspread'
df_creditspread=credit_spread.to_frame('creditspread')
upperband,middleband,lowerband = (tl.BBANDS(df_creditspread[col].values, timeperiod=25, nbdevup=1.8, nbdevdn=1.8))

df_creditspread['BBAND_upper']=upperband
df_creditspread['BBAND_middle']=middleband
df_creditspread['BBAND_lower']=lowerband
pre_position = 0
for date in df_creditspread.index:
    if df_creditspread.loc[date,col]>df_creditspread.loc[date,'BBAND_middle']:
        df_creditspread.loc[date,'position']=0
    elif df_creditspread.loc[date,col]<df_creditspread.loc[date,'BBAND_lower']:
        df_creditspread.loc[date,'position']=1.0
    else:
        df_creditspread.loc[date,'position']=pre_position
    pre_position=df_creditspread.loc[date,'position']
df_creditspread['position']=df_creditspread['position'].shift(1)

df_pct=pd.DataFrame()
prices = get_price('000300.XSHG',start_date='2005-01-01',end_date='2018-11-30',fields='close')['close']
df_pct['pct']=prices.pct_change()

rate_riskfree =0
df_pct = pd.concat([df_pct,df_creditspread],axis=1)['2007-01-01':'2018-11-30'].dropna()
df_pct['net_value'] =(df_pct['pct']+1).cumprod()
df_pct['net_value_timing'] = (df_pct['pct']*df_pct['position']+rate_riskfree*(1-df_pct['position'])+1).cumprod()
df_pct[['net_value','net_value_timing']].plot(figsize=(15,6),title='信用利差择时')
<matplotlib.axes._subplots.AxesSubplot at 0x7f607e981e50>
#M1,M2剪刀差择时
body=read_file(path+'/信贷.xls')
df_credit_loan_1=pd.read_excel(StringIO(body))
df_credit_loan_1=df_credit_loan_1.set_index(u'日期')
print df_credit_loan_1.columns
col = u'社会融资规模:当月值'
col_1 = u'M1:同比'
col_2 = u'M2:同比'
# col = col_1
col = u'M1-M2'
df_credit_loan_1[u'M1-M2'] = df_credit_loan_1[u'M1:同比']-df_credit_loan_1[u'M2:同比']
n=3
df_credit_loan_1.iloc[:,1:].plot(figsize=(15,6),title='M1,M2及剪刀差')
df_credit_loan_1['position']=pd.rolling_mean(df_credit_loan_1[col],n).shift(2)>pd.rolling_mean(df_credit_loan_1[col],n).shift(3)
prices = get_price('000300.XSHG',start_date='2005-01-01',end_date='2018-11-30',fields='close')['close']
prices_M = prices.resample('M',how='last')

rate_riskfree = 0#(1+1.25e-4)**21.0-1

df_pct=pd.DataFrame()
df_pct['pct']=prices_M.pct_change()
df_pct['position']=df_credit_loan_1['position']
df_pct['net_value'] =(df_pct['pct']+1).cumprod()
df_pct['net_value_timing'] = (df_pct['pct']*df_pct['position']+rate_riskfree*(1-df_pct['position'])+1).cumprod()
df_pct[['net_value','net_value_timing']].plot(figsize=(15,6),title='M1,M2剪刀差择时')
Index([u'社会融资规模:当月值', u'M1:同比', u'M2:同比'], dtype='object')
<matplotlib.axes._subplots.AxesSubplot at 0x7f607e5e7910>
#社融择时
body=read_file(path+'/信贷.xls')
df_credit_loan_2=pd.read_excel(StringIO(body))
df_credit_loan_2=df_credit_loan_2.set_index(u'日期')
print df_credit_loan_2.columns
col = u'社会融资规模:当月值'
col_1 = u'M1:同比'
col_2 = u'M2:同比'
n=3
pd.rolling_mean(df_credit_loan_2.iloc[:,:1],1)['2005-01-01':].plot(figsize=(15,6),title='社融规模:当月值')
df_credit_loan_2['position']=pd.rolling_mean(df_credit_loan_2[col],n).shift(2)>pd.rolling_mean(df_credit_loan_2[col],n).shift(3)
prices = get_price('000300.XSHG',start_date='2005-01-01',end_date='2018-12-07',fields='close')['close']
prices_M = prices.resample('M',how='last')

rate_riskfree = 0#(1+1.25e-4)**21.0-1

df_pct=pd.DataFrame()
df_pct['pct']=prices_M.pct_change()
df_pct['position']=df_credit_loan_2['position']
df_pct['net_value'] =(df_pct['pct']+1).cumprod()
df_pct['net_value_timing'] = (df_pct['pct']*df_pct['position']+rate_riskfree*(1-df_pct['position'])+1).cumprod()
df_pct[['net_value','net_value_timing']].plot(figsize=(15,6),title='社融择时')
Index([u'社会融资规模:当月值', u'M1:同比', u'M2:同比'], dtype='object')
<matplotlib.axes._subplots.AxesSubplot at 0x7f607e949d50>
#存款准备金择时
body=read_file(path+'/存款准备金率-大型存款类机构.xls')
df_reserves=pd.read_excel(StringIO(body))
df_reserves = df_reserves.set_index(u'日期')
df_reserves
col=u'人民币存款准备金率:大型存款类金融机构'
df_pct=pd.DataFrame()
prices = get_price('000300.XSHG',start_date='2006-01-01',end_date='2018-11-30',fields='close')['close']
prices_M = prices.resample('M',how='last')
df_pct['pct']=prices.pct_change()
df_pct
rate_riskfree=0
# df_reserves['position']=df_reservesdf_reserves
df_reserves=df_reserves.reindex(prices.index).fillna(method='ffill')
# df_reserves[col].plot(figsize=(15,6))
# df_reserves['position'].plot(figsize=(15,6))
fig = plt.figure(figsize=(15,6))
# fig = plt.grid(False)
ax1=fig.add_subplot(111)
ax1.plot(df_reserves[col],'y-',linewidth=2,label='大型机构存款准备金率')
ax1.legend(loc=2,fontsize=12)
ax2=ax1.twinx()#这是双坐标关键一步
ax2.plot(prices,'b-',linewidth=2,label='沪深300指数')
ax2.legend(loc=1,fontsize=12)
# ax1.grid(False)
ax2.grid(False)
plt.show()

pre_position=0
delay_days=120
for i in range(delay_days,len(df_reserves)):
    pre_index = df_reserves.index[i-delay_days]
    index = df_reserves.index[i]
#     print df_reserves.loc[index,col]
    if df_reserves.loc[index,col]<df_reserves.loc[pre_index,col]:
        df_reserves.loc[index,'position']=1
    elif df_reserves.loc[index,col]>df_reserves.loc[pre_index,col]:
        df_reserves.loc[index,'position']=0.
    else:
        df_reserves.loc[index,'position']=0.
    pre_position = df_reserves.loc[index,'position']
df_pct['position'] = df_reserves['position']
df_pct['net_value'] =(df_pct['pct']+1).cumprod()
df_pct['net_value_timing'] = (df_pct['pct']*df_pct['position']+rate_riskfree*(1-df_pct['position'])+1).cumprod()
df_pct[['net_value','net_value_timing']].plot(figsize=(15,6),title='存款准备金择时')
<matplotlib.axes._subplots.AxesSubplot at 0x7f607e15ef50>
#USDCNH:即期汇率择时
body=read_file(path+'/离岸汇率数据.xls')
df_exchange_rate=pd.read_excel(StringIO(body))
col = u'USDCNH:即期汇率'
df_exchange_rate=df_exchange_rate.set_index(u'日期')
df_exchange_rate.plot(figsize=(15,6),title='USDCNH:即期汇率')

upperband,middleband,lowerband = (tl.BBANDS(df_exchange_rate[col].values, timeperiod=25, nbdevup=1.8, nbdevdn=1.8))
df_exchange_rate['BBAND_upper']=upperband
df_exchange_rate['BBAND_middle']=middleband
df_exchange_rate['BBAND_lower']=lowerband
df_exchange_rate.head()
pre_position = 0
for date in df_exchange_rate.index:
    if df_exchange_rate.loc[date,col]>df_exchange_rate.loc[date,'BBAND_middle']:
        df_exchange_rate.loc[date,'position']=0
    elif df_exchange_rate.loc[date,col]<df_exchange_rate.loc[date,'BBAND_lower']:
        df_exchange_rate.loc[date,'position']=1.0
    else:
        df_exchange_rate.loc[date,'position']=pre_position
    pre_position=df_exchange_rate.loc[date,'position']
df_exchange_rate['position']=df_exchange_rate['position'].shift(1)
df_exchange_rate.head().append(df_exchange_rate.tail())

df_pct=pd.DataFrame()
prices = get_price('000300.XSHG',start_date='2005-01-01',end_date='2018-12-07',fields='close')['close']
df_pct['pct']=prices.pct_change()
df_pct = pd.concat([df_pct,df_exchange_rate],axis=1)['2007-01-01':'2018-11-30'].dropna()
df_pct['net_value'] =(df_pct['pct']+1).cumprod()
df_pct['net_value_timing'] = (df_pct['pct']*df_pct['position']+rate_riskfree*(1-df_pct['position'])+1).cumprod()
df_pct[['net_value','net_value_timing']].plot(figsize=(15,6),title='USDCNH:即期汇率择时')
<matplotlib.axes._subplots.AxesSubplot at 0x7f607e0832d0>
#通胀指数择时
body=read_file(path+'/CPI与PPI.xls')
df_inflation=pd.read_excel(StringIO(body))
print df_inflation.columns
col_0 =u'CPI:当月同比'
col_1 =u'PPI:全部工业品:当月同比'
df_inflation=df_inflation.set_index(u'日期')['2005-01-31':]
col_2 = u'PPI-CPI'
df_inflation[col_2] = -df_inflation[u'CPI:当月同比']+df_inflation[u'PPI:全部工业品:当月同比']
df_inflation[[col_0,col_1,col_2]].plot(figsize=(15,6))
def good_cpi(x):
    if x<0:
        y=0.
    elif x<5.:
        y=1.
    else:
        y=0
    return y
    
n=3
df_inflation['position']=(pd.rolling_mean(df_inflation[col_2],n).shift(2)<pd.rolling_mean(df_inflation[col_2],n).shift(3))*\
    (pd.rolling_mean(df_inflation[col_0],n).apply(good_cpi).shift(2))

prices = get_price('000300.XSHG',start_date='2006-01-01',end_date='2018-11-30',fields='close')['close']
prices_M = prices.resample('M',how='last')
rate_riskfree = 0#(1+1.25e-4)**20.0-1
df_pct=pd.DataFrame()
df_pct['pct']=prices_M.pct_change()
df_pct['position']=df_inflation['position']
df_pct['net_value'] =(df_pct['pct']+1).cumprod()
df_pct['net_value_timing'] = (df_pct['pct']*df_pct['position']+rate_riskfree*(1-df_pct['position'])+1).cumprod()
df_pct[['net_value','net_value_timing']].plot(figsize=(15,6),title='PPI,CPI剪刀差择时')
Index([u'日期', u'CPI:当月同比', u'预测平均值:CPI:当月同比', u'PPI:全部工业品:当月同比',
       u'预测平均值:PPI:当月同比'],
      dtype='object')
<matplotlib.axes._subplots.AxesSubplot at 0x7f607e036f90>
def dateRange(beginDate, endDate):
    dates = []
    dt=beginDate
    date = beginDate
    while date <= endDate:
        dates.append(date)
        dt = dt + datetime.timedelta(1)
        date = dt
    return dates
date_list = dateRange(prices_M.index[0],prices_M.index[-1])
len(date_list)
4687
#汇总以上宏观指标
df_interest_M = df_interest['position'].reindex(date_list).fillna(method='ffill').reindex(prices_M.index).shift(1)
#利率
df_termspread_M = df_termspread['position'].reindex(date_list).fillna(method='ffill').reindex(prices_M.index).shift(1)
#期限利差
df_creditspread_M = df_creditspread['position'].reindex(date_list).fillna(method='ffill').reindex(prices_M.index).shift(1)
#信用利差
df_monetray = ((df_interest_M*1 + df_termspread_M*1 + df_creditspread_M*1)/3.)*1
#货币政策择时指标=利率+期限利差+信用利差
df_forex = (df_exchange_rate['position'].reindex(date_list).fillna(method='ffill').reindex(prices_M.index).shift(1))
#汇率

df_credit_loan = ((df_credit_loan_1['position']*1+df_credit_loan_2['position']*1)/2.)*1
#信贷择时指标=M1,M2剪刀差+社融指标

df_month=pd.concat([df_monetray,df_forex,df_credit_loan,\
                  df_boom['position'],df_inflation['position']],axis=1)
factor_columns = ['monetary','forex','credit','boom','inflation']#货币政策,汇率,信贷,经济增长,通货膨胀
df_month.columns = factor_columns
weight_f=([1,1,1,1,1]) #五大类指标权重
timing_count=((df_month[factor_columns]>=0)*weight_f).sum(axis=1)
#每一期(月度)的满分(由于早期有些指标为NAN,因此满分不为1)
df_month['tot_pos'] = ((df_month[factor_columns]*weight_f).sum(axis=1)/timing_count>0.55)*0.5+\
    ((df_month[factor_columns]*weight_f).sum(axis=1)/timing_count>0.45)*0.5
#根据每一期得分占满分的比例做出仓位决策
prices = get_price('000300.XSHG',start_date='2006-01-01',end_date='2018-11-30',fields='close')['close']
prices_M = prices.resample('M',how='last')
rate_riskfree = 0
df_pct=pd.DataFrame()
start_date='2007-01-01'
df_pct['pct']=prices_M.pct_change()[start_date:]
df_pct['position']=df_month['tot_pos']
df_pct['net_value'] =(df_pct['pct']+1)[start_date:].cumprod()
df_pct['net_value_timing'] = (df_pct['pct']*df_pct['position']+rate_riskfree*(1-df_pct['position'])+1)[start_date:].cumprod()
df_pct[['net_value','net_value_timing']].plot(figsize=(15,6),title='宏观指标综合择时(信贷系数=1)')
print backtest_result(df_pct['net_value_timing']).Max_Drawback()#最大回撤
print backtest_result(df_pct['net_value_timing']).Sharpe()#夏普率
print backtest_result(df_pct['net_value_timing']).annualized_returns#年化收益
0.155687136332
0.743063645005
0.15687538484
#汇总以上宏观指标
df_interest_M = df_interest['position'].reindex(date_list).fillna(method='ffill').reindex(prices_M.index).shift(1)
#利率
df_termspread_M = df_termspread['position'].reindex(date_list).fillna(method='ffill').reindex(prices_M.index).shift(1)
#期限利差
df_creditspread_M = df_creditspread['position'].reindex(date_list).fillna(method='ffill').reindex(prices_M.index).shift(1)
#信用利差
df_monetray = ((df_interest_M*1 + df_termspread_M*1 + df_creditspread_M*1)/3.)*1
#货币政策择时指标=利率+期限利差+信用利差
df_forex = (df_exchange_rate['position'].reindex(date_list).fillna(method='ffill').reindex(prices_M.index).shift(1))
#汇率

df_credit_loan = ((df_credit_loan_1['position']*1+df_credit_loan_2['position']*1)/2.)*1
#信贷择时指标=M1,M2剪刀差+社融指标

df_month=pd.concat([df_monetray,df_forex,df_credit_loan,\
                  df_boom['position'],df_inflation['position']],axis=1)
factor_columns = ['monetary','forex','credit','boom','inflation']#货币政策,汇率,信贷,经济增长,通货膨胀
df_month.columns = factor_columns
weight_f=([1,1,2,1,1]) #五大类指标权重
timing_count=((df_month[factor_columns]>=0)*weight_f).sum(axis=1)
#每一期(月度)的满分(由于早期有些指标为NAN,因此满分不为1)
df_month['tot_pos'] = ((df_month[factor_columns]*weight_f).sum(axis=1)/timing_count>0.55)*0.5+\
    ((df_month[factor_columns]*weight_f).sum(axis=1)/timing_count>0.45)*0.5
#根据每一期得分占满分的比例做出仓位决策
prices = get_price('000300.XSHG',start_date='2006-01-01',end_date='2018-11-30',fields='close')['close']
prices_M = prices.resample('M',how='last')
rate_riskfree = 0
df_pct=pd.DataFrame()
start_date='2007-01-01'
df_pct['pct']=prices_M.pct_change()[start_date:]
df_pct['position']=df_month['tot_pos']
df_pct['net_value'] =(df_pct['pct']+1)[start_date:].cumprod()
df_pct['net_value_timing'] = (df_pct['pct']*df_pct['position']+rate_riskfree*(1-df_pct['position'])+1)[start_date:].cumprod()
df_pct[['net_value','net_value_timing']].plot(figsize=(15,6),title='宏观指标综合择时(信贷系数=2)')
print backtest_result(df_pct['net_value_timing']).Max_Drawback()#最大回撤
print backtest_result(df_pct['net_value_timing']).Sharpe()#夏普率
print backtest_result(df_pct['net_value_timing']).annualized_returns#年化收益
0.200432996889
0.818573247619
0.175762517663
#汇总以上宏观指标
df_interest_M = df_interest['position'].reindex(date_list).fillna(method='ffill').reindex(prices_M.index).shift(1)
#利率
df_termspread_M = df_termspread['position'].reindex(date_list).fillna(method='ffill').reindex(prices_M.index).shift(1)
#期限利差
df_creditspread_M = df_creditspread['position'].reindex(date_list).fillna(method='ffill').reindex(prices_M.index).shift(1)
#信用利差
df_reserves_M = df_reserves['position'].reindex(date_list).fillna(method='ffill').reindex(prices_M.index).shift(1)
df_monetray = ((df_interest_M*1 + df_termspread_M*1 + df_creditspread_M*1)/3.)*1

# df_monetray = ((df_interest_M*1 + df_termspread_M*1 + df_creditspread_M*1)/3.)*1 + df_reserves_M*0.33

df_monetray[df_monetray>1]=1

# df_monetray = ((df_interest_M*1 + df_termspread_M*1 + df_creditspread_M*1)/3.)*1
#货币政策择时指标=利率+期限利差+信用利差
df_forex = (df_exchange_rate['position'].reindex(date_list).fillna(method='ffill').reindex(prices_M.index).shift(1))
#汇率


df_credit_loan = ((df_credit_loan_1['position']*1+df_credit_loan_2['position']*1)/2.)*1 
df_credit_loan = df_credit_loan + df_reserves_M*0.3
df_credit_loan[df_credit_loan>1]=1
#信贷择时指标=M1,M2剪刀差+社融指标+降准


df_month=pd.concat([df_monetray,df_forex,df_credit_loan,\
                  df_boom['position'],df_inflation['position']],axis=1)
factor_columns = ['monetary','forex','credit','boom','inflation']#货币政策,汇率,信贷,经济增长,通货膨胀
df_month.columns = factor_columns
weight_f=([1,1,2,1,1]) #五大类指标权重,增大信贷指标的权重
timing_count=((df_month[factor_columns]>=0)*weight_f).sum(axis=1)
#每一期(月度)的满分(由于早期有些指标为NAN,因此满分不为1)
df_month['tot_pos'] = ((df_month[factor_columns]*weight_f).sum(axis=1)/timing_count>0.55)*0.5+\
    ((df_month[factor_columns]*weight_f).sum(axis=1)/timing_count>0.45)*0.5
#根据每一期得分占满分的比例做出仓位决策
prices = get_price('000300.XSHG',start_date='2006-01-01',end_date='2018-11-30',fields='close')['close']
prices_M = prices.resample('M',how='last')
rate_riskfree = 0
df_pct=pd.DataFrame()
start_date='2007-01-01'
df_pct['pct']=prices_M.pct_change()[start_date:]
df_pct['position']=df_month['tot_pos']
df_pct['net_value'] =(df_pct['pct']+1)[start_date:].cumprod()
df_pct['net_value_timing'] = (df_pct['pct']*df_pct['position']+rate_riskfree*(1-df_pct['position'])+1)[start_date:].cumprod()
df_pct[['net_value','net_value_timing']].plot(figsize=(15,6),title='宏观指标综合择时(信贷系数=2),考虑降准')
print backtest_result(df_pct['net_value_timing']).Max_Drawback()#最大回撤
print backtest_result(df_pct['net_value_timing']).Sharpe()#夏普率
print backtest_result(df_pct['net_value_timing']).annualized_returns#年化收益
0.200432996889
0.859588035117
0.188686503713

全部回复

0/140

量化课程

    移动端课程