2026年5月24日 | HolySheep AI 技術ブログ

🔓 この記事の対象読者:WebSocketリアルタイムデータ連携を学びたい開発者、暗号資産裁定取引 Bot を構築したいトレーダー、複数の取引所に低遅延で接続したい_quant desk_のエンジニア

こんにちは、HolySheep AIの技術ライターです。私は以前、暗号資産取引所のデータパイプラインを構築するエンジニアとして、OKX、Coinbase、Bybitなど複数の取引所の市場データに接続する仕事に5年以上従事してきました。今日は、私の実戦経験に基づき、Tardis.devからOKX永続契約の強制清算tickデータを取得し、Coinbase Internationalの市場データと照合して裁定取引チャンスを検出するシステムを構築する方法を、誰にも分かるように丁寧に説明します。

このガイド读完後に得ること

必要な準備と前提知識

必要なアカウント

技術的前提

💡 ヒント:Tardis.devとCoinbase Internationalの両方に接続する場合、各サービスの个別のAPI 키管理は複雑になりがちです。HolySheep AIの統合ゲートウェイを使用すると、単一のAPI キーで複数のサービスに接続でき、キーの管理負担が大幅に減ります。

HolySheep AI の役割を理解する

多くの開発者が直面する課題は、複数のデータプロバイダーに個別に接続する際の実装の複雑さです。例えば、OKX永続契約のデータをTardisから取得しながら、Coinbase InternationalのデータをCoinbase APIから取得したい場合、2つの独立した接続管理体系が必要になり maintenanca 비용이 상승합니다。

HolySheep AIは、この問題を解決する универсальный API ゲートウェイです:

プロジェクト架构設計

今回構築するシステムの全体架构は以下の通りです:

┌─────────────────────────────────────────────────────────────┐
│                    Arbitrage Detection System               │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌───────────────┐    ┌───────────────┐                     │
│  │  Tardis.dev   │    │   Coinbase    │                     │
│  │  OKX Perpetual│    │  International│                     │
│  │  WebSocket    │    │    Futures    │                     │
│  └───────┬───────┘    └───────┬───────┘                     │
│          │                    │                             │
│          ▼                    ▼                             │
│  ┌───────────────────────────────────────┐                  │
│  │         HolySheep AI Gateway          │                  │
│  │  (Unified Connection & Authentication)│                  │
│  └───────────────┬───────────────────────┘                  │
│                  │                                           │
│                  ▼                                           │
│  ┌───────────────────────────────────────┐                  │
│  │         Arbitrage Engine              │                  │
│  │  - Liquidation Tick Processing        │                  │
│  │  - Spread Calculation                 │                  │
│  │  - Opportunity Detection              │                  │
│  └───────────────┬───────────────────────┘                  │
│                  │                                           │
│                  ▼                                           │
│  ┌───────────────────────────────────────┐                  │
│  │         Alert / Execution Module      │                  │
│  └───────────────────────────────────────┘                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

ステップ1:開発環境のセットアップ

まず、Python 환경を構築します。터미널에서 다음 명령어를 실행하세요:

# Python 仮想環境の作成
python3 -m venv arbitrage_env

仮想環境の有効化(macOS / Linux)

source arbitrage_env/bin/activate

仮想環境の有効化(Windows)

arbitrage_env\Scripts\activate

必要なパッケージのインストール

pip install websockets asyncio aiohttp pandas numpy python-dotenv

プロジェクトフォルダ構造

arbitrage_project/
├── config.py              # 設定ファイル
├── connectors/
│   ├── __init__.py
│   ├── holy Sheep_connector.py    # HolySheep経由の接続
│   ├── tardis_connector.py        # Tardis.dev OKX接続
│   └── coinbase_connector.py      # Coinbase International接続
├── engine/
│   ├── __init__.py
│   ├── arbitrage_detector.py      # 裁定取引検出ロジック
│   └── liquidation_processor.py   # 清算tick処理
├── utils/
│   ├── __init__.py
│   └── logger.py                  # ロギングユーティリティ
├── main.py                        # メインエントリーポイント
└── .env                           # APIキーなど機密情報

ステップ2:設定ファイルの作成

# config.py
import os
from dotenv import load_dotenv

load_dotenv()

============================================

HolySheep AI 設定

============================================

