量化程序 while True 一直跑 CPU 很高:天勤降频与字段过滤
2026/6/5 13:25:31 网站建设 项目流程

前言

国内期货量化程序跑起来后,结构往往是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_changingquote 时间在走,机器发烫
行情滞后sleep、网络 IO、循环体过长quote.datetime 明显落后

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

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

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

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

whileTrue:api.wait_update()ifapi.is_changing(kl):# kl 整表任一列变都可能 Trueheavy_compute()# 内含多均线、多合约、打印

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

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

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

kl=api.get_kline_serial("SHFE.rb2510",300,data_length=200)# 300 秒=5 分钟线whileTrue:api.wait_update()ifnotapi.is_changing(kl.iloc[-1],"datetime"):continueheavy_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 推进。

风险提示

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询