跳转到内容

请求持仓

reqPositions() 用来请求这个 TWS 会话可见账户的持仓数据。

app.reqPositions()

这个方法没有参数,也不传账户号。TWS 会把可见账户的持仓通过 position() 回调返回,并在初始批次结束时调用 positionEnd()

检查项原因
TWS 或 IB Gateway 已登录持仓来自登录账户
API Socket 已开启程序需要连接 API 端口
已收到 nextValidId()确认基础连接已建立
知道持仓数据需要脱敏回调可能包含账户号、合约、数量和成本

reqPositions() 本身不需要市场数据订阅。即使没有行情权限,仍可能返回持仓合约、数量和成本;但它不会替代行情接口。

连接 TWS / IB Gateway
-> 等待 nextValidId()
-> reqPositions()
-> position(...)
-> positionEnd()
-> cancelPositions()

如果只需要初始持仓快照,收到 positionEnd() 后可以调用 cancelPositions()。如果要持续监听持仓变化,可以保持订阅,但退出前仍建议取消。

import threading
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
INFO_CODES = {2100, 2104, 2106, 2158}
class RequestPositionsApp(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.ready = threading.Event()
self.positions_end = threading.Event()
self.position_count = 0
self.info_codes = []
self.errors_seen = []
def nextValidId(self, orderId):
self.ready.set()
def position(self, account, contract, position, avgCost):
self.position_count += 1
def positionEnd(self):
self.positions_end.set()
def error(self, reqId, errorTime, errorCode, errorString, advancedOrderRejectJson=""):
if errorCode in INFO_CODES:
self.info_codes.append(errorCode)
else:
self.errors_seen.append((reqId, errorCode, errorString))
app = RequestPositionsApp()
try:
app.connect("127.0.0.1", 7497, clientId=985)
thread = threading.Thread(target=app.run, daemon=True)
thread.start()
connected = app.ready.wait(8)
if not connected:
raise RuntimeError("等待 nextValidId 超时")
app.reqPositions()
end_received = app.positions_end.wait(8)
finally:
if app.isConnected():
app.cancelPositions()
app.disconnect()
print(f"CONNECTED={connected}")
print("REQUEST_SENT=True")
print(f"POSITION_END_RECEIVED={end_received}")
print(f"POSITION_ROW_COUNT={app.position_count}")
print("INFO_CODES=" + (",".join(map(str, sorted(set(app.info_codes)))) if app.info_codes else "NONE"))
print(f"NON_INFO_ERROR_COUNT={len(app.errors_seen)}")
print(f"IS_CONNECTED_AFTER_DISCONNECT={app.isConnected()}")
CONNECTED=True
REQUEST_SENT=True
POSITION_END_RECEIVED=True
POSITION_ROW_COUNT=0
INFO_CODES=2104,2106,2158
NON_INFO_ERROR_COUNT=0
IS_CONNECTED_AFTER_DISCONNECT=False

这个环境返回 0 行持仓,但收到了 positionEnd(),说明请求链路是通的。

不是。没有持仓时,常见结果就是 0 行 position(),但仍然收到 positionEnd()。这表示初始批次已经结束,只是没有可返回的持仓。

普通 reqPositions() 请求这个会话可见账户的持仓。如果需要明确账户或模型组合过滤,使用下一组的 reqPositionsMulti()

建议取消。reqPositions() 是实时持仓更新请求,如果程序只需要一次快照,收到 positionEnd() 后调用 cancelPositions()

IBKR Campus: TWS API Documentation