前言 最近在看趋势择时,逛了下UQER,发现不少均线、MACD等指标的,但是木有看到关于TRIX的,就半参考着矿友accretion的策略Simple MACD 做了个TRIX策略。
TRIX简介 TRIX(Triple Exponentially Smoothed Moving Average)中文名称:三重指数平滑移动平均,长线操作时采用本指标的讯号,可以过滤掉一些短期波动的干扰,避免交易次数过于频繁,造成部分无利润的买卖,及手续费的损失。
本指标是一项超长周期的指标,长时间按照本指标讯号交易,获利百分比大于损失百分比,利润相当可观。
计算公式 1.计算N日的指数移动平均线EMA
2.对上述EMA再进行两次N日指数移动平均后得到TR
3.TRIX = (TR - TR(昨日))/昨日TR * 100
4.MATRIX = TRIX的M日简单平均移动
TRIX的运用 1.当TRIX线一旦从下向上突破TRMA线,形成“金叉”时,预示着股价开始进入强势拉升阶段,投资者应及时买进股票。
2.当TRIX线向上突破TRMA线后,TRIX线和TRMA线同时向上运动时,预示着股价强势依旧,投资者应坚决持股待涨。
3.当TRIX线在高位有走平或掉头向下时,可能预示着股价强势特征即将结束,投资者应密切注意股价的走势,一旦K线图上的股价出现大跌迹象,投资者应及时卖出股票。
4.当TRIX线在高位向下突破TRMA线,形成“死叉”时,预示着股价强势上涨行情已经结束,投资者应坚决卖出余下股票,及时离场观望。
5.当TRIX线向下突破TRMA线后,TRIX线和TRMA线同时向下运动时,预示着股价弱势特征依旧,投资者应坚决持币观望。
6.当TRIX线在TRMA下方向下运动很长一段时间后,并且股价已经有较大的跌幅时,如果TRIX线在底部有走平或向上勾头迹象时,一旦股价在大的成交量的推动下向上攀升时,投资者可以及时少量地中线建仓。
7.当TRIX线再次向上突破TRMA线时,预示着股价将重拾升势,投资者可及时买入,持股待涨。
其中1、4为最重要的买入卖出信号,也是本策略的基石。
策略如下:
start = '2011-08-01' # 回测起始时间 end = '2016-04-17' # 回测结束时间 benchmark = 'HS300' # 策略参考标准 universe = StockScreener (Factor .LCAP .nsmall (30 )) # 因子选股,选取市值最小的30只股票作为备选 capital_base = 1000000 # 起始资金 freq = 'd' # 策略类型,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测 refresh_rate = 5 # 调仓频率,表示执行handle_data的时间间隔,若freq = 'd'时间间隔的单位为交易日,若freq = 'm'时间间隔为分钟 def initialize (account ): # 初始化虚拟账户状态 def handle_data (account ): # 每个交易日的买入卖出指令 length_of_data = 3 * N + M + 10 # 取closeprice的天数,为了足够计算MATRIX、TRIX all_close_prices = account .get_attribute_history ('closePrice' , length_of_data ) # 获取历史closePrice数据 for stk in account .universe : prices = all_close_prices [stk ] TRIX = talib .TRIX (prices ,timeperiod =N ) # 计算TRIX MATRIX = talib .MA (TRIX ,M ,0 ) # 机选MATRIX if (TRIX [- 1 ]- MATRIX [- 1 ]) > 0 and (TRIX [- 5 ]- MATRIX [- 5 ]) < 0 : # 认为TRIX线向上突破TRMA线 金叉 elif (TRIX [- 1 ]- MATRIX [- 1 ]) < 0 and (TRIX [- 5 ]- MATRIX [- 5 ]) > 0 : # 认为TRIX线在高位向下突破TRMA线 死叉 for stk in account .valid_secpos : amout = account .referencePortfolioValue / len (buy ) # 每只股票买入数量 num = int (amout / account .referencePrice [stk ] / 100.0 ) * 100
查看全部 年化收益率 82.8% 基准年化收益率 8.4% 阿尔法 76.2% 贝塔 0.63 夏普比率 2.88 收益波动率 27.5% 信息比率 2.21 最大回撤 34.3% 换手率 18.55 累计收益率 策略 基准 2012-01 2012-07 2013-01 2013-07 2014-01 2014-07 2015-01 2015-07 2016-01 -250.00% 0.00% 250.00% 500.00% 750.00% 1000.00% 1250.00% 关于N、M的选取 N、M的选取将较大的影响策略效果,我也不是很懂如何去选,在TRIX的百度百科,最后有实践采用的是(24,72)的组合。
依葫芦画瓢,我以M=3N 试了下(9,27)、(24,72)、(15,45)的组合,其中(15,45)表现最优
不妨再试试其他的?下面再看看(12,9)和(12,72)
start = '2011-08-01' # 回测起始时间 end = '2016-04-17' # 回测结束时间 benchmark = 'HS300' # 策略参考标准 universe = StockScreener (Factor .LCAP .nsmall (30 )) # 因子选股,选取市值最小的30只股票作为备选 capital_base = 1000000 # 起始资金 freq = 'd' # 策略类型,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测 refresh_rate = 5 # 调仓频率,表示执行handle_data的时间间隔,若freq = 'd'时间间隔的单位为交易日,若freq = 'm'时间间隔为分钟 def initialize (account ): # 初始化虚拟账户状态 def handle_data (account ): # 每个交易日的买入卖出指令 length_of_data = 3 * N + M + 10 # 取closeprice的天数,为了足够计算MATRIX、TRIX all_close_prices = account .get_attribute_history ('closePrice' , length_of_data ) # 获取历史closePrice数据 for stk in account .universe : prices = all_close_prices [stk ] TRIX = talib .TRIX (prices ,timeperiod =N ) # 计算TRIX MATRIX = talib .MA (TRIX ,M ,0 ) # 机选MATRIX if (TRIX [- 1 ]- MATRIX [- 1 ]) > 0 and (TRIX [- 5 ]- MATRIX [- 5 ]) < 0 : # 认为TRIX线向上突破TRMA线 金叉 elif (TRIX [- 1 ]- MATRIX [- 1 ]) < 0 and (TRIX [- 5 ]- MATRIX [- 5 ]) > 0 : # 认为TRIX线在高位向下突破TRMA线 死叉 for stk in account .valid_secpos : amout = account .referencePortfolioValue / len (buy ) # 每只股票买入数量 num = int (amout / account .referencePrice [stk ] / 100.0 ) * 100
查看全部 年化收益率 66.0% 基准年化收益率 5.6% 阿尔法 60.9% 贝塔 0.74 夏普比率 1.98 收益波动率 31.4% 信息比率 1.84 最大回撤 44.5% 换手率 39.06 累计收益率 策略 基准 2012-01 2012-07 2013-01 2013-07 2014-01 2014-07 2015-01 2015-07 2016-01 0.00% 1000.00% -250.00% 250.00% 500.00% 750.00%
start = '2011-08-01' # 回测起始时间 end = '2016-04-17' # 回测结束时间 benchmark = 'HS300' # 策略参考标准 universe = StockScreener (Factor .LCAP .nsmall (30 )) # 因子选股,选取市值最小的30只股票作为备选 capital_base = 1000000 # 起始资金 freq = 'd' # 策略类型,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测 refresh_rate = 5 # 调仓频率,表示执行handle_data的时间间隔,若freq = 'd'时间间隔的单位为交易日,若freq = 'm'时间间隔为分钟 def initialize (account ): # 初始化虚拟账户状态 def handle_data (account ): # 每个交易日的买入卖出指令 length_of_data = 3 * N + M + 10 # 取closeprice的天数,为了足够计算MATRIX、TRIX all_close_prices = account .get_attribute_history ('closePrice' , length_of_data ) # 获取历史closePrice数据 for stk in account .universe : prices = all_close_prices [stk ] TRIX = talib .TRIX (prices ,timeperiod =N ) # 计算TRIX MATRIX = talib .MA (TRIX ,M ,0 ) # 机选MATRIX if (TRIX [- 1 ]- MATRIX [- 1 ]) > 0 and (TRIX [- 5 ]- MATRIX [- 5 ]) < 0 : # 认为TRIX线向上突破TRMA线 金叉 elif (TRIX [- 1 ]- MATRIX [- 1 ]) < 0 and (TRIX [- 5 ]- MATRIX [- 5 ]) > 0 : # 认为TRIX线在高位向下突破TRMA线 死叉 for stk in account .valid_secpos : amout = account .referencePortfolioValue / len (buy ) # 每只股票买入数量 num = int (amout / account .referencePrice [stk ] / 100.0 ) * 100
查看全部 年化收益率 75.4% 基准年化收益率 7.2% 阿尔法 69.6% 贝塔 0.63 夏普比率 2.60 收益波动率 27.7% 信息比率 2.06 最大回撤 37.6% 换手率 16.94 累计收益率 策略 基准 2012-07 2013-01 2013-07 2014-01 2014-07 2015-01 2015-07 2016-01 0.00% 1000.00% -250.00% 250.00% 500.00% 750.00% 小结 对比来看,似乎M越大,初期的效果越好。但是总体表现并无太大提高。
我这里是抛砖引玉、关于N,M的选择、策略性能的提高,希望社区牛人们能指点指点。
ValueError Traceback (most recent call last)
in () 98 freq=freq, security_base=security_base, security_cost=security_cost, 99 max_history_window=max_history_window, preload_data=_QUARTZ_PRELOAD_DATA, --> 100 display=True, return_quartz_data=True) 101 _QUARTZ_CACHE['start'] = start 102 _QUARTZ_CACHE['end'] = end
/home/ipython/anaconda/lib/python2.7/site-packages/mercuryq-quartz.egg/quartz/backtest.pyc in backtest(start, end, benchmark, universe, capital_base, initialize, handle_data, commission, slippage, refresh_rate, freq, security_base, security_cost, max_history_window, args, * kwargs)
/home/ipython/anaconda/lib/python2.7/site-packages/mercuryq-quartz.egg/quartz/backtest.pyc in backtest_daily(account, data, backtest_calendar, sim_params, **kwargs)
/home/ipython/anaconda/lib/python2.7/site-packages/mercuryq-quartz.egg/quartz/simulation/account.pyc in handle_data(self)
in handle_data(account) 22 length_of_data = 3*N+M +10 # 取closeprice的天数,为了足够计算MATRIX、TRIX 23 ---> 24 all_close_prices = account.get_attribute_history('closePrice', length_of_data) # 获取历史closePrice数据 25 26 buy_list = [] # 备选买入清单
/home/ipython/anaconda/lib/python2.7/site-packages/mercuryq-quartz.egg/quartz/simulation/account.pyc in get_attribute_history(self, attribute, time_range)
/home/ipython/anaconda/lib/python2.7/site-packages/mercuryq-quartz.egg/quartz/simulation/account.pyc in _get_daily_attribute_history(self, attribute, time_range)
ValueError: History overflow. Your current max daily history window is 30. Please use a shorter parameter, or change max_history_window according to document!
@fyiqi 错误
ValueError Traceback (most recent call last)
in () 98 freq=freq, security_base=security_base, security_cost=security_cost, 99 max_history_window=max_history_window, preload_data=_QUARTZ_PRELOAD_DATA, --> 100 display=True, return_quartz_data=True) 101 _QUARTZ_CACHE['start'] = start 102 _QUARTZ_CACHE['end'] = end
/home/ipython/anaconda/lib/python2.7/site-packages/mercuryq-quartz.egg/quartz/backtest.pyc in backtest(start, end, benchmark, universe, capital_base, initialize, handle_data, commission, slippage, refresh_rate, freq, security_base, security_cost, max_history_window, args, * kwargs)
/home/ipython/anaconda/lib/python2.7/site-packages/mercuryq-quartz.egg/quartz/backtest.pyc in backtest_daily(account, data, backtest_calendar, sim_params, **kwargs)
/home/ipython/anaconda/lib/python2.7/site-packages/mercuryq-quartz.egg/quartz/simulation/account.pyc in handle_data(self)
in handle_data(account) 22 length_of_data = 3*N+M +10 # 取closeprice的天数,为了足够计算MATRIX、TRIX 23 ---> 24 all_close_prices = account.get_attribute_history('closePrice', length_of_data) # 获取历史closePrice数据 25 26 buy_list = [] # 备选买入清单
/home/ipython/anaconda/lib/python2.7/site-packages/mercuryq-quartz.egg/quartz/simulation/account.pyc in get_attribute_history(self, attribute, time_range)
/home/ipython/anaconda/lib/python2.7/site-packages/mercuryq-quartz.egg/quartz/simulation/account.pyc in _get_daily_attribute_history(self, attribute, time_range)
ValueError: History overflow. Your current max daily history window is 30. Please use a shorter parameter, or change max_history_window according to document!
对应单只股票,实测效果并不好,参数选择上,有过度拟合嫌疑。对应不同的股票,通过调整N、M的参数的确可以产生好的效果,但是没有一个通用的参数可满足多个股票。 从效果上来说,和MACD应该差不多,都是基于ema来做的,同样有很强的延时效应。 实际使用上,感觉还不如MACD。
@xiaobingge 个人觉得1天的趋势可能不明显,而且本来换手率这边就确定的5,我就直接和5天前比了,-3,-4什么的都可以试试,你可以都跑一下看看效果。
if (TRIX[-1]-MATRIX[-1]) > 0 and (TRIX[-5]-MATRIX[-5]) < 0
请教一下,为什么不是取 -1 和 -2 相比,而是取 -1 和 -5 相比,这里有什么考虑吗?
@shinefuture 不好意思之前没看到回复。。。代码如下
# 去除ST股
STlist = DataAPI.SecSTGet(secID=account.universe, beginDate='20160422',endDate='20160422',field['secID']).tolist()
account.universe = [s for s in account.universe if s not in STlist]
# HS300中选市值最小30只的话,我不知道有啥函数可以直接获取,我的方法是:获取当天HS300所有LCAP因子数据,然后对得到的dataframe对LCAP排序,取最小的30只就行。代码如下:
universe = set_universe('HS300')
data = DataAPI.MktStockFactorsOneDayGet(tradeDate='20160422',secID=universe,field['SecID','LCAP'],pandas="1")
data = data.sort(columns='LCAP')
SecID_of_30_smallest =data['secID'][:30].tolist()
你好,看回测结果中有ST股,请问该如何去掉?请教下如果要从HS300中选市值最小的30只该怎么选,谢谢!