接收管理账户
managedAccounts() 是 reqManagedAccts() 的返回回调。它接收一个逗号分隔的账户字符串:
def managedAccounts(self, accountsList): ...accountsList 里是这个 TWS 会话可见的真实账户号。公开输出前必须脱敏。
| 字段 | 中文含义 | 说明 |
|---|---|---|
accountsList | 账户列表字符串 | 多个账户用逗号分隔 |
解析方式:
accounts = [item for item in accountsList.split(",") if item]用 if item 过滤空字符串,可以避免某些环境下尾部逗号造成空账户项。
Python 接收示例
Section titled “Python 接收示例”下面示例会保存真实账户列表,但输出时只显示脱敏别名。
import threadingfrom ibapi.client import EClientfrom ibapi.wrapper import EWrapper
INFO_CODES = {2100, 2104, 2106, 2158}
class ReceiveManagedAccountsApp(EWrapper, EClient): def __init__(self): EClient.__init__(self, self) self.ready = threading.Event() self.managed_ready = threading.Event() self.accounts_list_raw = "" self.accounts = [] self.info_codes = [] self.errors_seen = []
def nextValidId(self, orderId): self.ready.set()
def managedAccounts(self, accountsList): self.accounts_list_raw = accountsList or "" self.accounts = [item for item in self.accounts_list_raw.split(",") if item] self.managed_ready.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 = ReceiveManagedAccountsApp()
try: app.connect("127.0.0.1", 7497, clientId=983)
thread = threading.Thread(target=app.run, daemon=True) thread.start()
if not app.ready.wait(8): raise RuntimeError("等待 nextValidId 超时")
app.reqManagedAccts()
if not app.managed_ready.wait(8): raise RuntimeError("等待 managedAccounts 回调超时")
finally: if app.isConnected(): app.disconnect()
aliases = [f"ACCOUNT_{index}" for index, _ in enumerate(app.accounts, 1)]
print(f"MANAGED_CALLBACK_RECEIVED={app.managed_ready.is_set()}")print(f"ACCOUNT_COUNT={len(app.accounts)}")print("ACCOUNT_ALIASES=" + (",".join(aliases) if aliases else "NONE"))print(f"RAW_LIST_HAS_TRAILING_COMMA={app.accounts_list_raw.endswith(',')}")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)}")MANAGED_CALLBACK_RECEIVED=TrueACCOUNT_COUNT=1ACCOUNT_ALIASES=ACCOUNT_1RAW_LIST_HAS_TRAILING_COMMA=FalseINFO_CODES=2104,2106,2158NON_INFO_ERROR_COUNT=0这个环境返回 1 个可见账户,并且原始字符串没有尾部逗号。
如果返回多个账户,不要默认使用第一个账户做所有操作。更稳妥的方式是:
- 在配置里保存用户选择的目标账户。
- 每次启动后用
reqManagedAccts()验证该账户仍在可见列表里。 - 日志里输出脱敏别名,不输出真实账户号。
示例:
target_account = "DU1234567"
if target_account not in accounts: raise RuntimeError("目标账户不在这个 TWS 会话可见账户列表中")公开日志可写成:
TARGET_ACCOUNT_ALIAS=ACCOUNT_2TARGET_ACCOUNT_VISIBLE=TrueaccountsList 是数组吗?
Section titled “accountsList 是数组吗?”不是。Python API 回调里它是字符串,需要自己 split(",")。
账户列表为空怎么办?
Section titled “账户列表为空怎么办?”先确认是否收到回调。如果收到空字符串,说明这个会话没有返回可见账户;检查 TWS 登录状态、账户权限和 API 连接。普通模拟账户正常情况下应至少返回一个账户。
可以把 accountsList 直接传给账户更新接口吗?
Section titled “可以把 accountsList 直接传给账户更新接口吗?”不建议。accountsList 可能包含多个账户。应先解析成列表,再选择一个明确账户传给账户类接口。