🚀 AI 一键生成 qmt 策略代码

QMT回测中指定时间执行策略的解决方案与优化技巧

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

问题描述

求教一下,回测的时候怎么在指定时间执行程序

QMT 的回测只有 handler_bar 实在是很不方便。

很多时候,我们的策略需要指定时间执行,比如我需要每周执行一次,但是我希望在早上 10:00 的时候买入或者卖出。

如果只能用 handler_bar 函数,则需要调用分钟 K 线,然后每调用一次就判断是不是我的下单时间,不是就 PASS 掉,这太浪费资源了。

有没有更好的处理办法?

解决方案

QMT 回测机制解析

在 QMT 平台中,回测模式是严格基于 K 线行情驱动的。这意味着策略的推进完全依赖于历史 K 线数据的逐根回放,每走过一根 K 线,系统就会调用一次 handlebar(ContextInfo) 函数。

虽然 QMT 提供了定时器函数 ContextInfo.run_time(),但根据官方 API 文档说明:run_time() 在回测模式下是没有意义的(仅在实盘/模拟盘有效)。因此,在回测中,您必须通过调用包含目标时间的 K 线周期(如 1分钟、5分钟、15分钟、30分钟或 1小时线),并在 handlebar 中进行时间判断。

如何优化资源消耗?

虽然必须在 handlebar 中判断时间,但我们可以通过**“前置快速过滤(Fast Fail)”**的编程技巧,将资源浪费降到最低。只要在 handlebar 的最开头进行简单的时间戳比对,如果不符合条件直接 return,这种纯内存的简单判断对回测速度的影响微乎其微。

Python 实现代码:每周一早上 10:00 执行

以下是一个高效的实现模板,假设您在回测时选择的主图周期为 1分钟线5分钟线

#coding:gbk
import datetime

def init(ContextInfo):
    # 初始化股票池
    ContextInfo.set_universe(['000300.SH'])
    # 设置回测起止时间
    ContextInfo.start = '2023-01-01 09:00:00'
    ContextInfo.end = '2023-12-31 15:00:00'

def handlebar(ContextInfo):
    # 1. 获取当前 K 线的时间戳(毫秒)
    timetag = ContextInfo.get_bar_timetag(ContextInfo.barpos)
    
    # 2. 将时间戳转换为 datetime 对象
    # 注意:QMT的时间戳是毫秒级,需要除以1000转换为秒
    dt = datetime.datetime.fromtimestamp(timetag / 1000.0)
    
    # 3. 前置快速过滤:判断是否为 10:00
    # 如果主图是5分钟线,10:00的K线时间戳通常对应 10:00
    if dt.hour != 10 or dt.minute != 0:
        return  # 不是10:00,直接跳过,极低资源消耗
        
    # 4. 前置快速过滤:判断是否为每周的特定一天(例如周一,weekday() == 0)
    if dt.weekday() != 0:
        return  # 不是周一,直接跳过
        
    # ==========================================
    # 以下为您的核心策略逻辑,每周一 10:00 才会执行到这里
    # ==========================================
    print(f"触发交易时间: {dt.strftime('%Y-%m-%d %H:%M:%S')}")
    
    # 示例:获取最新价并下单
    close_price = ContextInfo.get_market_data(['close'], stock_code=['000300.SH'], period='1d', count=1)
    # passorder(23, 1101, ContextInfo.accid, '000300.SH', 5, -1, 100, ContextInfo)

实盘与回测的差异化处理

如果您希望策略在实盘/模拟盘中真正使用定时器,而在回测中使用 K 线判断,可以通过 ContextInfo.do_back_test 属性来区分运行环境:

def init(ContextInfo):
    if not ContextInfo.do_back_test:
        # 实盘/模拟盘模式:使用真正的定时器,每5秒执行一次自定义函数
        ContextInfo.run_time("my_timer_func", "5nSecond", "2023-01-01 09:30:00", "SH")

def my_timer_func(ContextInfo):
    # 实盘定时执行的逻辑
    pass

def handlebar(ContextInfo):
    if ContextInfo.do_back_test:
        # 回测模式:使用 K 线时间戳判断逻辑
        pass

总结

在 QMT 回测中,使用分钟 K 线配合 handlebar 顶部的快速 return 拦截,是目前唯一且最高效的指定时间执行方案。Python 的基础条件判断速度极快,只要不在此处调用复杂的 API(如获取历史数据、财务数据等),对整体回测性能的影响几乎可以忽略不计。