Home >  > 三根K线策略2

三根K线策略2

一、修改的内容
将原来的 has_callback 和 has_rebound 简单布尔逻辑,替换为:

统计 cb_count(下跌根数)和 rb_count(上涨根数)。

has_callback = (cb_count >= 2) 。

has_rebound = (rb_count >= 2)(至少2根上涨,保持原有宽松条件,你可以根据需要自行增加限制)。

二、测试结果
1.策略研究
(1)纯碱9.24行情没有开单
20240826 00:00 ZCE|F|SA|609 买平 限价单 1 1579 31580.00 1 -280.00 1.00 0.00
20250220 00:00 ZCE|F|SA|609 买开 限价单 1 1532 30640.00 1 0.00 1.00 0.00

(2)棕榈的2022.6.9-6.28这一波大跌也没有开仓
不符合has_callback的条件。
20230529 00:00 DCE|F|P|2609 卖开 限价单 1 6694 66940.00 1 0.00 1.00 0.00
20230602 00:00 DCE|F|P|2609 买平 限价单 1 6470 64700.00 1 2240.00 1.00 0.00
20230725 00:00 DCE|F|P|2609 买开 限价单 1 7680 76800.00 1 0.00 1.00 0.00
20230728 00:00 DCE|F|P|2609 卖平 限价单 1 7654 76540.00 1 -260.00 1.00 0.00

2.代码

# 极智量化策略:MA10斜率 + 回调突破 + 动态止盈止损
# 适用周期:推荐1分钟、5分钟或日线
# 作者:量化交易高手
# 说明:
#   开多:MA10向上,价格在MA10之上,近3根K线内有回调(收盘低于前一根),
#        当前Bar收盘价突破前一根Bar高点。
#   开空:MA10向下,价格在MA10之下,近3根K线内有反弹(收盘高于前一根),
#        当前Bar收盘价跌破前一根Bar低点。
#   止损:多单止损为前一根Bar最低价 - 1个最小变动价位;
#         空单止损为前一根Bar最高价 + 1个最小变动价位。
#   止盈:多单平仓条件:MA10斜率转下 或 收盘价跌破前一根Bar低点;
#         空单平仓条件:MA10斜率转上 或 收盘价突破前一根Bar高点。

import talib
import numpy as np

# ----- 策略参数(可优化) -----
ma_len = 10              # 均线周期
max_cb = 3               # 允许的回调/反弹K线根数(此处用于检测是否有回调/反弹)
qty = 1                  # 固定下单手数(可根据资金调整)

# ----- 策略初始化 -----
def initialize(context):
    # 设置基准合约(建议通过界面添加合约,此处示例用郑商所白糖主连)
    # 用户可改为自己的合约代码,或直接通过界面设置
    # SetBarInterval('ZCE|Z|SR|MAIN', 'M', 1, 200)
    # 若通过界面设置了合约,可注释掉上行,用界面合约作为基准
    SetTriggerType(5)          # K线触发(回测和实盘均适用)
    SetOrderWay(2)             # K线稳定后发单(推荐回测,实盘可改为1实时发单)
    # 设置初始资金、手续费等(可选)
    # SetInitCapital(1000000)
    # SetTradeFee('A', 2, 5)   # 固定手续费5元/手
    # SetSlippage(1)           # 滑点1跳
    LogInfo("策略初始化完成,MA周期:%d,回调允许根数:%d" % (ma_len, max_cb))

