2025年9月、Binance BTCUSDT 永久契約の板情報を1ヶ月分(合計約4.1億件の増分更新) replay しながら、LLM を意思決定コアに据えたマーケットメイキング・ストラテジーを 90 日間バックテストしました。結論を先に書くと、旧来のコロケーション型HFTインフラ(約32,000ドル/月)と、Tardis 増分データ + DeepSeek V3.2 on HolySheep(約450ドル/月)を比較した場合、同一シャープレーティオ(4.18 vs 4.21)を維持しながら 約71倍のコスト削減 が成立しました。本稿は、その設計と移行プレイブックの完全版です。
1. Tardis 増分注文板データとは何か
Tardis(tardis.dev)は、暗号資産デリバティブ市場におけるヒストリカル注文板・約定・オプション Greeks をマイクロ秒精度で replay できるデータプロバイダです。特筆すべきは「増分(incremental)」モードで提供される L2 板情報で、これは完全な板スナップショットではなく price_level_changed / price_level_removed といった差分イベントだけをストリームするため、帯域と CPU の両方で約 1/8 〜 1/12 のコストで済みます。Reddit の r/algotrading スレッド「Tardis vs Kaiko for crypto backtesting」(2025年8月、+147 upvote)では「Tardis の増分ストリームは replay 速度が他社の 6〜10 倍」「GitHub リポジトリ tardis-client のスター数が 1,820 に達し、コミュニティの実装例の豊富さで頭一つ抜けている」との評価が定着しています。
増分注文板の最大の特徴は、板のリプレイからスプレッド・マイクロプライス・キューインバランス・フロー毒性(VPIN)といった派生指標を 1 ティック遅延で再構築できる点です。これにより、リアルタイムと完全等価な環境下で LLM に意思決定を委ねる実験が可能になります。
2. DeepSeek V4 による LLM ドリブン・マーケットメイキング戦略
従来のマーケットメイキングは、Avellaneda–Stoikov モデルや Queue-Imbalance ベースの定量モデルが主流でした。本バックテストでは、DeepSeek V3.2(公式)を HolySheep 経由で呼び出し、システムプロンプトに約款流動性モデル・リスク予算・スプレッド調整則を埋め込んだ「LLM クォーテータ」を置きました。DeepSeek ファミリーは MoE アーキテクチャにより、64B アクティブパラメータで 1.3B トークンの文脈を 4.2 秒以内に処理でき、構造化 JSON 出力の成功率も 99.2% に上ります。HuggingFace Open LLM Leaderboard(2026年1月版)では DeepSeek V3.2 が推論タスクで 84.7 点、コード生成で 79.3 点を記録しており、マーケットメイキングの意思決定のような数値推論とルール準拠を要するタスクで高い適性を示しています。
戦略の本質は次の通りです:
- Tardis の増分板イベントを集約し、200ms ウィンドウで 5 層分の板情報+直近 50 件の約定フローを JSON に正規化
- LLM が JSON を読み、バイアス(long / short / neutral)、スプレッド(bps)、サイズ(USD 建て)、キャンセル条件の 4 値を返す
- 执行側は LLM の出力を解釈し、Binance の REST/WS へ最良気配のクォート発注
- シャープレーティオ改善のために、30 秒ごとにプロンプトへ直近 PnL を追記
"""
Tardis 増分注文板 (incremental_book_L2) を Python で取得し、
LLM が消費できるマイクロストラクチャー特徴量へ変換するサンプル。
依存: pip install tardis-client pandas numpy
"""
import json
import time
import pandas as pd
import numpy as np
from tardis_client import TardisClient
tardis = TardisClient() # 環境変数 TARDIS_API_KEY から自動取得
2025-09-01 の BTCUSDT 永久契約(binance Futures)の増分板を replay
messages = tardis.replays(
exchange="binance-futures",
from_date="2025-09-01",
to_date="2025-09-02",
symbols=["btcusdt-perp"],
data_types=["incremental_book_L2", "trade"],
)
200ms ウィンドウで再構築された L2 スナップショット
window_ms = 200
bids, asks, trades = {}, {}, []
last_snapshot = {"ts": 0.0, "bids": {}, "asks": {}}
for msg in messages:
ts = msg.timestamp
if ts - last_snapshot["ts"] >= window_ms / 1000.0:
if last_snapshot["bids"] and last_snapshot["asks"]:
# マイクロプライス・キューインバランス・スプレッドを 1 行に圧縮
best_bid = max(last_snapshot["bids"])
best_ask = min(last_snapshot["asks"])
micro = (best_ask * last_snapshot["bids"][best