第 10 章 · 02 WebSocket 基础设施与部署


文档摘要

第 10 章 · 02 WebSocket 基础设施与部署 本节摘要:本节钻取 Brokerages 项目的两块基础设施——实时数据怎么进来、订单怎么发出去。WebSocket 公共基础设施( / / )是所有券商实时行情和订单推送的底座,加密券商(Binance/Bybit/Coinbase/Kraken)和部分传统券商都基于它实现。实盘独有的两个 Handler—— (订单发到真实券商、成交由券商推送 )和 (实时行情源,如 既做 brokerage 又做 data-queue-handler)——是回测没有的额外注入项。

第 10 章 · 02 WebSocket 基础设施与部署

本节摘要:本节钻取 Brokerages 项目的两块基础设施——实时数据怎么进来、订单怎么发出去。WebSocket 公共基础设施(BaseWebsocketsBrokerage / IWebSocket / WebSocketClientWrapper)是所有券商实时行情和订单推送的底座,加密券商(Binance/Bybit/Coinbase/Kraken)和部分传统券商都基于它实现。实盘独有的两个 Handler——BrokerageTransactionHandler(订单发到真实券商、成交由券商推送 OrderEvent)和 IDataQueueHandler(实时行情源,如 InteractiveBrokersBrokerage 既做 brokerage 又做 data-queue-handler)——是回测没有的额外注入项。最后讲 Docker 多架构部署(Dockerfile 基础 / DockerfileLeanFoundation 含 Python+R+Java / DockerfileLeanFoundationARM 树莓派等 ARM)以及 lean CLI(pip install lean,init/backtest/live-trade/research 一条龙)。读完本节,你将理解实盘与回测在基础设施层面的全部差异。

内容来源:原项目源码 Brokerages/BaseWebsocketsBrokerage.csBrokerages/IWebSocket.csEngine/TransactionHandlers/BrokerageTransactionHandler.csCommon/Interfaces/IDataQueueHandler.csDockerfile*Launcher/config.json,精读并套用体系化模板。

⚠️ 注意:本节出现的 BrokerageTransactionHandlerIDataQueueHandler 是实盘专属,回测分别用 BacktestingTransactionHandlerFileSystemDataFeed。这正是第 3 章讲的"配置字符串注入同一引擎"在实盘层的具体落地,下一节(03)会做完整对照。

学习目标

阅读完本节,你应当能够:

  1. 说清 BaseWebsocketsBrokerage / IWebSocket / WebSocketClientWrapper 三层 WebSocket 抽象的作用。
  2. 解释 BrokerageTransactionHandlerBacktestingTransactionHandler 在订单处理上的差异。
  3. 解释 IDataQueueHandler 是实盘独有的"额外注入项",为什么很多券商类同时实现 IBrokerage 和 IDataQueueHandler。
  4. 列出三个 Dockerfile 的分工(基础 / Foundation 含 Python+R+Java / FoundationARM)。
  5. 用 lean CLI 的四条命令(init / backtest / live-trade / research)完成开发闭环。

一、WebSocket 公共基础设施

现代券商(尤其加密货币交易所)都用 WebSocket 推送实时行情和订单状态——它比 REST 轮询高效得多(单连接双向流,毫秒级延迟)。Lean 在 Brokerages/ 项目里提供三层 WebSocket 抽象,所有券商实现共享同一套基础设施。

1.1 IWebSocket:统一接口

Brokerages/IWebSocket.cs 定义 WebSocket 客户端的统一接口(连接/断开/发送/事件),屏蔽底层实现差异。核心成员:Connect() / Disconnect() / IsOpen / Send(string) / 事件 Message / Error / Closed

1.2 WebSocketClientWrapper:实现

