🚀 AI 一键生成 qmt 策略代码

QMT 策略逻辑基石:is_new_bar 和 is_last_bar 的应用场景辨析

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

问题描述

在策略中,如何判断现在是新K线的第一个tick,以及如何判断当前是实时行情的最后一根K线?

解决方案

在 QMT 的 Python API 中,可以通过 ContextInfo 对象提供的两个内置布尔型函数来判断这两个状态。这两个函数通常在 handlebar(ContextInfo) 函数中使用。

1. 判断是否为新 K 线的第一个 tick

使用函数:ContextInfo.is_new_bar()

  • 含义:当某根 K 线的第一个 tick 数据到来(或者回测时进入新的一根 K 线)时,该函数返回 True,否则返回 False
  • 用途:常用于在每一根 K 线开始时重置某些变量、计算开盘价逻辑或确保某个逻辑在每根 K 线只执行一次。

2. 判断当前是否为实时行情的最后一根 K 线

使用函数:ContextInfo.is_last_bar()

  • 含义:判断当前运行到的 K 线是否为整个数据序列的最后一根 K 线。返回 True 表示是最后一根,False 表示是历史 K 线。
  • 用途:QMT 在启动策略时会先回放历史 K 线。为了避免在回放历史数据时重复触发实盘交易信号,通常需要判断 if ContextInfo.is_last_bar():,确保策略逻辑只在最新的实时行情中执行下单操作。

代码示例

以下是一个完整的策略示例,展示了如何结合使用这两个函数:

# -*- coding: gbk -*-

def init(ContextInfo):
    # 设置股票池,这里以浦发银行为例
    ContextInfo.set_universe(['600000.SH'])
    print("策略初始化完成")

def handlebar(ContextInfo):
    # 获取当前 K 线索引
    bar_pos = ContextInfo.barpos
    
    # 1. 判断是否是最后一根 K 线(通常用于区分历史回测阶段和实时行情阶段)
    if ContextInfo.is_last_bar():
        # 这里是实时行情(或回测数据的最后一根)
        
        # 2. 判断是否是这根 K 线的第一个 tick(新 K 线生成)
        if ContextInfo.is_new_bar():
            # 获取当前时间
            timetag = ContextInfo.get_bar_timetag(bar_pos)
            import datetime
            date_time = datetime.datetime.fromtimestamp(timetag / 1000).strftime('%Y-%m-%d %H:%M:%S')
            
            print(f"检测到新 K 线生成!当前时间: {date_time}, K线索引: {bar_pos}")
            print("可以在此处执行每根 K 线初始化逻辑,例如重置计数器等。")
        
        # 以下逻辑在最后一根 K 线的每个 tick 都会执行
        # print(f"实时行情 tick 刷新中... barpos: {bar_pos}")
        
    else:
        # 这里是历史 K 线回放阶段
        pass

总结

判断目标 API 函数 返回值 典型应用场景
新 K 线首个 Tick ContextInfo.is_new_bar() bool 每日/每分钟初始化、开盘抢单、防止信号重复计算。
最新 K 线 ContextInfo.is_last_bar() bool 区分历史回放与实盘、确保只对最新行情下单、实盘风控检查。

Q&A

Q: is_new_bar() 在回测模式下和实盘模式下表现一样吗?
A: 逻辑上是一致的。在回测模式下,每当 handlebar 推进到下一根历史 K 线时,is_new_bar() 也会返回 True。在实盘模式下,只有当最新的行情数据切分出新的时间周期(例如从 10:00 变为 10:01 的第一笔数据),它才会返回 True。

Q: 如果我在 is_last_bar() 为 False 时下单会怎样?
A: 如果在 is_last_bar() 为 False 时调用交易函数(如 passorder),意味着你在对历史数据进行“交易”。在回测模式下,这是正常的逻辑,用于生成回测报告。但在实盘模式下(点击“运行”),如果不加此判断,策略启动瞬间会快速回放历史数据,导致历史信号在当前时刻集中触发,可能造成严重的误下单。因此,实盘策略务必加上 if ContextInfo.is_last_bar(): 判断

Q: is_new_bar() 可以用来控制一根 K 线只交易一次吗?
A: 可以。将交易逻辑放在 if ContextInfo.is_new_bar(): 代码块内,可以确保该逻辑在当前 K 线周期内只触发一次(即在 K 线刚生成时)。不过更严谨的做法通常是配合全局变量记录状态,或者使用 do_order 配合 quickTrade=1 参数在 K 线结束时确认信号。