期货量化程序 time.sleep 卡死:天勤单线程与 deadline 替代

前言

国内期货量化程序常见写法是:用 Python 调用天勤 TqSdk,创建 TqApi 连接行情和交易服务,在 while True 循环里反复调用 api.wait_update()------每调用一次,程序从服务器收一批螺纹钢等合约的行情更新、委托回报、成交回报,内存里的 quoteorderposition 才会刷新。交易信号多在 K 线上算:例如订阅 5 分钟 get_kline_serial,均线金叉时 TargetPosTask.set_target_volume(3) 表达「目标净多 3 手」,真正的报单发生在之后的 wait_update 里。

有人为「等下一分钟再检查信号」或「每 60 秒扫一眼持仓」,在循环里写 time.sleep(60)。这 60 秒里主线程被堵住,行情和成交回报堆在缓冲区,醒来一次性涌入,order.statusvolume_left 可能连跳几态,tick 级止损也来不及执行。还有一次在发钉钉告警时 sleep 等 HTTP 返回,接口卡住两分钟,回来时期货已经跳了一大段。天勤 TqApi 基于 asyncio 协作调度,wait_update() 才是程序心跳,长时间阻塞等于掐住脖子。下面说明该用什么替代、定时平仓怎么写。

一、先弄清几个名词

名称 是什么 和 sleep 的关系
TqApi 天勤连接行情、交易的主对象 单线程事件循环的载体
wait_update() 收一批行情/回报并刷新内存对象 正确的心跳,应用它代替 sleep
quote / order / position 行情、委托、持仓对象 sleep 期间不更新
TargetPosTask 自动调仓类 撤单报单发生在 wait_update 里
time.sleep Python 阻塞当前线程 会堵住整个 TqApi 循环

二、天勤单线程模型

  • 一个 TqApi 实例对应一个事件循环,负责收发包、更新 quoteorderposition
  • wait_update() 驱动循环前进;不调就 stagnate。
  • time.sleep、同步 HTTP、重计算都会占住线程,期间无法及时处理回报。

target_pos_task.py 里 task 的撤单报单也依赖后续 wait_update

三、sleep 的典型危害

场景 后果
sleep 等待下一分钟 K 线 应用 is_changing(klines, "datetime")
sleep 重试报单 错过撤单窗口、重复报单
sleep 等钉钉回调 断线无感知
Jupyter 里 sleep 调试 内核假死

四、正确替代:wait_update 与 deadline

等待一段时间或有更新:

python 复制代码
import time

deadline = time.time() + 60
while True:
    if not api.wait_update(deadline=deadline):
        # 60 秒内无业务包,做超时逻辑
        check_heartbeat()
        deadline = time.time() + 60
        continue
    # 有更新,正常处理
    on_market_update()

deadline 为 Unix 秒级时间戳,超时返回 False,不抛异常(与 TqTimeoutError 区分)。

五、定时任务:TqScheduler

若需 cron 式「每天 14:55 平仓」,可用 TqScheduler(见 tqsdk.lib)在 wait_update 循环里注册,避免 sleep 到点。事件驱动与交易时段过滤结合,比 while+sleep 稳。

六、耗时计算怎么办

指标计算放 is_changing 分支内,或把纯计算移出热路径、缩小 data_length。严禁在 wait_update 循环里做大规模网络 IO;日志写盘应异步或批量。

七、反模式对照表

写法 问题 替代
sleep(60) 等下一分钟 堵回报 is_changing(kline datetime)
sleep(3) 撤单重试 错过 FINISHED 循环 wait_update 判 status
requests.post 同步告警 堵循环 队列+独立线程或先写日志
while 空转无 wait CPU 100% wait_update 或 deadline

八、与 Jupyter 的关系

Notebook 里 time.sleep 同样阻塞内核里唯一的 Api 循环。调试定时逻辑应在 .py 脚本里用 deadline 验证,再贴回 Notebook;反复运行单元格更要 api.close(),避免多实例叠加。

九、静态检查建议

上线前对策略仓库 rg "time\.sleep",逐处改成 wait_update 模式。允许保留的例外:进程启动前、与 Api 无关的初始化、独立子进程里的 sleep。

总结

期货量化程序里 time.sleep 会阻塞天勤唯一的事件线程,导致行情与回报积压、止损延迟、状态跳变。用 wait_update(deadline=...) 做超时等待,用 is_changing 等 K 线或 tick,用 TqScheduler 做定时点,才能在不卡死连接的前提下实现节奏控制。把 sleep 从策略主循环里清干净,是上线前值得做的一次静态检查。

FAQ

1)sleep 0.1 秒可以吗?

仍不推荐高频;偶尔调试可用,生产去掉。

2)多线程能否一个线程 wait_update?

官方模型单 Api 单线程;多线程易竞态。

3)asyncio.sleep 呢?

若在天勤协程外自建 async,需与 Api 生命周期隔离,一般策略不必。

4)回测里 sleep 有害吗?

回测时钟由 wait_update 推进,sleep 同样拖慢或破坏时序。


本文基于天勤 TqSdk 公开 API 整理,不构成投资建议。

相关推荐
用户83562907805110 小时前
Python 实现 PDF 文件加密与解密方法
后端·python
用户83562907805110 小时前
使用 Python 冻结与拆分 Excel 窗格教程
后端·python
你好潘先生18 小时前
别再记命令了,用 yeero do 说句人话就能跑脚本,而且不烧 token
服务器·python·命令行
Agent_大师18 小时前
WebSocket 行情重连成功,K线缺口不会自动消失
python
荣码18 小时前
LLM结构化输出:让AI返回JSON而不是废话,我踩了4个坑
java·python
copyer_xyf19 小时前
FastAPI 如何连接 MySQL
后端·python
apocelipes1 天前
常用编程语言和库的正则表达式性能对比
c语言·c++·python·性能优化·golang·开发工具和环境
用户8356290780511 天前
使用 Python 在 PDF 中创建与管理书签
后端·python
MeixianAgent2 天前
Python 回测数据入口怎么验?历史 K 线入库前先做 5 个检查
后端·python
咕白m6252 天前
用 Python 实现一键批量查找与替换 Excel 数据
后端·python