量化程序 while True 一直跑 CPU 很高:天勤降频与字段过滤

前言

国内期货量化程序跑起来后,结构往往是 while True 里反复调用行情接口等待更新------在天勤 TqSdk 里就是 api.wait_update()。这是正常的:程序要一直活着等交易所和期货公司的业务数据 ,并不是 while 本身有问题。读者若从股票日线回测转过来,容易以为"循环越少越好";在期货 tick 和分钟线场景里,循环可以很勤,但每次循环里干什么决定了 CPU 会不会被打满。

常见现象是:策略逻辑没错,任务管理器里 Python 却长期占满一个核,风扇狂转,日志刷屏,可交易次数并没增加。原因之一是:每一帧行情更新(盘口跳一下、K 线 high/low 变一下、持仓浮盈变一下)都触发整段均线、多合约循环甚至写盘,属于算得太勤 ,而不是天勤"推送太密"。另一类原因是循环里 sleep、同步请求、大段 pandas------那会导致行情滞后 ,和 CPU 高是不同病,本文重点讲前者,并说明如何用天勤的 is_changing字段级过滤

下文默认你已有一个能连上模拟盘的 TqApi,并订了至少一个期货合约的 quote 或 K 线;不默认你熟悉 is_changing 的参数写法。

一、先分清:CPU 高和"收不到行情"不是一回事

现象 常见原因 读者可观察到的表现
CPU 占用高 每帧全量计算、对象级 is_changing quote 时间在走,机器发烫
行情滞后 sleep、网络 IO、循环体过长 quote.datetime 明显落后

天勤每次 wait_update() 收到业务包后,会更新内存里的行情、K 线、委托等对象。若你在每一次更新后都跑完整策略,而期货盘口一秒内可能多次变动,CPU 就会被无意义的重复计算吃掉。

二、对象级 is_changing 为什么容易"空转"

is_changing(obj) 不指定字段时,表示该对象任意字段本帧有更新即为 True。对 K 线 DataFrame 的一行来说,open/high/low/close/volume 任一变化都会成立;对 quote 来说,买卖盘、最新价变动都会成立。

错误示范(逻辑上能跑,但极耗 CPU):

python 复制代码
while True:
    api.wait_update()
    if api.is_changing(kl):  # kl 整表任一列变都可能 True
        heavy_compute()      # 内含多均线、多合约、打印

在螺纹钢活跃时段,这相当于把"每秒上百次 tick 更新"都当成"要重算策略",CPU 飙高是必然结果。

三、字段级过滤:只在你关心的业务变化时算策略

天勤允许 is_changing(obj, "字段名") 或传入字段列表。对按 K 线收盘做决策的期货策略 ,应盯住最后一根 K 线上的 datetime 字段------该字段来自行情服务写入 K 线表,表示这根 bar 的时间标签;当新的一根 K 线生成 时,最后一行的 datetime 会变化,通常意味着上一根已收盘,此时才适合用 iloc[-2] 算信号(详见专题文)。

python 复制代码
kl = api.get_kline_serial("SHFE.rb2510", 300, data_length=200)  # 300 秒=5 分钟线

while True:
    api.wait_update()
    if not api.is_changing(kl.iloc[-1], "datetime"):
        continue
    heavy_compute_on_bar_close()

依赖最新价 的短线规则,可改为 is_changing(quote, "last_price"),并自行加节流(例如同一秒内只处理一次),避免与 K 线策略混用两套触发条件。

持仓核对不必每 tick 打印,可仅在 is_changing(pos, "pos_long")pos_short 变化时记录,这与期货实盘里"成交回报到了才改仓位"的节奏一致。

四、计算与 IO 仍要外移

即使过滤正确,若 heavy_compute 里仍做全样本滚动回归、写大 CSV、同步调 webhook,单次循环耗时过长仍会拖慢 wait_update 调用频率,间接造成回报延迟。建议:指标在 bar 收盘算一次;日志批量写;通知进队列由别的线程发送,主循环只入队。

五、和 TargetPosTask 的叠加效应

国内期货程序化里,天勤 TargetPosTask 负责把净持仓调到目标手数,内部可能在 wait_update 时撤单、按最新对价重挂。行情剧烈时 task 工作频率也会上升。若同一帧你还做大规模 pandas 运算,CPU 会叠加。策略层应把"算信号"严格放在 bar 或仓位变化触发上,而不是每个 tick。

总结

期货量化里 while True + wait_update 是常态;CPU 过高多半是因为在过多的行情帧上跑了完整策略 。天勤提供 is_changing 的字段参数:K 线策略请用最后一根行的 datetime (由 get_kline_serial 返回的表提供)判断新 bar;盘口策略再选 quote 的具体字段;持仓变动用 position 的具体字段。

把"每一帧"变成"业务上需要反应的那一帧",CPU 会降到与策略频率匹配的水平(例如 5 分钟策略大约几分钟才算一次)。若你同时遇到行情变慢,再排查 sleep 和阻塞 IO,两类问题分开处理。

FAQ

1)wait_update 本身占 CPU 吗?

等待网络时线程阻塞,一般不应占满 CPU;占满核多半是循环体内的 Python 计算。

2)多个期货合约怎么过滤?

每个合约一条 kl,分别 is_changing(kl[s].iloc[-1], "datetime"),未变的合约 continue。

3)回测也很慢,能用同样办法吗?

可以,历史回放同样会产生大量帧,过滤后回测速度往往明显提升。

4)不用 is_changing,改用 sleep(1) 行吗?

会阻塞行情与发单,国内期货程序化不推荐用 sleep 代替 bar 推进。

风险提示

本文讨论程序性能与结构,不构成投资建议。

相关推荐
copyer_xyf2 小时前
Python 内存分析:从栈和堆理解对象引用
前端·后端·python
大蚂蚁2号2 小时前
深度剖析Python全局解释器锁(GIL):原理、瓶颈与终极破局方案
python
高洁012 小时前
打造行业知识图谱三步走
python·深度学习·数据挖掘·知识图谱
码云骑士2 小时前
ImToken智能合约交互避坑指南
区块链·智能合约·交互
装不满的克莱因瓶2 小时前
使用 PyTorch Tensor 的相关数据处理
人工智能·pytorch·python·深度学习·机器学习·ai
如烟花的信页2 小时前
易盾点选逆向分析
javascript·爬虫·python·js逆向
金銀銅鐵2 小时前
用 Tkinter 实现一个简单的罗马数字转化工具
后端·python
ckjoker3 小时前
四大AI Agent架构拆解:我手敲了一个迷你版,发现了7条可迁移的设计原则
python·agent
小二·3 小时前
Python 异步编程深度解析:Async/Await 实战
网络·python·github