HOLYSHEEP_API_KEY = os.getenv("HOLYSHEEP_API_KEY", "YOUR_HOLYSHEEP_API_KEY") HOLYSHEEP_BASE_URL = "https://api.holysheep.ai/v1"

============================================

Tardis.dev 設定(OKX Perpetual)

============================================

TARDIS_WS_URL = "wss://ws.tardis.dev" TARDIS_OKX_CHANNEL = "liquidation" # OKX永続契約の清算チャンネル TARDIS_SYMBOLS = [ "BTC-USDT-PERPETUAL", "ETH-USDT-PERPETUAL", ]

============================================

Coinbase International 設定

============================================

COINBASE_WS_URL = "wss://ws.coinbase-intnl.com/ws" COINBASE_PRODUCT_IDS = [ "BTC-PERPETUAL", "ETH-PERPETUAL", ]

============================================

裁定取引パラメータ

============================================

ARBITRAGE_CONFIG = { "min_spread_bps": 5, # 裁定取引判定的最小スプレッド(basis points) "min_volume_usd": 10000, # 最小取引量(USD) "lookback_window_ms": 500, # タイムスタンプ照合ウィンドウ(ミリ秒) "latency_threshold_ms": 100, # 許容最大遅延(ミリ秒) }

============================================

ログ設定

============================================

LOG_LEVEL = "INFO" LOG_FORMAT = "%(asctime)s | %(levelname)-8s | %(name)s | %(message)s"

⚠️ 重要.envファイルを作成して реальные APIキーを 保存してください。このファイルは絶対にGitHubなどにアップロードしないでください。

# .env ファイルの作成
cat > .env << 'EOF'
HOLYSHEEP_API_KEY=your_holysheep_api_key_here
TARDIS_API_KEY=your_tardis_api_key_here
COINBASE_API_KEY=your_coinbase_api_key_here
EOF

ステップ3:HolySheep AI コネクタの実装

ここが核心です。HolySheep AIは、複数のデータソースへの接続を标准化します,下列のは HolySheep 経由でTardisとCoinbaseに接続するための基盤クラスです:

# connectors/holy Sheep_connector.py
import aiohttp
import asyncio
import json
from typing import Dict, Optional, Callable, Any
from datetime import datetime
import logging

logger = logging.getLogger(__name__)


class HolySheepConnector:
    """
    HolySheep AI Gateway 経由でのデータソース接続管理器
    
    HolySheep는 단일 API 키로 여러 서비스에 연결할 수 있게 해주는
    универсальный 게이트웨이입니다.
    """
    
    def __init__(self, api_key: str, base_url: str = "https://api.holysheep.ai/v1"):
        self.api_key = api_key
        self.base_url = base_url
        self.session: Optional[aiohttp.ClientSession] = None
        self._connected = False
        
    async def __aenter__(self):
        """非同期コンテキストマネージャー入口"""
        await self.connect()
        return self
    
    async def __aexit__(self, exc_type, exc_val, exc_tb):
        """非同期コンテキストマネージャー出口"""
        await self.disconnect()
        
    async def connect(self) -> bool:
        """
        HolySheep AI 게이트웨이への接続を確立
        
        返り値:
            bool: 接続成功の場合はTrue
        """
        try:
            self.session = aiohttp.ClientSession(
                headers={
                    "Authorization": f"Bearer {self.api_key}",
                    "Content-Type": "application/json"
                },
                timeout=aiohttp.ClientTimeout(total=30)
            )
            
            # 接続テスト(Pingエンドポイント)
            async with self.session.get(f"{self.base_url}/models") as resp:
                if resp.status == 200:
                    self._connected = True
                    logger.info("HolySheep AI Gateway 连接成功")
                    return True
                else:
                    logger.error(f"HolySheep 连接失败: HTTP {resp.status}")
                    return False
                    
        except aiohttp.ClientError as e:
            logger.error(f"HolySheep 连接错误: {e}")
            return False
    
    async def disconnect(self):
        """接続解除"""
        if self.session:
            await self.session.close()
            self._connected = False
            logger.info("HolySheep AI Gateway 连接已断开")
    
    async def forward_to_tardis(
        self, 
        endpoint: str, 
        params: Optional[Dict] = None
    ) -> Dict[str, Any]:
        """
        Tardis.dev APIへのリクエストをHolySheep経由で転送
        
        引数:
            endpoint: Tardis API のエンドポイント
            params: リクエストパラメータ
            
        返り値:
            Dict: APIレスポンス
        """
        if not self._connected:
            raise ConnectionError("HolySheepに接続されていません")
            
        url = f"{self.base_url}/services/tardis/{endpoint}"
        
        try:
            async with self.session.get(url, params=params) as resp:
                data = await resp.json()
                if resp.status == 200:
                    return data
                else:
                    logger.error(f"Tardis API 错误: {data}")
                    return {"error": data}
        except Exception as e:
            logger.error(f"Tardis API 例外: {e}")
            return {"error": str(e)}
    
    async def forward_to_coinbase(
        self,
        endpoint: str,
        method: str = "GET",
        data: Optional[Dict] = None
    ) -> Dict[str, Any]:
        """
        Coinbase International APIへのリクエストをHolySheep経由で転送
        """
        if not self._connected:
            raise ConnectionError("HolySheepに接続されていません")
            
        url = f"{self.base_url}/services/coinbase/{endpoint}"
        
        try:
            if method == "GET":
                async with self.session.get(url) as resp:
                    return await resp.json()
            elif method == "POST":
                async with self.session.post(url, json=data) as resp:
                    return await resp.json()
        except Exception as e:
            logger.error(f"Coinbase API 例外: {e}")
            return {"error": str(e)}
    
    @property
    def is_connected(self) -> bool:
        return self._connected

ステップ4:Tardis.dev OKX永続データ接続

次に、Tardis.devからOKX永続契約の強制清算tickデータをリアルタイムで受信する接続口を実装します:

# connectors/tardis_connector.py
import asyncio
import json
import websockets
from websockets.client import WebSocketClientProtocol
from typing import List, Optional, Callable, Dict, Any
from dataclasses import dataclass, asdict
from datetime import datetime
import logging

logger = logging.getLogger(__name__)


@dataclass
class LiquidationTick:
    """
    強制清算イベントを表現するデータクラス
    """
    timestamp: datetime
    exchange: str
    symbol: str
    side: str              # "buy" or "sell"
    price: float
    size: float            # 清算数量
    volume_usd: float      # 清算代金(USD)
    is_auto_liquidate: bool  # 自動清算かどうか
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            "timestamp": self.timestamp.isoformat(),
            "exchange": self.exchange,
            "symbol": self.symbol,
            "side": self.side,
            "price": self.price,
            "size": self.size,
            "volume_usd": self.volume_usd,
            "is_auto_liquidate": self.is_auto_liquidate
        }


