跳转到内容

TWS API 文档介绍

TWS API 是 Interactive Brokers 提供给开发者连接 Trader Workstation(TWS)IB Gateway 的本地 Socket API。它不是直接访问云端的 REST 接口,而是让你的程序先连到已经登录的 TWS / IB Gateway,再由 TWS / IB Gateway 代表你的账户和 IBKR 后端通信。

官方入口:IBKR Campus - TWS API Documentation

旧版官方文档已经标注为 deprecated,但里面对 EClientEWrapper、连接流程和示例项目的解释仍然有参考价值。本站会以新版目录为准,同时结合旧版说明、Python 实测结果和中文开发者常见问题重新整理。

TWS API 适合把交易、行情和账户数据接入自己的程序,例如:

  • 查询账户摘要、持仓、盈亏和成交。
  • 查询合约详情,确认股票、期权、期货、外汇等金融工具的唯一标识。
  • 请求实时行情、延迟行情、历史 K 线和逐笔数据。
  • 在模拟账户或真实账户中提交、修改、取消订单。
  • 接收订单状态、成交回报、佣金费用和错误消息。

TWS API 最大的难点不是“怎么发一个请求”,而是要理解它的 请求 / 回调模型:程序通过 EClient 发请求,再由 EWrapper 中的回调函数接收结果。后面的示例都会围绕这个模型展开。

你的 Python / Java / C++ / C# 程序
↓ 发送请求:EClient
TWS / IB Gateway
↑ 接收回调:EWrapper

例如请求历史 K 线时,程序调用的是 reqHistoricalData(),但结果不是这个函数直接返回,而是从 historicalData()historicalDataEnd() 等回调里陆续回来。下单也是一样,placeOrder() 只是发出订单,真正的订单状态要看 openOrder()orderStatus()execDetails()error()

概念中文解释新手要记住什么
EClient请求发送端调用 reqMktData()reqHistoricalData()placeOrder() 等方法。
EWrapper回调接收端实现 tickPrice()historicalData()orderStatus() 等回调来接结果。
EReader消息读取线程负责从 Socket 读取 TWS 返回的消息,并触发对应回调。Python 里通常由 API 包自动处理读取线程,但仍然需要调用 app.run() 处理消息队列。
clientId客户端编号同一个 TWS 可以接多个 API 客户端,clientId 用来区分它们。不要让两个程序随便共用同一个编号。
nextValidId下一个可用订单 ID也是常用的“连接已经准备好”信号。收到它以后再发请求更稳。
reqId请求编号行情、合约、历史数据等请求常用它把请求和回调配对。

使用 TWS API 前,需要先满足这些条件:

项目说明
TWS 或 IB Gateway必须至少运行一个,并且已经登录账户。
API 设置需要在 TWS / IB Gateway 中启用 Socket API,并确认端口。
账户环境新手和调试阶段建议使用 Paper Account(模拟账户)。
本地网络默认连接 127.0.0.1,远程连接需要额外设置可信 IP 和安全边界。
API 包Python、Java、C++、C# 等语言需要安装对应 TWS API 包。Python 用户通常需要安装官方 ibapi 包。
行情权限模拟账户可以下模拟单,但不代表一定有全部实时行情、逐笔数据或新闻权限。

这些前提应分开排查:下载、安装、TWS 设置、连接测试、行情权限和订单风控不要混在一起看。

常见端口如下:

运行环境默认端口说明
TWS 模拟账户7497本地开发最常见。
TWS 实盘账户7496真实交易环境,必须额外加风控。
IB Gateway 模拟账户4002更适合服务器常驻。
IB Gateway 实盘账户4001常见服务器实盘端口,风险最高。

如果你是第一次做 IBKR 自动化交易,建议按这个顺序读:

  1. 先读本页和 注意事项与限制,知道 TWS API 能做什么、不能做什么。
  2. 再读 下载 TWS 或 IB Gateway下载 TWS APITWS 设置,把本机模拟账户环境准备好。
  3. 接着读 连接机制,理解 connect()nextValidIdEReader 和断线处理。
  4. 然后读 合约 / 金融工具,先学会构造正确的 Contract
  5. 最后进入 市场数据账户与投资组合数据订单订单管理

这个顺序能避免一个常见错误:还没有搞清楚合约、端口、权限和回调,就直接复制下单代码。

本文档会尽量提供 Python 示例,因为 Python 对新手更友好,也更适合快速验证 TWS API 的请求和回调。但示例必须遵守一个规则:

可复制示例优先使用已经在本机 TWS / IB Gateway 模拟账户环境验证过的 Python 代码。

如果某个接口受行情订阅、账户权限、地区限制或产品权限影响,页面会写清楚可能出现的真实错误码和处理方向。例如逐笔数据、市场深度、新闻和部分期权数据,经常不是“代码错了”,而是账户权限或数据源限制。

示例代码会尽量遵守这些约定:

约定说明
API 名保持英文reqHistoricalDataContractOrder 等不翻译,避免和官方资料脱节。
注释使用中文让中文读者知道每一步为什么这样写。
参数表尽量完整不只解释最小示例里的参数,也解释常见可选参数和默认写法。
输出写真实形态能实测的写真实输出;受权限影响的写真实错误和原因。
不跳过回调请求函数和回调函数成对解释,避免只会发请求不会收结果。

下面这段代码展示的是 TWS API 最基础的结构:继承 EWrapper 接收回调,继承 EClient 发送请求,连接本机模拟账户端口 7497,收到 nextValidId 后请求服务器时间。

from ibapi.client import EClient
from ibapi.wrapper import EWrapper
class DemoApp(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
def nextValidId(self, orderId: int):
# 收到 nextValidId 通常表示连接握手已经完成,可以开始发送请求。
print("下一个可用订单 ID:", orderId)
self.reqCurrentTime()
def currentTime(self, time_: int):
# 服务器时间是 Unix 时间戳。收到这个回调,说明请求和回调链路已经通了。
print("服务器时间:", time_)
self.disconnect()
app = DemoApp()
app.connect("127.0.0.1", 7497, clientId=901)
app.run()

这段代码里最重要的不是 reqCurrentTime() 本身,而是整个消息流程:

connect()
-> TWS 接受连接
-> nextValidId()
-> reqCurrentTime()
-> currentTime()
-> disconnect()

如果连接失败,优先检查 TWS 是否已登录、API 是否启用、端口是否正确、是否允许本机连接。

本站有两个不同层次的 TWS API 内容:

内容用途
TWS API Documentation 主线按实际开发流程解释:设置、连接、账户、合约、行情、订单。
TWS API Reference 类参考按类和字段查资料,例如 ContractOrderBarEWrapper

写程序时通常先看主线教程,遇到字段不理解时再查类参考。这样既能知道“该调用哪个接口”,也能知道“字段为什么要这样填”。

本站也包含 Client Portal Gateway、Client Portal Web API、WebSocket 和 Flex Web Service 相关页面。它们和 TWS API 不要混用:

类型通信方式典型写法
TWS APITCP Socket + 回调app.connect()reqMktData()EWrapper.tickPrice()
Client Portal Web APIHTTP / WebSocketGET /iserver/accountsPOST /iserver/auth/status
Flex Web ServiceHTTP 报表下载生成报表、轮询报表、下载 XML/CSV

如果示例里出现 EClientEWrapperContractOrder,通常是在讲 TWS API。如果示例里出现 URL endpoint、curlrequests.get() 或 WebSocket topic,通常是在讲 Client Portal / Web API。