定时器

在 TqSdk 里,定时逻辑通常不是单独开一个 sleep 循环,而是和 wait_update() 结合在同一个主循环里执行。这样可以保证订阅、下单、撤单以及后台任务仍然持续被驱动。

优先使用“行情时间”而不是本机时间

如果你的逻辑和交易时段、收盘前平仓、定时检查等场景有关,优先使用 quote.datetime 代表的行情时间:

from datetime import datetime
from tqsdk import TqApi, TqAuth, TargetPosTask

api = TqApi(auth=TqAuth("快期账户", "账户密码"))
quote = api.get_quote("SHFE.rb2405")
target_pos = TargetPosTask(api, "SHFE.rb2405")
close_hour, close_minute = 14, 50

while True:
    api.wait_update()
    if api.is_changing(quote, "datetime"):
        now_time = datetime.strptime(quote.datetime, "%Y-%m-%d %H:%M:%S.%f")
        if now_time.hour == close_hour and now_time.minute >= close_minute:
            print("临近收盘,平仓")
            target_pos.set_target_volume(0)
            break

这种方式的好处是:你的定时判断和交易所时间保持一致,不依赖本机时钟是否漂移。

用 deadline 做“等待一段时间后继续”

wait_update() 提供了 deadline 参数。它接收的是 time.time() 风格的 unix 时间戳,适合做“最多再等多久”的控制:

import time
from tqsdk import TqApi, TqAuth

api = TqApi(auth=TqAuth("快期账户", "账户密码"))
quote = api.get_quote("SHFE.rb2405")

while True:
    api.wait_update()
    if api.is_changing(quote, "datetime"):
        print("收到一次关键更新,接下来最多再等 60 秒")
        deadline = time.time() + 60
        while api.wait_update(deadline=deadline):
            pass
        print("等待结束,继续执行后续逻辑")

这类写法适合:

  • 收盘前平仓后再等待一小段时间,确认撤单和回报处理完毕

  • 给某个阶段性任务一个最长等待时间,避免长时间阻塞

  • 在同步主循环里做简单的“超时退出”控制

常见误区

  • 不要在主循环里频繁使用 time.sleep(), 否则会阻塞 wait_update,数据和后台任务都会停下来

  • deadline 是 unix 时间戳,不是“秒数”本身;通常写成 time.time() + 60

  • 如果你在定时逻辑里调用了 insert_orderTargetPosTask.set_target_volume,后面仍然要继续调用 wait_update,否则报单不会真正发出

  • 如果策略已经采用协程任务,优先考虑 register_update_notify(),不要把同步和异步等待方式混在一起