class TardisOKXConnector:
    """
    Tardis.dev WebSocket経由でOKX永続契約の清算tickを受信
    
    使用例:
        connector = TardisOKXConnector(api_key="your_tardis_key")
        await connector.connect(on_liquidation=handle_liquidation)
    """
    
    def __init__(
        self, 
        api_key: str,
        symbols: List[str] = None,
        holy Sheep_connector = None  # HolySheep経由の場合
    ):
        self.api_key = api_key
        self.symbols = symbols or ["BTC-USDT-PERPETUAL", "ETH-USDT-PERPETUAL"]
        self.holy Sheep = holy Sheep_connector
        
        self.ws: Optional[WebSocketClientProtocol] = None
        self._running = False
        self._reconnect_delay = 1  # 秒
        self._max_reconnect_delay = 60
        
        # コールバック
        self.on_liquidation: Optional[Callable[[LiquidationTick], None]] = None
        
    async def connect(self):
        """
        Tardis.dev OKX清算チャンネルに接続
        """
        self._running = True
        reconnect_count = 0
        
        while self._running:
            try:
                # Tardis WebSocket URL(OKX先物用)
                url = "wss://ws.tardis.dev"
                
                headers = {
                    "Authorization": f"Bearer {self.api_key}"
                }
                
                logger.info(f"Tardis.devに接続中... URL: {url}")
                
                async with websockets.connect(url, extra_headers=headers) as ws:
                    self.ws = ws
                    logger.info("Tardis.dev WebSocket 连接成功")
                    
                    # サブスクリプション設定
                    subscription = {
                        "type": "subscribe",
                        "channel": "liquidation",
                        "exchange": "okx",
                        "symbols": self.symbols
                    }
                    
                    await ws.send(json.dumps(subscription))
                    logger.info(f"サブスクリプション送信: {subscription}")
                    
                    reconnect_count = 0  # 接続成功時にカウンタをリセット
                    
                    # メッセージ受信用ループ
                    while self._running:
                        try:
                            message = await asyncio.wait_for(
                                ws.recv(), 
                                timeout=30.0
                            )
                            await self._process_message(message)
                            
                        except asyncio.TimeoutError:
                            # ハートビート(30秒ごとに Ping送信)
                            await ws.send(json.dumps({"type": "ping"}))
                            
            except websockets.WebSocketException as e:
                reconnect_count += 1
                delay = min(
                    self._reconnect_delay * (2 ** reconnect_count),
                    self._max_reconnect_delay
                )
                logger.warning(
                    f"Tardis接続切断 (試行 {reconnect_count}): {e}. "
                    f"{delay}秒後に再接続..."
                )
                await asyncio.sleep(delay)
                
            except Exception as e:
                logger.error(f"予期しないエラー: {e}")
                await asyncio.sleep(5)
    
    async def _process_message(self, raw_message: str):
        """
        受信メッセージを処理して清算tickを抽出
        
        引数:
            raw_message: WebSocketから受信したJSON文字列
        """
        try:
            data = json.loads(raw_message)
            
            # 清算メッセージのみを処理
            if data.get("type") == "liquidation" and data.get("exchange") == "okx":
                tick = self._parse_liquidation(data)
                
                if tick:
                    logger.info(
                        f"清算tick受信 | {tick.symbol} | "
                        f"{tick.side.upper()} | "
                        f"${tick.price:,.2f} | "
                        f"数量: {tick.size} | "
                        f"代金: ${tick.volume_usd:,.2f}"
                    )
                    
                    # コールバック実行
                    if self.on_liquidation:
                        await self._safe_callback(self.on_liquidation, tick)
                        
        except json.JSONDecodeError as e:
            logger.warning(f"JSON解析エラー: {e}")
        except Exception as e:
            logger.error(f"メッセージ処理エラー: {e}")
    
    def _parse_liquidation(self, data: Dict) -> Optional[LiquidationTick]:
        """
        清算データをLiquidationTickオブジェクトに変換
        """
        try:
            # Tardisからのデータ構造に合わせてパース
            ticker_data = data.get("data", {})
            
            return LiquidationTick(
                timestamp=datetime.fromisoformat(
                    data.get("timestamp", datetime.now().isoformat())
                ),
                exchange=data.get("exchange", "okx"),
                symbol=ticker_data.get("symbol", ""),
                side=ticker_data.get("side", "buy"),
                price=float(ticker_data.get("price", 0)),
                size=float(ticker_data.get("size", 0)),
                volume_usd=float(ticker_data.get("volume", 0)),
                is_auto_liquidate=ticker_data.get("isAutoLiquidate", False)
            )
        except (ValueError, KeyError) as e:
            logger.error(f"清算データ解析エラー: {e}")
            return None
    
    async def _safe_callback(
        self, 
        callback: Callable, 
        *args, **kwargs
    ):
        """コールバックを安全に実行(例外を捕获)"""
        try:
            if asyncio.iscoroutinefunction(callback):
                await callback(*args, **kwargs)
            else:
                callback(*args, **kwargs)
        except Exception as e:
            logger.error(f"コールバック実行エラー: {e}")
    
    async def disconnect(self):
        """接続解除"""
        self._running = False
        if self.ws:
            await self.ws.close()
        logger.info("Tardis OKX接続を解除しました")

