暗号通貨取引所の板情報(Order Book)は、リアルタイムの市場深度と流動性を把握する上で不可欠なデータです。私は以前、アルゴリズム取引システムの開発において、1秒間に数百件の注文更新を処理する必要があり、Binance WebSocket APIを活用した高頻度データ収集アーキテクチャを実装しました。本記事では、その際に構築したアーキテクチャの詳細と、HolySheep AIを活用したAI統合アプローチについて解説します。

ユースケース:ECサイトのAIカスタマーサービス最適化

具体的なユースケースとして、ECサイトのAIチャットボットがあります。ユーザーが「在庫状況は?」と質問した際、リアルタイムの板情報を解析することで、「現在A社は ¥1,200 で 0.5 BTC を売却可能、B社は ¥1,195 で 1.2 BTC を売却可能」といった具体的な情報を基に、より精度の高い回答が可能になります。

アーキテクチャ概要

高頻度データ収集システムは、以下の3層構造で設計します。

実装:WebSocket接続とデータ収集

まずは、基本となるWebSocket接続クラスを作成します。

import websocket
import json
import threading
import time
from collections import deque
from datetime import datetime

class BinanceOrderBookCollector:
    """
    Binance WebSocket API から板情報を高頻度で収集するクラス
    """
    
    def __init__(self, symbol='btcusdt', depth=100, 
                 buffer_size=10000, on_update_callback=None):
        self.symbol = symbol.lower()
        self.depth = depth
        self.buffer_size = buffer_size
        self.on_update_callback = on_update_callback
        
        # WebSocket URL
        self.ws_url = f"wss://stream.binance.com:9443/ws/{self.symbol}@depth{depth}@100ms"
        
        # データバッファ
        self.order_book_buffer = deque(maxlen=buffer_size)
        self.last_update_id = None
        
        # スレッド管理
        self.ws = None
        self.running = False
        self.reconnect_delay = 1
        self.max_reconnect_delay = 60
        
        # 接続統計
        self.stats = {
            'messages_received': 0,
            'messages_per_second': 0,
            'last_message_time': None,
            'connection_errors': 0
        }
        self._stats_lock = threading.Lock()
        
    def start(self):
        """WebSocket接続を開始"""
        self.running = True
        self.connection_thread = threading.Thread(target=self._run_websocket, daemon=True)
        self.connection_thread.start()
        print(f"[{datetime.now()}] Binance {self.symbol.upper()} 接続開始")
        
    def _run_websocket(self):
        """WebSocket接続のメインループ"""
        while self.running:
            try:
                self.ws = websocket.WebSocketApp(
                    self.ws_url,
                    on_message=self._on_message,
                    on_error=self._on_error,
                    on_close=self._on_close,
                    on_open=self._on_open
                )
                self.ws.run_forever(ping_interval=30, ping_timeout=10)
                
            except Exception as e:
                print(f"[{datetime.now()}] WebSocketエラー: {e}")
                with self._stats_lock:
                    self.stats['connection_errors'] += 1
                    
            if self.running:
                time.sleep(self.reconnect_delay)
                # 指数バックオフ
                self.reconnect_delay = min(self.reconnect_delay * 2, 
                                           self.max_reconnect_delay)
    
    def _on_open(self, ws):
        print(f"[{datetime.now()}] WebSocket接続確立")
        self.reconnect_delay = 1  # リセット
        
    def _on_message(self, ws, message):
        try:
            data = json.loads(message)
            
            # 統計更新
            with self._stats_lock:
                self.stats['messages_received'] += 1
                self.stats['last_message_time'] = time.time()
                now = time.time()
                if self.stats.get('_last_calc_time'):
                    elapsed = now - self.stats['_last_calc_time']
                    if elapsed >= 1.0:
                        self.stats['messages_per_second'] = \
                            self.stats['messages_received'] / elapsed
                        self.stats['_last_calc_time'] = now
                else:
                    self.stats['_last_calc_time'] = now
            
            # バッファに追加
            order_book = self._parse_order_book(data)
            self.order_book_buffer.append({
                'timestamp': datetime.now().isoformat(),
                'data': order_book
            })
            
            # コールバック実行
            if self.on_update_callback:
                self.on_update_callback(order_book)
                
        except json.JSONDecodeError as e:
            print(f"JSON解析エラー: {e}")
            
    def _parse_order_book(self, data):
        """板情報データをパース"""
        return {
            'last_update_id': data.get('u') or data.get('lastUpdateId'),
            'bids': [[float(p), float(q)] for p, q in data.get('b', data.get('bids', []))],
            'asks': [[float(p), float(q)] for p, q in data.get('a', data.get('asks', []))],
            'symbol': self.symbol.upper()
        }
    
    def _on_error(self, ws, error):
        print(f"[{datetime.now()}] WebSocketエラー: {error}")
        with self._stats_lock:
            self.stats['connection_errors'] += 1
            
    def _on_close(self, ws, close_status_code, close_msg):
        print(f"[{datetime.now()}] WebSocket切断: {close_status_code}")
        
    def get_latest_order_book(self):
        """最新の手形帳を取得"""
        if self.order_book_buffer:
            return self.order_book_buffer[-1]['data']
        return None
        
    def get_statistics(self):
        """接続統計を取得"""
        with self._stats_lock:
            return self.stats.copy()
            
    def stop(self):
        """接続を停止"""
        self.running = False
        if self.ws:
            self.ws.close()
        print(f"[{datetime.now()}] 接続停止")


使用例

def on_order_book_update(order_book): """板情報更新時のコールバック""" best_bid = order_book['bids'][0] if order_book['bids'] else None best_ask = order_book['asks'][0] if order_book['asks'] else None if best_bid and best_ask: spread = best_ask[0] - best_bid[0] spread_pct = (spread / best_bid[0]) * 100 print(f"spread: {spread:.2f} ({spread_pct:.4f}%)") collector = BinanceOrderBookCollector(symbol='btcusdt', depth=100) collector.start()

AI統合:BinanceデータとHolySheep APIの連携

収集した板情報をAIで分析し、自然言語で市場状況を解説するシステムを構築します。HolySheep AI APIを使用すると、レートが¥1=$1