问题描述
5 分钟的 handlebar 回调的首个 tick 有时为啥会慢个 1,2 分钟才会到达。
例如目前时间 9:37,理论上这时 handlerbar 的时间戳是 0940,但仍然时 0935,过一会才变成 0940
解决方案
在 QMT 平台中,遇到 handlebar 回调延迟、K 线时间戳更新慢(例如 9:37 仍然显示 0935 的 K 线)的情况,核心原因在于 QMT 的运行机制是行情驱动(Tick 驱动),而非纯时间驱动。
以下是详细的原因解析及相应的解决方法:
1. 核心原因:行情驱动机制
QMT 平台的 handlebar(ContextInfo) 函数在实盘或模拟运行模式下,是依赖于实际的行情数据(Tick)推送来触发的。
- K 线的生成依赖 Tick:对于 5 分钟周期,9:35 到 9:40 之间的 K 线(时间戳标记为 0940),必须在这个时间段内有真实的交易发生(即交易所推送了该品种的 Tick 数据),系统才会生成这根新的 K 线。
- 交易不活跃导致延迟:如果当前主图运行的品种交易不够活跃,在 9:35 到 9:37 之间没有任何成交(没有 Tick 推送),QMT 就不会触发
handlebar,此时你获取到的最新 K 线依然是上一根(即 0935)。直到 9:37 之后该品种产生了新的成交,Tick 推送过来,系统才会生成 0940 这根 K 线,handlebar的时间戳才会更新。
验证方法:你可以打开该品种的分时图或 Tick 明细,观察在 9:35 到 9:37 之间是否确实没有任何成交记录。这种情况在冷门股票、非主力期货合约或期权上非常常见。
2. 解决方法
如果你的策略对时间非常敏感,不能容忍这种由品种不活跃导致的延迟,可以采用以下几种解决方案:
方案一:使用活跃品种作为主图驱动
将策略的主图品种设置为一个极其活跃、每秒都有 Tick 的品种(例如上证指数 000000.SH 或沪深300 000300.SH)。
这样,活跃品种的 Tick 会准时驱动 handlebar 运行。在 handlebar 内部,你再使用 ContextInfo.get_market_data_ex() 或 ContextInfo.get_full_tick() 去获取你真正想要交易的目标品种的数据。
方案二:使用定时器 ContextInfo.run_time()
如果你的策略逻辑完全依赖于物理时间(例如严格在 9:37 执行某项操作),可以放弃依赖 handlebar 的 Tick 驱动,改用 QMT 提供的定时器函数 ContextInfo.run_time()。
在 init 函数中设置定时器,让系统按照固定的时间间隔(如每 3 秒或每 1 分钟)强制执行回调函数。
def init(ContextInfo):
# 设置自 09:30:00 起,每 3 秒运行一次 my_timer_func
ContextInfo.run_time("my_timer_func", "3nSecond", "2023-01-01 09:30:00", "SH")
def my_timer_func(ContextInfo):
# 在这里编写你的策略逻辑,它会严格按时间触发,不受 Tick 影响
print("定时器触发")
# 获取目标品种最新数据
# data = ContextInfo.get_full_tick(['目标代码'])
def handlebar(ContextInfo):
# handlebar 可以留空,或者仅处理必须由 K 线驱动的逻辑
pass
方案三:使用 subscribe_quote 订阅行情
如果你需要监控多个品种,可以使用 ContextInfo.subscribe_quote() 订阅这些品种的 Tick 数据。只要其中任何一个品种有 Tick 更新,就会触发回调函数,从而提高策略的响应速度。
总结
handlebar 的“延迟”并不是系统卡顿,而是因为目标品种在那个时间段内没有产生交易数据。理解了 QMT 的行情驱动机制后,通过更换活跃主图或使用 run_time 定时器,即可完美解决此类时间同步问题。