← 返回文章列表
March 4, 2026
5 分鐘閱讀

QuestDB 演算法交易實戰:從訂單簿到生產架構

QuestDB 演算法交易實戰:從訂單簿到生產架構
#QuestDB
#materialized views
#order book
#OHLC
#production
#algorithmic trading
🗄️
Part 3 of 3 · Collection
QuestDB for Algorithmic Trading

第 3 篇,共 3 篇 — 也可閱讀 RU · EN

免責聲明:本文內容僅供教育和參考目的,不構成任何財務、投資或交易建議。加密貨幣交易存在重大虧損風險。


歡迎來到 QuestDB 系列的最終篇。在第 1 篇中,我們介紹了儲存架構。在第 2 篇中,我們探討了 SQL 擴充。現在讓我們將一切融合在一起:用於即時分析的物化檢視、原生 2D 陣列的訂單簿儲存,以及生產級演算法交易平臺的參考架構。

物化檢視:以網路速度提供預計算分析

從原始 tick 資料到日線 OHLC 的級聯物化檢視管道 級聯物化檢視:原始 tick 資料流經逐級粗化的聚合層,每一層處理的資料量都大幅減少

如果 SAMPLE BY 是 QuestDB 最常用的查詢,那麼物化檢視就是其最有影響力的最佳化。概念很簡單:不是在每次儀表板重新整理或 API 呼叫時計算 OHLCV 聚合,而是預先計算一次,並保持結果持續更新。

基礎 OHLC 物化檢視

CREATE MATERIALIZED VIEW trades_OHLC_15m
  WITH BASE 'trades'
  REFRESH IMMEDIATE
AS
SELECT timestamp, symbol,
  first(price) AS open,
  max(price) AS high,
  min(price) AS low,
  last(price) AS close,
  sum(quantity) AS volume
FROM trades
SAMPLE BY 15m;

這就是完整的定義。每當新行被插入 trades 表時,QuestDB 會自動對該檢視進行增量重新整理。不是完整重算——只有受影響的時間桶會被更新。針對 trades_OHLC_15m 的查詢變成了對更小的預聚合資料集的簡單查詢。

效能差異是戲劇性的。在一張有數十億行的表上,查詢基礎表獲取 OHLC 資料可能需要 200 毫秒。物化檢視在 5 毫秒以內返回相同結果。當多個儀表板使用者併發訪問時,這不僅僅是一種最佳化——而是響應系統與崩潰系統之間的差距。

級聯檢視:單一資料來源支援多個時間週期

物化檢視在架構上優雅之處在於此。你可以將它們連結起來——每個檢視以下一個為基礎,從單一原始資料來源建立多層次的聚合層級:

-- 从原始成交数据生成 1 秒 K 线
CREATE MATERIALIZED VIEW ohlc_1s AS
SELECT timestamp, symbol,
  first(price) AS open, max(price) AS high,
  min(price) AS low, last(price) AS close,
  sum(quantity) AS volume
FROM trades
SAMPLE BY 1s;

-- 从 1 秒 K 线生成 5 秒 K 线
CREATE MATERIALIZED VIEW ohlc_5s AS
SELECT timestamp, symbol,
  first(open) AS open, max(high) AS high,
  min(low) AS low, last(close) AS close,
  sum(volume) AS volume
FROM ohlc_1s
SAMPLE BY 5s;

-- 从 5 秒 K 线生成 1 分钟 K 线
CREATE MATERIALIZED VIEW ohlc_1m AS
SELECT timestamp, symbol,
  first(open) AS open, max(high) AS high,
  min(low) AS low, last(close) AS close,
  sum(volume) AS volume
FROM ohlc_5s
SAMPLE BY 1m;

每一層處理的資料集都比前一層小得多。1 分鐘檢視不掃描原始成交資料——它只讀取預聚合的 5 秒 K 線。這種級聯模式可以擴充到任意數量的時間週期:1s → 5s → 1m → 5m → 15m → 1h → 4h → 1d。

對於從 100 多家交易所寫入資料的加密資料平臺,這是整個 OHLC 分發管道的骨幹。

重新整理策略

QuestDB 提供三種重新整理模式,各自適合不同的工作負載:

REFRESH IMMEDIATE 在每次基礎表事務後觸發非同步重新整理。最適合亞秒級延遲至關重要的即時儀表板。

REFRESH EVERY 1h(基於定時器)將更新批次合併到定期重新整理中。對於高吞吐量寫入場景更合適,因為在每個微批次後觸發重新整理會產生額外開銷。

REFRESH PERIOD (LENGTH 1d TIME ZONE 'Europe/London' DELAY 2h) 定義日曆對齊的週期。"延遲"考慮了遲到資料的情況——對於可能在交易時段結束後數小時才傳送修正資料的市場,這一點至關重要。

