跳转到内容

请求下一个有效 ID

下一个有效 ID 是 TWS 分配给 API 客户端的订单编号起点。只要准备调用 placeOrder(),就必须先拿到一个可用的 orderId

TWS 在连接成功后通常会主动触发一次 nextValidId() 回调。也可以显式调用 reqIds(-1),让 TWS 再返回一次下一个可用订单 ID。官方说明里也强调,reqIds() 的参数会被忽略,常见写法就是传 -1

官方参考:IBKR Campus - TWS API 文档

app.reqIds(-1)

numIds 参数已经废弃。不要把 -1 理解成“请求 -1 个 ID”;它只是一个兼容参数。

字段中文说明
reqIds(numIds)请求 TWS 再发送一次 nextValidId() 回调。
numIds兼容参数,TWS 会忽略它,通常传 -1
nextValidId(orderId)TWS 返回下一个可用于下单的订单编号。
orderIdplaceOrder(orderId, contract, order) 的第一个参数。
场景是否需要调用 reqIds(-1)
刚连接 TWS通常不需要,连接完成后 TWS 会主动返回一次 nextValidId()
程序丢失了本地订单编号状态可以调用,用 TWS 返回值重新同步。
多个 API 客户端同时运行可以调用,但还要结合已看到的 openOrder() / orderStatus() 编号判断。
每次下单前都调用通常没必要,正确做法是本地保存并递增。

reqIds(-1) 不是“预占订单号”。它只是让 TWS 告诉你下一个可用编号。真正消耗编号的是你后续用这个 orderId 发送订单请求。

from __future__ import annotations
import threading
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
class NextValidIdApp(EWrapper, EClient):
def __init__(self) -> None:
EClient.__init__(self, self)
self.ready = threading.Event()
self.order_id = None
def nextValidId(self, orderId: int) -> None:
# orderId 就是下一次 placeOrder 可以使用的订单编号。
self.order_id = orderId
self.ready.set()
app = NextValidIdApp()
app.connect("127.0.0.1", 7497, clientId=98200)
threading.Thread(target=app.run, daemon=True).start()
if app.ready.wait(10):
print("连接后收到订单 ID:", app.order_id)
# 需要重新确认时,可以显式请求。
app.reqIds(-1)

这段代码只演示 ID 获取,不提交订单。正式下单代码要等 ready 被设置后再继续,否则程序可能还没有收到 TWS 分配的订单编号。

CONNECTED=True
INITIAL_NEXT_VALID_ID=1
REQ_IDS_SENT=True
REQUESTED_NEXT_VALID_ID_RECEIVED=True
REQUESTED_NEXT_VALID_ID=1
NON_INFO_ERROR_COUNT=0

连接握手和显式请求都返回 1。这说明这次测试里的 TWS API 订单序列起点是 1,且中间没有新的 API 订单消耗编号。

规则说明
orderId 必须唯一同一个客户端不要重复用已经提交过的订单 ID。
连接后先等 nextValidId()不要在还没拿到 ID 时就下单。
每次下单后自行递增常见做法是 next_order_id += 1
多客户端要小心不同 clientId 或 TWS 手工订单可能影响可见订单和编号判断。
丢失状态时重新请求程序不知道下一个编号时,可以再次调用 reqIds(-1)

orderId 是订单编号,给 placeOrder() 用;行情、历史数据、扫描器等接口里的 reqId 只是请求编号。

二者可以都用整数,但语义不同。写程序时建议分开命名,例如 next_order_idmarket_data_req_id

示例里返回 1 只是这次账户和订单序列状态下的结果。只要 TWS 曾经接收过 API 订单,或者其它客户端使用过更大的订单编号,下一次返回值就可能变成更大的数字。

新手最容易犯的错误是把示例输出里的 1 写进程序。正确做法是:每次连接后读取 nextValidId(orderId) 返回的值,再用程序变量保存它。