第二階段:核心組件深度解讀
模組 07:數據引擎 — 市場數據高速公路從市場到策略,數據如何被收集、處理和分發
一、數據引擎的職責
flowchart LR
subgraph sources["🌍 數據源"]
ws["交易所 WebSocket"]
rest["REST API"]
file["歷史數據文件"]
end
subgraph dc["📡 DataClient 適配器"]
parse["解析原始數據"]
normalize["標準化格式"]
end
subgraph de["📊 DataEngine 數據引擎"]
route["路由分發"]
aggregate["Bar 聚合"]
validate["數據驗證"]
end
subgraph output["📤 輸出"]
cache["💾 Cache"]
msgbus["📡 MessageBus"]
end
sources --> dc --> de --> output
圖 1:數據引擎的完整數據管道
📥
接收
從各種 DataClient 接收標準化後的市場數據(報價、成交、訂單簿)
🔄
聚合
將逐筆成交數據聚合為 K 線 (Bar),定義了 18 種聚合方式(其中 12 種已實現,6 種規劃中)
📤
分發
根據訂閱關係,透過 MessageBus 將數據推送給需要的組件
💾
緩存
將最新數據寫入 Cache,供其他組件隨時查詢
二、訂閱機制
策略不是「拉取」數據,而是「訂閱」數據。數據引擎負責管理所有訂閱關係:
# 在策略的 on_start() 中訂閱數據
def on_start(self):
# 訂閱報價 — 每次有新報價就調用 on_quote_tick
self.subscribe_quote_ticks(instrument_id)
# 訂閱逐筆成交
self.subscribe_trade_ticks(instrument_id)
# 訂閱 K 線 — 例如 1 分鐘 K 線
self.subscribe_bars(BarType.from_str("BTCUSDT.BINANCE-1-MINUTE-LAST"))
# 訂閱訂單簿(深度 10 檔)
self.subscribe_order_book_at_interval(
instrument_id,
depth=10,
interval_ms=1000, # 每秒快照一次
)三、Bar 聚合 — 18 種定義(12 種已實現)
K 線不一定是按時間分的。NautilusTrader 定義了多種聚合方式(✅ = 已實現,⚠️ = 規劃中未實現):
| 類別 | 聚合方式 | 說明 | 適用場景 |
|---|---|---|---|
| ⏱️ 時間 | MILLISECOND | 每 N 毫秒 | 超高頻策略 |
| SECOND | 每 N 秒 | 超短線 | |
| MINUTE | 每 N 分鐘 | 日內交易 | |
| HOUR | 每 N 小時 | 波段交易 | |
| DAY | 每 N 天 | 中期趨勢 | |
| WEEK | 每 N 週 | 長期趨勢 | |
| MONTH | 每 N 月 | 宏觀分析 | |
| 📊 活動量 | TICK | 每 N 筆成交 | 高頻策略 |
| VOLUME | 每 N 單位成交量 | 量價分析 | |
| VALUE | 每 N 金額成交 | 大額流動性分析 | |
| 📉 不平衡 | TICK_IMBALANCE ⚠️ | 買賣筆數不平衡達閾值 | 訂單流分析(規劃中) |
| VOLUME_IMBALANCE ⚠️ | 買賣量不平衡達閾值 | 大單偵測(規劃中) | |
| VALUE_IMBALANCE ⚠️ | 買賣金額不平衡達閾值 | 資金流向分析(規劃中) | |
| 🏃 連續 | TICK_RUNS ⚠️ | 連續同向成交筆數達閾值 | 動量偵測(規劃中) |
| VOLUME_RUNS ⚠️ | 連續同向成交量達閾值 | 趨勢確認(規劃中) | |
| VALUE_RUNS ⚠️ | 連續同向成交金額達閾值 | 機構行為分析(規劃中) | |
| 📈 價格 | RENKO | 磚形圖(價格移動固定幅度) | 趨勢過濾、噪音消除 |
| 📅 年度 | YEAR | 每 N 年 | 超長期分析 |
# Bar 類型格式:{品種ID}-{數量}-{聚合方式}-{價格來源}-{聚合來源}
# 聚合來源:INTERNAL(本地聚合)或 EXTERNAL(交易所提供)
bar_type_1min = BarType.from_str("BTCUSDT.BINANCE-1-MINUTE-LAST-INTERNAL")
bar_type_tick = BarType.from_str("BTCUSDT.BINANCE-100-TICK-LAST-INTERNAL")
bar_type_vol = BarType.from_str("BTCUSDT.BINANCE-1000-VOLUME-LAST-INTERNAL")
bar_type_renko = BarType.from_str("BTCUSDT.BINANCE-50-RENKO-MID-INTERNAL")
# ✨ 新功能:Composite Bar(Bar-to-Bar 聚合)
# 從 1 分鐘 K 線聚合出 5 分鐘 K 線,使用 @ 語法
bar_type_5min = BarType.from_str("BTCUSDT.BINANCE-5-MINUTE-LAST-INTERNAL@1-MINUTE-EXTERNAL")💡 為什麼時間以外的聚合方式很重要?
時間 K 線在波動很低的時段會產生很多「空洞」的 K 線(幾乎沒有成交)。成交量 K 線和 Tick K 線則只在有實際交易發生時才形成,能更真實地反映市場活動。
四、數據客戶端 (DataClient)
DataClient 是連接外部數據源的適配器。每個交易所或數據供應商都有自己的 DataClient 實現:
flowchart LR
subgraph clients["DataClient 實現 (接入層)"]
direction TB
binance_dc["Binance Client"]
ib_dc["IB Client"]
sim_dc["Backtest Client"]
end
de["📊 DataEngine<br/>數據引擎主體"]
clients ==> de
style de fill:#0f1419,stroke:#4fc3f7,stroke-width:2px
style clients fill:#0f1419,stroke:#ab47bc,stroke-width:1px
圖 2:不同的 DataClient 都接入同一個 DataEngine
五、互動練習
🧠 練習:設計數據訂閱
你的策略需要以下數據,寫出對應的訂閱代碼:
- BTC/USDT 的即時報價(用於判斷買賣價差)
- 每 500 筆成交一根的 Tick K 線(用於高頻信號)
- 5 分鐘 K 線(用於趨勢判斷)
def on_start(self):
btc_id = InstrumentId.from_str("BTCUSDT.BINANCE")
# 1. 即時報價
self.subscribe_quote_ticks(btc_id)
# 2. 每 500 筆成交的 Tick K 線
self.subscribe_bars(
BarType.from_str("BTCUSDT.BINANCE-500-TICK-LAST")
)
# 3. 5 分鐘 K 線
self.subscribe_bars(
BarType.from_str("BTCUSDT.BINANCE-5-MINUTE-LAST")
)六、本模組重點回顧
📋 關鍵點
- 數據引擎負責接收、聚合、驗證和分發所有市場數據
- 訂閱模式:策略訂閱感興趣的數據,引擎自動推送
- 18 種 Bar 聚合定義(其中 12 種已實現):時間、成交量、Tick、Renko 等多種方式
- DataClient:統一介面,不同實現連接不同數據源