Python量化交易——股票择时到底能否赚钱?TA-Lib 33种技术指标有效性横向大评比
Python
量化交易——TA-Lib
中33种股票择时技术指标的有效性研究
为什么要做这个评测
技术指标是股票交易中最常用的技术手段之一,几乎所有的技术文章或股票分析文章都离不开通过MACD等各种指标来判断一支股票的买点和卖点,做量化的也会经常接触TA-Lib
中提供的各种技术指标。从股评人的文章里看,似乎这些指标都有指哪打哪的能力,但是,我们既然做量化交易,就必须用数据说话,一个技术指标到底好不好,有没有用,不是靠嘴说的,是靠数据来验证的。因此,我这个系列文章的目标,就是把TA-Lib
中的技术指标全都拿出来溜一溜,做一个横向大评比。俗话说,是骡子是马拉出来溜溜,通过大数据分析,我们就应该对指标的有效性有一个大致的了解。
这个评测,就是为了使用实际数据来回答两个问题:
- 技术指标择时到底有没有效果?
- 如果有效,应该选哪个技术指标效果更好?
我会写一系列的文章,每一篇评测一种技术指标,以逐步解答上面的问题。一共评测33种技术指标,文章链接在后文表格中。
技术指标清单
在这个系列文章中,将要评测下列技术指标,这些技术指标都来自TA-Lib
,分为两大类:动量指标和均线交叉指标,在qteasy
的内置交易策略中,产生交易信号的规则在下表中。
每个指标都依赖一定的可调参数产生效果,例如,均线交叉指标总需要两根均线,一根快均线,一根慢均线,这两根均线的历史周期是不同的。在测试过程中,我们全部使用默认参数。qteasy
的策略优化模块可以使用多种算法进行参数寻优,以达到更好的择时效果。但我们这里测试结果侧重于统计结果,因此全部采用默认参数,如下表。
已经完成评测的指标结果也在表中,点击指标名称链接到相关文章。
指标 | 英文全称 | 中文名称 | 交易策略说明 | 结果:强度 | 结果:适应度 |
---|---|---|---|---|---|
ADX | Average Directional Movement Index | 平均定向运动指数 | ADX交易策略: 基于ADX指标判断当前趋势的强度,从而根据趋势强度产生交易信号 1, 当ADX大于25时,判断趋势向上,设定持仓比例为1 2, 当ADX介于20到25之间时,判断为中性趋势,设定持仓比例为0 3, 当ADX小于20时,判断趋势向下,设定持仓比例为-1 | 12.45% | 45.50% |
APO | Absolute Price Oscillator | 绝对价格震荡指标 | APO交易策略: 基于APO指标判断当前股价变动的牛熊趋势,从而根据趋势产生交易信号 1, 当APO大于0时,判断为牛市趋势,设定持仓比例为1 2, 当ADX小于0时,判断为熊市趋势,设定持仓比例为-1 | -23.3% | -33% |
AROON | AROON | AROON指标 | AROON交易策略: 通过计算AROON指标趋势的强弱程度输出强多/空头和弱多/空头 1, 当UP在DOWN的上方时,输出弱多头 2, 当UP位于DOWN下方时,输出弱空头 3, 当UP大于70且DOWN小于30时,输出强多头 4, 当UP小于30且DOWN大于70时,输出强空头 | -82.1% | -107% |
AROONOSC | AROON Oscillator | AROON震荡指标 | 交易策略: 当AROONOSC大于0时表示价格趋势向上,反之趋势向下,绝对值大于50时表示强烈的趋势 1, 当AROONOSC大于0时,输出弱多头 2, 当AROONOSC小于0时,输出弱空头 3, 当AROONOSC大于50时,输出强多头 4, 当AROONOSC小于-50时,输出强空头 | ||
CCI | Commodity Channel Index | 商品渠道指数 | 交易策略: CCI商品渠道指数被用来判断当前股价位于超卖还是超买区间,本策略使用这个指标生成投资仓位目标 1, 当CCI大于0时,输出弱多头 2, 当CCI小于0时,输出弱空头 3, 当CCI大于50时,输出强多头 4, 当CCI小于-50时,输出强空头 | -62.1% | -147.1% |
CMO | Chande Momentum Oscillator | 钱德动量振荡器 | 交易策略: CMO 是一个在-100到100之间波动的动量指标,它被用来判断当前股价位于超卖还是超买区间,本策略使用这个指标生成投资仓位目标 1, 当CMO大于0时,输出弱多头 2, 当CMO小于0时,输出弱空头 3, 当CMO大于50时,输出强多头 4, 当CMO小于-50时,输出强空头 | -45.8% | -71.95% |
MACDEXT | Extended MACD | 扩展MACD指数 | 交易策略: 本策略使用MACD指标生成持仓目标,但是与标准的MACD不同,MACDEXT的快、慢、及信号均线的类型均可选 1, 当hist>0时输出多头 2, 当hist<0时输出空头 | ||
MFI | Money Flow Index | 货币流向指数 | MFI 交易策略: MFI指数用于判断股价属于超买还是超卖状态,本策略使用MFI指标生成交易信号 1, 当MFI>20时,持续不断产生10%买入交易信号 2, 当MFI>80时,持续不断产生30%卖出交易信号,持续卖出持仓股票 | ||
DI | Directory Indicator | 方向指标 | DI 交易策略: DI 指标包含负方向指标与正方向指标,它们分别表示价格上行和下行的趋势强度,本策略使用±DI指标生成交易信号 1, 当+DI > -DI时,设置持仓目标为1 2, 当+DI < -DI时,设置持仓目标为-1 | -16.7% | 38.23% |
DM | Directional Movement | 方向运动指标 | DM交易策略: DM 指标包含负方向运动指标(Negative Directional Movement)与正方向运动指标(Positive Directional Movement),它们分别表示价格上行和下行的趋势,本策略使用±DM指标生成交易信号 1, 当+DM > -DM时,设置持仓目标为1 2, 当+DM < -DM时,设置持仓目标为-1 3, 其余情况设置持仓目标为0 | -16.7% | 38.23% |
MOM | momentum indicator | 动量指标 | MOM 交易策略: MOM 指标可以用于识别价格的上行或下行趋势的强度,当前价格高于N日前价格时,MOM为正,反之为负。 1, 当MOM > 0时,设置持仓目标为1 2, 当MOM < 0时,设置持仓目标为-1 3, 其余情况设置持仓目标为0 | -5.87% | 104.99% |
PPO | Percentage Price Oscillator | 百分比价格振荡器 | PO 交易策略: PPO 指标表示快慢两根移动均线之间的百分比差值,用于判断价格的变化趋势。长短均线的计算周期和均线类型均为策略参数。 1, 当PPO > 0时,设置持仓目标为1 2, 当PPO < 0时,设置持仓目标为-1 3, 其余情况设置持仓目标为0 | -27.2% | -29.99% |
RSI | Relative Strength Index | 相对强度指数 | RSI 交易策略: RSI 指标度量最近价格变化的幅度,从而判断目前股票属于超卖还是超买状态 1, 当RSI > ulim时,设置持仓目标为1 2, 当RSI < llim时,设置持仓目标为-1 3, 其余情况设置持仓目标为0 | -78.74% | -405.13% |
STOCH | Stochastic Indicator | 随机指数 | STOCH 交易策略: STOCH 指标度量价格变化的动量,并且动量的大小判断价格趋势,并生成比例买卖交易信号。 1, 当k > 80时,产生逐步卖出信号,每周期卖出持有份额的30% 2, 当k < 20时,产生逐步买入信号,每周期买入总投资额的10% | -72.15% | -197.07% |
STOCHF | Stochastic Fast Indicator | 快速随机指标 | STOCHF 交易策略: STOCHF 指标度量价格变化的动量,与STOCH策略类似,使用快速随机指标判断价格趋势,并生成比例买卖交易信号。 1, 当k > 80时,产生逐步卖出信号,每周期卖出持有份额的30% 2, 当k < 20时,产生逐步买入信号,每周期买入总投资额的10% | -71.5% | -210.3% |
STOCHRSI | Stochastic Relative Strength Index | 随机相对强弱指标 | STOCHRSI 交易策略: STOCHRSI 指标度量价格变化的动量,该指标在0~1之间波动,表示相对的价格趋势强弱程度,并生成比例买卖交易信号 1, 当k > 0.8时,产生逐步卖出信号,每周期卖出持有份额的30% 2, 当k < 0.2时,产生逐步买入信号,每周期买入总投资额的10% | ||
ULTOSC | Ultimate Oscillator Indicator | 终极振荡器指标 | ULTOSC 交易策略: ULTOSC 指标通过三个不同的时间跨度计算价格动量,并根据多种不同动量之间的偏离值生成交易信号。 1, 当ULTOSC > u时,产生逐步卖出信号,每周期卖出持有份额的30% 2, 当ULTOSC < l时,产生逐步买入信号,每周期买入总投资额的10% | ||
WILLR | William’s %R | 威廉姆斯百分比 | WILLR 交易策略: WILLR 指标被用于计算股价当前处于超买还是超卖区间,并用于生成交易信号 1, 当WILLR > -l时,产生逐步卖出信号,每周期卖出持有份额的30% 2, 当WILLR < -u时,产生逐步买入信号,每周期买入总投资额的10% | ||
MACD | Moving Average Convergence & Divergence | 平滑异同移动平均线 | MACD交易策略: 1,当MACD值大于0时,设置仓位目标为1 2,当MACD值小于0时,设置仓位目标为0 | 5.8% | 182.9% |
DMA | Difference of Moving Average | 平行线差指标 | DMA交易策略: 1, DMA在AMA上方时,多头区间,即DMA线自下而上穿越AMA线后,输出为1 2, DMA在AMA下方时,空头区间,即DMA线自上而下穿越AMA线后,输出为0 | 2.3% | 131.32% |
TRIX | Triple Exponentially Smoothed Average | 三重指数平滑移动平均变化率 | TRIX交易策略,使用股票价格的三重平滑指数移动平均价格进行多空判断: 计算价格的三重平滑指数移动平均价TRIX,再计算M日TRIX的移动平均: 1, TRIX位于MATRIX上方时,设置仓位目标为1 2, TRIX位于MATRIX下方时,设置仓位目标位-1 | -11.2% | 85.36% |
SAREXT | Parabolic SAR Extendec | 扩展抛物线SAR指标 | 扩展抛物线SAR策略,当指标大于0时发出买入信号,当指标小于0时发出卖出信号 | ||
BBAND | Bollinger Bands | 布林带线指标 | 布林带线交易策略,根据股价与布林带上轨和布林带下轨之间的关系确定多空,在价格上穿或下穿布林带线上下轨时产生交易信号。布林带线的均线类型不可选 1,当价格上穿上轨时,产生全仓买入信号 2,当价格下穿下轨时,产生全仓卖出信号 | -45.53% | -147.64% |
S-BBAND | Soft Bollinger Bands | 软性布林带线指标 | 布林带线渐进交易策略,根据股价与布林带上轨和布林带下轨之间的关系确定多空,交易信号不是一次性产生的,而是逐步渐进买入和卖出。计算BBAND,检查价格是否超过BBAND的上轨或下轨: 1,当价格大于上轨后,每天产生10%的比例买入交易信号 2,当价格低于下轨后,每天产生33%的比例卖出交易信号 | -59.08% | -182.81% |
DSMA | D-Cross Simple Moving Average | 简单移动平均交叉 | DSMA 双均线交叉策略: 基于SMA均线计算规则生成快慢两根均线,根据快与慢两根均线的相对位置设定持仓比例 | -27.2% | -30.0% |
DDEMA | D-Cross Double Exponential Moving Average | 双重指数平滑移动平均线交叉 | DDEMA 双均线交叉策略: 基于DEMA均线计算规则生成快慢两根均线,根据快与慢两根均线的相对位置设定持仓比例 | ||
DEMA | D-Cross Exponential Moving Average | 指数平滑移动平均线交叉 | DEMA 双均线交叉策略: 基于EMA均线计算规则生成快慢两根均线,根据快与慢两根均线的相对位置设定持仓比例 | ||
DKAMA | D-Cross Kaufman Adaptive Moving Average | 考夫曼自适应移动均线交叉 | DKAMA 双均线交叉策略: 基于KAMA均线计算规则生成快慢两根均线,根据快与慢两根均线的相对位置设定持仓比例 | ||
DMAMA | D-Cross MESA Adaptive Moving Average | MESA自适应移动均线交叉 | DMAMA 双均线交叉策略: 基于MAMA均线计算规则生成快慢两根均线,根据快与慢两根均线的相对位置设定持仓比例 | ||
DT3 | D-Cross Triple Exponential Moving Average | 三重指数平滑移动平均线交叉 | DT3 双均线交叉策略: 基于T3均线计算规则生成快慢两根均线,根据快与慢两根均线的相对位置设定持仓比例 | ||
DTEMA | D-Cross Triple Exponential Moving Average | 三重指数平滑移动平均线交叉 | DTEMA 双均线交叉策略: 基于TEMA均线计算规则生成快慢两根均线,根据快与慢两根均线的相对位置设定持仓比例 | ||
DTRIMA | D-Cross Triple Exponential Moving Average | 三重指数平滑移动平均线交叉 | DTRIMA 双均线交叉策略: 基于TRIMA均线计算规则生成快慢两根均线,根据快与慢两根均线的相对位置设定持仓比例 | ||
DWMA | D-Cross Weighted Moving Average | 加权移动平均线交叉 | DWMA 双均线交叉策略: 基于WMA均线计算规则生成快慢两根均线,根据快与慢两根均线的相对位置设定持仓比例 |
评测方法
既然是评测,那么就必须公平且广泛。我们将利用这些技术指标,使用同样的历史数据进行模拟交易,对比择时交易和一直持有的收益率差异。
每次回测的时间跨度都是5年,从2015年1月1日开始投资于一个股票,在技术指标发出买入信号时全仓买入,在发出卖出信号后全仓卖出,一直到2019年21月31日为止,记录总收益率,记做择时收益率。与之对比,我们同时考察全仓买入同一支股票并跟踪五年的收益率,记做基准收益率。
在理想情况下,我们希望择时收益率应该大于基准收益率,因为我们理论上应该总是在高点卖出,在低点买进,就如同下面的交易曲线图所示(绿线是股票价格,红线是投资曲线):
但是如果策略表现不佳,也有可能在多次反复空仓中错过本身涨幅很好的股票,造成择时收益率低于基准收益。例如下面这种情况:
一个好的技术指标,理论上应该能够识别出上涨机会,从而从总体上获得比基准收益率更高的收益,不是么?但是为了避免出现统计偏差,我们需要进行大量的数据对比。
因此,我们以2015年以来的共计433支沪深300指数成分股为目标,逐一投资于这433支股票,分别记录433个五年择时收益率与五年基准收益率,来回答前面提出的问题。
评测工具
我会使用qteasy
作为回测评测的工具。
qteasy
是本人正在开发的一个快速量化交易工具包,使用这个工具包,可以快速灵活地生成各种量化交易策略,生成历史数据并回测策略的表现,有针对性地优化策略的性能;未来还将提供实时自动化交易功能。该项目正在开发中,Github项目地址在这里:https://github.com/shepherdpp/qteasy
qteasy
利用TA-Lib
中大部分动量和均线技术指标,内置了相当多的交易策略,开箱即用。因此,我们可以利用这一点,用一行代码快速创建交易策略,而且回测操作也只需要一行代码即可:
import qteasy as qt
# 创建一个基于ADX(平均定向运动指数)的交易策略
op = qt.Operator('adx', signal_type='pt')
# 设置基本参数并开始回测(回测前需要确保下载足够的历史数据,参见qteasy文档)
qt.run(op,
mode=1,
asset_pool='000001.SZ', # 投资标的
asset_type='E', # 投资标的为股票
benchmark_asset='000001.SZ', # 收益率基准,与投资标的相同
benchmark_asset_type='E',
invest_start='20150101', # 回测开始日期
invest_end='20191231' # 回测结束日期
)
运行上述代码,如果没有报错,可以看到下面文字形式的输出结果,以及详细回测结果分析图表:
====================================
| |
| BACK TESTING RESULT |
| |
====================================
qteasy running mode: 1 - History back testing
time consumption for operate signal creation: 23.5ms
time consumption for operation back looping: 361.3ms
investment starts on 2015-01-05 00:00:00
ends on 2019-12-31 00:00:00
Total looped periods: 5.0 years.
-------------operation summary:------------
Only non-empty shares are displayed, call
"loop_result["oper_count"]" for complete operation summary
Sell Cnt Buy Cnt Total Long pct Short pct Empty pct
000001.SZ 29 29 58 58.7% 0.0% 41.3%
Total operation fee: ¥ 1,236.87
total investment amount: ¥ 100,000.00
final value: ¥ 143,880.70
Total return: 43.88%
Avg Yearly return: 7.56%
Skewness: 0.16
Kurtosis: 9.06
Benchmark return: 57.77%
Benchmark Yearly return: 9.57%
------strategy loop_results indicators------
alpha: -0.006
Beta: 1.000
Sharp ratio: 0.452
Info ratio: -0.032
250 day volatility: 0.232
Max drawdown: 36.34%
peak / valley: 2015-07-10 / 2015-08-25
recovered on: 2017-11-22
===========END OF REPORT=============
qteasy
给出了很多的结果分析指标,但现在我们只需要择时收益率:43.88%,以及基准收益率:57.77%。
为了列出2015年以来的所有沪深300指数成份股,可以使用下面的代码:
import qteasy as qt
stocks = qt.filter_stock_codes(index='000300.SH', date='20150101')
然后,我们就可以循环操作,逐一回测所有的成份股了:
for stk in stocks:
qt.run(op,
mode=1,
asset_pool=stk,
asset_type='E',
benchmark_asset=stk,
benchmark_asset_type='E',
visual=False, # 批量执行时,关闭可视化图表输出
report=False, # 批量执行时,关闭回测结果输出
invest_start='20150101',
invest_end='20191231',
trade_log=False # 批量执行时,关闭回测交易结果日志
)
测试方法及评价指标
使用qteasy
回测所有433支股票的回测结果,每次回测的时间跨度都是5年,从2015年1月1日开始投资于一个股票,在技术指标发出买入信号时全仓买入,在发出卖出信号后全仓卖出,一直到2019年21月31日为止,记录总收益率,记做择时收益率。与之对比,我们同时考察全仓买入同一支股票并跟踪五年的收益率,记做基准收益率。
我们的第一个评价指标就是平均择时收益率与平均基准收益率之差,称为指标的强度:
S t r e n g t h = a v g ( 择时收益率 − 基准收益率 ) Strength = avg(择时收益率 - 基准收益率) Strength=avg(择时收益率−基准收益率)
指标的强度 S t r e n g t h Strength Strength越高,代表策略获取超额收益的能力越强。因此强度越高越好
不过,这个评价指标只能代表择时收益率总体上的表现,但是有可能较高的择时收益率只是通过少数股票的超高收益得到的,其余大多数股票的择时收益率表现平平,只是平均值较高而已。就像99个穷光蛋和1个马云一平均,一百个都是百万富翁一样,因此我们不能光看平均,还得看这个策略在多少股票上跑得好,多少股票上跑得差。
因此我们还可以,根据所有回测后股票的基准收益率和择时收益率之间的关系,将所有股票分成六组:
- 第一组:力挽狂澜,股票基准收益为负,但择时后收益为正
- 第二组:锦上添花:股票基准收益为正,择时后收益更高,收益为正
- 第三组:差强人意,股票基准收益为正,择时后收益降低,但仍然为正
- 第四组:无力回天,股票基准收益为负,择时后收益有所改善,但仍然为负
- 第五组:屋漏逢雨,股票基准收益为负,择时后收益更差,收益为负
- 第六组:乐极生悲,股票基准收益为正,择时后反而亏损,最终收益为负
显然,上面六组中,我们希望前三组里股票越多越好,尤其是第一组和第二组,可以得到高于基准的收益率,同时希望后三组的股票越少越好,尤其是最后一组,将本来可观的收益变为负的。因此,我们第二个评价指标就是每一组里股票个数的加权平均值,称为指标的适应性:
A d a p t a b i l i t y = ∑ ( w e i g h t G ∗ c o u n t G ) 6 Adaptability = \frac{\sum(weight_G * count_G)} 6 Adaptability=6∑(weightG∗countG)
其中count_G是每一组股票的个数,而weight_G是每一组的权重,这个权重分别如下:
- 第一组:力挽狂澜,权重为3倍该组平均收益率差
- 第二组:锦上添花:权重为2倍该组平均收益率差
- 第三组:差强人意,权重为1倍该组平均收益率差
- 第四组:无力回天,权重为1倍该组平均收益率差
- 第五组:屋漏逢雨,权重为2倍该组平均收益率差,因为平均收益率差为负,因此会降低
- 第六组:乐极生悲,权重为3倍该组平均收益率差
指标的适应性体现了指标的适用范围,适应性强的指标,对更多的个股都能产生作用,这个指标也是越高越好。我们后面就将用强度和适应性两个评价指标来对前文所列出的33个指标进行一次横向大评比,敬请期待!
期待你的意见
我们将从下一篇文章开始,逐一解释每一个技术指标,并进行433轮回测,记录择时收益率和基准收益率,并借以评价每个技术指标的有效性以及优劣。
如果您对评测方法或指标有任何意见或建议,欢迎回复或私信交流,希望大家学习交流、共同进步!