Brokerages/WebSocketClientWrapper.csIWebSocket 的标准实现,封装 .NET 的 ClientWebSocket,提供自动重连、消息队列、心跳等通用能力。每个券商实例化一个 WebSocketClientWrapper 指向自己的 WebSocket 服务端(Binance: wss://stream.binance.com:9443/ws、Coinbase: wss://advanced-trade-ws.coinbase.com、Bybit: wss://stream.bybit.com),消息回调里解析 JSON 转 BaseDataOrderEvent

1.3 BaseWebsocketsBrokerage:券商基类

Brokerages/BaseWebsocketsBrokerage.cs:33-87:

30 /// <summary> 31 /// Provides shared brokerage websockets implementation 32 /// </summary> 33 public abstract class BaseWebsocketsBrokerage : Brokerage 34 { 35 private const int ConnectionTimeout = 30000; 43 protected bool IsInitialized { get; set; } 48 protected IWebSocket WebSocket { get; set; } // 统一 WS 抽象 54 protected IRestClient RestClient { ... } // [Obsolete] 旧 REST 73 protected HttpClient HttpClient { ... } // 新 HTTP 89 protected static JsonSerializerSettings JsonSettings { ... } // 统一 JSON 解析

BaseWebsocketsBrokerage 继承 Brokerage(实现 IBrokerage),预置了 WebSocket / HttpClient / JsonSettings 三个共享字段。具体券商(如 BinanceBrokerage / BybitBrokerage / CoinbaseBrokerage)继承它,只需实现:

  • REST 调用:登录、查账户、下单、撤单(用 HttpClient)。
  • WebSocket 订阅:订阅行情流和用户流(订单/成交推送),解析 JSON 转 Tick / OrderEvent
  • 消息分发:把解析后的事件通过 OrdersStatusChanged / Message 等事件回调给引擎。

加密券商典型结构:REST 用于动作(下单/撤单/查账户),WebSocket 用于推送(成交回报/行情)。这是因为加密交易所的 REST 有速率限制(每秒几十次),而 WebSocket 无限制且实时。传统券商(如 IB)用自家协议(TWS API / FIX),不直接继承 BaseWebsocketsBrokerage,但底层同样是长连接 + 事件回调。

💡 钻取要点:WebSocket 是"实时"的关键——回测从磁盘按时间顺序读历史数据是"伪实时"(任意加速),实盘必须等真实 tick 到达才能推进时间。所以实盘的 IDataQueueHandler 通过 WebSocket 接收真实 tick,推到 LiveTradingDataFeed(第 5 章),后者再走与回测相同的 Slice 装配流程。实时性差异只在这一层,引擎主体对回测/实盘一视同仁——这是"回测实盘统一"架构的胜利。

二、BrokerageTransactionHandler:实盘真实成交

回顾第 3 章和第 8 章,ITransactionHandler 是订单的"门房"。回测用 BacktestingTransactionHandler——订单内部消化,BacktestingBrokerage 用 Fill 模型算成交价,立即产生 OrderEvent(因为回测不需要等真实撮合)。

实盘用 BrokerageTransactionHandler(Engine/TransactionHandlers/BrokerageTransactionHandler.cs)——订单真的发到券商:

策略调 SetHoldings / MarketOrder │ ▼ BrokerageTransactionHandler.Process(orderRequest) ← 接收订单请求 │ ▼ IBrokerage.PlaceOrder(order) ← 调券商 API 真实下单 │ (券商撮合,可能几毫秒到几秒) ▼ IBrokerage.OrdersStatusChanged 事件触发 ← 券商推送成交回报 │ ▼ BrokerageTransactionHandler.HandleOrderEvent(...) ← 接收成交事件 │ ▼ 走与回测完全相同的 OrderEvent 处理(Portfolio 更新持仓 + 现金)

关键差异:回测成交是同步的(下单后立刻算出成交价),实盘成交是异步的(下单后等券商推送)BrokerageTransactionHandler 内部维护订单状态机(Submitted → PartiallyFilled → Filled / Canceled / Invalid),用并发队列处理券商推送的事件流。它还实现了错误重试——券商返回临时错误(如网络抖动、速率限制)时自动重试,只在永久错误(资金不足、参数错)时才把订单置 Invalid。

三、IDataQueueHandler:实时行情源

Common/Interfaces/IDataQueueHandler.cs:

[InheritedExport(typeof(IDataQueueHandler))] public interface IDataQueueHandler : IDisposable { IEnumerator<BaseData> Subscribe(SubscriptionDataConfig dataConfig, EventHandler newDataAvailableHandler); void Unsubscribe(SubscriptionDataConfig dataConfig); void SetJob(LiveNodePacket job); bool IsConnected { get; } }

这是实盘独有的注入项。回测的行情来自 FileSystemDataFeed(读磁盘历史),实盘的行情来自 IDataQueueHandler(实时数据流)。引擎在实盘启动时根据 config.jsondata-queue-handler 字段实例化它,挂到 LiveTradingDataFeed

3.1 券商既是 brokerage 又是 data-queue-handler

注意 config.json 的 live environment:

"live-interactive": { "live-mode-brokerage": "InteractiveBrokersBrokerage", "data-queue-handler": [ "InteractiveBrokersBrokerage" ], ... }

live-mode-brokeragedata-queue-handler 都填 InteractiveBrokersBrokerage——同一个类同时实现 IBrokerageIDataQueueHandler。这是因为 IB 通过同一根 TWS 连接既下单又推行情,行情和订单共用会话,没必要分两个连接。

加密券商也一样——BinanceBrokerage 同时实现两个接口,WebSocket 流里既有用户事件(成交)又有市场事件(tick)。少数情况下两者分离,比如 live-interactive-iqfeed environment:

"live-interactive-iqfeed": { "live-mode-brokerage": "InteractiveBrokersBrokerage", // IB 下单 "data-queue-handler": [ "QuantConnect.IQFeed.IQFeedDataQueueHandler" ], // IQFeed 推行情 ... }

——IB 只下单,IQFeed(专业付费数据源)推行情。这种"下单/行情分离"在专业机构常见,因为专业数据源比券商自带行情更全更快。

💡 钻取要点:IDataQueueHandler 标了 [InheritedExport(typeof(IDataQueueHandler))]——MEF(Managed Extensibility Framework)的导出特性,让引擎启动时能通过反射按字符串名("InteractiveBrokersBrokerage")自动发现并实例化。这与第 3 章的 Handler 字符串注入、第 4 章的 Composer 是同一套"配置字符串 → 类型解析"机制,只是底座用 MEF 而非自定义 Composer。

四、Docker 多架构部署

Lean 提供三个 Dockerfile,组成"基础镜像 → 富镜像 → 应用镜像"的分层构建:

Dockerfile 用途 内容
DockerfileLeanFoundation 基础镜像 quantconnect/lean:foundation Ubuntu base + Python(miniconda) + R + Java + C++ 库 + IB Gateway + 各种数据/数学依赖,约 8 GB
DockerfileLeanFoundationARM ARM 镜像 quantconnect/lean:foundation-arm 同 Foundation 但适配 ARM 架构(树莓派、Apple Silicon、AWS Graviton)
Dockerfile 应用镜像 quantconnect/lean:latest FROM foundation,COPY 编译产物(Lean DLL、Data 目录),ENTRYPOINT 跑 Launcher

Dockerfile(已读,28 行)极简——大部分内容来自 Foundation:

7 FROM quantconnect/lean:foundation 12 RUN pip install --no-cache-dir ptvsd==4.3.2 debugpy~=1.6.7 pydevd-pycharm~=231.9225.15 # 远程 Python 调试 15 RUN wget https://aka.ms/getvsdbgsh -O - 2>/dev/null | /bin/sh /dev/stdin -v 17.10.20209.7 -l /root/vsdbg # 远程 C# 调试 17 COPY ./DataLibraries /Lean/Launcher/bin/Debug/ 19 COPY ./Lean/Data/ /Lean/Data/ 20 COPY ./Lean/Launcher/bin/Debug/ /Lean/Launcher/bin/Debug/ # 编译产物 25 WORKDIR /Lean/Launcher/bin/Debug 27 ENTRYPOINT [ "dotnet", "QuantConnect.Lean.Launcher.dll" ]

镜像设计哲学:Foundation 镜像稳定且大(8 GB,装 Python/R/IB/数学库),很少重建;应用镜像小,只 COPY 编译产物,每次发版重建。这样 CI/CD 推一次代码只需重新 COPY 几十兆的 DLL,不用重装 8 GB 依赖。这种"基础镜像 + 应用镜像分层"是 Docker 化量化系统的标准做法。

DockerfileLeanFoundation 的内容(DockerfileLeanFoundation.cs:17-40)装了 Python 3.11、Java 17(给 h2o 等 JVM 库)、各种数学库(liblapack/pyomo 求解器)、IB Gateway headless 等——这就是为什么 Foundation 这么大。

4.1 ARM 支持

DockerfileLeanFoundationARM 让 Lean 能跑在树莓派、Apple Silicon Mac、AWS Graviton 实例上。ARM 的优势是功耗低(树莓派 5W)、性价比高(Graviton 比 x86 便宜 20%)。交易系统通常不是计算密集型(指标和优化器除外),ARM 足够。这让 Lean 能部署在便宜的边缘设备上做长期实盘。

五、lean CLI:命令行管理

QuantConnect 还提供官方 Python CLI 工具 lean(pip install lean),封装本地开发常用操作:

pip install lean # 安装 CLI lean init # 初始化项目目录,拉取 Docker 镜像 lean create-project "MyAlgo" # 创建算法模板项目(C# 或 Python) lean backtest "MyAlgo" # 用 Docker 跑回测 lean live-trade "MyAlgo" --brokerage "Interactive Brokers" --ib-user-name ... --ib-password ... lean research "MyAlgo" # 启 Jupyter 研究环境(用 Docker) lean optimize "MyAlgo" # 参数优化

lean CLI 的核心价值是封装 Docker 调用和 config.json 管理——用户不用手写 config.json,CLI 根据参数(起止日期、券商、API 密钥等)生成 config,挂载数据目录,启动 Docker 容器跑。这让"本地写代码 + 本地回测 + 本地实盘"的闭环只需几条命令。

5.1 config.json 的 live-mode-brokerage

回顾第 01 节,实盘券商由 config.json 的 environment 块决定。每个 environment(live-interactive / live-binance / live-alpaca ...)指定三个关键字段:

  • live-mode-brokerage:订单发到哪个券商(字符串类名,如 "InteractiveBrokersBrokerage")。
  • data-queue-handler:实时行情从哪个 IDataQueueHandler 取(数组,通常与 brokerage 同名,有时分离如 IQFeed)。
  • transaction-handler:几乎总是 BrokerageTransactionHandler(模拟盘 PaperBrokerage 例外,用 BacktestingTransactionHandler)。

加上券商特定的连接配置(如 ib-account / ib-user-name / ib-password / binance-api-key / binance-api-secret)。lean CLI 在 lean live-trade 时把这些参数拼成对应的 environment。

💡 钻取要点:回测和实盘切换只改 config.json 的 environment 字符串——把 "environment": "backtesting" 改成 "environment": "live-interactive",引擎启动时读不同 environment 块的 handler 配置,实例化不同的 Brokerage/DataFeed/TransactionHandler。策略代码(用户 QCAlgorithm)零改动。这是第 3 章"配置驱动 + 接口插件"哲学在部署层的最终胜利,下一节(03)会做完整对照。

本节要点回顾

  1. WebSocket 三层抽象:IWebSocket(接口)→ WebSocketClientWrapper(实现,封装 .NET ClientWebSocket + 自动重连)→ BaseWebsocketsBrokerage(券商基类,预置 WebSocket/HttpClient/JsonSettings)。
  2. 加密券商基于 WebSocket:REST 用于动作(下单/查账户),WebSocket 用于推送(成交/行情),因为加密交易所 REST 有速率限制而 WS 实时无限制。
  3. BrokerageTransactionHandler vs BacktestingTransactionHandler:回测同步成交(下单立即算价),实盘异步成交(下单后等券商 OrdersStatusChanged 推送);实盘有错误重试和状态机。
  4. IDataQueueHandler 实盘独有:Subscribe / Unsubscribe / IsConnected,实盘行情源;回测用 FileSystemDataFeed 读磁盘。
  5. 券商双身份:很多券商类同时实现 IBrokerageIDataQueueHandler(InteractiveBrokersBrokerage、BinanceBrokerage 等),共用一根连接既下单又推行情;少数分离(如 IB 下单 + IQFeed 推行情)。
  6. 三个 Dockerfile:Foundation(8 GB,Python/R/Java/IB base)→ FoundationARM(ARM 适配,树莓派/Graviton)→ Dockerfile(FROM foundation + COPY 编译产物)。
  7. lean CLI:pip install lean,init / create-project / backtest / live-trade / research / optimize,封装 Docker 调用与 config.json 生成。
  8. 回测实盘切换:只改 config.json 的 environment 字符串,策略代码零改动;environment 块里 live-mode-brokerage / data-queue-handler / transaction-handler 决定实盘行为。

下一节是全书最后一节——回测实盘切换的完整对照(三个分叉点总结)与全书 10 章分层钻取回顾。


作者与出处
原作者: 灏天文库
整理: 灏天文库整理
本站整理收录,版权归原作者/开源协议所有;欢迎通过原文链接访问源仓库。
发布者: 作者: 灏天文库 转发
评论区 (0)
U