一、动量策略的一点历史
1.1 三大互补选股维度
1、Momentum:当价格沿着过去的轨迹继续运动时,我们能够获得收益;
2、Value:当价格恢复到之前的某种均衡状态时,我们能够获得收益;
3、Carry:当价格不发生变化时,我们能够获得收益。
注:假如我们买入一支股票并一直持有,如果股票价格不变,那么我们获得的收益就是该股票的分红。股息率(diviedend yield)就是Carry收益率。
1.2 动量策略的发展1967年,Robert Levy在Journal of Finance 发表了Relative Strength as a Criterion for Investment Selection 的文章(当年动量一词还未被造出);
1970s开始,有效市场假说(EMH)被提出并成为主流;动量现象的研究被极大地抑制。随着人们对市场理解的加深以及价值投资的巨大成功,EMH不再权威,但动量任然被认为是‘一种黑色艺术、一种巫术魔力’;
1993年,Jegadeesh和Titman在Journal of Finance 发表了一篇里程碑式的文章,题为Return to Buying Winners and Selling Losers:Implications for Stock Market Efficiency;
2008年,EMH之父Eugene Fama在美国金融协会的采访中承认了动量的存在;
2013年,Asness等人在Journal of Finance 发表了影响深远的Value and Momentum Everywhere。
1.3 Momentum和Value无处不在(Q1:下图哪里体现了呢?)
二、基础版动量策略
2.1 策略出发点
1、在中国股市中,反转强于动量,且海外流行的动量选股方法(即使用t-12月到t-1月之间的收益率选股)并不好使。
2、在构造动量因子时,应该注意其在市值因子上的暴露。(Q2:什么意思啊?)
2.2 构造动量因子
使用过去60个交易日风险调整后的涨跌幅作为动量因子(它和市值因子的相关性仅0.085),其计算公式如下所示:
60−3000∗ ∗ (Q3:3000是什么)
其中 60为60日涨跌幅,即60个交易日内的收益率; 为60个交易日内收益率的标准差,代表风险。
2.3 策略思想
1、回测期:2009年1月1日至2018年9月12日;
2、调仓日:按月调仓,每月末按收盘价买卖股票;
3、股票池:中证500成分股;剔除ST股票;剔除由于停牌等原因而无法买卖的股票;
4、交易模型:每月末更新动量指标并重新对股票排名,新股理想仓位为1%,等权配置;
将中证500成分股按因子排名分为5组,由于因子值越大越好,按由小到大排名,组别越大的组合越好,即G5组优于G1组;
单边交易费用为千分之一。
备注:由于按日调仓需提取的日度数据量较为庞大,此处且先采用按月调仓的策略来传递高质量动量选股思想和呈现选股效果。
2.4 策略实现
2.4.1 导入python库
2.4.2 提取调仓日期
先是提取2009年1月1日-2018年9月12日回测区间内的各个月末交易日期,再提取每月月末往前推60日的交易日期,以便后面计算回测区间内的各个月末交易日期对应的过去60日涨跌幅。
##提取区间内的月末交易日期
def get_trade_date(start_date, end_date, period='M'): #输入参数start_date为回测起始日期,end_date为回测结束日期,period='M'代表提取的是月末交易日期
data = w.tdays(start_date,end_date, period=period)
trade_dates = data.Data[0]
trade_dates = [dt.strftime("%Y-%m-%d") for dt in trade_dates]
return trade_dates
##设置回测区间
start_date='20090101' #回测起始时间
end_date='20180912' #回测结束时间
dates=get_trade_date(start_date, end_date, period='M') #提取区间各月末交易日
dates_bef60_=[w.tdaysoffset(-60,date,"").Data[0][0].strftime("%Y-%m-%d") for date in dates] #得每月月末往前推60日的交易日期
2.4.3 构建选股函数
先提取各调仓日的中证500成分股,再剔除ST和由于停牌等原因而无法买卖的股票,即保留中证500中非ST和处于交易状态的股票。
2.4.4 构建动量因子
先提取出各调仓日满足选股条件的股票对应的过去60日涨跌幅,再提取各股票过去60日的收益波动率,最后利用前面的因子计算公式计算动量因子。
##提取数据并计算动量因子
def get_momentum_factor(dates_bef60_,dates): #输入参数dates_bef60_为各调仓日前推60日的交易日期, dates为回测期内各个月末交易日(也就是调仓日)
dict_=OrderedDict() #创建每期存取数据字典
for (date_bef60,date) in zip(dates_bef60_,dates):
stocks=get_stocks(date) #提取各交易日的中证500成分股中满足筛选条件的股票池
#step1:计算股票过去60日的收益率
returns=w.wss(stocks, "pct_chg_per","startDate="+date_bef60+";endDate="+date,usedf=True)[1]/100#提取各股票过去60个交易日的涨跌幅,即为过去60日内的收益率
returns.columns=[