金融市場の高速取引(HFT)やアルゴリズム取引において、Order Book(発注帳簿・板情報)は最も基礎的かつ重要なデータ構造です。本稿では、Order Bookの基本原理、データ構造の詳細、そしてTardis L2データの活用方法について、HolySheep AIを活用した実装例とともに解説します。
Order Bookとは何か:市場流動性のデジタル表現
Order Bookとは、特定の金融商品に対して出された買い注文と売り注文を価格順に記録した帳簿です。板情報とも呼ばれ、市場参加者の需給関係をリアルタイムで可視化します。
私は以前、暗号通貨取引所の注文執行エンジン開発において、 Order Bookは通常、以下の2つの стороны(面)で構成されます: ビッド価格とアスク価格の差額をスプレッド(spread)と呼び、これが市場の流動性と取引コストを示します。 この実装は理解易于ですが、大量の注文がある場合には поиск效率が低下します。 Tardisは、暗号通貨・株式・先物市場の高速 историческихデータとリアルタイムストリームを提供するプロフェッショナルな金融データプロバイダーです。L2データはOrder Bookの基本原理
ビッド(Bid)とアスク(Ask)
板寄せ方式と気配値表示方式
Order Bookのデータ構造
配列ベースのアプローチ
# 単純なPythonによるOrder Bookの実装
class SimpleOrderBook:
def __init__(self):
self.bids = [] # [(price, quantity), ...]
self.asks = [] # [(price, quantity), ...]
def add_bid(self, price, quantity):
self.bids.append((price, quantity))
self.bids.sort(key=lambda x: x[0], reverse=True) # 高い順に並べる
def add_ask(self, price, quantity):
self.asks.append((price, quantity))
self.asks.sort(key=lambda x: x[0]) # 低い順に並べる
def get_best_bid(self):
return self.bids[0] if self.bids else None
def get_best_ask(self):
return self.asks[0] if self.asks else None
def get_spread(self):
best_bid = self.get_best_bid()
best_ask = self.get_best_ask()
if best_bid and best_ask:
return best_ask[0] - best_bid[0]
return None
ヒープベースのアプローチ(優先度キュー)
import heapq
from dataclasses import dataclass
from typing import Dict, List, Optional
@dataclass
class Order:
order_id: str
price: float
quantity: float
side: str # 'bid' or 'ask'
class HeapOrderBook:
"""
ヒープを用いた高性能Order Book実装
時間計算量: O(log n)
"""
def __init__(self):
# 最小ヒープ(最安値を探すのに効率的)
self.bid_heap: List[Order] = []
self.ask_heap: List[Order] = []
# O(1)アクセス用の辞書
self.bid_orders: Dict[str, Order] = {}
self.ask_orders: Dict[str, Order] = {}
# 価格ごとの累積数量
self.bid_levels: Dict[float, float] = {}
self.ask_levels: Dict[float, float] = {}
def add_order(self, order: Order) -> None:
"""新規注文の追加"""
if order.side == 'bid':
heapq.heappush(self.bid_heap, order)
self.bid_orders[order.order_id] = order
self.bid_levels[order.price] = \
self.bid_levels.get(order.price, 0) + order.quantity
else:
heapq.heappush(self.ask_heap, order)
self.ask_orders[order.order_id] = order
self.ask_levels[order.price] = \
self.ask_levels.get(order.price, 0) + order.quantity
def get_best_bid(self) -> Optional[float]:
"""最高買い気配値の取得"""
while self.bid_heap:
best = self.bid_heap[0]
if best in self.bid_orders and best.quantity > 0:
return best.price
heapq.heappop(self.bid_heap) # 無効な注文を削除
return None
def get_best_ask(self) -> Optional[float]:
"""最安売り気配値の取得"""
while self.ask_heap:
best = self.ask_heap[0]
if best in self.ask_orders and best.quantity > 0:
return best.price
heapq.heappop(self.ask_heap) # 無効な注文を削除
return None
def get_depth(self, levels: int = 10) -> Dict:
"""板の深さ(指定した本数)を取得"""
bid_depth = sorted(
self.bid_levels.items(),
key=lambda x: x[0],
reverse=True
)[:levels]
ask_depth = sorted(
self.ask_levels.items(),
key=lambda x: x[0]
)[:levels]
return {'bids': bid_depth, 'asks': ask_depth}
Tardis L2データとは
Tardis L2データの特徴
Tardis L2データの構造例
# Tardis L2データのJSON構造例
{
"type": "book-change",
"exchange": "binance",
"market": "BTC-USDT",
"timestamp": 1704067200123,
"data": {
"bids": [
{"p": 42000.50, "q":