🚀 AI 一键生成 qmt 策略代码

QMT `passorder` 函数 `quickTrade` 参数详解:如何实现信号立即触发下单?

qmt | 发布时间: 2025/12/15
以下内容由 EasyQuant 生成。

问题描述

如何让我的交易信号在K线没走完时就立即下单,而不是等到下一根K线?

解决方案

在 QMT 中,默认的交易机制是K线走完确认信号后,在下一根K线的第一个Tick下单

如果您希望在信号触发的当前K线(盘中)立即下单,主要有两种方法:

  1. 使用 passorder 函数的 quickTrade 参数(推荐):将该参数设置为 1
  2. 使用 do_order 函数:强制立即执行当前产生的信号(常用于日线策略在收盘前几分钟提前下单)。

以下是详细说明和代码实现。

方法一:设置 quickTrade=1 (最常用)

在调用 passorder 函数时,第 9 个参数是 quickTrade

  • 0 (默认):当前K线走完,下一根K线开盘下单。
  • 1 (立即下单):只要 handlebar 在最新一根K线(ContextInfo.is_last_bar() 为 True)运行时被调用且条件满足,立即发出委托,不等待K线结束。

代码示例

# -*- coding: gbk -*-

def init(ContextInfo):
    # 设置资金账号
    ContextInfo.accid = '6000000000' # 请替换为您的实际账号
    ContextInfo.set_account(ContextInfo.accid)
    
    # 设置股票池
    ContextInfo.set_universe(['600000.SH'])

def handlebar(ContextInfo):
    # 获取当前K线索引
    index = ContextInfo.barpos
    # 获取当前主图代码
    code = ContextInfo.stockcode
    
    # 获取收盘价
    close_data = ContextInfo.get_market_data(['close'], stock_code=[code], count=1, period=ContextInfo.period)
    if code not in close_data or len(close_data[code]) == 0:
        return
    current_price = close_data[code]['close'][-1]
    
    # 示例策略逻辑:价格大于 10 元时买入
    # 注意:在实盘中,handlebar 会在每个 tick 更新时调用。
    # 如果不加控制,可能会导致一个K线内重复下单。
    # 建议配合全局变量或持仓判断来防止单根K线重复交易。
    
    # 获取当前持仓,防止重复买入
    positions = get_trade_detail_data(ContextInfo.accid, 'stock', 'position')
    has_position = False
    for pos in positions:
        if pos.m_strInstrumentID == code and pos.m_nVolume > 0:
            has_position = True
            break
            
    if current_price > 10.0 and not has_position:
        print(f"触发立即下单信号,当前价: {current_price}")
        
        # passorder 参数详解:
        # opType: 23 (买入)
        # orderType: 1101 (单股单账号普通股/手下单)
        # accountid: 账号
        # orderCode: 代码
        # prType: 5 (最新价)
        # modelprice: -1 (使用prType报价)
        # volume: 100 (股数)
        # strategyName: "my_strategy" (策略名,不可省略,否则无法传递后面的参数)
        # quickTrade: 1 (重点:设置为 1 代表立即下单)
        # userOrderId: "remark" (备注)
        # ContextInfo: 上下文对象
        
        passorder(23, 1101, ContextInfo.accid, code, 5, -1, 100, "my_strategy", 1, "buy_signal", ContextInfo)

方法二:使用 do_order 函数

do_order 通常用于日线级别的策略,在收盘前(例如 14:55)强制将本该在明天开盘发的信号在今天发出。它会把上一根K线(或者当前未走完的K线视为已完成)生成的信号立即执行。

代码示例

# -*- coding: gbk -*-
import time

def init(ContextInfo):
    ContextInfo.accid = '6000000000'
    ContextInfo.set_account(ContextInfo.accid)
    ContextInfo.set_universe(['600000.SH'])

def timetag_to_datetime(timetag, format):
    import time
    return time.strftime(format, time.localtime(timetag / 1000))

def handlebar(ContextInfo):
    # 正常的交易逻辑,使用普通的下单函数(quickTrade默认为0)
    # 这里的 order_lots 默认是在下一根K线才发单
    order_lots(ContextInfo.stockcode, 1, ContextInfo, ContextInfo.accid)
    
    # 获取当前 Tick 的时间
    ticktimetag = ContextInfo.get_tick_timetag()
    if ticktimetag == 0:
        return
        
    # 格式化时间为 HHMMSS
    int_time = int(timetag_to_datetime(ticktimetag, '%H%M%S'))
    
    # 设定在 14:55:00 到 14:55:05 之间强制触发下单
    # 这样可以将原本要在明日开盘执行的信号,提前到今日收盘前执行
    if 145500 <= int_time < 145505:
        print("收盘前强制触发信号")
        do_order(ContextInfo)

总结

需求场景 推荐方法 关键设置
盘中即时交易 (如分钟线突破、Tick级止损) 方法一 passorder(..., quickTrade=1, ...)
日线收盘前抢跑 (如日线策略在14:55执行) 方法二 配合时间判断调用 do_order(ContextInfo)

Q&A

Q: 设置 quickTrade=1 后,回测结果会受影响吗?
A: quickTrade 参数在回测模式下通常无效(回测通常严格遵循K线收盘结算机制)。但在实盘或模拟交易模式下,它决定了信号是立即发出还是等待K线结束。

Q: 为什么使用了 quickTrade=1 还是没有成交?
A: 请检查以下几点:

  1. passorder 的参数顺序是否正确。quickTrade 是第9个参数,因此第8个参数 strategyName 必须填写(可以填空字符串 "" 或策略名称),不能跳过。
  2. 是否处于 ContextInfo.is_last_bar()True 的状态(即最新的实时行情)。
  3. 是否有风控限制或资金不足。

Q: quickTrade=2 是什么意思?
A: quickTrade=2 表示不判断 Bar 的状态,即使在历史 K 线上也会触发下单。这通常用于极其特殊的调试场景,实盘中请勿使用,否则策略启动加载历史数据时可能会导致大量错误下单。