暗号資産トレーディングにおける市場再生データ(リプレイデータ)は、アルゴリズム開発の精度向上や歷史的な流動性分析に不可欠なリソースです。本稿では、Tardis.devを活用したBinanceおよびOKXのブックデータ取得方法から、実際の実装コード、よくあるエラーの回避策までを徹底解説します。

Tardis.devとは

Tardis.devは、暗号通貨取引所のリアルタイム・歴史的市場データを提供するSaaSプラットフォームです。Tick-level(ティックレベル)の詳細データをサポートし、特に以下に強いendelます:

私は以前、Binanceの約定データだけで月間2TB超の生データを処理していましたが、Tardis.devの統一APIを用いることでデータ整形の手間を70%以上削減できました。特にを原生で扱える点は非常に有用です。

対応取引所とデータ種別

取引所OrderbookTradesKlinesWebSocket対応
Binance Spot✅ フル深度✅ Tick-level✅ 1m〜1M
Binance Futures✅ フル深度✅ Tick-level✅ 1m〜1M
OKX Spot✅ フル深度✅ Tick-level✅ 1m〜1M
OKX Swap/Futures✅ フル深度✅ Tick-level✅ 1m〜1M

環境準備

まずは必要なパッケージをインストールします。Python環境を前提とした実装例を続けます。

pip install tardis-client pandas requests websockets-json-logger

Binance Orderbook 歴史データ取得の実装

import requests
import pandas as pd
from datetime import datetime, timedelta

class TardisOrderbookFetcher:
    """Tardis.dev API 用于获取历史Orderbook数据"""
    
    BASE_URL = "https://api.tardis.dev/v1"
    
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        }
    
    def get_symbols(self, exchange: str) -> list:
        """获取指定交易所支持的交易对"""
        url = f"{self.BASE_URL}/exchanges/{exchange}/symbols"
        response = requests.get(url, headers=self.headers)
        response.raise_for_status()
        data = response.json()
        return [s['symbol'] for s in data.get('data', [])]
    
    def fetch_orderbook_replay(
        self,
        exchange: str,
        symbol: str,
        start_date: str,  # ISO format: "2025-01-01T00:00:00Z"
        end_date: str,
        limit: int = 100000
    ) -> pd.DataFrame:
        """
        获取指定时间范围的Orderbook快照数据
        
        Args:
            exchange: 交易所名称 (binance, okx)
            symbol: 交易对 (如 BTCUSDT)
            start_date: 开始时间
            end_date: 结束时间
            limit: 最大返回条数
        
        Returns:
            DataFrame 包含 bids, asks, timestamp 等字段
        """
        url = f"{self.BASE_URL}/replay"
        
        payload = {
            "exchange": exchange,
            "symbol": symbol,
            "startDate": start_date,
            "endDate": end_date,
            "channels": ["orderbook"],  # 只获取orderbook数据
            "limit": limit,
            "format": "pandas"  # 自动转换为pandas格式
        }
        
        response = requests.post(url, json=payload, headers=self.headers)
        response.raise_for_status()
        
        result = response.json()
        
        if result.get('data'):
            df = pd.DataFrame(result['data'])
            df['timestamp'] = pd.to_datetime(df['timestamp'])
            return df
        else:
            return pd.DataFrame()

使用例

if __name__ == "__main__": API_KEY = "YOUR_TARDIS_API_KEY" fetcher = TardisOrderbookFetcher(API_KEY) # 获取Binance BTCUSDT 2025年1月1日的数据 df = fetcher.fetch_orderbook_replay( exchange="binance", symbol="btcusdt", start_date="2025-01-01T00:00:00Z", end_date="2025-01-01T01:00:00Z", limit=50000 ) print(f"获取到 {len(df)} 条Orderbook记录") print(df.head())

OKX Orderbook 歴史データ取得の実装

import asyncio
import websockets
import json
import pandas as pd
from datetime import datetime

class OKXOrderbookWebSocket:
    """通过WebSocket实时获取OKX Orderbook数据"""
    
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.ws_url = "wss://ws.okx.com:8443/ws/v5/public"
        self.data_buffer = []
    
    async def subscribe_orderbook(self, symbol: str, depth: int = 400):
        """
        订阅OKX Orderbook实时数据
        
        Args:
            symbol: 交易对 (OKX格式: BTC-USDT-SWAP)
            depth: 档位数 (400 或 10)
        """
        subscribe_msg = {
            "op": "subscribe",
            "args": [{
                "channel": "books",
                "instId": symbol,
                "sz": str(depth)
            }]
        }
        
        async with websockets.connect(self.ws_url) as ws:
            await ws.send(json.dumps(subscribe_msg))
            print(f"已订阅: {symbol} 的Orderbook数据")
            
            async for message in ws:
                data = json.loads(message)
                if 'data' in data:
                    for item in data['data']:
                        snapshot = self._parse_orderbook(item)