TWS API
TWS API 是 Interactive Brokers 最常用于程序化交易的接口之一。它通过 Socket 连接已经登录的 Trader Workstation(TWS) 或 IB Gateway,然后由 TWS / IB Gateway 负责和 IBKR 后端通信。
它适合需要完整交易能力的开发场景,例如读取行情、查询合约、获取历史 K 线、查询账户持仓、提交订单、撤单、监听订单状态和处理错误码。
什么时候选择 TWS API
Section titled “什么时候选择 TWS API”优先选择 TWS API 的典型情况:
| 场景 | 说明 |
|---|---|
| 本地 Python 策略开发 | Windows 或 Mac 本机打开 TWS,Python 连接 127.0.0.1:7497。 |
| 模拟账户测试 | 用 paper trading 先测试行情、合约、订单对象和 WhatIf 预览。 |
| 需要完整订单能力 | TWS API 覆盖普通订单、组合订单、条件订单、算法订单等大量交易功能。 |
| 需要账户和持仓数据 | 可以读取账户摘要、持仓、盈亏、执行记录、订单状态等。 |
| 服务器长期运行 | 可以用 IB Gateway 代替完整 TWS,但仍然使用 TWS API 协议。 |
不适合选择 TWS API 的情况:
| 场景 | 更合适的方向 |
|---|---|
| 只想用浏览器直接请求接口 | Client Portal Web API 或 Web API。 |
| 只需要日终报表和流水 | Flex Web Service。 |
| 不想运行 TWS 或 IB Gateway | TWS API 不适合,因为它必须连接本地或服务器上的客户端。 |
| 已经明确需要标准 HTTP endpoint | Client Portal Web API / Web API 更接近普通 Web 服务。 |
TWS API 的连接链路可以理解为:
你的 Python 程序 ↓ TCP SocketTWS 或 IB Gateway ↓IBKR 后端常见端口:
| 客户端 | 账户类型 | 默认端口 |
|---|---|---|
| TWS | 模拟账户 | 7497 |
| TWS | 实盘账户 | 7496 |
| IB Gateway | 模拟账户 | 4002 |
| IB Gateway | 实盘账户 | 4001 |
初学阶段建议先用 TWS 模拟账户 + 7497。这样既能看到 TWS 图形界面,又能避免误操作真实资金。
请求与回调模型
Section titled “请求与回调模型”TWS API 不是普通 REST API。它使用请求与回调模型:
调用请求方法 ↓TWS 接收请求 ↓TWS 通过回调方法返回数据例如请求服务器时间:
| 步骤 | 方法 | 说明 |
|---|---|---|
| 建立连接 | connect(host, port, clientId) | 连接 TWS 或 IB Gateway。 |
| 等待连接可用 | nextValidId(orderId) | TWS 告诉程序连接已经准备好。 |
| 发起请求 | reqCurrentTime() | 请求当前服务器时间。 |
| 接收返回 | currentTime(time_) | TWS 通过回调返回服务器时间。 |
这种模型对新手来说有一点绕,但非常重要。很多接口不是“调用后立刻返回结果”,而是“调用请求方法后,在另一个回调方法里收到结果”。
最小 Python 示例:请求服务器时间
Section titled “最小 Python 示例:请求服务器时间”下面的示例只做一件事:连接本机 TWS,然后请求 IBKR 服务器时间。
运行前需要确认:
- TWS 已经登录模拟账户。
- TWS API 设置里已经启用 Socket 客户端。
- 模拟账户端口是
7497。 - 本机连接时保留
127.0.0.1。
from ibapi.client import EClientfrom ibapi.wrapper import EWrapper
class TimeDemoApp(EWrapper, EClient): def __init__(self): EClient.__init__(self, self)
def nextValidId(self, orderId: int): # 收到 nextValidId 通常表示连接已经准备好。 # 这里再请求服务器时间,避免连接还没准备好就发送请求。 self.reqCurrentTime()
def currentTime(self, time_: int): # time_ 是 Unix 时间戳,表示 IBKR 服务器时间。 print("服务器时间:", time_) self.disconnect()
def error(self, reqId, errorCode, errorString, advancedOrderRejectJson=""): # TWS API 的错误和系统消息都会从 error 回调出来。 print("错误消息:", reqId, errorCode, errorString)
app = TimeDemoApp()
# 127.0.0.1 表示连接本机 TWS。# 7497 是 TWS 模拟账户常用端口。# clientId 是当前程序的客户端编号,同一个 TWS 下不要和其他程序重复。app.connect("127.0.0.1", 7497, clientId=901)
# app.run() 会启动消息循环,等待 TWS 回调。app.run()本机验证时,TWS 返回过下面的真实输出:
IB_ERROR=-1|2104|市场数据场连接正常:usfarm.njIB_ERROR=-1|2104|市场数据场连接正常:usfutureIB_ERROR=-1|2104|市场数据场连接正常:usopt.njIB_ERROR=-1|2104|市场数据场连接正常:cashfarmIB_ERROR=-1|2104|市场数据场连接正常:usfarmIB_ERROR=-1|2106|历史市场数据场连接正常:ushmds服务器时间: 17812715882104 和 2106 是连接状态消息,表示行情场和历史行情场连接正常。只要后面收到了 服务器时间,就说明 Socket 连接和回调链路已经跑通。
如果没有输出,通常先检查 TWS API 设置、端口、只允许本机连接、TWS 是否已经登录,以及防火墙是否拦截。
关键参数解释
Section titled “关键参数解释”| 参数 | 中文解释 | 常见取值 |
|---|---|---|
host | TWS / IB Gateway 所在机器的地址。 | 本机一般是 127.0.0.1。 |
port | TWS / IB Gateway 的 API 端口。 | TWS 模拟常用 7497。 |
clientId | 当前 API 客户端编号。 | 可以用 1、101、901 等,不要和其他连接重复。 |
orderId | TWS 分配或确认的订单编号起点。 | 在 nextValidId 回调中收到。 |
reqId | 请求编号,用来区分多个并发请求。 | 行情、历史数据、合约查询经常需要。 |
clientId 和 reqId 容易混淆:
clientId是“这个程序连接 TWS 的身份编号”。reqId是“某一次请求的编号”。
例如一个程序用 clientId=901 连接 TWS,然后它可以发出 reqId=1001 的合约查询、reqId=2001 的历史 K 线请求。
| 误区 | 正确理解 |
|---|---|
| TWS API 是网页接口 | 不是。它是 Socket API,浏览器不能直接调用。 |
| 调用方法后会立刻返回数据 | 多数请求通过回调返回,需要实现对应的 EWrapper 方法。 |
| 只要安装 Python 包就能连 IBKR | 还必须打开并登录 TWS 或 IB Gateway。 |
| 模拟账户一定有所有行情 | 模拟账户也受行情订阅、延迟行情和权限限制影响。 |
| 连接成功就能下单 | 下单还需要合约正确、账户权限正确、订单参数正确,并通过 TWS 风控检查。 |
本地验证方式
Section titled “本地验证方式”TWS API 不能由浏览器直接连接 TWS 端口。学习和开发时,更可靠的方式是把示例代码复制到自己的 Python 项目里运行:
Python 示例代码 ↓ TWS API SocketTWS / IB Gateway适合优先本地验证的功能:
| 功能 | 验证重点 | 原因 |
|---|---|---|
| 测试连接 | reqCurrentTime() 是否返回服务器时间 | 先确认 Socket、端口和 API 设置正确。 |
| 合约详情查询 | reqContractDetails() 是否返回唯一合约 | 后面的行情、历史 K 线和订单都依赖合约定义。 |
| 历史 K 线 | reqHistoricalData() 是否返回 bars | 可以同时验证参数、权限和限频。 |
| WhatIf 订单预览 | whatIf=True 是否返回保证金信息 | 能检查订单对象,但不真正成交。 |
| 模拟账户下单 | 订单状态和错误回调 | 适合在 paper trading 环境验证完整订单链路。 |
接口示例会优先给可复制的 Python 代码,并说明请求参数、回调结果和常见错误。MCP 文档查询会把这些规则整理成 Agent 更容易读取的结构化内容。