实现 Visual Basic .NET
Visual Basic .NET 不是 TWS API 新项目的首选路线,但官方 API 包仍然提供了 VB.NET 示例。理解这一页的关键是:VB.NET 示例不是直接使用一个独立的 VB API,而是通过引用官方 C# 客户端库 CSharpAPI 来访问 IBApi 命名空间。
如果你只是从零开始做自动化交易系统,优先选择 Python、Java 或 C# 会更省事;如果你的团队已有 VB.NET、WinForms、桌面工具或旧系统代码,那么可以按这里的方式接入。
官方推荐方式
Section titled “官方推荐方式”官方 VB.NET 示例在 MainModule.vb 里明确建议:以前使用 ActiveX 控件的 VB.NET 用户,应改用 C# client library,也就是 CSharpAPI。
这句话很重要,因为很多旧资料会把 VB.NET、ActiveX、VBA 混在一起:
| 名称 | 适用场景 | 建议 |
|---|---|---|
| VB.NET | Visual Studio 里的 .NET Framework 项目 | 可以引用 CSharpAPI 项目或编译后的 DLL |
| ActiveX / COM | 更老的 Windows 集成方式 | 新项目不建议继续作为主线 |
| Excel VBA | Excel 宏环境 | 不等同于 VB.NET,工程结构和依赖方式不同 |
| C# API 库 | 官方 .NET 客户端库 | VB.NET 示例实际依赖它 |
因此,VB.NET 接入 TWS API 的核心不是寻找 VBApi.dll,而是在 VB.NET 工程里引用 CSharpAPI.csproj 或它编译出的 CSharpAPI.dll,然后使用 IBApi.EClientSocket、IBApi.EWrapper、IBApi.EReader 这些类。
示例文件位置
Section titled “示例文件位置”安装 TWS API 后,官方 VB.NET 示例通常位于 API 包的 samples/VB 目录下。以常见目录结构为例:
| 文件或目录 | 作用 |
|---|---|
samples/VB/Testbed/VB_Testbed.sln | VB.NET 控制台示例解决方案 |
samples/VB/Testbed/Testbed.vbproj | VB.NET 示例工程,目标框架为 .NET Framework 4.8 |
samples/VB/Testbed/MainModule.vb | 示例入口,包含连接 TWS、启动消息线程、等待 nextValidId 的主流程 |
samples/VB/Testbed/EWrapperImpl.vb | EWrapper 回调实现,接收 nextValidId、行情、订单、账户等回调 |
source/CSharpClient/client/CSharpAPI.csproj | 官方 C# API 客户端库,VB.NET 工程通过项目引用使用它 |
samples/VB/VB_API_Sample/VB_API_sample.sln | 更完整的 WinForms 示例,界面和代码量较大 |
学习时先看 Testbed,它更适合理解连接链路;VB_API_Sample 更像完整桌面程序示例,适合已经熟悉 TWS API 后参考界面组织方式。
VB.NET 和 C#、Python 的底层逻辑相同:先连接 TWS 或 IB Gateway,再由后台读取线程处理服务端回调。
典型流程如下:
- 在 TWS 或 IB Gateway 中启用 API Socket。
- 确认端口:模拟账户 TWS 常用
7497,真实账户 TWS 常用7496。 - VB.NET 工程引用
CSharpAPI。 - 创建
EWrapper实现类,用来接收回调。 - 创建
EClientSocket并调用eConnect()。 - 启动
EReader消息线程。 - 等待
nextValidId回调,确认连接已经建立。 - 再发送行情、账户、订单等请求。
nextValidId 经常被新手忽略。它不仅是下单编号的起点,也可以作为连接建立后的第一个重要信号:如果一直收不到它,通常说明 Socket 没真正连通、端口错误、API 没启用,或 TWS 阻止了这个客户端连接。
连接骨架示例
Section titled “连接骨架示例”下面的片段对应官方 Testbed 示例的连接骨架。它依赖同一工程中的 EWrapperImpl.vb,不是单文件脚本。
Imports IBApiImports System.Threading
Module MainModule Dim wrapperImpl As EWrapperImpl = New EWrapperImpl
Sub Main() ' EClientSocket 负责向 TWS / IB Gateway 发送请求。 Dim socketClient As EClientSocket = wrapperImpl.socketClient
' 连接同一台机器上的 TWS 模拟账户。真实账户通常改为 7496。 socketClient.eConnect("127.0.0.1", 7497, 0)
' EReader 负责从 Socket 队列中读取服务端消息。 Dim msgThread As Thread = New Thread(AddressOf messageProcessing) msgThread.IsBackground = True
If wrapperImpl.serverVersion() > 0 Then msgThread.Start() End If
' 等待 nextValidId 回调。收到后说明连接链路已经可用。 While wrapperImpl.nextOrderId = 0 Thread.Sleep(100) End While
' 发送一个简单请求:获取服务器时间。 socketClient.reqCurrentTime()
Thread.Sleep(1000) socketClient.eDisconnect() End Sub
Private Sub messageProcessing() Dim reader As EReader = New EReader(wrapperImpl.socketClient, wrapperImpl.eReaderSignal) reader.Start()
While wrapperImpl.socketClient.IsConnected wrapperImpl.eReaderSignal.waitForSignal() reader.processMsgs() End While End SubEnd Module关键对象解释
Section titled “关键对象解释”| 对象或参数 | 中文解释 |
|---|---|
EClientSocket | 客户端请求入口。调用 reqCurrentTime()、reqMktData()、placeOrder() 等方法时,都是通过它发送到 TWS。 |
EWrapper | 回调接口。TWS 返回的数据不会直接从请求函数返回,而是进入 EWrapper 的对应回调方法。 |
EWrapperImpl | 示例工程里自己写的回调实现类,负责保存 socketClient、eReaderSignal、nextOrderId 等状态。 |
EReader | 消息读取器。连接后必须持续处理消息队列,否则回调不会正常进入程序。 |
eConnect(host, port, clientId) | 建立连接。host 通常是 127.0.0.1,port 要和 TWS API 设置一致,clientId 用来区分不同 API 客户端。 |
nextValidId(orderId) | 连接成功后常见的回调之一,也是后续下单编号的起点。 |
reqCurrentTime() | 获取服务器时间的简单请求,适合用来验证回调链路。 |
工程配置注意点
Section titled “工程配置注意点”官方 Testbed.vbproj 使用的是 .NET Framework 4.8,并引用 source/CSharpClient/client/CSharpAPI.csproj。在 Visual Studio 中打开时,要确认以下几点:
- 解决方案能找到
CSharpAPI.csproj,否则会出现项目引用丢失。 PlatformTarget与依赖一致。官方示例常见为x86。Google.Protobuf等依赖要能还原或从示例包路径中找到。- TWS 或 IB Gateway 已登录,并且 API Socket 已启用。
host、port、clientId与运行环境一致。
如果你只是想验证 TWS 是否能连通,Python 的 currentTime 脚本通常更快;VB.NET 更适合已有 .NET 桌面工程需要集成 IBKR 交易能力的场景。
为什么 VB.NET 示例还要引用 C# 项目?
Section titled “为什么 VB.NET 示例还要引用 C# 项目?”因为官方 .NET 客户端库主要以 C# 项目形式提供。VB.NET 可以引用 C# 项目或 DLL,然后调用同一个 IBApi 命名空间。这样比继续维护 ActiveX / COM 集成更清晰。
可以直接把示例代码复制进自己的工程吗?
Section titled “可以直接把示例代码复制进自己的工程吗?”可以参考结构,但不要只复制 MainModule.vb。它依赖 EWrapperImpl.vb、工程引用、回调实现和 NuGet/本地 DLL 依赖。更稳妥的做法是先让官方 Testbed 能编译,再把连接、回调、请求代码迁移到自己的工程。
为什么连接后没有任何数据?
Section titled “为什么连接后没有任何数据?”优先检查四件事:
- TWS API 设置中是否启用了 Socket 客户端。
- 端口是否匹配模拟账户或真实账户环境。
EReader消息线程是否已经启动。EWrapperImpl.nextValidId()是否收到回调并保存了nextOrderId。
如果 eConnect() 没报错,但 nextValidId 一直不出现,重点看 TWS 端口、API 设置、连接限制和客户端 ID 冲突。