验证 API 连接
验证 API 连接,不只是看 connect() 有没有返回。真正可靠的验证要分三层:
- Python 能导入
ibapi。 - 程序能连上 TWS / IB Gateway 的 Socket 端口。
- TWS / IB Gateway 能返回
nextValidId()和至少一个简单请求结果。
| 顺序 | 验证内容 | 通过信号 |
|---|---|---|
| 1 | TWS / IB Gateway 已登录 | 客户端处于可使用状态。 |
| 2 | API Socket 已启用 | API Settings 中勾选 Enable ActiveX and Socket Clients。 |
| 3 | 端口一致 | 程序端口和 Socket Port 一致。 |
| 4 | ibapi 可导入 | Python 不报 ModuleNotFoundError。 |
| 5 | 收到 nextValidId() | 初始握手完成。 |
| 6 | reqCurrentTime() 返回 | 请求、响应、回调全部通了。 |
验证 Python 包
Section titled “验证 Python 包”先确认命令行里使用的 Python 能导入 ibapi:
python -c "import sys, ibapi; print(sys.executable); print(ibapi.__file__)"如果看到:
ModuleNotFoundError: No module named 'ibapi'说明这个 Python 环境没有安装 TWS API Python 包。此时不要先改 TWS 设置,应该回到安装章节,确认 python 和 pip 使用的是同一个环境。
验证 Socket 端口
Section titled “验证 Socket 端口”同一台电脑运行 TWS 模拟账户和 Python 脚本时,常见配置是:
host = 127.0.0.1port = 7497常见端口如下:
| 场景 | 常见端口 |
|---|---|
| TWS 模拟账户 | 7497 |
| TWS 真实账户 | 7496 |
| IB Gateway 模拟账户 | 4002 |
| IB Gateway 真实账户 | 4001 |
端口不是固定规则,最终以 TWS / IB Gateway 的 API 设置页面为准。
运行最小验证脚本
Section titled “运行最小验证脚本”最小验证不要一上来请求行情、账户或下单。先用 reqCurrentTime() 验证连接链路,因为它不依赖行情订阅,也不会触发订单风险。
可以把上一页的最小连接示例保存为 Python 文件,然后按自己的环境传入 host、port 和 clientId。重点不是脚本文件名,而是确认 nextValidId() 和 currentTime() 都能返回。
参数含义:
| 参数 | 示例 | 含义 |
|---|---|---|
--host | 127.0.0.1 | TWS / IB Gateway 所在机器。同一台电脑运行时通常使用回环地址。 |
--port | 7497 | TWS API Socket 端口。模拟账户常见为 7497。 |
--client-id | 901 | 本次 API 客户端编号,建议每个脚本用不同编号。 |
--timeout | 12 | 等待连接和回调的最长秒数。 |
通过时会看到类似输出:
TWS API OK: server_time=1781368619, host=127.0.0.1, port=7497这说明:
- Python 可以导入
ibapi。 - 程序可以连接 TWS 的 Socket 端口。
- TWS 已接受这个 API 客户端。
nextValidId()已返回。reqCurrentTime()请求和currentTime()回调都正常。
最小代码结构
Section titled “最小代码结构”核心回调只需要三个:
def nextValidId(self, orderId: int): self.reqCurrentTime()
def currentTime(self, time_: int): print(f"SERVER_TIME={time_}") self.disconnect()
def error(self, reqId, errorCode, errorString, advancedOrderRejectJson=""): print(f"API message: reqId={reqId}, code={errorCode}, message={errorString}")这里故意不用行情、合约详情、账户数据或订单接口。reqCurrentTime() 不依赖行情权限,也不会触发交易风险,是验证连接最干净的请求之一。
TWS 里的连接确认
Section titled “TWS 里的连接确认”第一次连接时,TWS 可能弹出 API 连接确认窗口。确认后,TWS 才会真正接受这个 API 客户端。
如果没有弹窗,也不一定是异常:同一台电脑、同一套 TWS 设置之前已经允许过连接时,TWS 可能直接接受连接。
因此连接验证不要依赖“有没有看到弹窗”,而应该依赖两个回调信号:
| 信号 | 含义 |
|---|---|
nextValidId(orderId) | 初始握手完成,可以开始发送请求。 |
currentTime(time_) | 一个简单请求已经成功返回。 |
| 现象 | 常见原因 | 处理方式 |
|---|---|---|
| Python 导入失败 | 这个解释器没装 ibapi | 确认 python 和 pip 属于同一环境。 |
connect() 报 502 | TWS 未启动、端口错、API 未启用、防火墙拦截 | 检查 TWS API Settings 和端口。 |
收不到 nextValidId() | TWS 弹出 API 连接确认未接受,或握手未完成 | 看 TWS 界面是否有确认窗口;已经信任过同一台电脑的连接时可能不会再弹。 |
收到 nextValidId() 但无 currentTime() | 没有运行消息循环,或脚本提前退出 | 确认 app.run() 在线程中运行。 |
| 连接一会儿断开 | TWS 重启、锁定、网络变化或 clientId 冲突 | 看日志并换一个独立 clientId。 |
继续验证什么
Section titled “继续验证什么”连接验证通过后,再按目标选择下一步接口:
| 目标 | 下一步接口 |
|---|---|
| 查合约是否写对 | reqContractDetails() |
| 拉历史 K 线 | reqHistoricalData() |
| 看实时行情 | reqMktData() |
| 看账户和持仓 | reqAccountSummary()、reqPositions() |
| 测试订单结构 | placeOrder() + whatIf=True |