ステップ5:Coinbase International 先物データ接続

# connectors/coinbase_connector.py
import asyncio
import json
from typing import List, Optional, Callable, Dict, Any
from dataclasses import dataclass
from datetime import datetime
import websockets
from websockets.client import WebSocketClientProtocol
import logging

logger = logging.getLogger(__name__)


@dataclass
class CBFuturesTick:
    """
    Coinbase International 先物市場データを表現
    """
    timestamp: datetime
    product_id: str
    best_bid: float
    best_ask: float
    bid_size: float
    ask_size: float
    spread: float           # ビッドアスクスプレッド
    spread_bps: float      # スプレッド(basis points)
    volume_24h: float


class CoinbaseFuturesConnector:
    """
    Coinbase International Exchange 先物WebSocketに接続
    
    注意事項:
        Coinbase Internationalは米国向けCoinbaseとは別の取引所です。
        別途の開発者登録が必要です。
    """
    
    def __init__(
        self,
        api_key: str,
        api_secret: str,
        product_ids: List[str] = None,
        holy Sheep_connector = None
    ):
        self.api_key = api_key
        self.api_secret = api_secret
        self.product_ids = product_ids or ["BTC-PERPETUAL", "ETH-PERPETUAL"]
        self.holy Sheep = holy Sheep_connector
        
        self.ws: Optional[WebSocketClientProtocol] = None
        self._running = False
        self._last_heartbeat = None
        
        # 市場データ缓存
        self._market_data: Dict[str, CBFuturesTick] = {}
        
        # コールバック
        self.on_tick: Optional[Callable[[CBFuturesTick], None]] = None
        
    async def connect(self):
        """
        Coinbase International WebSocketに接続
        """
        self._running = True
        
        # Coinbase International WebSocket URL
        url = "wss://ws.coinbase-intnl.com/ws"
        
        while self._running:
            try:
                logger.info(f"Coinbase Internationalに接続中...")
                
                async with websockets.connect(url) as ws:
                    self.ws = ws
                    logger.info("Coinbase International WebSocket 连接成功")
                    
                    # 認証とサブスクリプション
                    await self._authenticate()
                    await self._subscribe()
                    
                    # メッセージ受信用ループ
                    while self._running:
                        try:
                            message = await asyncio.wait_for(
                                ws.recv(),
                                timeout=30.0
                            )
                            await self._process_message(message)
                            
                        except asyncio.TimeoutError:
                            await ws.send(json.dumps({"type": "ping"}))
                            
            except websockets.WebSocketException as e:
                logger.warning(f"Coinbase接続切断: {e}. 再接続中...")
                await asyncio.sleep(5)
                
            except Exception as e:
                logger.error(f"予期しないエラー: {e}")
                await asyncio.sleep(5)
    
    async def _authenticate(self):
        """Coinbase API 認証"""
        auth_msg = {
            "type": "auth",
            "api_key": self.api_key,
            "timestamp": str(int(datetime.now().timestamp())),
            "signature": self._generate_signature()  # 实际实现需要HMAC
        }
        await self.ws.send(json.dumps(auth_msg))
        logger.info("Coinbase 認証メッセージ送信完了")
    
    def _generate_signature(self) -> str:
        """
        APIリクエスト用の署名生成
        
        实际実装ではHMAC-SHA256を使用します:
        signature = HMAC-SHA256(api_secret, timestamp + "GET" + "/ws")
        """
        import hmac
        import hashlib
        
        timestamp = str(int(datetime.now().timestamp()))
        message = timestamp + "GET" + "/ws"
        
        signature = hmac.new(
            self.api_secret.encode(),
            message.encode(),
            hashlib.sha256
        ).hexdigest()
        
        return signature
    
    async def _subscribe(self):
        """マーケットデータチャンネルにサブスクライブ"""
        subscribe_msg = {
            "type": "subscribe",
            "product_ids": self.product_ids,
            "channel": "level1"  # 最良ビッド·阿スク
        }
        await self.ws.send(json.dumps(subscribe_msg))
        logger.info(f"Coinbase サブスクリプション送信: {subscribe_msg}")
    
    async def _process_message(self, raw_message: str):
        """受信メッセージを処理"""
        try:
            data = json.loads(raw_message)
            msg_type = data.get("type")
            
            if msg_type == "l1update":
                tick = self._parse_l1_update(data)
                if tick:
                    self._market_data[tick.product_id] = tick
                    
                    logger.debug(
                        f"Coinbase tick | {tick.product_id} | "
                        f"Bid: {tick.best_bid} | "
                        f"Ask: {tick.best_ask} | "
                        f"Spread: {tick.spread_bps:.2f} bps"
                    )
                    
                    if self.on_tick:
                        await self._safe_callback(self.on_tick, tick)
                        
            elif msg_type == "subscriptions":
                logger.info(f"サブスクライブ確認: {data}")
                
        except Exception as e:
            logger.error(f"メッセージ処理エラー: {e}")
    
    def _parse_l1_update(self, data: Dict) -> Optional[CBFuturesTick]:
        """Level1数据をパース"""
        try:
            bids = data.get("bids", [[0, 0]])[0]
            asks = data.get("asks", [[0, 0]])[0]
            
            best_bid = float(bids[0])
            best_ask = float(asks[0])
            spread = best_ask - best_bid
            mid_price = (best_bid + best_ask) / 2
            spread_bps = (spread / mid_price) * 10000 if mid_price > 0 else 0
            
            return CBFuturesTick(
                timestamp=datetime.fromisoformat(data.get("timestamp", datetime.now().isoformat())),
                product_id=data.get("product_id", ""),
                best_bid=best_bid,
                best_ask=best_ask,
                bid_size=float(bids[1]) if len(bids) > 1 else 0,
                ask_size=float(asks[1]) if len(asks) > 1 else 0,
                spread=spread,
                spread_bps=spread_bps,
                volume_24h=data.get("volume_24h", 0)
            )
        except Exception as e:
            logger.error(f"Level1データ解析エラー: {e}")
            return None
    
    async def _safe_callback(self, callback, *args, **kwargs):
        try:
            if asyncio.iscoroutinefunction(callback):
                await callback(*args, **kwargs)
            else:
                callback(*args, **kwargs)
        except Exception as e:
            logger.error(f"コールバックエラー: {e}")
    
    def get_market_data(self, product_id: str) -> Optional[CBFuturesTick]:
        """最新の市場データを取得"""
        return self._market_data.get(product_id)
    
    async def disconnect(self):
        """接続解除"""
        self._running = False
        if self.ws:
            await self.ws.close()
        logger.info("Coinbase International接続を解除しました")