# ----- 策略主逻辑 -----
def handle_data(context):
    # 获取基准合约的K线数据(若需多合约,可自行扩展)
    close = Close()  ##获取当前基准合约、基准周期的所有收盘价历史序列(一个数组)
    high = High()
    low = Low()
    
    # 确保数据足够计算均线
    if len(close) < ma_len + 2:
        return
    
    # 计算10日均线
    ma = talib.SMA(close, ma_len)
    
    # 当前Bar索引(用于判断数据就绪)
    bar_idx = CurrentBar()
    if bar_idx < ma_len + 2:
        return
    
    # ---- 构造当前K线时间字符串(格式:YYYYMMDD HH:MM:SS) ----
    date_str = str(Date())
    t = Time()
    # Time() 返回 0.HHMMSS,转换为整数秒
    time_int = int(t * 1000000)          # 例如 0.113421 -> 113421
    hh = time_int // 10000
    mm = (time_int // 100) % 100
    ss = time_int % 100
    cur_time_str = "%s %02d:%02d:%02d" % (date_str, hh, mm, ss)
    
    # ---- 获取关键价格 ----
    cur_close = close[-1]
    cur_high = high[-1]
    cur_low  = low[-1]
    prev_high = high[-2]   # 前一根Bar最高价
    prev_low  = low[-2]    # 前一根Bar最低价
    ma_cur = ma[-1]
    ma_prev = ma[-2]
    
    # ---- 判断MA10斜率 ----
    ma_up = ma_cur > ma_prev      # 均线向上
    ma_down = ma_cur < ma_prev    # 均线向下
    
    # ---- 判断价格与MA10的关系 ----
    above_ma = cur_close > ma_cur
    below_ma = cur_close < ma_cur
    
    # ---- 检测近3根K线是否有回调(收盘低于前一根)或反弹(收盘高于前一根) ----
    # 采用“层次一 + 层次二”组合:统计下跌/上涨根数 + 是否触及均线
    cb_count = 0
    rb_count = 0
    if len(close) >= 4:
        for i in range(1, 4):  # i=1,2,3 分别对应前1、前2、前3根
            if close[-i] < close[-i-1]:
                cb_count += 1
            if close[-i] > close[-i-1]:
                rb_count += 1

    # 回调:至少2根下跌
    has_callback = (cb_count >= 2) 
    # 反弹:至少2根上涨 + 且没有真回踩(即价格一直在均线之上反弹),注意这里对反弹的判定也加上了“不触及均线”以区分回调
    # 为简化,这里沿用原意:只要反弹根数>=2就算,但也可增加条件,这里按“层次一”处理,暂不加额外限制,仅使用根数
    has_rebound = (rb_count >= 2)

    # ---- 开仓信号 ----
    # 多单开仓条件:MA向上,价格在MA之上,有回调(至少一根阴线),且当前收盘突破前一根高点
    if ma_up and above_ma and has_callback and cur_close > prev_high:
        if MarketPosition() == 0:   # 无持仓时开多
            Buy(qty, cur_close)
            LogInfo("[%s] 开多仓,价格:%.2f,MA10:%.2f,前高:%.2f" % (cur_time_str, cur_close, ma_cur, prev_high))
            # 记录止损价(前一根低点 - 1跳)
            context.stop_loss = prev_low - PriceTick()
            # 记录开仓价(用于止盈参考)
            context.entry_price = cur_close
            # 记录开仓时均线斜率
            context.ma_up_at_entry = ma_up
    
    # 空单开仓条件:MA向下,价格在MA之下,有反弹(至少一根阳线),且当前收盘跌破前一根低点
    if ma_down and below_ma and has_rebound and cur_close < prev_low:
        if MarketPosition() == 0:
            SellShort(qty, cur_close)
            LogInfo("[%s] 开空仓,价格:%.2f,MA10:%.2f,前低:%.2f" % (cur_time_str, cur_close, ma_cur, prev_low))
            context.stop_loss = prev_high + PriceTick()
            context.entry_price = cur_close
            context.ma_up_at_entry = ma_up  # 开空时记录当前斜率(应为False)
    
    # ---- 持仓管理(止盈止损) ----
    if MarketPosition() == 1:   # 持多仓
        # 止损:价格跌破止损价
        if cur_close <= context.stop_loss:
            Sell(0, cur_close)   # 平多(数量0表示平全部)
            LogInfo("[%s] 多仓止损,价格:%.2f,止损价:%.2f" % (cur_time_str, cur_close, context.stop_loss))
        # 止盈条件1:MA斜率转下(反转走掉)
        elif ma_down:   # 均线由向上转为向下
            Sell(0, cur_close)
            LogInfo("[%s] 多仓止盈(均线转下),价格:%.2f" % (cur_time_str, cur_close))
        # 止盈条件2:跌破前一根低点(涨不动了)
        elif cur_close < low[-2]:
            Sell(0, cur_close)
            LogInfo("[%s] 多仓止盈(跌破前低),价格:%.2f,前低:%.2f" % (cur_time_str, cur_close, low[-2]))
        # 其他情况可添加动态止盈(如移动止损),此处暂略
    
    elif MarketPosition() == -1:  # 持空仓
        # 止损:价格突破止损价
        if cur_close >= context.stop_loss:
            BuyToCover(0, cur_close)
            LogInfo("[%s] 空仓止损,价格:%.2f,止损价:%.2f" % (cur_time_str, cur_close, context.stop_loss))
        # 止盈条件1:MA斜率转上(反转走掉)
        elif ma_up:
            BuyToCover(0, cur_close)
            LogInfo("[%s] 空仓止盈(均线转上),价格:%.2f" % (cur_time_str, cur_close))
        # 止盈条件2:突破前一根高点(涨不动了)
        elif cur_close > high[-2]:
            BuyToCover(0, cur_close)
            LogInfo("[%s] 空仓止盈(突破前高),价格:%.2f,前高:%.2f" % (cur_time_str, cur_close, high[-2]))
    
    # 可选:记录策略运行信息
    # LogDebug("当前Bar:%d,收盘:%.2f,MA10:%.2f,持仓:%d" % (CurrentBar(), cur_close, ma_cur, MarketPosition()))

    # ---- 绘制指标 ----
    # 在主图上绘制MA10均线(红色)
    PlotNumeric("MA10", ma_cur, RGB_Red())

    # 在副图上绘制累计盈亏曲线(紫色,独立坐标)
    PlotNumeric("Profit", NetProfit() + FloatProfit() - TradeCost(), RGB_Purple(), False, True)

# ----- 历史阶段结束回调(可选) -----
def hisover_callback(context):
    # 平掉所有持仓(如果策略在历史结束时需要平仓)
    if MarketPosition() == 1:
        Sell(0, Close()[-1])
        LogInfo("历史阶段结束,多仓平仓")
    elif MarketPosition() == -1:
        BuyToCover(0, Close()[-1])
        LogInfo("历史阶段结束,空仓平仓")
    LogInfo("历史回测结束")

# ----- 策略退出回调(可选) -----
def exit_callback(context):
    LogInfo("策略退出")

暧昧帖

本文暂无标签