金融市場の高速取引(HFT)やアルゴリズム取引において、Order Book(発注帳簿・板情報)は最も基礎的かつ重要なデータ構造です。本稿では、Order Bookの基本原理、データ構造の詳細、そしてTardis L2データの活用方法について、HolySheep AIを活用した実装例とともに解説します。

Order Bookとは何か:市場流動性のデジタル表現

Order Bookとは、特定の金融商品に対して出された買い注文と売り注文を価格順に記録した帳簿です。板情報とも呼ばれ、市場参加者の需給関係をリアルタイムで可視化します。

私は以前、暗号通貨取引所の注文執行エンジン開発において、

Order Bookの基本原理

ビッド(Bid)とアスク(Ask)

Order Bookは通常、以下の2つの стороны(面)で構成されます:

ビッド価格とアスク価格の差額をスプレッド(spread)と呼び、これが市場の流動性と取引コストを示します。

板寄せ方式と気配値表示方式

  1. 板寄せ方式:約定するたびに板信息が更新される方式(日本市場の традиционная方式)
  2. 気配値表示方式:現在atinaの買い気配・売り気配を表示する方式(米国市場などで一般的)

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データの構造例

# Tardis L2データのJSON構造例
{
    "type": "book-change",
    "exchange": "binance",
    "market": "BTC-USDT",
    "timestamp": 1704067200123,
    "data": {
        "bids": [
            {"p": 42000.50, "q":