ステップ6:裁定取引検出エンジンの実装

ここが核心アルゴリズムです。OKXとCoinbaseの清算tickを受信し、両市場の価格差から裁定取引チャンスを 检测します:

# engine/arbitrage_detector.py
import asyncio
from typing import Dict, Optional, List
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from collections import deque
import logging
from engine.liquidation_processor import LiquidationTick
from connectors.coinbase_connector import CBFuturesTick

logger = logging.getLogger(__name__)


@dataclass
class ArbitrageOpportunity:
    """
    裁定取引チャンスを表現
    """
    detected_at: datetime
    symbol: str
    okx_liquidation_price: float
    coinbase_bid: float
    coinbase_ask: float
    spread_bps: float
    okx_liquidation_volume: float
    latency_ms: float
    confidence: float  # 0.0 - 1.0
    
    def to_dict(self):
        return {
            "detected_at": self.detected_at.isoformat(),
            "symbol": self.symbol,
            "okx_liquidation_price": self.okx_liquidation_price,
            "coinbase_bid": self.coinbase_bid,
            "coinbase_ask": self.coinbase_ask,
            "spread_bps": self.spread_bps,
            "okx_liquidation_volume": self.okx_liquidation_volume,
            "latency_ms": self.latency_ms,
            "confidence": self.confidence
        }


