如何取得股票即時資料?Level‑2 行情下本機增量訂單簿該如何建置?
研究分享|本文探討 Level‑2 深度行情之接入與本機增量訂單簿的工程實作,供量化策略研究、回測以及盤口數據分析參考,不構成任何投資建議。
在量化策略研究的過程當中,時常會遇見回測結果與模擬推演出現明顯落差的狀況。除了策略本身的邏輯缺陷之外,行情資料的精細度不足、本機端盤口狀態維護錯誤,是很容易被忽略的關鍵因素。
若僅依賴 Level‑1 基礎行情,僅能取得最新成交價、漲跌幅、累計成交量等彙總指標,無法觀察盤口各檔委託的增減、撤單與改單等微觀行為。對於需要盤口深度做為輸入的短線模型、訂單流分析類策略,資訊的缺失會直接降低模型的有效程度。因此我們需要接入 Level‑2 深度行情,並於本機維護一份狀態正確的增量訂單簿,做為回測與模擬演算的高品質底層資料來源。
Level‑2 深度行情的核心資料維度
基礎行情介面的開發門檻低,適合一般行情觀測,卻無法支撐高細緻度的量化建模。Level‑2 深度行情會提供盤口多面向的原始資訊,主要包含:
買賣盤各個檔位的委託報價
各價格檔位對應的委託數量
盤口深度檔位明細
行情事件時間戳
時間戳是維護本機訂單簿正確性的關鍵欄位,用來驗證封包的先後順序;不少研究者在開發階段容易忽略這一點,最後導致盤口狀態發生偏移。
我在早期測試階段曾經使用全量快照儲存的做法:每收到一次行情推送,就完整儲存整份盤口資料。單一標的測試時看不出異常,但一旦同時訂閱多檔標的,記憶體占用與運算成本便會快速上升,系統延遲隨之增加,不利於策略的低延遲運算。
增量更新模式可以有效改善此問題:不需要重複儲存完整盤口,僅針對發生變動的價格檔位執行更新。
舉個實例:買盤某個檔位原本有 500 手委託,新行情推送後該檔僅剩 300 手,本機端只更新該價位的掛單數量;倘若某檔委託數歸零,就直接移除該筆檔位紀錄。此方法除了降低多餘的運算負荷,也方便後續展開訂單流、盤口衝擊等量化研究。
行情傳輸方案選擇:以 WebSocket 取代 HTTP 輪詢
股票深度行情屬於高頻持續更新的資料流。HTTP 輪詢機制需要客戶端不斷送出請求來取得資料,在高頻場景下會產生大量無效請求,同時帶來不可預期的網路延遲,並不適合盤口的即時重建作業。
WebSocket 完成握手連線之後,伺服器可以主動推送行情增量,客戶端不需重複發送請求。應用端接收推送的資料負載,解析檔位的變動,持續迭代維護本機訂單簿的狀態。以下為可執行的基礎範例程式,用於行情訂閱與本機訂單簿更新演示:
import websocket
import json
# 初始化本機訂單簿,分開管理買盤、賣盤
order_book = {
"bids": {},
"asks": {}
}
def on_message(ws, message):
"""接收伺服器推送訊息,更新本機訂單簿"""
data = json.loads(message)
symbol = data.get("symbol")
bids = data.get("bids", [])
asks = data.get("asks", [])
# 更新買方掛單檔位
for item in bids:
price = item["price"]
volume = item["volume"]
order_book["bids"][price] = volume
# 更新賣方掛單檔位
for item in asks:
price = item["price"]
volume = item["volume"]
order_book["asks"][price] = volume
print(symbol, order_book)
def on_open(ws):
"""連線建立完成後,送出深度行情訂閱請求"""
subscribe_req = {
"id": 1,
"cmd": "subscribe",
"symbol": "AAPL",
"type": "depth"
}
ws.send(json.dumps(subscribe_req))
if __name__ == "__main__":
ws = websocket.WebSocketApp(
"wss://api.alltick.co/stock/websocket",
on_open=on_open,
on_message=on_message
)
ws.run_forever()備註:範例僅演示基礎接收與更新邏輯。若要用於回測、模型模擬等正式研究場景,需要參照介面文件,調整欄位解析邏輯。
建置增量訂單簿必須處理的工程議題
程式可以執行,不代表訂單簿的狀態可以穩定對應市場真實盤口。下面三個議題會直接影響回測、模擬研究的資料可信度:
透過時間戳執行時序驗證
網路傳輸有可能造成資料封包抵達順序錯亂。若沒有透過時間戳分辨新舊資料,過時的行情就會覆蓋最新盤口,造成本機訂單簿錯亂;依據這份資料產生的模型訊號、回測結論都會跟著失真。
斷線重連搭配完整快照同步
WebSocket 連線可能因為網路環境中斷。連線斷開之後,記憶體當中的訂單簿就不再具備參考價值。重新連線後不可以直接處理增量資料,必須先取得一份完整盤口快照,把本機狀態對齊之後,再繼續接收後續的增量推送。
跨市場的行情規格調適
不同市場的 Level‑2 行情,最小報價單位、欄位命名、回傳的檔位數量皆有差異,無法同一套程式直接套用在全部標的,需要依照資料來源的規格做對應調整。
研究小結
取得股票即時資料,僅是量化研究工作的開端。不少策略研究者把重心放在尋找資料來源,卻輕視資料處理、狀態維護這類底層工程環節,但正是這些環節,決定回測與模擬的資料品質。
Level‑2 深度行情的價值,並非僅僅多出幾組價格欄位,而是提供給模型觀察訂單動態變化的微觀資訊。透過增量模式維護本機訂單簿,可以做為盤口特徵挖掘、訂單流建模、策略回測、模擬演算的穩固資料基礎。行情介面接入僅是工具層面的實作,唯有嚴謹的資料處理流程,才能確保後續模型研究的可靠度。進行相關研究時,也可以運用 AllTick API 取得 Level‑2 深度行情,把更多心力投入策略模型與回測分析。