跳转到内容

请求账户摘要

reqAccountSummary() 用来向 TWS 或 IB Gateway 请求账户摘要数据。它读取的是 TWS Account Window 的 Summary 类字段,例如净清算值、购买力、可用资金等。

这个方法不是“调用后立刻返回结果”的普通函数。它会发送一个请求,然后由 accountSummary() 回调一行一行返回数据,最后用 accountSummaryEnd() 表示本轮初始数据已经发完。

reqAccountSummary(reqId, groupName, tags)
-> accountSummary(reqId, account, tag, value, currency)
-> accountSummaryEnd(reqId)

Python API 中的调用形式如下:

self.reqAccountSummary(reqId, groupName, tags)
参数中文含义常见写法
reqId请求 ID,用来把后面的回调和本次请求对应起来使用一个尚未被占用的整数
groupName账户组名称普通账户通常填 "All"
tags需要返回的字段名,用英文逗号分隔"NetLiquidation,BuyingPower,AvailableFunds"

reqId 只需要在这次连接中便于区分即可。实际项目里通常会维护一个自增请求 ID,避免两个还没结束的请求使用同一个 reqId

大多数个人账户或单账户开发环境,直接使用:

app.reqAccountSummary(reqId=9001, groupName="All", tags="NetLiquidation")

"All" 表示请求登录会话中可见账户的摘要数据。

如果是 Financial Advisor 或多账户结构,并且已经在 TWS Global Configuration 里创建了 Advisor Account Group,可以把 groupName 改成对应的账户组名称。没有账户组时不要随便填写自定义字符串,否则可能收不到数据。

tags 是一个逗号分隔字符串,不是 Python 列表。建议先从少量字段开始:

tags = "NetLiquidation,BuyingPower,AvailableFunds"

常见字段含义:

字段中文含义适合用途
NetLiquidation净清算值估算账户总权益
BuyingPower购买力判断大致还能买入多少保证金证券
AvailableFunds可用资金下单前做资金余量检查
TotalCashValue总现金价值查看现金类余额
ExcessLiquidity超额流动性观察保证金压力
Cushion安全垫比例粗略判断账户离保证金压力有多远

“账户摘要标签”页面会整理更多字段。这里先记住一个原则:调试阶段不要一次请求太多字段,先把连接、回调和字段解析跑通。

官方说明里 reqAccountSummary() 的语义是 request and keep up to date,也就是请求后会保持更新。实际编程时有两种用法:

用法做法
只想取一次账户摘要发送请求,等到 accountSummaryEnd(),整理结果后调用 cancelAccountSummary(reqId)
想持续监听摘要变化发送请求后保持连接,持续处理 accountSummary(),不用立刻取消

新手示例一般采用第一种:拿到初始摘要后就取消订阅。这样程序生命周期清楚,也不容易把旧请求留在后台。

下面示例直接使用官方 EWrapper + EClient 模型,不依赖同步封装。它会请求三个账户摘要字段,等待 accountSummaryEnd(),然后取消订阅。

import threading
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
REQ_ID = 9002
TAGS = "NetLiquidation,BuyingPower,AvailableFunds"
class AccountSummaryApp(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.ready = threading.Event()
self.done = threading.Event()
self.rows = []
self.errors_seen = []
def nextValidId(self, orderId):
# 收到这个回调,说明 API 握手完成,可以发送请求。
self.ready.set()
def accountSummary(self, reqId, account, tag, value, currency):
# account 和 value 都是敏感数据,公开日志里应当脱敏。
self.rows.append((reqId, account, tag, currency or "EMPTY"))
def accountSummaryEnd(self, reqId):
# 初始账户摘要已经返回完毕。
self.done.set()
def error(self, reqId, errorTime, errorCode, errorString, advancedOrderRejectJson=""):
# 2104、2106、2158 常见于行情/数据服务连接状态提示,不作为本例错误输出。
if errorCode not in (2104, 2106, 2158):
self.errors_seen.append((reqId, errorCode, errorString))
app = AccountSummaryApp()
try:
app.connect("127.0.0.1", 7497, clientId=961)
thread = threading.Thread(target=app.run, daemon=True)
thread.start()
if not app.ready.wait(8):
raise RuntimeError("等待 nextValidId 超时")
app.reqAccountSummary(REQ_ID, "All", TAGS)
if not app.done.wait(8):
raise RuntimeError("等待 accountSummaryEnd 超时")
app.cancelAccountSummary(REQ_ID)
latest = {}
for req_id, account, tag, currency in app.rows:
latest[(account, tag, currency)] = req_id
print(f"ACCOUNT_COUNT={len({account for account, _, _ in latest.keys()})}")
print(f"RAW_CALLBACK_ROWS={len(app.rows)}")
print(f"UNIQUE_FIELD_ROWS={len(latest)}")
finally:
if app.isConnected():
app.disconnect()

这里用 latest[(account, tag, currency)] = req_id 保存最新字段,是因为 reqAccountSummary() 可能先返回初始快照,随后又推送更新。同一个账户、同一个字段收到多次回调并不一定是错误。

使用TWS 模拟账户、127.0.0.1:7497 和独立 clientId 检查时,脱敏后的输出如下:

CONNECTED=True
REQUEST_ID=9002
GROUP=All
TAGS_REQUESTED=NetLiquidation,BuyingPower,AvailableFunds
ACCOUNT_COUNT=1
RAW_CALLBACK_ROWS=6
UNIQUE_FIELD_ROWS=3
TAGS_RECEIVED=AvailableFunds,BuyingPower,NetLiquidation
CURRENCIES=USD
ACCOUNT_ALIAS=ACCOUNT_1;FIELD=AvailableFunds;CURRENCY=USD;VALUE=<redacted>
ACCOUNT_ALIAS=ACCOUNT_1;FIELD=BuyingPower;CURRENCY=USD;VALUE=<redacted>
ACCOUNT_ALIAS=ACCOUNT_1;FIELD=NetLiquidation;CURRENCY=USD;VALUE=<redacted>
NON_INFO_ERROR_COUNT=0
IS_CONNECTED_AFTER_DISCONNECT=False

UNIQUE_FIELD_ROWS=3 说明本次请求按预期收到了 3 个去重字段。RAW_CALLBACK_ROWS=6 说明同一字段可能收到初始值和更新值各一次;程序应当按账户、字段和币种做归并,而不是简单把每一行都当成新字段。

现象常见原因处理方式
收不到 accountSummaryEnd()TWS 未允许 API、端口不对、请求参数不正确先用 groupName="All" 和少量官方字段测试
返回字段比预期多或重复账户摘要是订阅式数据,可能有初始值和更新值(account, tag, currency) 保存最新值
某些字段没有返回字段名拼写错误,或账户不支持该字段先使用常见字段检查时,再扩大标签范围
currency 为空该字段不是金额字段,或官方回调本身没有币种程序里允许空币种,显示为 EMPTY 或空字符串
日志里出现真实账户号或金额直接打印了 accountvalue公开日志和文档中必须脱敏

IBKR Campus: TWS API Documentation