TWS API 基础教程
官方 TWS API Basics Tutorial 是一个学习入口。官方说明,这个教程系列用 Python 演示 TWS API 功能,但函数调用在 Java、C++、C# 等语言里也遵循相似模式。它覆盖的主题包括下载和运行 TWS / IB Gateway、安装 TWS API、请求实时和历史行情、提交和监控订单、查看账户信息、使用市场扫描器。
本文档把这页整理成中文学习地图:先让新手知道每一类接口在系统里负责什么,再去具体页面看字段、参数、回调、示例代码和错误处理。
官方入口:IBKR TWS API Documentation
先理解这条链路
Section titled “先理解这条链路”TWS API 不是“浏览器访问 URL,然后立刻返回 JSON”的接口。它是本地 Socket 通道:
你的程序 -> 连接已登录的 TWS / IB Gateway -> 通过 EClient 发送请求 -> 通过 EWrapper 接收回调 -> 由 TWS / IB Gateway 与 IBKR 后端通信这条链路里每个部分都很重要:
| 部分 | 中文理解 | 新手要记住什么 |
|---|---|---|
| TWS / IB Gateway | 已登录的交易终端或交易网关 | API 程序不能替代登录,也不能绕过 2FA。 |
| Socket 端口 | 程序连接 TWS / IB Gateway 的端口 | TWS 模拟账户常见 7497,真实账户常见 7496;IB Gateway 端口通常不同。 |
EClient | 请求发送端 | 调用 reqMktData()、reqHistoricalData()、placeOrder() 等方法。 |
EWrapper | 回调接收端 | 实现 tickPrice()、historicalData()、orderStatus() 等回调。 |
| 消息循环 | 持续读取 TWS 返回消息 | Python 里通常要启动 app.run(),否则很多回调不会被处理。 |
如果只复制请求方法,没有写对应回调,程序通常看起来像“没有返回”。TWS API 的核心是:请求方法和回调方法成对理解。
最小程序骨架
Section titled “最小程序骨架”下面是 TWS API Python 程序的最小骨架。它只连接已登录的模拟账户端口、等待 nextValidId(),再调用 reqIds(-1) 请求一次订单 ID。它不会请求行情,也不会下单。
from __future__ import annotations
import threadingimport time
from ibapi.client import EClientfrom ibapi.wrapper import EWrapper
class App(EWrapper, EClient): def __init__(self) -> None: EClient.__init__(self, self) self.ready = threading.Event() self.ids: list[int] = []
def nextValidId(self, orderId: int) -> None: # 收到 nextValidId 代表基础连接已经完成,可以开始发送请求。 self.ids.append(orderId) self.ready.set()
app = App()
try: app.connect("127.0.0.1", 7497, clientId=98200) thread = threading.Thread(target=app.run, daemon=True) thread.start()
if not app.ready.wait(10): raise RuntimeError("等待 nextValidId 超时,请检查 TWS API 设置和端口")
print(f"NEXT_VALID_ID={app.ids[0]}") app.reqIds(-1) time.sleep(1)
finally: app.disconnect()关键点:
| 代码 | 作用 |
|---|---|
class App(EWrapper, EClient) | 同一个对象既负责发请求,也负责收回调。 |
EClient.__init__(self, self) | 初始化客户端,并把回调接收对象设置为这个对象。 |
app.connect("127.0.0.1", 7497, clientId=98200) | 连接同一台机器上的 TWS 模拟账户端口。 |
threading.Thread(target=app.run, daemon=True) | 启动消息循环,让回调能被处理。 |
nextValidId() | TWS 返回下一个可用订单 ID,也是常用连接就绪信号。 |
如果连接、端口和 API 设置都正确,输出通常类似:
NEXT_VALID_ID=1NEXT_VALID_ID 的具体数字不重要。重要的是程序收到了 nextValidId() 回调,说明 Socket 握手完成,后续可以继续请求合约详情、行情、账户或订单预览。
推荐学习顺序
Section titled “推荐学习顺序”不要一开始就写复杂策略。更稳妥的学习顺序是:
- 安装并登录 TWS / IB Gateway,启用 Socket API。
- 安装 TWS API 包,确认 Python 能导入
ibapi。 - 连接 TWS 或 IB Gateway 的 Socket 端口,收到
nextValidId()。 - 用
reqContractDetails()确认一个简单股票合约,例如 AAPL。 - 请求历史 K 线,理解
durationStr、barSizeSetting、whatToShow、useRTH。 - 请求实时或延迟行情,理解行情权限、tick 类型和回调频率。
- 请求账户、持仓、PnL,确认账户权限和字段含义。
- 用
whatIf预览订单,再理解正式下单、改单、撤单和订单状态。 - 再看扫描器、新闻、FA、事件交易、WSH 等扩展能力。
这个顺序能避免一个常见错误:端口、合约、权限、回调还没弄清楚,就直接复制下单代码。
常见主题对应关系
Section titled “常见主题对应关系”| 主题 | 请求方法 | 回调方法 | 先看什么 |
|---|---|---|---|
| 服务器时间 | reqCurrentTime() | currentTime() | 连接是否通。 |
| 下一个订单 ID | reqIds() | nextValidId() | 连接就绪和订单 ID 管理。 |
| 合约详情 | reqContractDetails() | contractDetails()、contractDetailsEnd() | 合约是否唯一。 |
| 历史 K 线 | reqHistoricalData() | historicalData()、historicalDataEnd() | 参数、周期、权限、pacing。 |
| 实时行情 | reqMktData() | tickPrice()、tickSize()、tickString() | 行情权限和 tick 类型。 |
| 账户摘要 | reqAccountSummary() | accountSummary()、accountSummaryEnd() | 账户字段和币种。 |
| 持仓 | reqPositions() | position()、positionEnd() | 合约、数量、成本。 |
| 下单 | placeOrder() | openOrder()、orderStatus()、execDetails()、error() | 订单对象、风控、状态同步。 |
| 撤单 | cancelOrder() | orderStatus()、error() | 是否同一 clientId、订单是否仍可撤。 |
| 扫描器 | reqScannerSubscription() | scannerData()、scannerDataEnd() | 扫描条件、结果数量、取消订阅。 |
读文档时可以用这个表反查:看到一个 req... 请求,就去找它对应的 EWrapper 回调;看到一个回调,就反推是哪类请求触发的。
TWS API 参数可以先分成几类:
| 类型 | 常见字段 | 中文理解 |
|---|---|---|
| 连接参数 | host、port、clientId | 连接到哪个 TWS / IB Gateway,以及用哪个客户端编号。 |
| 请求编号 | reqId | 自己给请求取的编号,用来把回调和请求配对。 |
| 订单编号 | orderId | 下单使用的编号,需要遵守 nextValidId 规则。 |
| 合约字段 | symbol、secType、exchange、currency、primaryExchange | 描述要查询或交易的金融工具。 |
| 行情参数 | whatToShow、useRTH、marketDataType、genericTickList | 决定请求什么行情、是否只看常规交易时段、是否请求扩展 tick。 |
| 订单字段 | action、orderType、totalQuantity、lmtPrice、tif | 决定买卖方向、订单类型、数量、价格和有效期。 |
| 取消请求 | cancel... 系列方法 | 取消行情、历史数据、扫描器或订单请求。 |
不要孤立背字段名。正确方式是把字段放回“请求方法 + 回调方法 + TWS 界面含义”里理解。
新手最容易混淆的事
Section titled “新手最容易混淆的事”| 混淆点 | 正确理解 |
|---|---|
| 能连接端口等于 API 可用 | 不一定。收到 nextValidId() 才基本说明 TWS API 握手完成。 |
调用 reqHistoricalData() 会直接返回列表 | 不会。K 线会逐条从 historicalData() 回调回来。 |
| 能看行情就能下单 | 不一定。行情权限、交易权限、产品权限和订单风控是不同层面的权限。 |
| 模拟账户没有风险 | 仍要认真处理订单 ID、数量、价格、状态同步和错误码。 |
clientId 随便填 | 多个程序共用或冲突时,会影响订单绑定和状态接收。 |
| 官方示例能跑,自己的代码不能跑 | 先对比消息循环、回调、端口、clientId 和 TWS 设置。 |
示例验证原则
Section titled “示例验证原则”本文档里的代码示例按这个原则处理:
| 情况 | 写法 |
|---|---|
| 能在模拟账户实测 | 写可复制代码、真实输出形态和字段解释。 |
| 需要行情权限 | 写代码和错误处理,并说明模拟账户可能出现权限错误。 |
| 需要 FA、新闻、WSH 或特殊订阅 | 写清权限条件;没有权限时展示真实错误或说明限制。 |
| 涉及下单 | 优先使用 whatIf、模拟账户、清晰风控和订单状态回调。 |
如果读者复制示例后得到不同结果,优先检查:TWS 是否已登录、API 是否启用、端口是否正确、Python 是否导入了同一个 ibapi、账户是否有对应权限。
官方 TWS API Basics Tutorial 说明基础教程系列使用 Python 演示 TWS API 功能,覆盖下载运行 TWS / IB Gateway、安装 TWS API、请求实时和历史行情、提交和监控订单、查看账户信息、处理市场扫描器。官方也说明函数调用在各语言中相似。