REFRESH MANUAL 提供完全控制權。檢視僅在你顯式執行 REFRESH 命令時才會更新——對於日終對賬工作流非常有用。

LATEST ON 加速模式

最強大的模式之一是將物化檢視與 LATEST ON 結合,用於即時投資組合快照。掃描 13 億行原始資料以獲取每個交易對的最新價格需要數秒時間。但有了每日預聚合檢視:

CREATE MATERIALIZED VIEW trades_latest_1d AS
SELECT timestamp, symbol, side,
  last(price) AS price,
  last(quantity) AS quantity,
  last(timestamp) AS latest
FROM trades
SAMPLE BY 1d;

LATEST ON 查詢掃描大約 25,000 行預聚合資料,而非數十億行:

SELECT symbol, side, price, quantity, latest AS timestamp
FROM (
  trades_latest_1d
  LATEST ON timestamp PARTITION BY symbol, side
)
ORDER BY timestamp DESC;

從數秒降至毫秒級。這就是生產交易儀表板如何在海量資料集上實現即時響應的秘訣。

TTL:自動資料生命週期管理

物化檢視支援 TTL(存活時間)策略用於自動資料過期:

CREATE MATERIALIZED VIEW ohlc_1h AS (
  SELECT timestamp, symbol,
    avg(price) AS avg_price
  FROM trades
  SAMPLE BY 1h
) PARTITION BY WEEK TTL 8 WEEKS;

這保留 8 周的小時資料,自動刪除較舊的分割槽。結合三層儲存引擎,你獲得了自然的資料生命週期:原始 tick 資料流經 WAL → 列式儲存 → 物件儲存中的 Parquet,而物化檢視維護著應用實際查詢的預聚合摘要。

2D 陣列:原生訂單簿分析

3D 訂單簿深度視覺化,綠色買盤和紅色賣盤 3D 訂單簿深度:買賣盤以原生 2D 陣列儲存,支援 SIMD 最佳化的價差計算和流動性分析

QuestDB 9.0 引入了 N 維陣列——真正的具有形狀和步長的類 NumPy 陣列,以零複製方式處理常見操作(切片、轉置)。對於交易而言,殺手級應用是訂單簿儲存。

傳統方案的痛點

歷史上,在關係型資料庫中儲存訂單簿快照是件苦差事。你只有兩種選擇:每個價格檔位一行(行數爆炸,查詢深度代價高昂),或者固定數量的列,如 bid1_pricebid1_sizebid2_pricebid2_size 等(僵硬、浪費且難看)。

QuestDB 的 2D 陣列徹底消除了這兩個問題:

CREATE TABLE market_data (
  timestamp TIMESTAMP,
  symbol SYMBOL,
  bids DOUBLE[][],
  asks DOUBLE[][]
) TIMESTAMP(timestamp) PARTITION BY HOUR;

每個 bidsasks 列儲存一個 2D 陣列,其中第一行包含每個檔位的價格,第二行包含每個檔位的數量。一個 20 檔訂單簿是一個緊湊的單一陣列,而非 40 個獨立的列。

SQL 中的訂單簿分析

價差計算——最基礎也是最頻繁計算的指標:

SELECT timestamp,
  spread(bids[1][1], asks[1][1]) AS spread
FROM market_data
WHERE symbol = 'EURUSD'
  AND timestamp IN today();

spread() 函數是內建函數,計算最優買價與最優賣價之差。bids[1][1] 訪問買盤陣列第一行(價格)的第一個元素(最優價格)。

對於更復雜的分析——流動性深度、訂單簿不平衡、特定價格檔位的成交機率——陣列切片和向量化操作使原本複雜的查詢變得直接:

-- 找到目标价格会被成交的档位
-- 并对该档位以上的所有数量求和
DECLARE @target := bids[1][1] * 1.01;
SELECT timestamp,
  array_sum(asks[2][1:level_idx]) AS volume_to_fill
FROM market_data
WHERE symbol = 'EURUSD';

SIMD 最佳化的陣列操作意味著這些計算以接近硬體的速度執行,即使面對數百萬個快照也是如此。

陣列資料的寫入

QuestDB 的客戶端庫支援原生陣列寫入。Python 客戶端直接與 NumPy 陣列整合:

import numpy as np
from questdb.ingress import Sender

bids = np.array([[9.3, 9.2, 9.1], [100, 200, 150]])  # 价格, 数量
asks = np.array([[9.5, 9.6, 9.7], [80, 160, 120]])

with Sender.from_conf("http::addr=localhost:9000;") as sender:
    sender.row(
        'market_data',
        symbols={'symbol': 'EURUSD'},
        columns={'bids': bids, 'asks': asks},
        at=timestamp
    )

