🚀 AI 一键生成 qmt 策略代码
立即体验

QMT 如何设置多个 run_time 定时器以在集合竞价、盘中和尾盘执行不同策略逻辑?

qmt | 发布时间: 2026/7/29
以下内容由 EasyQuant 生成。

问题描述

请根据以下 SEO 主题生成完整页面内容:

Title: qmt 多定时器策略:使用 run_time 实现日内不同时段精准逻辑触发

Question: 如何在 qmt 中设置多个 run_time 定时器以在集合竞价、盘中和尾盘分别执行不同的策略逻辑?

解决方案

QMT 多定时器策略:使用 run_time 实现日内不同时段精准逻辑触发

在 QMT(迅投量化交易系统)中,标准的 handlebar 函数是依赖行情 K 线或 Tick 推送驱动的。然而在实际量化实盘中,我们常常需要在特定时间点(如集合竞价结束时、盘中固定时间间隔、尾盘收盘前)精准触发指定的策略逻辑。通过在 init 初始化函数中多次调用 ContextInfo.run_time(),可以轻松注册多个独立定时器,绑定不同的回调函数。


1. 核心接口说明:ContextInfo.run_time

语法定义

ContextInfo.run_time(funcName, period, startTime, market)

参数详解

  • funcName (str): 定时触发时调用的回调函数名称(字符串格式)。
  • period (str): 重复调用的时间间隔。例如:
    • '1nSecond', '5nSecond':每 1 秒或 5 秒执行一次。
    • '500nMilliSecond':每 500 毫秒执行一次。
    • '1nDay':每天执行一次。
  • startTime (str): 定时器第一次启动的时间,格式为 'YYYY-MM-DD HH:MM:SS'。若设为历史时间则会立即启动。
  • market (str): 市场简称代码,如 'SH'(上交所)或 'SZ'(深交所)。

2. 完整 Python 策略源码示例

以下示例展示了如何在 QMT 中设置 3 个独立的定时器,分别处理早盘集合竞价准备盘中高频监控以及尾盘风控/平仓逻辑:

#coding:gbk
import time

def init(ContextInfo):
    # 1. 绑定交易账号
    ContextInfo.account = '6000000001'
    ContextInfo.set_account(ContextInfo.account)
    ContextInfo.stock = '600000.SH'
    ContextInfo.set_universe([ContextInfo.stock])
    
    print("策略初始化完成,开始注册多定时器...")
    
    # 2. 定时器 1:集合竞价阶段(09:25:00 启动,每天执行一次,用于选股与数据准备)
    ContextInfo.run_time("call_auction_logic", "1nDay", "2023-01-01 09:25:00", "SH")
    
    # 3. 定时器 2:盘中高频监控(09:30:00 启动,每 5 秒执行一次)
    ContextInfo.run_time("intraday_monitoring", "5nSecond", "2023-01-01 09:30:00", "SH")
    
    # 4. 定时器 3:尾盘风控/清仓(14:55:00 启动,每天执行一次)
    ContextInfo.run_time("tail_market_logic", "1nDay", "2023-01-01 14:55:00", "SH")

def call_auction_logic(ContextInfo):
    """ 集合竞价/开盘前准备逻辑 """
    print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] 触发集合竞价逻辑:获取开盘喊价数据并初始化日内信号")
    # 示例:获取最新分笔数据
    full_tick = ContextInfo.get_full_tick([ContextInfo.stock])
    if ContextInfo.stock in full_tick:
        open_price = full_tick[ContextInfo.stock]['open']
        print(f"{ContextInfo.stock} 今日开盘价: {open_price}")

def intraday_monitoring(ContextInfo):
    """ 盘中高频监控逻辑 """
    # 仅在交易时间段内运行
    now_time = time.strftime('%H%M%S')
    if not ('093000' <= now_time <= '113000' or '130000' <= now_time <= '150000'):
        return
    
    # 获取当前最新价格并判断是否触发下单条件
    full_tick = ContextInfo.get_full_tick([ContextInfo.stock])
    if ContextInfo.stock in full_tick:
        last_price = full_tick[ContextInfo.stock]['lastPrice']
        # 示例:若最新价大于 0 则执行交易(此处为演示,实际需结合选股信号)
        # passorder(23, 1101, ContextInfo.account, ContextInfo.stock, 5, -1, 100, ContextInfo)
        pass

def tail_market_logic(ContextInfo):
    """ 尾盘风控/平仓/结算逻辑 """
    print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] 触发尾盘逻辑:检查仓位、平隔夜仓或生成日终报告")
    # 示例:查询持仓
    positions = get_trade_detail_data(ContextInfo.account, 'STOCK', 'POSITION')
    for pos in positions:
        print(f"持仓标的: {pos.m_strInstrumentID}, 可用数量: {pos.m_nCanUseVolume}")

def handlebar(ContextInfo):
    """ 主行情驱动函数(必填) """
    pass

3. 开发注意事项与技巧

  1. 时间段过滤period='5nSecond' 等时间间隔触发器在非交易时间(如午休、夜间)仍会按时间间隔触发回调,因此必须在回调函数内部加入当前系统时间(如 time.strftime('%H%M%S'))过滤判断。
  2. 模式差异ContextInfo.run_time() 定时器仅在实盘与模拟运行模式下生效,在历史回测模式(Backtest)中不会被触发。回测模式下请依赖 handlebar 逐 Bar 运行。
  3. 非阻塞原则:所有定时器回调函数均应保持轻量,避免在回调中执行长时间的同步 I/O 或耗时计算,以免阻塞主线程和其他定时器的触发。