前言最近写了不少以动量因子为核心的量化策略,结果收益和回撤都不太理想 跑去社区发了个帖子贴了下自己的回测情况,有人推荐我看看这本书,遂有如下经历 原书思想简单点说,整个策略是期望基于动量因子寻找到有上升趋势的股票,买入并持有直到趋势消失,从而在牛市中获取超额利润 作者以标普500作为股票池,他的理由是:
关于动量效应的解释: 当一只股票的股价上涨一段时间后,继续上涨的可能性要高于回落的可能性,比其他股票上涨的快的股票会继续比其他股票上涨的快 而且作者不是仅仅是通过计算股票的年化收益率作为动量因子来筛选股票(后面我会列举具体的计算步骤),他还有一些附加条件,比如:
归根结底,对动量因子的应用,其实就是一种趋势跟随的实操方案,而趋势跟随的弊端及补偿方案,原书中也提到过:
这一点在实际回测中也被很好的印证了,基本跑不过大盘 ![]() image
上图15年熊市末期到18年末的收益情况,红线是沪深300收益,蓝线是策略收益 当然,除了依据动量因子给池中的股票做排名之外,作者也提到了头寸规模 他说的这句话一定要画上重点:我们不是分配资金,而是分配风险 很多人给资产分配不同的权重时往往容易忽视背后的逻辑,要记住,我们正在做的是均衡风险,而不是表面上的资金分配 最后,关于卖出时机,这一点不是动量策略要考虑的,因此书中并未提及止损方法 回测的具体步骤首先贴下代码逻辑,这是我最近的心得之一,回测前一定要画好流程图,后面撸代码时效率会高很多 ![]() image
上面是根据原书的策略优化后作出的第一版流程图,实际回测时我是有部分改动的,后续会提到 下面讲讲核心算法 股票排名指导思想:找到一类稳步上升的股票,不仅随着时间的推移获得可观的收益,而且还尽可能平稳地移动 这里主要以两个指标为依据:
关于第一点,这里所说的年化收益其实是通过指数回归计算日涨幅从而得到的,目的是为了量化动量这一指标,收益越高,动量越大 股票的波动率是借助r-squared这个判定系数来衡量价格序列与回归直线的拟合程度,拟合性越差,判定系数越低,给最终分数添加更高的惩罚 所以最后将二者乘积作为股票的分值 具体计算方法:
以上是原书的计算方法,详情可参考我的代码: def get_socre(stock):
''' 基于股票年化收益和判定系数打分
Returns:
score (float): score of stock
'''
data = attribute_history(stock, g.stock_mean_day, '1d', ['close'])
y = data['log'] = np.log(data.close)
x = data['num'] = np.arange(data.log.size)
slope, intercept = np.polyfit(x, y, 1)
annualized_returns = math.pow(math.exp(slope), 250) - 1
r_squared = 1 - (sum((y - (slope * x + intercept))**2) / ((len(y) - 1) * np.var(y, ddof=1)))
return annualized_returns * r_squared
头寸规模关于波动的计算,作者引入ATR,即Average True Range(平均真实波幅)这一指标,来衡量股票价格波动 其中,TR =∣今日最高价 - 今日最低价∣和∣今日最高价 -昨日收盘价∣和∣今日最低价 - 昨日收盘价∣的最大值 原书ATR取近20日内TR的均值 关于风险因子,用于设定头寸规模,举个例子:
最后,设定一个阈值,一旦目标股票当前的资金暴露风险与期望风险相差大于阈值,则触发再平衡操作,这么做的一个考量是为了减少换手率,防止过多的小额交易 参考代码:
最后策略表现: ![]() image
本次回测只是复制原书的整个策略,作者选用的标普500,我选取的沪深300,并未依据A股市场做任何变动 但是从牛市情况来看,原策略在国内的表现也还是可圈可点的,至于熊市和震荡市的表现,就得结合其他策略做进一步的改进了 比如原策略对熊市的判断是依据标普500的200日均线,这一点用在A股的结果从上图就能看出 关于参数的优化,作者说的一些话我很中意,比如:
做量化交易很容易陷入过度优化的误区,我的观念是定性首先比定量要重要,一个策略如果要求一套非常精确的规则和参数,那这样的策略通常不会是健壮的策略。 从这一点看,上面的动量策略的表现其实我是比较满意的 |
|
来自: 冷雨雪 > 《《趋势永存:打败市场的动量策略》》