class ArbitrageDetector:
    """
    複数取引所間の裁定取引チャンスを検出するエンジン
    
    戦略:
    1. OKXで大規模な強制清算が発生
    2. 清算价格为市場から大きく乖離(通常是買い手过多导致清算)
    3. Coinbaseで同製品の気配値を確認
    4. 価格差が閾値を超えている場合にアラート发出
    """
    
    def __init__(
        self,
        min_spread_bps: float = 5.0,
        min_volume_usd: float = 10000.0,
        lookback_window_ms: int = 500,
        latency_threshold_ms: float = 100.0
    ):
        self.min_spread_bps = min_spread_bps
        self.min_volume_usd = min_volume_usd
        self.lookback_window = timedelta(milliseconds=lookback_window_ms)
        self.latency_threshold_ms = latency_threshold_ms
        
        # 清算tickの缓存( 시간순으로 정렬)
        self._liquidation_buffer: Dict[str, deque] = {
            "BTC": deque(maxlen=100),
            "ETH": deque(maxlen=100)
        }
        
        # 検出された裁定取引チャンス
        self._opportunities: List[ArbitrageOpportunity] = []
        
        # シンボルマッピング
        self._symbol_map = {
            "BTC-USDT-PERPETUAL": "BTC-PERPETUAL",
            "ETH-USDT-PERPETUAL": "ETH-PERPETUAL"
        }
    
    def process_okx_liquidation(self, tick: LiquidationTick):
        """
        OKXからの清算tickを処理
        
        引数:
            tick: Tardisから受信した清算tick
        """
        # シンボル标准化
        normalized_symbol = self._normalize_symbol(tick.symbol)
        if not normalized_symbol:
            return
        
        # キャッシュに追加
        self._liquidation_buffer[normalized_symbol].append(tick)
        
        # 古いエントリをクリーンアップ(タイムスタンプベース)
        self._cleanup_old_entries(normalized_symbol)
        
        logger.debug(
            f"OKX清算缓存更新 | {normalized_symbol} | "
            f"バッファサイズ: {len(self._liquidation_buffer[normalized_symbol])}"
        )
    
    def check_arbitrage(
        self,
        symbol: str,
        coinbase_data: CBFuturesTick
    ) -> Optional[ArbitrageOpportunity]:
        """
        Coinbaseデータと既存の清算tickを照合して裁定チャンスを检测
        
        引数:
            symbol: シンボル名
            coinbase_data: Coinbaseからの最新気配値
            
        返り値:
            ArbitrageOpportunity: 裁定チャンス(无ければNone)
        """
        normalized_symbol = self._normalize_symbol(symbol)
        if not normalized_symbol:
            return None
        
        # キャッシュから最近の清算tickを取得
        recent_liquidation = self._find_recent_liquidation(
            normalized_symbol,
            coinbase_data.timestamp
        )
        
        if not recent_liquidation:
            return None
        
        # 遅延計算
        latency_ms = (
            coinbase_data.timestamp - recent_liquidation.timestamp
        ).total_seconds() * 1000
        
        # 遅延チェック
        if latency_ms > self.latency_threshold_ms:
            logger.debug(f"遅延が閾値を超過: {latency_ms:.1f}ms > {self.latency_threshold_ms}ms")
            return None
        
        # 裁定計算
        # 清算が売り(ショート清算)の場合:CBOE에서 살機会
        # 清算が買い(ロング清算)の場合:CBOE에서 팔機会
        
        if recent_liquidation.side == "sell":
            # ショート清算 → Coinbaseで買う(Ask価格)
            reference_price = coinbase_data.best_ask
            execution_side = "BUY on Coinbase"
        else:
            # ロング清算 → Coinbaseで売る(Bid価格)
            reference_price = coinbase_data.best_bid
            execution_side = "SELL on Coinbase"
        
        # スプレッド計算(basis points)
        price_diff = abs(recent_liquidation.price - reference_price)
        spread_bps = (price_diff / reference_price) * 10000 if reference_price > 0 else 0
        
        # 裁定判別
        if (spread_bps < self.min_spread_bps or 
            recent_liquidation.volume_usd < self.min_volume_usd):
            return None
        
        # 信頼度計算(複数の要素を 종합)
        confidence = self._calculate_confidence(
            spread_bps,
            recent_liquidation.volume_usd,
            latency_ms
        )
        
        opportunity = ArbitrageOpportunity(
            detected_at=datetime.now(),
            symbol=normalized_symbol,
            okx_liquidation_price=recent_liquidation.price,
            coinbase_bid=coinbase_data.best_bid,
            coinbase_ask=coinbase_data.best_ask,
            spread_bps=spread_bps,
            okx_liquidation_volume=recent_liquidation.volume_usd,
            latency_ms=latency_ms,
            confidence=confidence
        )
        
        self._opportunities.append(opportunity)
        
        logger.info(
            f"🚀 裁定取引チャンス検出!\n"
            f"   シンボル: {normalized_symbol}\n"
            f"   スプレッド: {spread_bps:.2f} bps\n"
            f"   OKX清算価格: ${recent_liquidation.price:,.2f}\n"
            f"   Coinbase参照: ${reference_price:,.2f}\n"
            f"   清算代金: ${recent_liquidation.volume_usd:,.2f}\n"
            f"   遅延: {latency_ms:.1f}ms\n"
            f"   信頼度: {confidence:.2%}"
        )
        
        return opportunity
    
    def _normalize_symbol(self, symbol: str) -> Optional[str]: