量化投资系列文章:
Backtrader 教程 — Python 量化投资原来这么简单(1)
Python 量化投资原来这么简单(2) —MACD策略(+26.9%)
Python 量化投资原来这么简单(3) —A股回测MACD策略
Github仓库:https://github.com/Ckend/pythondict-quant
今天我们来使用backtrader试试另一个量化投资策略:KDJ策略,KDJ是最常用的指标之一,其中文名叫“随机指标”。它通过统计学原理,识别N个交易日内最高价、最低价、最新收盘价三者之间的比例关系来计算随机值(RSV),然后再根据加权移动平均线(EMA)的方法来计算K值、D值、J值。
具体计算方法如下:
- RSV = (收盘价-N周期最低价)/(N周期最高价-N周期最低价)*100
- K值 = RSV的N周期加权移动平均值
- D值 = K值的N周期加权移动平均值
- J值 = 3K-2D
一般来说,RSV的N周期选择9,K和D的N周期选择3。
基本概念大家都懂了,那如何根据KDJ值决定买入和卖出呢?
当J值上穿K值的时候,是买入信号,此时买入。
当J值下穿K值的时候,是卖出信号,此时卖出。
这个策略有用吗?让我们来试试看。
1.准备
开始之前,你要确保Python和pip已经成功安装在电脑上噢,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda
Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),准备开始输入命令安装依赖。
当然,我更推荐大家用VSCode编辑器,把本文代码Copy下来,在编辑器下方的终端运行命令安装依赖模块,多舒服的一件事啊:Python 编程的最好搭档—VSCode 详细指南。
在终端输入以下命令安装我们所需要的依赖模块:
pip install backtrader
看到 Successfully installed xxx 则说明安装成功。
Backtrader基本使用请看我们前一篇文章:
backtrader教程—量化投资原来这么简单(1)
本文全部代码,请在Python实用宝典后台回复:量化投资4 进行下载。
2.单一KDJ策略
如果你以前没用过backtrader,请先看:
进行学习,不然你会有点蒙。直接下载代码学习也是一种方式,但前提是你的自学本领够强。
首先我们需要先计算K、D、J三个值,前面我们也说过了他们的计算方式:
- RSV = (收盘价-N周期最低价)/(N周期最高价-N周期最低价)*100
- K值 = RSV的N周期加权移动平均值
- D值 = K值的N周期加权移动平均值
- J值 = 3K-2D
知道了计算方式,那之后的工作就简单了:
# 9个交易日内最高价 self.high_nine = bt.indicators.Highest(self.data.high, period=9) # 9个交易日内最低价 self.low_nine = bt.indicators.Lowest(self.data.low, period=9) # 计算rsv值 self.rsv = 100 * bt.DivByZero( self.data_close - self.low_nine, self.high_nine - self.low_nine, zero=None ) # 计算rsv的3周期加权平均值,即K值 self.K = bt.indicators.EMA(self.rsv, period=3) # D值=K值的3周期加权平均值 self.D = bt.indicators.EMA(self.K, period=3) # J=3*K-2*D self.J = 3 * self.K - 2 * self.D
最后决定买入点和卖出点:
# Python 实用宝典 def next(self): self.log("Close, %.2f" % self.dataclose[0]) if self.order: return if not self.position: # J - D 值 condition1 = self.J[-1] - self.D[-1] condition2 = self.J[0] - self.D[0] if condition1 < 0 and condition2 > 0: self.log("BUY CREATE, %.2f" % self.dataclose[0]) self.order = self.buy() else: condition = (self.dataclose[0] - self.bar_executed_close) / self.dataclose[0] if condition > 0.1 or condition < -0.1: self.log("SELL CREATE, %.2f" % self.dataclose[0]) self.order = self.sell()
不过从卖出策略中可以看到,我暂时没有使用J下穿K值的方式来卖出股票,而是采用涨跌10%的限制性条件作为卖出信号,看看这样的策略表现如何。
这里和上篇文章一样,咱用10000元作为本金,对002859这只股票,回测其2010年1月1日至2020年4月21日期间的走势:
效果不是很好,本金10000元,最后剩余9892元,也就是还亏损了。从盈利和亏损点上来看,该策略确实亏损次数更多,比盈利次数多了一次。
不过这是我们基于限制性卖出的条件,如果是J值下穿K值作为卖出信号呢?
基于backtrader,我们做这样的买入卖出信号调整真的非常简单:
# Python 实用宝典 def next(self): self.log("Close, %.2f" % self.dataclose[0]) if self.order: return condition1 = self.J[-1] - self.D[-1] condition2 = self.J[0] - self.D[0] if not self.position: # J - D 值 if condition1 < 0 and condition2 > 0: self.log("BUY CREATE, %.2f" % self.dataclose[0]) self.order = self.buy() else: if condition1 > 0 or condition2 < 0: self.log("SELL CREATE, %.2f" % self.dataclose[0]) self.order = self.sell()
效果如何?
我勒个去,您这个不太靠谱啊,10000元本金只剩9029元了。
但是这样并没有足够证据否认这个策略的价值,接下来我们尝试将它和MACD策略结合在一起使用。
3.多策略回测
通过回测得到的图表,我发现,KDJ指标在决定买入信号的时候有很大的延迟,比MACD的买入信号延迟重得多,但是它的卖出信号却不错,很敏感。
所以我们可以考虑将MACD策略也引入进来,使用MACD决策买入,KDJ信号决策卖出。引入MACD策略相关变量:
# MACD策略参数 me1 = EMA(self.data, period=12) me2 = EMA(self.data, period=26) self.macd = me1 - me2 self.signal = EMA(self.macd, period=9) bt.indicators.MACDHisto(self.data)
至于为什么MACD策略是这么计算的,请看我们上一篇文章:Python 量化投资原来这么简单(2) —MACD策略(+26.9%)。所以我们的文章是环环相扣的哦,如果没有阅读,请记得回头补上。
从上面两张图中,大家可以看到两条变化非常大的线,这是两条3日EMA的线。我们可以将其取消掉,因为它们没有太多价值。加一个plot=False参数即可让它们不显示:
# 计算rsv的3周期加权平均值,即K值 self.K = bt.indicators.EMA(self.rsv, period=3, plot=False) # D值=K值的3周期加权平均值 self.D = bt.indicators.EMA(self.K, period=3, plot=False)
基于MACD策略的买入信号进行买入,KDJ策略的卖出信号进行卖出:
if not self.position: # 买入基于MACD策略 condition1 = self.macd[-1] - self.signal[-1] condition2 = self.macd[0] - self.signal[0] if condition1 < 0 and condition2 > 0: self.log('BUY CREATE, %.2f' % self.dataclose[0]) self.order = self.buy() else: # 卖出基于KDJ策略 condition1 = self.J[-1] - self.D[-1] condition2 = self.J[0] - self.D[0] if condition1 > 0 or condition2 < 0: self.log("SELL CREATE, %.2f" % self.dataclose[0]) self.order = self.sell()
回测效果如下:
最终得到10057.06,赚了57块钱。。当然,总比单纯KDJ策略不赚的好。但是这个策略依然存在问题,它在很多能赚大钱的时候,过于保险地将股票卖出了,以至于其亏损的次数其实大于盈利的次数。
当然,单纯从一只股票上我们是无法看出这个策略的整体好坏的,下一篇量化投资文章(大约在2020/05/09),我们将在A股中随机取1000只股票,来验证这个复合策略的整体收益。敬请期待Python实用宝典的最新更新哦。
我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。
有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。
原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!
Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典
非常实用!期待关于backtrader后续更新
大佬好,请问如何实时获取kdj中的各个指标,感谢赐教
实时请求相关接口进行计算