協議第 2 版以二進位制形式對陣列進行編碼,與基於文本的協議相比顯著降低了頻寬和伺服器端解析開銷。對於高頻訂單簿寫入——你可能每秒每個交易對接收數千個快照——這種效率至關重要。

C/C++ 客戶端使用帶形狀描述符的平鋪行主陣列,支援從現有交易系統資料結構進行零複製寫入。

融會貫通:參考架構

基於 QuestDB 的演算法交易平臺等距系統架構圖 參考架構:交易所聯結器、列式資料庫核心、分析層、策略引擎和監控儀表板——全部互聯互通

讓我們為加密市場設計一個完整的基於 QuestDB 的演算法交易平臺。該架構處理來自多家交易所的資料寫入、即時分析、回測和策略執行。

資料寫入層

多交易所資料寫入管道,WebSocket 資料流匯入資料庫 資料寫入:多個交易所聯結器通過 WebSocket 管道將即時行情資料經 ILP 協議寫入 QuestDB

通過 HTTP 上的 ILP,連線到各交易所(Binance、Bybit、OKX 等)的多個 WebSocket 連線將原始行情資料寫入 QuestDB。每個交易所聯結器是一個獨立程序,提供隔離性和容錯性。

資料流包括:成交資料(timestamp, symbol, side, price, quantity)、訂單簿快照(timestamp, symbol, bids[][], asks[][]),以及作為輔助流的資金費率/強平資料。

寫入吞吐量目標:所有交易所合計每秒數百萬行。QuestDB 的 WAL 能夠輕鬆應對,去重功能捕獲來自冗餘交易所連線的不可避免的重複資料。

即時分析層

物化檢視構成分析層的核心:

原始成交 → ohlc_1s → ohlc_5s → ohlc_1m → ohlc_5m → ohlc_15m → ohlc_1h → ohlc_1d

每一層增量重新整理。通過 QuestDB 原生外掛連線的 Grafana 儀表板查詢這些檢視繪製 K 線圖,無論歷史資料量多大,響應時間都在 5 毫秒以內。

額外的物化檢視計算:每日每交易對的 VWAP(成交量加權平均價格)、滾動波動率估算,以及跨交易所價差監控。

針對預聚合檢視的 LATEST ON 查詢支援即時投資組合儀表板——顯示當前持倉、未實現盈虧和各交易所敞口。

策略引擎

演算法交易策略引擎,帶神經處理核心和行情資料流 策略引擎:即時指標計算驅動演算法決策,買賣執行路徑通過物化檢視最佳化

交易策略查詢 QuestDB 以獲取當前市場狀態和歷史模式。QuestDB 的 PG 協議意味著任何具有 PostgreSQL 驅動的語言都可以連線:Python 用於研究策略,Rust 或 C++ 用於延遲敏感的執行。

策略的關鍵查詢模式:ASOF JOIN 用於將執行成交與成交時的市場狀況匹配、WINDOW JOIN 用於計算每個事件周圍的短週期指標,以及用於即時指標計算的視窗函數(RSI、布林帶、ATR)。

對於延遲敏感的策略,預計算物化檢視最大程度地減少了查詢時間。監控 50 個交易對的網格機器人不需要在每個 tick 時計算 50 個獨立的移動平均線——它從物化檢視中讀取。

回測管道

歷史資料以 Parquet 格式儲存在物件儲存中。QuestDB 可以透明地查詢它,但對於繁重的回測工作負載,資料也可以由 Polars、Pandas 或 DuckDB 直接讀取——完全繞過資料庫。

這種雙訪問模式非常強大:即時策略使用 QuestDB 的 SQL 介面進行即時決策,而回測框架通過 Parquet/Arrow 讀取相同資料進行批處理。相同的資料,兩條最佳化的訪問路徑。

監控與交易後分析

HORIZON JOIN 為交易後分析管道提供支援:

  • 滑點分析:將執行價格與成交時的中間價進行比較
  • 標記曲線:追蹤每筆成交後 1 秒、5 秒、30 秒、60 秒的價格演變
  • 實施差異:將執行成本分解為價差成本、臨時衝擊和永久衝擊
  • 交易場所評分:比較各交易所的成交質量以最佳化訂單路由

這些分析作為計劃查詢執行,將結果寫入專用表,為監控儀表板提供資料。告警規則在異常情況下觸發——突然的滑點峰值、異常的標記模式,或特定交易場所成交質量下降。

效能注意事項

效能監控儀表板,顯示延遲儀表和 hot-warm-cold 儲存層級 生產環境效能調優:延遲、吞吐量和記憶體監控,以及 hot-warm-cold 資料生命週期管理

