Hyperliquid 實時訂單簿訂閱
- hyperliquid orderbook websocket
- real time hyperliquid api
- hyperliquid 實時訂單簿
- hyperliquid websocket 訂閱
- hyperliquid l2 book
訂單簿是交易所最核心的市場數據結構,實時反映所有未成交買賣掛單的價格及數量分佈。對量化交易機械人、套利程式及行情分析系統來說,能否以毫秒級延遲取得最新訂單簿狀態,往往會直接影響策略表現。
Hyperliquid 提供完整 WebSocket 介面,讓訂閱者即時接收 L2 訂單簿快照及增量更新。本文會講解訂閱方式、訊息格式、本地訂單簿維護、斷線重連等較接近生產環境的工程細節。若你不是要自建基建,而是想直接進行加密貨幣永續合約交易,OneKey Perps 已整合實時行情及交易流程,可作為更直接的實用選擇。
WebSocket 與 REST 輪詢的分別
在進入技術細節之前,先理解為何實時訂單簿一般會使用 WebSocket,而不是用 REST API 不斷輪詢。
REST 輪詢適合查詢低頻資料,例如帳戶狀態、歷史紀錄或偶爾更新的行情;但對需要連續追蹤盤口深度、最優買賣價及價差變化的場景,REST 輪詢通常會遇到三個問題:
- 延遲較高,無法穩定捕捉毫秒級變化
- 請求頻率過高時容易觸及限速
- 兩次輪詢之間的訂單簿變化可能被完全錯過
因此,對於需要實時訂單簿的系統,WebSocket 幾乎是標準做法。完整介面規格應以 Hyperliquid 官方文件為準。
WebSocket 連線建立
端點地址
Hyperliquid 的 WebSocket 端點(以官方文件最新資料為準)如下:
wss://api.hyperliquid.xyz/ws
基礎連線程式碼
以下是使用 Python 建立 WebSocket 連線並訂閱 BTC L2 訂單簿的基本例子:
import asyncio
import json
import websockets
WS_URL = "wss://api.hyperliquid.xyz/ws"
async def connect_and_subscribe():
async with websockets.connect(WS_URL) as ws:
subscribe_msg = {
"method": "subscribe",
"subscription": {
"type": "l2Book",
"coin": "BTC"
}
}
await ws.send(json.dumps(subscribe_msg))
async for raw_msg in ws:
msg = json.loads(raw_msg)
handle_message(msg)
asyncio.run(connect_and_subscribe())
訂閱訊息格式
L2 訂單簿訂閱
訂閱 BTC 的 L2 訂單簿:
{
"method": "subscribe",
"subscription": {
"type": "l2Book",
"coin": "BTC"
}
}
Hyperliquid 支援同時訂閱多個交易對。你只需要重複發送訂閱訊息,每個交易對會獨立推送更新。
取消訂閱
{
"method": "unsubscribe",
"subscription": {
"type": "l2Book",
"coin": "BTC"
}
}
訊息類型:快照與增量更新
初始快照(Snapshot)
訂閱後,伺服器會先推送完整訂單簿快照,包含當前各個價位的掛單量:
{
"channel": "l2Book",
"data": {
"coin": "BTC",
"time": 1714500000000,
"levels": [
[
[{"px": "64000.0", "sz": "0.5", "n": 3}],
[{"px": "64010.0", "sz": "0.3", "n": 2}]
]
]
}
}
欄位說明:
px:價格sz:該價位的掛單總量;如為0,代表該價位已清空n:該價位的掛單筆數
一般情況下,bids(買盤)會由高至低排列,asks(賣盤)會由低至高排列。
增量更新(Delta)
快照之後,伺服器只會推送有變化的價位:
{
"channel": "l2Book",
"data": {
"coin": "BTC",
"time": 1714500000100,
"levels": [
[
[{"px": "63990.0", "sz": "0.0", "n": 0}],
[{"px": "64010.0", "sz": "0.8", "n": 4}]
]
]
}
}
當 sz 為 "0" 或 0 時,表示該價位的掛單已全部成交或撤銷,需要從本地訂單簿中移除該價位。
維護本地訂單簿狀態
正確維護本地訂單簿,是使用 WebSocket 數據時最重要的工程挑戰之一。
from sortedcontainers import SortedDict
class LocalOrderBook:
def __init__(self, coin):
self.coin = coin
self.bids = SortedDict(lambda x: -float(x)) # 買盤:價格由高至低
self.asks = SortedDict(lambda x: float(x)) # 賣盤:價格由低至高
self.last_time = None
def apply_snapshot(self, data):
self.bids.clear()
self.asks.clear()
levels = data["levels"][0]
for bid in levels[0]:
if float(bid["sz"]) > 0:
self.bids[bid["px"]] = float(bid["sz"])
for ask in levels[1]:
if float(ask["sz"]) > 0:
self.asks[ask["px"]] = float(ask["sz"])
self.last_time = data["time"]
def apply_delta(self, data):
levels = data["levels"][0]
for bid in levels[0]:
px, sz = bid["px"], float(bid["sz"])
if sz == 0:
self.bids.pop(px, None)
else:
self.bids[px] = sz
for ask in levels[1]:
px, sz = ask["px"], float(ask["sz"])
if sz == 0:
self.asks.pop(px, None)
else:
self.asks[px] = sz
self.last_time = data["time"]
@property
def best_bid(self):
return next(iter(self.bids.items()), None)
@property
def best_ask(self):
return next(iter(self.asks.items()), None)
@property
def mid_price(self):
bid = self.best_bid
ask = self.best_ask
if bid and ask:
return (float(bid[0]) + float(ask[0])) / 2
return None
@property
def spread(self):
bid = self.best_bid
ask = self.best_ask
if bid and ask:
return float(ask[0]) - float(bid[0])
return None
訊息處理邏輯
處理訊息時,需要區分快照與增量更新,並套用至本地狀態:
order_book = LocalOrderBook("BTC")
is_initialized = False
def handle_message(msg):
global is_initialized
if msg.get("channel") != "l2Book":
return
data = msg["data"]
if not is_initialized:
order_book.apply_snapshot(data)
is_initialized = True
print(
f"訂單簿初始化完成,共 {len(order_book.bids)} 檔買盤,"
f"{len(order_book.asks)} 檔賣盤"
)
else:
order_book.apply_delta(data)
print(
f"最優買價: {order_book.best_bid}, "
f"最優賣價: {order_book.best_ask}, "
f"價差: {order_book.spread}"
)
斷線重連處理
WebSocket 連線可能因網絡波動、伺服器維護或主動斷開而中止。生產系統必須實作自動重連:
import asyncio
import json
import websockets
async def subscribe_with_reconnect(coin, handle_fn, max_retries=None):
retries = 0
while max_retries is None or retries < max_retries:
try:
async with websockets.connect(
WS_URL,
ping_interval=20,
ping_timeout=10
) as ws:
retries = 0
is_initialized = False
await ws.send(json.dumps({
"method": "subscribe",
"subscription": {"type": "l2Book", "coin": coin}
}))
async for raw_msg in ws:
handle_fn(json.loads(raw_msg))
except (websockets.ConnectionClosed, ConnectionError, OSError) as e:
retries += 1
wait = min(2 ** retries, 60)
print(f"連線中斷({e}),{wait} 秒後重試(第 {retries} 次)")
is_initialized = False
await asyncio.sleep(wait)
重連時必須重置 is_initialized。原因是重新連線後,伺服器會再次推送完整快照,而不是由中斷位置繼續補發增量更新。
序列、時間戳與訊息順序
Hyperliquid 的 WebSocket 訊息包含時間戳欄位,可用於檢測訊息是否亂序。生產系統建議:
- 記錄上一條已處理訊息的時間戳;如新訊息早於已處理訊息,可視為過期訊息並丟棄
- 如長時間沒有收到訊息,應主動發送 ping 或重新連線
- 如屬高頻策略,可考慮使用更低延遲的網絡環境或地理位置更接近的節點
多幣種並發訂閱
單一 WebSocket 連線可以同時訂閱多個交易對。建議使用異步架構管理並發:
coins = ["BTC", "ETH", "SOL"]
order_books = {coin: LocalOrderBook(coin) for coin in coins}
async def multi_subscribe():
async with websockets.connect(WS_URL) as ws:
for coin in coins:
await ws.send(json.dumps({
"method": "subscribe",
"subscription": {"type": "l2Book", "coin": coin}
}))
async for raw_msg in ws:
msg = json.loads(raw_msg)
if msg.get("channel") == "l2Book":
coin = msg["data"]["coin"]
if coin in order_books:
order_books[coin].apply_delta(msg["data"])
實際部署時,建議為每個交易對維護獨立的初始化狀態,避免某個幣種尚未收到快照時就錯誤套用增量更新。
實際應用場景
實時訂單簿數據常見用途包括:
- 交易機械人:根據盤口價差動態調整掛單價格
- 套利系統:監控 Hyperliquid 與其他交易所或協議之間的價格差異,例如 dYdX、GMX
- 行情分析面板:可視化訂單簿深度、價差歷史及流動性分佈
- 風控系統:當價差異常擴大或流動性急跌時觸發警報
OneKey Perps:不用自建基建的實用流程
自建 WebSocket 訂單簿系統需要不少工程投入,包括連線穩定性、狀態校驗、數據存儲、監控及異常恢復。如果你的目標是進行永續合約交易,而不是開發量化基建,OneKey Perps 提供了更直接的流程:實時行情展示、交易操作及配合 OneKey 硬件錢包的簽名保護,讓你將重點放在交易決策及風險控制上。
如你希望透過 WalletConnect 連接去中心化應用,應參考 WalletConnect 文件的整合指引。OneKey 支援標準 WalletConnect 協議,可與 Hyperliquid 等 Web3 應用互動,同時保留硬件錢包簽名的安全邊界。
你可以下載並試用 OneKey,於 OneKey Perps 查看實時行情及進行加密貨幣永續合約交易。使用槓桿前,請先確認自己理解保證金、強平及市場波動風險,並只投入可承受風險的資金。
常見問題
Q1:WebSocket 連線有並發上限嗎?
答:連線數及訂閱限制應以 Hyperliquid 官方文件為準。一般建議單一 IP 不要建立過多並發連線;多交易對訂閱應優先重用同一條 WebSocket 連線,而不是為每個交易對各開一條。
Q2:如果漏收一條增量更新,訂單簿狀態會出錯嗎?
答:會。如果增量訊息因網絡問題丟失,本地訂單簿狀態就可能與伺服器實際狀態出現偏差。建議做法是:當懷疑狀態不一致時,例如價差異常、最優價格突然跳變或長時間無更新,主動關閉連線並重新訂閱,以取得最新快照。
Q3:實時訂單簿數據可以直接用於回測嗎?
答:不太適合直接使用。回測需要歷史數據,而不是即時數據流。較實際的做法是將實時訂單簿按時間存成 tick data,累積足夠歷史後再用於研究。亦可配合 Hyperliquid 的歷史 K 線 API 做初步回測,但兩者數據粒度不同,需要注意假設差異。
Q4:如何判斷 WebSocket 連線是否健康?
答:可以定期檢查以下指標:距離上次收到訊息的時間是否超過預設閾值,例如 5 秒;ping/pong 往返延遲是否在合理範圍;訂閱交易對是否持續有有效更新。若偵測到異常,應觸發主動重連流程。
Q5:OneKey 錢包會否影響交易延遲?
答:OneKey 硬件錢包的簽名操作通常在數百毫秒內完成,對大多數手動交易或一般策略影響有限。若是每秒多次下單的超高頻策略,可考慮使用 API Agent 子帳戶熱錢包處理高頻簽名,並由 OneKey 保護主帳戶資金管理,將交易執行與資金保管分開處理。
結語
實時訂單簿訂閱是高質量量化交易系統的重要數據來源。Hyperliquid 的 WebSocket API 設計清晰,配合本文的程式框架,開發者可以建立本地訂單簿維護系統,用於做市、套利、風控或行情分析。
但如果你並不需要自行處理底層 WebSocket、快照同步及重連邏輯,而是希望直接參與鏈上永續合約交易,OneKey Perps 會是更簡單的實務選擇。你可以下載 OneKey,連接錢包後使用 OneKey Perps 查看行情及下單;整個過程仍應以風險控制為先,尤其在使用槓桿時更要審慎。
風險提示: 實時訂單簿數據只反映特定時刻的市場狀態,不能作為交易決策的唯一依據。基於訂單簿數據的自動化交易策略,可能因市場劇烈波動、技術故障、網絡延遲或策略設計缺陷而造成重大虧損。永續合約及槓桿交易屬高風險產品,可能導致全部本金損失。本文內容僅供技術參考,不構成法律、稅務或投資建議;請在充分了解相關風險後審慎操作。



