家庭代码总览
家庭代码接口用来判断可见账户是否属于 IBKR 的 account family,并返回账户对应的 family code。它主要服务于顾问账户、IBroker、家庭账户结构或需要按账户家庭关系做分组的程序。
reqFamilyCodes() -> familyCodes(familyCodes)这组接口很小:没有请求参数,也没有取消方法。请求一次后,结果通过 familyCodes() 回调返回。
什么时候需要它
Section titled “什么时候需要它”| 场景 | 是否适合 |
|---|---|
| 判断账户是否属于 account family | 适合 |
| 顾问账户、IBroker、家庭账户结构分组 | 适合 |
| 普通单账户入门开发 | 通常不是必需 |
| 获取账户资金、保证金、购买力 | 不适合,应看账户摘要或账户更新 |
| 获取持仓、盈亏、订单 | 不适合,应看对应账户、持仓、订单接口 |
如果你只是开发普通模拟账户的行情、下单、账户余额展示,家庭代码不是第一优先级。它更像账户结构辅助信息。
| 名称 | 类型 | 中文含义 | 说明 |
|---|---|---|---|
reqFamilyCodes() | 请求方法 | 请求家庭代码 | 没有参数 |
familyCodes() | 回调方法 | 接收家庭代码列表 | 返回 FamilyCode 对象列表 |
FamilyCode.accountID | 字段 | 账户代码 | 真实账户号,公开输出应脱敏 |
FamilyCode.familyCodeStr | 字段 | 家庭代码字符串 | 不属于 account family 时可能为空 |
本地 Python API 源码里的 FamilyCode 对象只有两个主要字段:
class FamilyCode: accountID = "" familyCodeStr = ""返回为空是什么意思
Section titled “返回为空是什么意思”家庭代码接口有一个容易误解的点:回调返回了账户行,但 familyCodeStr 可能是空字符串。
这通常表示:
- 账户可以被 TWS API 看见。
- 但这个账户没有归属于 account family,或者登录环境没有对应家庭代码。
所以,空 family code 不是一定失败。判断是否失败时,应同时看是否收到 familyCodes() 回调、是否有非信息类错误。
Python 总览示例
Section titled “Python 总览示例”下面示例会连接TWS 模拟账户,请求家庭代码,并只输出脱敏后的结构:
import threadingfrom ibapi.client import EClientfrom ibapi.wrapper import EWrapper
INFO_CODES = {2100, 2104, 2106, 2158}
class FamilyCodesOverviewApp(EWrapper, EClient): def __init__(self): EClient.__init__(self, self) self.ready = threading.Event() self.family_ready = threading.Event() self.family_codes = [] self.info_codes = [] self.errors_seen = []
def nextValidId(self, orderId): self.ready.set()
def familyCodes(self, familyCodes): # familyCodes 是 FamilyCode 对象列表,真实 accountID 不要直接打印到公开日志。 self.family_codes = list(familyCodes or []) self.family_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 = FamilyCodesOverviewApp()
try: app.connect("127.0.0.1", 7497, clientId=978)
thread = threading.Thread(target=app.run, daemon=True) thread.start()
if not app.ready.wait(8): raise RuntimeError("等待 nextValidId 超时")
app.reqFamilyCodes()
if not app.family_ready.wait(8): raise RuntimeError("等待 familyCodes 回调超时")
finally: if app.isConnected(): app.disconnect()
rows = []for index, item in enumerate(app.family_codes, 1): rows.append({ "alias": f"ACCOUNT_{index}", "has_account_id": bool(item.accountID), "family_code": item.familyCodeStr or "EMPTY", })
print("FAMILY_CALLBACK_RECEIVED=True")print(f"FAMILY_CODE_ROW_COUNT={len(app.family_codes)}")print("ROWS=" + (str(rows) if rows else "EMPTY"))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)}")使用TWS 模拟账户、127.0.0.1:7497 和独立 clientId 检查时,脱敏输出如下:
CONNECTED=TrueREQUEST_SENT=TrueFAMILY_CALLBACK_RECEIVED=TrueFAMILY_CODE_ROW_COUNT=1ROWS=[{'alias': 'ACCOUNT_1', 'has_account_id': True, 'family_code': 'EMPTY'}]INFO_CODES=2104,2106,2158NON_INFO_ERROR_COUNT=0IS_CONNECTED_AFTER_DISCONNECT=False这次结果说明:接口调用成功,这个会话返回了 1 个可见账户行;账户号存在,但 family code 为空。对普通模拟账户来说,这是合理结果,不应当当成接口失败。
FamilyCode.accountID 是真实账户号,公开文档、日志和报错里建议统一脱敏。例如:
DU1234567 -> ACCOUNT_1familyCodeStr 本身也可能暴露账户组织关系。如果你在团队系统里记录它,建议只在受控日志或后台页面中展示。
本组页面导览
Section titled “本组页面导览”| 页面 | 内容 |
|---|---|
| 请求家庭代码 | reqFamilyCodes() 的请求流程和请求前检查 |
| 接收家庭代码 | familyCodes() 回调、FamilyCode 字段和空 family code 的判断 |