持续行动1期 58/100,“AI技术应用于量化投资研究”。
前面我们说轮动其实是一种“范式”,天然带着分散、组合的特点。动量也不是一个策略或者某一个因子,而是一簇。比如N天收益率,均线,MACD金叉或者RSRS(光大证券的一个阻力支撑指标),甚至是通道突破(唐奇安通道或者布林带)都是动量的逻辑。
动量背后的逻辑是“强者恒强”,“惯性”。其实这是有道理的。价格趋势会保持一定的运动惯性,市场情绪消化需要一定的时间。
从策略上看,其实就是“追涨杀跌”,大家用来嘲讽新手韭菜的行事风格。但其实这符合人的直觉,“左侧交易”的低位价值投资或者“均值回归”是反人性的,而“右侧交易”更符合直觉。
其实并没有对错,只是周期的不同阶段罢了。
投资是知道自己在做什么,承担什么样的风险,赚什么样的回报。
01 大小盘动量轮动
轮动的基础是二者确实”有此消彼长“负相关性。
A股市场大小盘:沪深300指数、创业板指数就存在这样的效应。那么使用20日均量这样一个简单的指标。
年化21%,夏普比0.83,最大回撤21%。
说白了,过去12年(从2010年开始,就买这两个指数,过去20天的动量大的,如果动量都小于0,则空仓),年化收益超过股神巴菲特了,回撤21%也在可接受范围内,真的能做到一定的“抄底逃顶”的。
加上中证500之后,收益率下降,回撤增加。
如果换成标普500和日经225指数,效果会差很多。
原因分析:动量策略对于单边大牛市很有效,可能吃到大部分,并且可以把成果保留下来,但对于震荡向上的市场,则效果一般。
02 自定义RSRS指标
RSRS是光大证券提出的一个“阻力支撑”指标,广义上讲也是趋势指标。
我们用bt的框架里实现一下。
bt里的指标,都是继承自bt.indicator或者它的子类。
至少要定义1个lines,这里我们定义两个lines,一个rsrs,一个rsrs_dev。
它的参数用的是元组tuple
import backtrader as bt import numpy as np import statsmodels.api as sm class RSRS(bt.Indicator): lines = ('rsrs', 'rsrs_dev') params = (('N', 18), ('value', 5)) def __init__(self): self.high = self.data.high self.low = self.data.low self.lines.rsrs = bt.Max(0.0, self.params.value) self.lines.rsrs_dev = bt.Min(0.0, self.params.value) def next(self): high_N = self.high.get(ago=0, size=self.p.N) low_N = self.low.get(ago=0, size=self.p.N) print(low_N, len(low_N)) try: X = sm.add_constant(np.array(low_N)) model = sm.OLS(np.array(high_N), X) results = model.fit() self.lines.rsrs[0] = results.params[1] except: self.lines.rsrs[0] = 0
这里用了statsmodels的线性回归求两个序列的斜率。
rsrs还有正则化,修正正则化,右偏修正正则化的实现,明天继续了。
今天主要是在bt框架里,演示如何实现自定义的指标,熟悉了之后其实很容易。