來自生產部署的一些實踐說明:

分割槽大小:對於每天每個交易對有數百萬行的加密 tick 資料,PARTITION BY HOUR 通常是最優選擇。這使單個分割槽在儲存和查詢效能方面都保持可管理。

物化檢視級聯:不要建立太多中間層次。每一層都會增加重新整理延遲。對於大多數用例,3-4 層(1s → 1m → 15m → 1d)在查詢效能和資料新鮮度之間提供了良好平衡。

去重開銷:對具有冗餘資料來源的表啟用去重。對於時間戳唯一的資料成本很小,但當許多相同時間戳的行需要基於列級別去重時,開銷會增加。

記憶體分配:QuestDB 的零 GC 引擎效率很高,但要為熱分割槽和寫入快取分配足夠的記憶體。通過內建指標端點進行監控。

客戶端協議選擇:使用 HTTP 上的 ILP 進行寫入(具有自動重試和健康檢查)。使用 PG 協議進行查詢。ILP 協議第 2 版(二進位制編碼)對於陣列資料和高吞吐量雙精度浮點值顯著更高效。

QuestDB 與競爭對手對比

資料庫對比雷達圖,展示查詢速度、時序功能、SQL 支援、成本和可擴充性等維度 競爭格局:QuestDB 與 TimescaleDB、ClickHouse、InfluxDB 和 kdb+ 在關鍵能力維度的對比

簡要對比交易領域常用的資料庫:

對比 TimescaleDB:TimescaleDB 是帶時序擴充的 PostgreSQL。它繼承了 PG 的通用性,但也繼承了其開銷。QuestDB 的原生列式引擎和 SIMD 執行在時序工作負載上提供了顯著更好的查詢效能,而 ASOF JOIN 等功能在 TimescaleDB 中沒有直接對應項。

對比 ClickHouse:ClickHouse 擅長對海量資料集進行分析查詢。但它並非專為時序設計——沒有原生 ASOF JOIN,沒有帶 FILL 的 SAMPLE BY,沒有用於訂單簿的 2D 陣列。對於混合 OLAP + 時序工作負載,ClickHouse 可能勝出;對於純交易資料,QuestDB 使用體驗更佳。

對比 InfluxDB:InfluxDB 存在高基數限制,對於多交易所加密資料非常棘手。其查詢語言(Flux,現已廢棄;InfluxQL)缺乏 QuestDB SQL 擴充的表達能力。大型歷史查詢的效能通常更差。

對比 kdb+/q:高頻交易的黃金標準。kdb+ 在某些單執行緒向量運算上更快,其 q 語言極為簡潔。但它是專有的、昂貴的,且學習曲線陡峭。QuestDB 以極低的成本提供了 80-90% 的能力,具備標準 SQL 和開源許可。

結論:真正懂交易的資料庫

在這三篇文章中,我們介紹了 QuestDB 的架構(三層儲存:WAL、列式儲存和 Parquet)、其 SQL 擴充(SAMPLE BY、ASOF JOIN、HORIZON JOIN、WINDOW JOIN、LATEST ON、TWAP),以及實際應用(物化檢視、訂單簿陣列、參考架構)。

貫穿始終的主線是一致的:QuestDB 正是為演算法交易所產生的工作負載而設計的。它不會強迫你繞開資料庫——相反,其原語直接對映到交易概念。OHLC 聚合是一行程式碼。成交-報價對齊是一個 JOIN。交易後分析是一個 HORIZON JOIN,而非多頁 PL/SQL 過程。

對於構建交易基礎設施的團隊——無論是加密行情資料平臺、量化研究環境,還是完整的演算法交易引擎——QuestDB 值得認真評估。開源版本涵蓋大多數用例,企業版填補了受監管環境的空白。

金融資料基礎設施格局正在快速演變。能夠讀懂市場語言的資料庫將會勝出。QuestDB 已經流利掌握了這門語言。

祝交易順利,願你的延遲永遠低。

引用

@software{soloviov2025questdb_algotrading_p3,
  author = {Soloviov, Eugen},
  title = {QuestDB for Algorithmic Trading: From Order Books to Production Architecture},
  year = {2025},
  url = {https://marketmaker.cc/en/blog/post/questdb-algotrading-production},
  version = {0.1.0},
  description = {Materialized views, 2D array order book analytics, and reference architecture for a QuestDB-powered algorithmic trading platform.}
}
免責宣告:本文提供的資訊僅用於教育和參考目的,不構成財務、投資或交易建議。加密貨幣交易涉及重大損失風險。

Authors

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

緊跟市場步伐

訂閱我們的時事通訊,獲取獨家 AI 交易見解、市場分析和平台更新。

我們尊重您的隱私。您可以隨時退訂。