跳转到内容

限频行为

Pacing Behavior 指的是:当 API 程序短时间内发送太多消息时,TWS / IB Gateway 怎样处理这些超额请求。

这不是某一个接口的参数,而是整个 TWS API 连接层的行为。无论调用 reqMktData()reqHistoricalData()reqContractDetails()placeOrder() 还是 cancelOrder(),只要请求节奏超过允许范围,都可能受到影响。

官方参考:

IBKR Campus: TWS API Documentation

TWS / IB Gateway 的 API 设置里有一个选项:

Reject messages above maximum allowed message rate vs. applying pacing

可以理解成:

超过最大允许消息速率时,直接拒绝,而不是应用 pacing 排队

这个选项会影响超额请求的表现:

设置状态表现适合场景
不勾选TWS / IB Gateway 尝试按允许速率排队处理,超额请求可能延迟执行更接近默认运行方式
勾选超过速率的消息更容易被快速拒绝,并返回错误适合开发排查,方便发现哪段代码发得太快

两种方式都不是“无限制”。不勾选不代表可以随便发请求;勾选也不代表程序更安全。可靠做法仍然是在程序里自己做请求队列、节流、去重和恢复策略。

超过 API 消息速率时,常见错误是:

100 Max rate of messages per second has been exceeded

在 Python 的 EWrapper.error() 回调里,通常需要优先判断 errorCode == 100

from ibapi.wrapper import EWrapper
class App(EWrapper):
def error(self, reqId, errorCode, errorString, advancedOrderRejectJson=""):
# errorCode=100 表示 API 消息发送太快。
# 不要在这里立刻重试,否则会继续冲击限频。
if errorCode == 100:
print(f"触发限频:reqId={reqId}, message={errorString}")
self.pause_request_queues(reason="pacing")
return
print(f"API 错误:reqId={reqId}, code={errorCode}, message={errorString}")
def pause_request_queues(self, reason: str):
# 实际项目里可以暂停行情、历史数据、合约查询、订单等队列。
print(f"暂停请求队列:{reason}")

字段解释:

字段含义
reqId触发错误的请求编号;连接级错误可能是 -1
errorCodeTWS API 错误码,限频常见为 100
errorStringTWS 返回的错误说明
advancedOrderRejectJson高级拒单信息;普通限频通常用不到

不要依赖完整英文错误文本做逻辑判断。不同版本的 TWS / IB Gateway 可能在错误文本里增加 maxrec 等细节,程序逻辑应优先判断错误码。

不勾选“直接拒绝”时,TWS / IB Gateway 会尝试按允许速率处理请求。这个行为看起来更友好,但有一个隐藏风险:程序以为请求已经立刻执行,实际上它可能已经排队。

容易出问题的场景包括:

  • 批量提交订单、改单、撤单。
  • 快速切换一批行情订阅。
  • 循环拉取大量历史 K 线。
  • 前端页面刷新时重复触发同一批请求。
  • 错误重试没有退避,失败后立刻再次发送。

如果队列堆得太长,用户看到的可能不是一个清晰异常,而是“数据很慢”“订单状态晚到”“界面等待很久”。所以应用层仍然要自己限速,不能完全依赖 TWS 帮忙排队。

勾选 Reject messages above maximum allowed message rate vs. applying pacing 后,超额请求更容易快速返回错误。这个模式适合排查:

  • 哪个模块发请求太快。
  • 哪类请求没有缓存。
  • 是否存在重复订阅。
  • 是否有异常重试循环。
  • 多个脚本是否同时冲同一个 TWS / IB Gateway。

开发阶段可以临时开启这个选项,让问题更早暴露。正式运行时是否开启,要看系统设计:如果程序已经有完善限流和日志,两种模式都可以运行;如果程序没有限流,任何模式都不可靠。

官方错误说明提到,超过最大消息速率可能导致客户端断开连接。实际表现可能是:

表现含义
errorCode=100TWS 明确提示消息速率过高
socket closedAPI Socket 被关闭
connection reset连接被对端重置
broken pipe程序继续写入已断开的连接

收到 100 后,程序应该立即暂停相关队列,而不是继续发送请求。恢复时要降速,并重新检查已经丢失的订阅和未完成任务。

比较稳的处理顺序:

  1. 记录触发时间、clientIdreqId、接口名、合约和参数。
  2. 暂停同类型请求队列,例如历史数据队列先停。
  3. 取消明显重复或已经过期的请求。
  4. 等待冷却时间,不要立即重试。
  5. 降低队列速率后逐步恢复。
  6. 如果连接已经断开,先重新连接,再重新订阅必要数据。

恢复逻辑不要所有请求一股脑重发。行情订阅、历史数据、订单状态、账户数据应该按优先级恢复。

可以按用途选择:

程序类型建议
学习脚本可以临时勾选直接拒绝,方便发现请求过快
文档示例脚本程序里保守限流,避免读者一复制就触发错误
批量历史数据任务使用独立慢速队列,并缓存已经请求过的数据
自动化交易程序必须在程序层限流,不能依赖 TWS 排队兜底
多模块系统每个模块有独立队列,同时有全局总速率控制

最重要的原则是:限频应该由你的程序主动管理。TWS / IB Gateway 的 pacing 只是保护机制,不应该成为系统设计的一部分。