您好,登录后才能下订单哦!
本篇文章给大家分享的是有关VNPY中基于Ta-lib的KDJ策略怎样实现,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
VNPY自带演示策略中,没有kdj策略,作为一个国内常用策略,这里讲讲怎么实现。
首先,Ta-lib这个python库里面并没有提供kdj策略,估计主要因为这个策略主要在流行,不过ta-lib提供了类似的方法STOCH()。可以实现KD效果。
那么首先为class ArrayManager新增一个方法kdj,来输出KDJ值。我是直接修改ctaTemplate.py 文件,更合适方法是继承class ArrayManager。
def kdj(self, fastk_period, slowk_period, slowk_matype ,slowd_period ,slowd_matype, array=False):
				        """KDJ指标"""
				        slowk, slowd = talib.STOCH(self.high,self.low,self.close,fastk_period, slowk_period,
				                                         slowk_matype, slowd_period ,slowd_matype)
				        # 求出J值,J = (3 * D) - (2 * K)
				        slowj = list(map(lambda x,y: 3 * x - 2 * y, slowk, slowd))
				        if array:
				            return slowk, slowd, slowj
return slowk[-1], slowd[-1], slowj[-1]
上面是新增的kdj功能,首先是利用SHOCH计算出kd,在利用kd算出j,输出kdj三个指标。
SHOCH计算需要每条k线中的最高值,最低值,和结束值参数,作为list数列提供;这个直接使用ArraManger提供值;然后是fastK_period, slowk_period和slowd_period, 这个就是kdj设定中常见的N,M1,M2三个窗口参数, 通常设置是(9,3,3)。
然后是slowk_matype, slowd_matype就是平均算法类型,这里可以用SMA滑动平均或EMA指数平滑移动平均等。为了和文华一致,用了SMA。
#MA_Type: 0=SMA, 1=EMA, 2=WMA, 3=DEMA, 4=TEMA, 5=TRIMA, 6=KAMA, 7=MAMA, 8=T3 (Default=SMA)
这个后来发现不是一回事,Ta-lib中的SMA中S是simple简单的意思,SMA是简单移动平均。和文华SMA不一样,文华SMA是指数加权移动平均线,这样的化用EWMA更合适。但是Ta-lib本身并不提供提供EWMA;按照下图发现默认权重为1; EMA或者较为合适,不过此时权重为2。
后来看着此文又不是一回事,以后有空填这个坑。
https://www.joinquant.com/post/7920

j值不提供直接只算,直接用kd值,用3*k-2*d算出j值。对了这些返回都是一堆kdj组list,就是可以画成一个线。如果是array是false就返回一个点的kdj值。
好了上面就是对 ArrayManager增加一个kdj方法,在下来就是继承CtaTemplate, 生成策略,这里基本就是
买入思想就是k或d小于某个阈值时候为超卖,当k大于d,就是描述里面K线上穿d线时候,开多单。反之k或d值大于阈值多超买,那么此时k小于d,开空单。。
如果持有多头,那么因为j更加敏感,用j值来做平仓指标. 如果持有多单,,如果j小于d,即j线下穿d线时候卖出多单,或者j值快速下降,下降幅度大于定好的jlimit。。
如果持有空头,同理,如果j大于d,或者j快速增大则平仓。
代码如下:
# encoding: UTF-8
"""
				这里的Demo是一个kdj策略实现
				"""
from __future__ import division
from vnpy.trader.vtConstant import EMPTY_STRING, EMPTY_FLOAT
from vnpy.trader.app.ctaStrategy.ctaTemplate import (CtaTemplate,
				                                                     BarGenerator,
				                                                     ArrayManager)
from talib import MA_Type
				########################################################################
