跳转到内容

TWS API

TWS API 是 Interactive Brokers 最常用于程序化交易的接口之一。它通过 Socket 连接已经登录的 Trader Workstation(TWS)IB Gateway,然后由 TWS / IB Gateway 负责和 IBKR 后端通信。

它适合需要完整交易能力的开发场景,例如读取行情、查询合约、获取历史 K 线、查询账户持仓、提交订单、撤单、监听订单状态和处理错误码。

优先选择 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 GatewayTWS API 不适合,因为它必须连接本地或服务器上的客户端。
已经明确需要标准 HTTP endpointClient Portal Web API / Web API 更接近普通 Web 服务。

TWS API 的连接链路可以理解为:

你的 Python 程序
↓ TCP Socket
TWS 或 IB Gateway
IBKR 后端

常见端口:

客户端账户类型默认端口
TWS模拟账户7497
TWS实盘账户7496
IB Gateway模拟账户4002
IB Gateway实盘账户4001

初学阶段建议先用 TWS 模拟账户 + 7497。这样既能看到 TWS 图形界面,又能避免误操作真实资金。

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 EClient
from 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.nj
IB_ERROR=-1|2104|市场数据场连接正常:usfuture
IB_ERROR=-1|2104|市场数据场连接正常:usopt.nj
IB_ERROR=-1|2104|市场数据场连接正常:cashfarm
IB_ERROR=-1|2104|市场数据场连接正常:usfarm
IB_ERROR=-1|2106|历史市场数据场连接正常:ushmds
服务器时间: 1781271588

21042106 是连接状态消息,表示行情场和历史行情场连接正常。只要后面收到了 服务器时间,就说明 Socket 连接和回调链路已经跑通。

如果没有输出,通常先检查 TWS API 设置、端口、只允许本机连接、TWS 是否已经登录,以及防火墙是否拦截。

参数中文解释常见取值
hostTWS / IB Gateway 所在机器的地址。本机一般是 127.0.0.1
portTWS / IB Gateway 的 API 端口。TWS 模拟常用 7497
clientId当前 API 客户端编号。可以用 1101901 等,不要和其他连接重复。
orderIdTWS 分配或确认的订单编号起点。nextValidId 回调中收到。
reqId请求编号,用来区分多个并发请求。行情、历史数据、合约查询经常需要。

clientIdreqId 容易混淆:

  • clientId 是“这个程序连接 TWS 的身份编号”。
  • reqId 是“某一次请求的编号”。

例如一个程序用 clientId=901 连接 TWS,然后它可以发出 reqId=1001 的合约查询、reqId=2001 的历史 K 线请求。

误区正确理解
TWS API 是网页接口不是。它是 Socket API,浏览器不能直接调用。
调用方法后会立刻返回数据多数请求通过回调返回,需要实现对应的 EWrapper 方法。
只要安装 Python 包就能连 IBKR还必须打开并登录 TWS 或 IB Gateway。
模拟账户一定有所有行情模拟账户也受行情订阅、延迟行情和权限限制影响。
连接成功就能下单下单还需要合约正确、账户权限正确、订单参数正确,并通过 TWS 风控检查。

TWS API 不能由浏览器直接连接 TWS 端口。学习和开发时,更可靠的方式是把示例代码复制到自己的 Python 项目里运行:

Python 示例代码
↓ TWS API Socket
TWS / IB Gateway

适合优先本地验证的功能:

功能验证重点原因
测试连接reqCurrentTime() 是否返回服务器时间先确认 Socket、端口和 API 设置正确。
合约详情查询reqContractDetails() 是否返回唯一合约后面的行情、历史 K 线和订单都依赖合约定义。
历史 K 线reqHistoricalData() 是否返回 bars可以同时验证参数、权限和限频。
WhatIf 订单预览whatIf=True 是否返回保证金信息能检查订单对象,但不真正成交。
模拟账户下单订单状态和错误回调适合在 paper trading 环境验证完整订单链路。

接口示例会优先给可复制的 Python 代码,并说明请求参数、回调结果和常见错误。MCP 文档查询会把这些规则整理成 Agent 更容易读取的结构化内容。