Python版简单的KDJ策略

Author: 雨幕, Created: 2019-10-26 10:13:36, Updated: 2023-12-07 20:28:46

img

KDJ指标简介

技术分析中最常用的三大指标之一KDJ,相信那些交易老手已经不陌生了。KDJ的全名叫“随机指标”,它是一种很新颖,并且很实用的技术分析指标,最早起先用于股票市场,后被广泛用于期货和外汇的中短期趋势分析,也是金融交易市场上最常用的技术分析工具。

KDJ是通过统计学原理,通过9根K线内出现过的最高价、最低价、最新的收盘价三者之间的比例关系,来计算随机值(RSV),然后根据平滑移动平均线的方法来计算K值、D值与J值,并绘成曲线图来研判价格走势。

img

由于融合了动量观念、强弱指标和移动平均线的一些优点,来度量股价脱离价格正常范围的变异程度。因此,能够比较迅速、快捷、直观地研判行情。当K值大于D值时,表明股价当前正处于上升趋势之中,因此,当K线从下向上交叉突破D线时,正是买进股票的时机。反之,当K值小于D值时,表明股市当前处于下降趋势。因此,当K线从上向下交叉突破D线时,正是卖出股票的时机。

KDJ指标计算方法

KDJ指标的计算比较复杂,首先计算出随机值(RSV),然后再计算K值、D值和J值。其计算方法如下:

  • RSV = (收盘价-N周期最低价)/(N周期最高价-N周期最低价)*100
  • K值 = RSV的N周期平均值
  • D值 = K值的N周期平均值
  • J值 = 3K值-2D值

我们可以用Python代码简单的表示为:

arr = TA.KDJ(r, 9, 3, 3) ## 计算KDJ指标,这里用到了二维数组。
k = arr[0][-2] ## 获取上根K线KDJ指标的K值
d = arr[1][-2] ## 获取上根K线KDJ指标的D值
dPre = arr[1][-3] ## 获取上上根K线KDJ指标的D值

策略逻辑

KDJ的使用方法有很多,可以单独使用,也可以和其他指标结合在一起使用。 本节教程我们将用最简单的使用方法,来抛砖引玉。即:如果K值大于D值,我们认为多方力量正在走强,一波上涨行情已经形成,买入开仓信号产生;如果K值小于D值,我们认为空方力量正在走强,一波下跌趋势已经形成,卖出开仓信号产生。

img

如果买入开仓后,D值由向上转为向下,我们认为多方力量正在走弱,或者空方力量正在加强,卖出平仓信号产生;如果卖出开仓后,D值由向下转为向上,我们认为空方力量正在走弱,或者多方力量正在加强,买入平仓信号产生。

买卖条件

  • 多头开仓:如果无持仓,并且K值大于D值
  • 空头开仓:如果无持仓,并且K值小于D值
  • 多头平仓:如果持多单,并且D值小于上根K线的D值
  • 空头平仓:如果持空单,并且D值大于上根K线的D值

策略代码实现

用代码实现策略的第一步,就是先考虑我们需要什么数据?通过什么API去获取?然后获取数据滞后,如何计算交易逻辑?最后通过哪些方式下单方式去交易?接下来,让我们一步一步来实现吧:

第一步:架构和交易类库

所谓的策略架构就是设计整个策略的方式,如下图所示,该架构由2个函数构成:一个是main主函数,程序是从主函数开始执行代码,它的功能是处理策略逻辑核心之外的事情,比如:判断与交易所连接是否正常、过滤一些不必要的日志信息、控制执行策略逻辑核心执行的时间间隔等等;另一个是onTick函数,在这个函数里面,主要编写策略逻辑,包括:获取原始数据、计算数据、下单买卖等等。

def onTick(): 
    ## 这里是我们整个策略的核心判断逻辑以及具体的下单操作

def main():  ## 程序从这里开始执行代码
    if not onTick(): ## 这里先判断onTick函数是否正常
        Sleep(1000) ## 休眠一秒钟,然后开始重试

第二步:获取各种数据

各种原始数据是组成交易逻辑的重要部分,仔细想下,都需要哪些数据呢?从我们的策略交易逻辑中发现:首先需要需要获取K线数据,有了原始的K线数据,就可以计算出KDJ指标了,最后比较K值与D值的相互关系,判断是否下单。那么接下来让我们一以获取这些数据吧。

  • 获取K线数据

首先就是获取K线数组,因为有了K线数组,才能计算出KDJ指标。用代码写出来是这样的:

def onTick():
ct = exchange.SetContractType("rb888") ## 设置合约代码,方面后边的容错判断
    
    position = 0 ## 定义变量用来储存持仓状态和方向,初始为0,代表为空仓
    
    if ct == false: ## 如果设置合约不成功
        return false ## 返回false
    
    r = exchange.GetRecords() ## 获取K线数组,这里用到了发明者量化的API,可以为你省去很多再去自己写逻辑判断的时间和精力
    if len(r) < 10: ## 如果K线数量少于10根
        return false ## 返回false

我们把以上代码写入onTick函数中,注意其中的注释部分,有非常详细的逻辑说明。

  • 获取KDJ指标以及K值和D值

接着就需要计算KDJ指标的K值和D值了。那就要先获取KDJ指标数组,在从数组中获取K值和D值。在发明者量化工具中,获取KDJ数组还很简单,直接调用KDJ的API就可以了,难的是获取K值和D值,因为KDJ数组是一个二维数组。