class KDJStrategy(CtaTemplate):
				    """KDJ策略Demo"""
				    className = 'KDJStrategy'
				    author = u'BillyZhang'
				    # 策略参数
				    fastk_period = 9
				    slowk_period = 3
				    slowk_matype = MA_Type.EMA
				    slowd_period = 3
				    slowd_matype = MA_Type.EMA
				    kdlimit = 20
				    jlimit = 10
				    initDays = 10
				    fixedSize = 1
				    barmins = 15
				    # 策略变量
				    k = 0
				    d = 0
				    j = 0
				    # 参数列表,保存了参数的名称
				    paramList = ['name',
				                 'className',
				                 'author',
				                 'vtSymbol',
				                 'fastk_period',
				                 'slowk_period',
				                 'slowk_matype',
				                 'slowd_period',
				                 'slowd_matype',
				                 'fixedSize'
				                 'barmins'
				                 ]
				    # 变量列表,保存了变量的名称
				    varList = ['inited',
				               'pos',
				               'k',
				               'd',
				               'j']
				    # 同步列表,保存了需要保存到数据库的变量名称
				    syncList = ['pos']
				    # ----------------------------------------------------------------------
				    def __init__(self, ctaEngine, setting):
				        """Constructor"""
				        super(KDJStrategy, self).__init__(ctaEngine, setting)
				        self.bg = BarGenerator(self.onBar, self.barmins, self.onXminBar)
				        self.am = ArrayManager()
				        # 注意策略类中的可变对象属性(通常是list和dict等),在策略初始化时需要重新创建,
				        # 否则会出现多个策略实例之间数据共享的情况,有可能导致潜在的策略逻辑错误风险,
				        # 策略类中的这些可变对象属性可以选择不写,全都放在__init__下面,写主要是为了阅读
				        # 策略时方便(更多是个编程习惯的选择)
				    # ----------------------------------------------------------------------
				    def onInit(self):
				        """初始化策略(必须由用户继承实现)"""
				        self.writeCtaLog(u'KDJ策略初始化')
				        initData = self.loadBar(self.initDays)
				        for bar in initData:
				            self.onBar(bar)
				        self.putEvent()
				    # ----------------------------------------------------------------------
				    def onStart(self):
				        """启动策略(必须由用户继承实现)"""
				        self.writeCtaLog(u'KDJ策略启动')
				        self.putEvent()
				    # ----------------------------------------------------------------------
				    def onStop(self):
				        """停止策略(必须由用户继承实现)"""
				        self.writeCtaLog(u'KDJ策略停止')
				        self.putEvent()
				    # ----------------------------------------------------------------------
				    def onTick(self, tick):
				        """收到行情TICK推送(必须由用户继承实现)"""
				        self.bg.updateTick(tick)
				    # ----------------------------------------------------------------------
				    def onBar(self, bar):
				        """收到Bar推送(必须由用户继承实现)"""
				        self.bg.updateBar(bar)
				    # ----------------------------------------------------------------------
				    def onXminBar(self, bar):
				        """收到Bar推送(必须由用户继承实现)"""
				        am = self.am
				        am.updateBar(bar)
				        if not am.inited:
				            return
				        # 计算kdj数值
				        slowk, slowd, slowj = am.kdj(self.fastk_period, self.slowk_period, self.slowk_matype,
				                                     self.slowd_period, self.slowd_matype, array=True)
				        self.k = slowk[-1]
				        self.d = slowd[-1]
				        self.j = slowj[-1]
				        self.jdif = slowj[-1] - slowj[-2]
				        tradeindictor = 0
				        if self.k > (100 - self.kdlimit) or self.d > (100 - self.kdlimit):
				            tradeindictor = -1
				        if self.k < self.kdlimit or self.d < self.kdlimit:
				            tradeindictor = 1
				        # 当前无仓位,发送开仓委托
				        if self.pos == 0:
				            self.intraTradeHigh = bar.high
				            self.intraTradeLow = bar.low
				            # 如果k值大于d值均线,开多单;反之,如果如果k值小于d值时候开空单
				            if self.k > self.d and tradeindictor == 1:
				                self.buy(bar.close, self.fixedSize, False)
				            elif self.k < self.d and tradeindictor == -1:
				                self.short(bar.close, self.fixedSize, False)
				        # 持有多头仓位; 如果j小于d,或者j最近两个k线,j值下跌超过jlimi平仓, :
				        elif self.pos > 0:
				            if self.j < self.d or self.jdif < -1 *self.jlimit:
				                self.sell(bar.close * 1.03, abs(self.pos))
				        # 持有空头仓位;如果j大于d,或j快速上扬 平仓;
				        elif self.pos < 0:
				            if self.j > self.d or self.jdif > self.jlimit:
				                self.cover(bar.close * 0.97, abs(self.pos))
				        # 同步数据到数据库
				        self.saveSyncData()
				        # 发出状态更新事件
				        self.putEvent()
				    # ----------------------------------------------------------------------
				    def onOrder(self, order):
				        """收到委托变化推送(必须由用户继承实现)"""
				        # 对于无需做细粒度委托控制的策略,可以忽略onOrder
				        pass
				    # ----------------------------------------------------------------------
				    def onTrade(self, trade):
				        """收到成交推送(必须由用户继承实现)"""
				        # 对于无需做细粒度委托控制的策略,可以忽略onOrder
				        pass
				    # ----------------------------------------------------------------------
				    def onStopOrder(self, so):
				        """停止单推送"""
pass
以上就是VNPY中基于Ta-lib的KDJ策略怎样实现,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。