跳转到内容

通过 TWS 远程连接 TWS API

远程连接的意思是:TWS 运行在一台机器上,API 程序运行在另一台机器上。程序不再连接 127.0.0.1,而是连接 TWS 所在机器的局域网 IP、内网 IP 或经过安全隧道暴露出来的地址。

典型链路如下:

远程 API 程序 -> 网络 -> 运行 TWS 的机器 -> TWS Socket 端口 -> IBKR 后端

远程连接能用,但不适合作为新手的第一步。建议先把同一台电脑上的 127.0.0.1:7497 跑通,再改成远程地址。否则一旦失败,很难判断是 TWS 设置、网络、防火墙、IP 白名单、端口还是代码本身的问题。

场景是否适合说明
同一台电脑上的脚本连接 TWS更适合新手使用 127.0.0.1,变量最少
局域网内另一台电脑连接 TWS可以使用需要 Trusted IPs 和防火墙放行
服务器连接家里或办公室电脑上的 TWS谨慎使用网络不稳定、IP 变化和安全风险更高
公开互联网直接暴露 TWS API 端口不建议TWS API Socket 不应当当作公网 Web 接口使用
服务器长期运行自动化程序更建议用 IB GatewayIB Gateway 界面更轻,更适合服务端会话

如果只是让网页前端直接连接用户电脑上的 TWS,这条路不适合。浏览器不能原生连接 TWS API 的 TCP Socket,真正需要网页界面时,应由本地脚本或服务器后端作为中间层。

在运行 TWS 的机器上,进入:

Global Configuration -> API -> Settings

远程连接通常要确认这些设置:

设置建议说明
Enable ActiveX and Socket Clients勾选启用 TWS API Socket
Socket Port记录实际端口TWS 模拟账户常见为 7497,真实账户常见为 7496
Read-Only API按用途决定只读测试可勾选;需要测试订单或 WhatIf 时不能只读
Allow connections from localhost only远程连接时不能只允许本地连接只允许本地连接时,外部机器无法连接
Trusted IPs只添加需要连接的单个 IP不要放宽到不确定的地址范围

官方文档说明,远程连接需要在 Trusted IPs 中配置允许连接的 IP;这里填写的是远程 API 程序所在机器的 IP,不是 TWS 机器自己的 IP。

假设:

  • TWS 运行在 Windows 电脑:192.168.1.20
  • Python 程序运行在另一台电脑:192.168.1.31
  • TWS API 端口:7497

那么配置关系是:

位置应该填写
TWS 的 Trusted IPs192.168.1.31
Python 的 host192.168.1.20
Python 的 port7497

很多连接失败来自把这两个 IP 写反:Trusted IPs 写的是“谁被允许连接我”,代码里的 host 写的是“我要连接谁”。

只改 TWS API 设置还不够。运行 TWS 的电脑还必须允许入站连接到对应端口。

常见做法是:

  1. 只在专用网络或内网环境中放行。
  2. 只放行 TWS API 使用的端口,例如 7497
  3. 只允许可信来源 IP 访问,不要对公网开放。

如果 TWS 设置正确,但远程程序仍然报连接失败,先检查网络是否能访问这台机器和端口,再看 Python 代码。端口不通时,改 EWrapper 回调没有帮助。

远程连接代码和本地连接代码几乎一样,唯一变化是 host 不再是 127.0.0.1

import threading
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
class App(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.ready = threading.Event()
self.done = threading.Event()
self.server_time = None
def nextValidId(self, orderId: int):
# 收到 nextValidId,说明远程 socket 已经完成 API 握手。
self.ready.set()
self.reqCurrentTime()
def currentTime(self, time_: int):
# time_ 是 IBKR 服务器时间戳,用来验证请求和回调链路。
self.server_time = time_
self.done.set()
self.disconnect()
def error(self, reqId, errorCode, errorString, advancedOrderRejectJson=""):
print(f"API message: reqId={reqId}, code={errorCode}, message={errorString}")
app = App()
# 改成运行 TWS 的那台机器的地址。
TWS_HOST = "192.168.1.20"
TWS_PORT = 7497
CLIENT_ID = 21
app.connect(TWS_HOST, TWS_PORT, clientId=CLIENT_ID)
thread = threading.Thread(target=app.run, daemon=True)
thread.start()
if not app.ready.wait(8):
app.disconnect()
raise TimeoutError("已发起远程连接,但没有收到 nextValidId 回调")
if not app.done.wait(8):
app.disconnect()
raise TimeoutError("已连接,但 reqCurrentTime 没有返回")
print(f"SERVER_TIME={app.server_time}")
thread.join(timeout=1)

这段示例只验证连接和 reqCurrentTime(),不请求行情、不读账户、不下单。远程连接第一次调试时,先用这种最小请求确认链路,再继续写业务接口。

TWS API 是给受信任的本地程序或内网程序使用的交易接口,不应该像普通网站 API 一样裸露在公网。

建议按下面优先级选择:

优先级方式说明
1同一台电脑 127.0.0.1最简单,适合开发和连接检查
2局域网固定 IP适合两台可信设备在同一网络中调试
3VPN 或 SSH 隧道适合跨网络,但仍把 TWS 端口限制在受控通道内
4公网直接开放端口不建议

如果要做网站或后端服务,更合理的结构是:网站后端连接服务器上的 IB Gateway,或者用户本地安装连接器,由连接器和 TWS 通信。不要让网页前端直接承担 TWS Socket 连接职责。

现象常见原因处理方式
远程连接直接失败TWS 只允许 localhost检查 Allow connections from localhost only
本地连接能连,另一台机器不能连Trusted IPs 没加对,或防火墙拦截确认远程程序所在机器 IP
连接后一直没有回调TWS 弹窗未接受、消息循环没启动、网络中断看 TWS 界面和 app.run() 是否运行
改了 IP 仍然连不上写成了 TWS 机器自己的 IP,或 IP 已变化重新确认两台机器的实际内网 IP
远程偶发断开Wi-Fi、休眠、TWS 重启、认证过期程序要设计重连和状态恢复

远程连接失败时,先回到本地连接检查。如果 TWS 所在机器上使用 127.0.0.1 也连不上,问题通常不在远程网络,而在 TWS API 设置、端口或 Python 环境。

IBKR Campus: TWS API Documentation