zoukankan      html  css  js  c++  java
  • WeQuant交易策略—KDJ

    KDJ随机指标策略

    策略介绍
    KDJ指标又叫随机指标,是一种相当新颖、实用的技术分析指标,它起先用于期货市场的分析,后被广泛用于股市的中短期趋势分析,是期货和股票市场上最常用的技术分析工具。

    随机指标KDJ一般是用于股票分析的统计体系,根据统计学原理,通过一个特定的周期(常为9日、9周等)内出现过的最高价、最低价及最后一个计算周期的收盘价及这三者之间的比例关系,来计算最后一个计算周期的未成熟随机值RSV,然后根据平滑移动平均线的方法来计算K值、D值与J值,并绘成曲线图来研判股票走势。适合趋势分析。

    计算公式
    (1)N日的RSV值(未成熟随机指标)
         RSV(n)=(Cn-Ln)÷(Hn-Ln)×100
    (2)计算K值
         K = 2/3 * 前一日K 值+ 1/3 * 当日RSV
    (3)计算D值
         D = 2/3 * 前一日D值+ 1/3 * 当日K值
    (4)计算J值
         J = 3 * D – 2 * K
    其中,Cn为第n日收盘价;Ln为n日内的最低价;Hn为n日内的最高价。

    当没有前一日的K值或D值时,用50来代替。

    使用方法
    由KDJ指标的公式我们可以看出,K值和D值一定位于0到100之间。根据KDJ的取值,可将其划分为几个区域,即超买区、超卖区和徘徊区。按一般划分标准,K、D、J这三值在20以下为超卖区,是买入信号;K、D、J这三值在80以上为超买区,是卖出信号;K、D、J这三值在20-80之间为徘徊区,宜观望。

    从变化趋势上看,K值比D值变化要快,而J值最快。我们可以从KDJ三条线的走势上判断行情。

    本策略在D<20, K线和D线同时上升,且K线从下向上穿过D线时,全仓买入;当 D>80, K线和D线同时下降,且K线从上向下穿过D线时,全仓卖出。
     
    优点
    KDJ指标在计算中考虑了计算周期内的最高价、最低价,兼顾了股价波动中的随机振幅,因而人们认为随机指标更真实地反映股价的波动,其提示作用更加明显。

    缺点
    (1) 在短期波动剧烈或者瞬间行情幅度太大时,使用KD值交叉讯号买卖,经常发生买在高点、卖在低点的窘境。
    (2) 极强或者极弱的行情,会造成指标在超买或超卖区内上下徘徊,反复震荡,出现来回金叉死叉的钝化现象,此时KDJ指标的状态让投资者无法继续按照买卖标准继续使用。

    KDJ指标较为适用于震荡的行情,通过对超买超卖的判断以及价格走势的分析来产生交易信号。这里使用30分钟频率来回测,所以回看周期不宜过大,否则会有很大的滞后性。
    在急速的上涨和下跌中反应的都很慢,甚至出现的高买低卖的现象。所以在使用KDJ指标时,要结合其他指标一起使用,对行情有所判断,不能盲目交易。

    总结
    KDJ指标利用一段时间的最高价、最低价以及收盘价,绘制出了3条参考线。利用这三条线,可以有很多种不同的使用方法。KDJ比较适合在中短期的震荡行情中使用,而在单边行情或是急剧的大幅震荡中效果不佳,使用者需要结合其他指标对行情进行判断,再考虑择机使用。

    代码

    # !/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    # 策略代码总共分为三大部分,1)PARAMS变量 2)initialize函数 3)handle_data函数
    # 请根据指示阅读。或者直接点击运行回测按钮,进行测试,查看策略效果。
    
    # 策略名称:KDJ指标策略
    # 策略详细介绍:https://wequant.io/study/strategy.kdj.html
    # 关键词:随机指标、中短期。
    # 方法:
    # 1)通过特定周期内的最高价、最低价、收盘价以及移动平均线法计算KDJ值;
    # 2)用KDJ判断超买超卖线,超买则卖出,超卖则买入。
    
    
    import numpy as np
    import talib
    
    # 阅读1,首次阅读可跳过:
    # PARAMS用于设定程序参数,回测的起始时间、结束时间、滑点误差、初始资金和持仓。
    # 可以仿照格式修改,基本都能运行。如果想了解详情请参考新手学堂的API文档。
    PARAMS = {
        "start_time": "2017-02-01 00:00:00",  # 回测起始时间
        "end_time": "2017-08-01 00:00:00",  # 回测结束时间
        "slippage": 0.003,  # 此处"slippage"包含佣金(千二)+交易滑点(千一)
        "account_initial": {"huobi_cny_cash": 100000,
                          "huobi_cny_btc": 0},  # 设置账户初始状态
    }
    
    
    # 阅读2,遇到不明白的变量可以跳过,需要的时候回来查阅:
    # initialize函数是两大核心函数之一(另一个是handle_data),用于初始化策略变量。
    # 策略变量包含:必填变量,以及非必填(用户自己方便使用)的变量
    def initialize(context):
        # 设置回测频率, 可选:"1m", "5m", "15m", "30m", "60m", "4h", "1d", "1w"
        context.frequency = "30m"
        # 设置回测基准, 比特币:"huobi_cny_btc", 莱特币:"huobi_cny_ltc", 以太坊:"huobi_cny_eth"
        context.benchmark = "huobi_cny_btc"
        # 设置回测标的, 比特币:"huobi_cny_btc", 莱特币:"huobi_cny_ltc", 以太坊:"huobi_cny_eth"
        context.security = "huobi_cny_btc"
    
        # 设置策略的参数
        # 快线回看周期为9
        context.user_data.fastk_period = 9
        # 慢线回看周期为3
        context.user_data.slowk_period = 3
        context.user_data.slowd_period = 3
        # 使用简单平均
        context.user_data.slowk_matype = 0
        # 每个frequency读取历史数据的bar数
        context.user_data.longest_history = 100
        # 超买信号线
        context.user_data.over_buy_signal = 80
        # 超卖信号线
        context.user_data.over_sell_signal = 20
    
        # 至此initialize函数定义完毕。
    
    
    # 阅读3,策略核心逻辑:
    # handle_data函数定义了策略的执行逻辑,按照frequency生成的bar依次读取并执行策略逻辑,直至程序结束。
    # handle_data和bar的详细说明,请参考新手学堂的解释文档。
    def handle_data(context):
        # 获取历史数据, 取后longest_history根bar
        hist = context.data.get_price(context.security, count=context.user_data.longest_history, frequency=context.frequency)
        if len(hist.index) < context.user_data.longest_history:
            context.log.warn("bar的数量不足, 等待下一根bar...")
            return
        # 最高价
        high_prices = np.array(hist["high"])
        # 最低价
        low_prices = np.array(hist["low"])
        # 收盘价
        close_prices = np.array(hist["close"])
    
        # matype: 0=SMA, 1=EMA, 2=WMA, 3=DEMA, 4=TEMA, 5=TRIMA, 6=KAMA, 7=MAMA, 8=T3 (Default=SMA)
        # 用talib计算K,D两条线
        K, D = talib.STOCH(high_prices, low_prices, close_prices, fastk_period=context.user_data.fastk_period, 
        slowk_matype=context.user_data.slowk_matype, slowk_period=context.user_data.slowk_period, slowd_period=context.user_data.slowd_period)
        current_k_value = K[-1]
        current_d_value = D[-1]
        previous_k_value = K[-2]
        previous_d_value = D[-2]
    
        long_signal_triggered = False
        short_signal_triggered = False
    
        context.log.info("当前 K = %s, D = %s; 前一周期 K = %s, D = %s" % (current_k_value, current_d_value, previous_k_value, previous_d_value))
    
        # 生成买入/卖出信号
        # 当D < 超卖线, K线和D线同时上升,且K线从下向上穿过D线时,买入
        if current_d_value < context.user_data.over_sell_signal and current_d_value > previous_d_value and 
            current_k_value > previous_k_value and previous_k_value < previous_d_value and current_k_value > current_d_value:
            long_signal_triggered = True
        # 当D > 超买线, K线和D线同时下降,且K线从上向下穿过D线时,卖出
        elif current_d_value > context.user_data.over_buy_signal and current_d_value < previous_d_value and 
            current_k_value < previous_k_value and previous_k_value > previous_d_value and current_k_value < current_d_value:
            short_signal_triggered = True
    
        # 有卖出信号,卖出全部仓位
        if short_signal_triggered:
            if context.account.huobi_cny_btc >= HUOBI_CNY_BTC_MIN_ORDER_QUANTITY:
                context.log.info("产生卖出信号")
                # 若持有仓位,则全仓卖出
                if context.account.huobi_cny_btc >= HUOBI_CNY_BTC_MIN_ORDER_QUANTITY:
                    context.log.info("正在卖出 %s" % context.security)
                    context.log.info("卖出数量为 %s" % context.account.huobi_cny_btc)
                    context.order.sell(context.security, quantity=str(context.account.huobi_cny_btc))
                else:
                    context.log.info("仓位不足,无法卖出")
        # 有买入信号,全仓买入
        elif long_signal_triggered:
            context.log.info("产生买入信号")
            if context.account.huobi_cny_cash >= HUOBI_CNY_BTC_MIN_ORDER_CASH_AMOUNT:
                context.log.info("正在买入 %s" % context.security)
                context.log.info("下单金额为 %s 元" % context.account.huobi_cny_cash)
                context.order.buy(context.security, cash_amount=str(context.account.huobi_cny_cash))
            else:
                context.log.info("现金不足,无法下单")
        else:
            context.log.info("无交易信号,进入下一根bar")

    15m

    30m

     

    60m

     

    4h

     

    1d

     

  • 相关阅读:
    How to alter department in PMS system
    Can't create new folder in windows7
    calculate fraction by oracle
    Long Wei information technology development Limited by Share Ltd interview summary.
    ORACLE BACKUP AND RECOVERY
    DESCRIBE:When you mouse click right-side is open an application and click left-side is attribution.
    ORACLE_TO_CHAR Function
    电脑BOIS设置
    JSP点击表头排序
    jsp+js实现可排序表格
  • 原文地址:https://www.cnblogs.com/bitquant/p/wequant-strategy-kdj.html
Copyright © 2011-2022 走看看