二维数组其实很好理解,它就是数组中的数组,那么获取的顺序就是:先获取数组中指定的数组,然后在从指定的数组中获取指定的元素,如下所示:

def onTick():
ct = exchange.SetContractType("rb888") ## 设置合约代码,方面后边的容错判断
    
    position = 0 ## 定义变量用来储存持仓状态和方向,初始为0,代表为空仓
    
    if ct == false: ## 如果设置合约不成功
        return false ## 返回false
    
    r = exchange.GetRecords() ## 获取K线数组,这里用到了发明者量化的API,可以为你省去很多再去自己写逻辑判断的时间和精力
    if len(r) < 10: ## 如果K线数量少于10根
        return false ## 返回false

    arr = TA.KDJ(r, 9, 3, 3) ## 计算KDJ指标,这里用到了二维数组。
    k = arr[0][-2] ## 获取上根K线KDJ指标的K值
    d = arr[1][-2] ## 获取上根K线KDJ指标的D值
    dPre = arr[1][-3] ## 获取上上根K线KDJ指标的D值

这里我们继续添加OnTick函数的内容,如上,我们直接使用发明者量化工具的API(arr = TA.KDJ),获取KDJ指标数组,这是一个二维数组:arr = [[K值, K值, K值…], [D值, D值, D值…], [J值, J值, J值…]]。

第三步:下单交易

有了以上数据,就可以编写交易逻辑以及下单交易的代码了。格式也非常简单,最常用到的是“if语句”,用文字可以描述为:如果条件1和条件2成立,下单;如果条件3或条件4成立,下单。如下所示:

def onTick(): ## 首先我们定义一个onTick函数,策略的核心逻辑都在这个函数内
    ct = exchange.SetContractType("rb888") ## 设置合约代码,方面后边的容错判断
    
    position = 0 ## 定义变量用来储存持仓状态和方向,初始为0,代表为空仓
    
    if ct == false: ## 如果设置合约不成功
        return false ## 返回false
    
    r = exchange.GetRecords() ## 获取K线数组,这里用到了发明者量化的API,可以为你省去很多再去自己写逻辑判断的时间和精力
    if len(r) < 10: ## 如果K线数量少于10根
        return false ## 返回false

    arr = TA.KDJ(r, 9, 3, 3) ## 计算KDJ指标,这里用到了二维数组。
    k = arr[0][-2] ## 获取上根K线KDJ指标的K值
    d = arr[1][-2] ## 获取上根K线KDJ指标的D值
    dPre = arr[1][-3] ## 获取上上根K线KDJ指标的D值

    action = "" ## 定义一个变量用来储存将要执行的开仓平仓操作信号,初始值我们设置为空。
    
    ## 如果上根K线的D值小于上上根K线的D值,并且持有多单,就全部平仓
    ## 如果上根K线的D值大于上上根K线的D值,并且持有空单,就全部平仓

    if (d < dPre and position > 0) or (d > dPre and position < 0):
        action = 'cover'
    
    elif (k > d and position <= 0):  ## 如果上根K线的K值大于上根K线的D值,并且没有持有多单
        action = 'buy'   ## 把变量action设置为buy

    elif (k < d and position >= 0):  ## 如果上根K线的K值小于上根K线的D值,并且没有持有空单
        action = 'sell'  ## 把变量action设置为sell

    ## 这里需要注意的是,我们需要用到发明者量化平台的国内商品期货模版,模版地址为:https://www.fmz.cn/strategy/24288 各位在发明者量化策略编写页面进行编码时,需要把此模版先复制到自己的策略库,然后在回测时勾选上,这里请各位读者注意

    obj = ext.NewPositionManager()  ## 发明者量化平台的国内商品期货模版

    if action == 'cover': ## 根据action的值来进行平仓操作
        obj.CoverAll()
    
    if action == 'buy':  ## 根据action的值来进行开多操作
        obj.OpenLong("rb888", 1)
    
    if action == 'sell':  ## 根据action的值来进行开空操作
        obj.OpenShort("rb888", 1)
        
    return true ## 返回true


def main():  ## 程序从这里开始执行代码
    if not onTick(): ## 这里先判断onTick函数是否正常
        Sleep(1000) ## 休眠一秒钟,然后开始重试

有两个地方需要注意:

  • 尽量(但不是必须)把策略逻辑写成当根K线条件成立,下根K线发单,或者上根K线条件成立,当根K线发单,这样回测的结果与实盘的结果相差不大。不这样写也可以,但是要注意策略逻辑是否正确。

  • 一般而言,把平仓的逻辑写在开仓逻辑的前面,这样做的目的是,尽量让策略逻辑符合你的预期。比如:如果策略逻辑刚好赶上反手的时候,反手的规则是,先平仓再开新仓。而不是先开新仓,再平仓。如果我们直接把平仓逻辑写到开仓逻辑前面,就不会出现这种问题。

以上我们学习了如何分析KDJ技术指标,并把它转换成一个完整的量化交易策略。包括:策略简介、KDJ指标的计算方法、策略逻辑、买卖条件、策略代码实现等。通过这个策略案例,不仅熟悉发明者量化工具的编程方法,还可以根据本节的案例改编成不同的策略。

实现量化交易策略就是总结自己的主观交易经验或系统,然后分别获取所需要的原始数据,并根据这些原始数据,计算出下单逻辑所需要的数据,最后调用下单API实现买卖交易。可以说大部分简单的量化交易策略,都是按照这个步骤实现的!


相关内容

更多内容