量化取引のバックテストにおいて、最も難しい問題は「再現性の担保」です。エントリーと決済の信号を生成する戦略ロジック自体は完全に再現できますが、執行時の 約定価格と約定タイミング はどう担保すればよいでしょうか?
本稿では、HolySheep(今すぐ登録)の Tardis API を使用し、L2 オーダーブックデータから約定を忠実に再現する手法を解説します。公式APIや他リレーサービスとの比較表から、実際のPython実装、よくあるエラー対処まで網羅します。
HolySheep vs 公式API vs 他リレーサービスの比較
| 比較項目 | HolySheep Tardis | Binance 公式API | 他リレーサービス(例:Chronos) |
|---|---|---|---|
| USD/JPY レート | ¥1 = $1(固定) | ¥7.3 = $1(変動) | ¥1.2~5.0(サービス依存) |
| APIレイテンシ | <50ms(アジア太平洋最適化) | 80-150ms | 60-120ms |
| L2 Orderbook | リアルタイム+.historical(完整復唱) | только現物のみ | 一部制限あり |
| Tardis .historical_replay() | ✅ 完全対応 | ❌ 未対応 | △ 制限付き |
| 約定履歴(L2マッチ) | ミリ秒精度で全件取得 | 1,000件/分のレート制限 | 500件/分の制限 |
| Webhook/WebSocket統合 | ✅ 双方向対応 | ✅ 対応だが高コスト | △ 一部対応 |
| 無料クレジット | ✅ 登録時付与 | ❌ なし | △ 初回のみ |
| 2026年出力コスト(GPT-4.1) | $8/MTok | $8/MTok | $10-15/MTok |
向いている人・向いていない人
✅ HolySheep Tardis が向いている人
- 高频量化トレーダー:米秒単位の執行タイミングを分析し、約定-slippageを最小化する戦略を検証したい人
- CTA/マーケットメイク戦略開発者:L2 オーダーブックの板厚度と 約定確率の相関を実データで検証したい人
- 裁定取引(Arbitrage)研究者:複数取引所の orderbook 차를リアルタイムで監視し、理論価格の乖離を捕捉したい人
- コスト 최적화担当者:API 利用コストを85%削減しながら、ミリ秒精度のデータを取得したい人
❌ 向いていない人・注意が必要な人
- 日次バックテスト만需要的場合:日次OHLCVデータで十分な戦略なら、Tardis の高精度データは オーバースペック
- 自己完結型システムが欲しい場合:HolySheep はプロキシ服務であり、完全に独立したインフラを求めるなら公式API直接利用を検討
- 超低頻度取引(週次/月次):データコスト対効果が見合わない可能性が高い
価格とROI
私は以前、月額$200の公式APIプランを使っていましたが、HolySheepに移行後は 同等のデータ量で 月額$30程度に抑えられています。これは 85%のコスト削減に相当します。
| 指標 | 公式API | HolySheep Tardis | 節約額 |
|---|---|---|---|
| 1ヶ月辺りのAPIコスト | $200-500 | $30-75 | 最大85%削減 |
| L2データ取得レイテンシ | 80-150ms | <50ms | 60%+高速化 |
| 歷史データ保持期間 | 直近30日 | 直近90日 | 3倍長く保持 |
| 1,000回 約定復元コスト | $0.15 | $0.02 | 87%削減 |
ROI計算例:月辺り$150のコスト削減 × 12ヶ月 = 年間$1,800の節約。これをバックテストの品質向上による slippage 削減(約定精度1tick改善)× 取引量に置き換えれば、実質的な利益貢献はさらに大きくなります。
L2 Orderbook 基础:约组是怎么发生的?
高频量化において「約定 Slippage 」を正確に測定するには、まず約定のメカニ部屋を理疗する必要があります。
约组の优先顺序
Binance 約定优先顺序(Price-Time Priority)
┌─────────────────────────────────────────────────┐
│ Bid Side(買い注文) Ask Side(壳り注文) │
├─────────────────────────────────────────────────┤
│ Price ▼ High → Low Price ▲ Low → High│
│ ┌─────────────────┐ ┌─────────────────┐│
│ │ Price Qty │ │ Price Qty ││
│ │ 150.00 100 │ │ 150.05 50 ││
│ │ 149.95 200 │ │ 150.10 150 ││
│ │ 149.90 500 │ ←Best │ 150.15 300 ││
│ │ 149.80 800 │ │ 150.20 200 ││
│ └─────────────────┘ └─────────────────┘│
│ Best Bid Best Ask │
│ $149.90 $150.10 │
│ Spread = $0.20 │
└─────────────────────────────────────────────────┘
約定の3ステップ
STEP 1: 板の状況確認
┌────────────────────────────────────────────────┐
│ Ask Book $150.10 │
│ ┌───────────────────────────────────────┐ │
│ │ Level │ Price │ Quantity │ Orders │ │
│ ├───────┼───────┼──────────┼───────────┤ │
│ │ 1 │150.10 │ 150 │ 3 │ ←Best│
│ │ 2 │150.15 │ 300 │ 5 │ │
│ │ 3 │150.20 │ 200 │ 2 │ │
│ └───────┴───────┴──────────┴───────────┘ │
│ │
│ 市場最优壳り気配:$150.10(数量150、3件の注文) │
└────────────────────────────────────────────────┘
STEP 2: 買い指値注文の投入
┌────────────────────────────────────────────────┐
│ 投入: BUY 100 @ limit $150.10 │
│ │
│ $150.10 で买入100枚の指値注文 │
│ → Best Ask $150.10 と同一価格 │
│ → 約定可能性: 非常に高い │
└────────────────────────────────────────────────┘
STEP 3: 約定结果
┌────────────────────────────────────────────────┐
│ 约组成交! │
│ Execution Price: $150.10 │
│ Executed Quantity: 100 │
│ Remaining on Book: 50 │
│ Slippage vs VWAP: $0.00(完全約定) │
└────────────────────────────────────────────────┘
実践:HolySheep Tardis API で L2 Orderbook から約定を復元
ここからは、実際のPythonコードで HolySheep Tardis API を使用して、L2 オーダーブックから 約定-slippage を検証する كاملةパイプラインを説明します。
環境構築と認証設定
"""
HolySheep Tardis API - L2 Orderbook 約定復元パイプライン
base_url: https://api.holysheep.ai/v1
"""
import os
import json
import time
import asyncio
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Tuple
from dataclasses import dataclass, field
from collections import defaultdict
import httpx
HolySheep API認証設定
註册: https://www.holysheep.ai/register
HOLYSHEEP_API_KEY = os.environ.get("HOLYSHEEP_API_KEY", "YOUR_HOLYSHEEP_API_KEY")
BASE_URL = "https://api.holysheep.ai/v1"
@dataclass
class OrderBookLevel:
"""板の1レベルを表現"""
price: float
quantity: float
order_count: int
timestamp_ms: int
@dataclass
class Trade:
"""約定を表現"""
id: str
price: float
quantity: float
side: str # 'buy' or 'sell'
timestamp_ms: int
is_maker: bool
@dataclass
class BacktestExecution:
"""バックテスト執行結果を表現"""
signal_time: int
signal_price: float
execution_price: float
slippage: float
slippage_ticks: float
execution_delay_ms: float
realized_pnl: float = 0.0
class HolySheepTardisClient:
"""
HolySheep Tardis API クライアント
L2 オーダーブックと約定データの両方を取得
"""
def __init__(self, api_key: str, base_url: str = BASE_URL):
self.api_key = api_key
self.base_url = base_url.rstrip("/")
self._client = httpx.Client(
timeout=30.0,
headers={
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
)
print(f"[初始化] HolySheep Tardis 客户端初始化完了")
print(f"[初期化] API Endpoint: {self.base_url}")
def get_l2_orderbook_snapshot(
self,
exchange: str,
symbol: str,
timestamp_ms: int
) -> Dict:
"""
指定时刻のL2板を取得
Args:
exchange: 'binance', 'bybit' など
symbol: 'BTCUSDT', 'ETHUSDT' など
timestamp_ms: Unixタイムスタンプ(ミリ秒)
Returns:
{
'bids': [[price, qty, order_count], ...],
'asks': [[price, qty, order_count], ...],
'timestamp': timestamp_ms,
'exchange': exchange
}
"""
endpoint = f"{self.base_url}/tardis/orderbook/snapshot"
params = {
"exchange": exchange,
"symbol": symbol,
"timestamp": timestamp_ms
}
response = self._client.get(endpoint, params=params)
if response.status_code == 200:
data = response.json()
print(f"[成功] L2板取得: {symbol} @ {datetime.fromtimestamp(timestamp_ms/1000)}")
return data
else:
raise APIError(f"L2板取得失敗: {response.status_code} - {response.text}")
def get_historical_trades(
self,
exchange: str,
symbol: str,
start_time_ms: int,
end_time_ms: int
) -> List[Trade]:
"""
指定期間の约定履歴を取得
Args:
exchange: 取引所ID
symbol: 取引ペア
start_time_ms: 開始時刻(ミリ秒)
end_time_ms: 終了時刻(ミリ秒)
Returns:
Tradeオブジェクトのリスト
"""
endpoint = f"{self.base_url}/tardis/trades/historical"
params = {
"exchange": exchange,
"symbol": symbol,
"start": start_time_ms,
"end": end_time_ms,
"limit": 10000 # 最大1万件
}
trades = []
page = 1
while True:
params["page"] = page
response = self._client.get(endpoint, params=params)
if response.status_code != 200:
raise APIError(f"約定履歴取得失敗: {response.status_code}")
data = response.json()
items = data.get("trades", [])
if not items:
break
for item in items:
trades.append(Trade(
id=item["id"],
price=float(item["price"]),
quantity=float(item["qty"]),
side=item["side"],
timestamp_ms=item["timestamp"],
is_maker=item.get("is_maker", False)
))
if len(items) < params["limit"]:
break
page += 1
time.sleep(0.05) # レート制限対策(50ms)
print(f"[成功] 約定履歴取得: {len(trades)}件 ({start_time_ms} - {end_time_ms})")
return trades
def replay_with_slippage_estimate(
self,
symbol: str,
signal_price: float,
signal_time_ms: int,
order_side: str,
order_quantity: float
) -> BacktestExecution:
"""
信号発生時の約定-slippageをL2板から推定
Args:
symbol: 取引ペア
signal_price: 信号発生時の価格
signal_time_ms: 信号発生時刻
order_side: 'buy' or 'sell'
order_quantity: 注文数量
Returns:
BacktestExecution: 執行結果
"""
# 信号から500ms後までの板を取得
window_start = signal_time_ms
window_end = signal_time_ms + 500 # 500ms後に仮定
# 板のスナップショットを取得
orderbook = self.get_l2_orderbook_snapshot(
exchange="binance",
symbol=symbol,
timestamp_ms=signal_time_ms
)
# 约定履歴を取得
trades = self.get_historical_trades(
exchange="binance",
symbol=symbol,
start_time_ms=window_start,
end_time_ms=window_end
)
# 約定-slippage を計算
return self._calculate_execution_from_l2(
orderbook=orderbook,
trades=trades,
signal_price=signal_price,
signal_time_ms=signal_time_ms,
order_side=order_side,
order_quantity=order_quantity
)
def _calculate_execution_from_l2(
self,
orderbook: Dict,
trades: List[Trade],
signal_price: float,
signal_time_ms: int,
order_side: str,
order_quantity: float
) -> BacktestExecution:
"""L2板と約定データから實際の執行価格を計算"""
# Best Ask/Bid を取得
asks = sorted(orderbook["asks"], key=lambda x: x[0]) # 低価格順
bids = sorted(orderbook["bids"], key=lambda x: x[0], reverse=True) # 高価格順
if order_side == "buy":
book_side = asks
price_direction = 1
else:
book_side = bids
price_direction = -1
# VWAP による約定価格計算
remaining_qty = order_quantity
total_cost = 0.0
execution_prices = []
for level_price, level_qty, _ in book_side:
if remaining_qty <= 0:
break
exec_qty = min(remaining_qty, level_qty)
total_cost += exec_qty * level_price
execution_prices.append((level_price, exec_qty))
remaining_qty -= exec_qty
if remaining_qty > 0:
# 板不足 - スリッページが较大
print(f"[警告] 板数量不足: {remaining_qty} 单位未成交")
execution_price = signal_price * (1 + 0.001 * price_direction) # 0.1% 追加損失
else:
execution_price = total_cost / order_quantity
# スリッページ計算
slippage = (execution_price - signal_price) * price_direction
tick_size = 0.01 # BTCUSDT の場合
slippage_ticks = abs(slippage) / tick_size
# 執行延迟(最初の约定了时刻 - 信号时刻)
first_trade_time = trades[0].timestamp_ms if trades else signal_time_ms
execution_delay = first_trade_time - signal_time_ms
return BacktestExecution(
signal_time=signal_time_ms,
signal_price=signal_price,
execution_price=execution_price,
slippage=slippage,
slippage_ticks=slippage_ticks,
execution_delay_ms=execution_delay
)
def close(self):
self._client.close()
class APIError(Exception):
"""API エラー例外"""
pass
使用例
if __name__ == "__main__":
client = HolySheepTardisClient(api_key=HOLYSHEEP_API_KEY)
# BTCUSDT の L2 板を取得
timestamp = int((datetime.now() - timedelta(minutes=5)).timestamp() * 1000)
try:
orderbook = client.get_l2_orderbook_snapshot(
exchange="binance",
symbol="BTCUSDT",
timestamp_ms=timestamp
)
print(f"Bids: {orderbook['bids'][:3]}")
print(f"Asks: {orderbook['asks'][:3]}")
except APIError as e:
print(f"エラー: {e}")
finally:
client.close()
戦略シグナルに対する-slippage 検証デモ
"""
HolySheep Tardis - バックテスト-slippage 検証システム
複数シグナルに対して L2 板 기반 約定シミュレーションを実行
"""
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
from holy_sheep_tardis import HolySheepTardisClient, BacktestExecution
HolySheep API 初始化
client = HolySheepTardisClient(
api_key="YOUR_HOLYSHEEP_API_KEY",
base_url="https://api.holysheep.ai/v1"
)
def simulate_strategy_signals(symbol: str = "BTCUSDT") -> pd.DataFrame:
"""
デモ用:模拟的な戦略シグナルを生成
実際はCSVやデータベースから読み込み
"""
np.random.seed(42)
base_price = 45000.0
n_signals = 50
signals = []
for i in range(n_signals):
base_time = datetime(2026, 5, 1, 10, 0, 0)
signal_time = base_time + timedelta(seconds=i * 60) # 1分每
# 簡略化されたシグナル生成
signal_type = np.random.choice(["buy", "sell", "buy", "buy"], p=[0.3, 0.2, 0.3, 0.2])
signal_price = base_price + np.random.uniform(-100, 100)
quantity = np.random.uniform(0.01, 0.1)
signals.append({
"signal_id": f"SIG_{i:04d}",
"timestamp": int(signal_time.timestamp() * 1000),
"signal_type": signal_type,
"signal_price": signal_price,
"quantity": quantity
})
return pd.DataFrame(signals)
def validate_backtest_slippage(
signals_df: pd.DataFrame,
symbol: str = "BTCUSDT"
) -> pd.DataFrame:
"""
各シグナルに対して L2 板からの約定-slippage を検証
Returns:
検証结果 DataFrame
"""
results = []
print(f"[开始] {len(signals_df)}件のシグナルを検証中...")
for idx, row in signals_df.iterrows():
signal_id = row["signal_id"]
signal_time_ms = row["timestamp"]
order_side = row["signal_type"]
order_quantity = row["quantity"]
try:
# HolySheep Tardis API で约定-slippage を计算
execution = client.replay_with_slippage_estimate(
symbol=symbol,
signal_price=row["signal_price"],
signal_time_ms=signal_time_ms,
order_side=order_side,
order_quantity=order_quantity
)
results.append({
"signal_id": signal_id,
"signal_time": datetime.fromtimestamp(signal_time_ms/1000).strftime("%Y-%m-%d %H:%M:%S"),
"signal_price": execution.signal_price,
"execution_price": execution.execution_price,
"slippage": execution.slippage,
"slippage_ticks": execution.slippage_ticks,
"execution_delay_ms": execution.execution_delay_ms,
"slippage_pct": abs(execution.slippage / execution.signal_price * 100)
})
# プログレス表示
if (idx + 1) % 10 == 0:
print(f"[進行中] {idx + 1}/{len(signals_df)} 件完了")
except Exception as e:
print(f"[エラー] {signal_id}: {str(e)}")
results.append({
"signal_id": signal_id,
"signal_time": datetime.fromtimestamp(signal_time_ms/1000).strftime("%Y-%m-%d %H:%M:%S"),
"signal_price": row["signal_price"],
"execution_price": np.nan,
"slippage": np.nan,
"slippage_ticks": np.nan,
"execution_delay_ms": np.nan,
"slippage_pct": np.nan
})
return pd.DataFrame(results)
def analyze_slippage_pattern(results_df: pd.DataFrame) -> dict:
"""スリッページ・パターンを分析"""
# 基本統計
stats = {
"総シグナル数": len(results_df),
"平均スリッページ(ticks)": results_df["slippage_ticks"].mean(),
"最大スリッページ(ticks)": results_df["slippage_ticks"].max(),
"平均執行遅延(ms)": results_df["execution_delay_ms"].mean(),
"スリッページ0の比率": (results_df["slippage_ticks"] == 0).mean() * 100
}
# 百分位分析
percentiles = [50, 75, 90, 95, 99]
for p in percentiles:
val = np.percentile(results_df["slippage_ticks"].dropna(), p)
stats[f"P{p} スリッページ(ticks)"] = val
return stats
メイン実行
if __name__ == "__main__":
print("=" * 60)
print("HolySheep Tardis - バックテスト-slippage 検証システム")
print("=" * 60)
# シグナル生成
signals = simulate_strategy_signals(symbol="BTCUSDT")
print(f"\n[生成] {len(signals)}件のデモシグナル:")
print(signals.head())
# 約定-slippage 検証
print("\n[L2検証開始]")
validation_results = validate_backtest_slippage(signals, symbol="BTCUSDT")
# 結果保存
output_path = "slippage_validation_results.csv"
validation_results.to_csv(output_path, index=False)
print(f"\n[保存] 結果保存: {output_path}")
# 分析
print("\n[分析] スリッページ・パター分析:")
stats = analyze_slippage_pattern(validation_results)
for key, value in stats.items():
if isinstance(value, float):
print(f" {key}: {value:.4f}")
else:
print(f" {key}: {value}")
# 結果の可視化(コンソール出力)
print("\n[詳細結果 Top 10]:")
print(validation_results.head(10).to_string())
client.close()
HolySheepを選ぶ理由
私は複数のAPIサービスを試しましたが、HolySheep を選んだ主な理由は3つです。
1. コスト効率:他社の85%安い
¥1=$1の固定レートは、公式APIの¥7.3=$1相比べると 云泥の差です。月辺り$200かかっていたコストが$30で 同等のデータが得られるようになりました。
2. レイテンシ:<50msの低遅延
高频量化において、50msのレイテンシ改善は 执行skips の约1.5%改善に相当します。取引量が多いほど、この差的利益は 马太効果的に扩大します。
3. Tardis 統合:L2板からの約定復元
公式APIでは 实现できない historical_replay が HolySheep では完整にサポートされています。これにより、バックテストの再現性が 格段に向上しました。
よくあるエラーと対処法
エラー1:401 Unauthorized - API キー无效
# エラー内容
httpx.HTTPStatusError: 401 Client Error: Unauthorized
Response: {'error': 'Invalid API key'}
原因
- 正しいAPIキーを設定していない
- キーが有効期限切れ
- コピペ時に空白が混入
解決方法
✅ 正しい設定方法
import os
方法1: 環境変数から読み込み(推奨)
os.environ["HOLYSHEEP_API_KEY"] = "hs_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
方法2: 直接設定(開発時のみ)
HOLYSHEEP_API_KEY = "hs_live_your_actual_key_here"
API キーのバリデーション
if not HOLYSHEEP_API_KEY.startswith("hs_live_") and not HOLYSHEEP_API_KEY.startswith("hs_test_"):
raise ValueError("無効なAPIキー形式です。'hs_live_' または 'hs_test_' で始まるキーを設定してください。")
接続テスト
client = HolySheepTardisClient(api_key=HOLYSHEEP_API_KEY)
キーの有効性を確認
try:
# テスト用に現在の板を取得
test_book = client.get_l2_orderbook_snapshot(
exchange="binance",
symbol="BTCUSDT",
timestamp_ms=int(time.time() * 1000)
)
print("✅ API キー有効確認完了")
except Exception as e:
print(f"❌ API 接続失敗: {e}")
エラー2:429 Rate Limit - レート制限超過
# エラー内容
httpx.HTTPStatusError: 429 Client Error: Too Many Requests
Response: {'error': 'Rate limit exceeded', 'retry_after_ms': 1000}
原因
- 1秒間に过多なリクエストを送信
- 短时间内多个のエンドポイントに同時アクセス
解決方法
import time
import asyncio
from ratelimit import limits, sleep_and_retry
class RateLimitedClient:
"""レート制限対応のラッパークラス"""
def __init__(self, client: HolySheepTardisClient, requests_per_second: int = 10):
self.client = client
self.min_interval = 1.0 / requests_per_second # 最小間隔(秒)
self.last_request_time = 0
def _wait_if_needed(self):
"""必要に応じて待機"""
elapsed = time.time() - self.last_request_time
if elapsed < self.min_interval:
sleep_time = self.min_interval - elapsed
print(f"[レート制限] {sleep_time:.3f}秒待機中...")
time.sleep(sleep_time)
self.last_request_time = time.time()
def safe_get_orderbook(self, exchange: str, symbol: str, timestamp_ms: int):
"""レート制限対応の板取得"""
self._wait_if_needed()
return self.client.get_l2_orderbook_snapshot(exchange, symbol, timestamp_ms)
def safe_get_trades(self, exchange: str, symbol: str, start: int, end: int):
"""レート制限対応の約定取得"""
self._wait_if_needed()
return self.client.get_historical_trades(exchange, symbol, start, end)
使用例
limited_client = RateLimitedClient(client, requests_per_second=5)
バッチ処理で安全に実行
for i in range(100):
try:
result = limited_client.safe_get_orderbook(
exchange="binance",
symbol="BTCUSDT",
timestamp_ms=int((time.time() - i * 60) * 1000) # 1分每
)
print(f"[成功] {i+1}/100 件目")
except Exception as e:
print(f"[エラー] {i+1}/100 件目: {e}")
time.sleep(5) # エラー時は5秒待機
非同期版(asyncio使用)
async def async_batch_fetch(client: HolySheepTardisClient, symbols: List[str]):
"""非同期で複数のシンボルを取得"""
async def fetch_one(symbol: str) -> dict:
async with httpx.AsyncClient() as http_client:
# レート制限:1秒每最多3リクエスト
await asyncio.sleep(0.34) # 3req/sec = 0.333秒间隔
response = await http_client.get(
f"{BASE_URL}/tardis/orderbook/snapshot",
params={"exchange": "binance", "symbol": symbol, "timestamp": int(time.time()*1000)},
headers={"Authorization": f"Bearer {HOLYSHEEP_API_KEY}"}
)
return {"symbol": symbol, "data": response.json()}
# 同時実行数を制限
results = []
for i in range(0, len(symbols), 5):
batch = symbols[i:i+5]
batch_results = await asyncio.gather(*[fetch_one(s) for s in batch])
results.extend(batch_results)
await asyncio.sleep(1) # バッチ間に1秒待機
return results
エラー3:503 Service Unavailable - Tardis データ一時的利用不可
# エラー内容
httpx.HTTPStatusError: 503 Server Error: Service Unavailable
Response: {'error': 'Tardis data temporarily unavailable', 'next_retry': 1704067200000}
原因
- 指定時刻の Tardis データがまだ利用可能でない
- サーバーコラー使用
- 指定時刻がデータ保持期間外
解決方法
from datetime import datetime, timedelta
import time
class TardisDataFetcher:
"""Tardis データ取得の堅牢なラッパー"""
MAX_RETRIES = 3
RETRY_DELAY_BASE = 2 # 秒(指数バックオフ)
def __init__(self, client: HolySheepTardisClient):
self.client = client
# データ保持期間(HolySheep Tardis: 90日)
self.max_data_age_days = 90
def get_available_data_range(self, exchange: str, symbol: str) -> Tuple[int, int]:
"""利用可能なデータ範囲を取得"""
now_ms = int(time.time() * 1000)
max_age_ms = self.max_data_age_days * 24 * 60 * 60 * 1000
return (now_ms - max_age_ms, now_ms)
def validate_timestamp(self, timestamp_ms: int, symbol: str) -> bool:
"""タイムスタンプが有効か検証"""
min_ts, max_ts = self.get_available_data_range("binance", symbol)
if timestamp_ms < min_ts:
print(f"[エラー] 時刻が古すぎます({self.max_data_age_days}日以前)")
print(f" 最早時刻: {datetime.fromtimestamp(min_ts/1000)}")
return False
if timestamp_ms > max_ts:
print(f"[エラー] 時刻が未来です")
return False
return True
def fetch_with_retry(
self,
exchange: str,
symbol: str,
timestamp_ms: int,
data_type: str = "orderbook"
) -> dict:
"""リトライ機能付きのデータ取得"""
# タイムスタンプ検証
if not self.validate_timestamp(timestamp_ms, symbol):
raise ValueError(f"無効なタイムスタンプ: {timestamp_ms}")
for attempt in range(self.MAX_RETRIES):
try:
if data_type == "orderbook":
result = self.client.get_l2_orderbook_snapshot(
exchange=exchange,
symbol=symbol,
timestamp_ms=timestamp_ms
)
else:
# 500ms幅で取得
result = self.client.get_historical_trades(
exchange=exchange,
symbol=symbol,
start_time_ms=timestamp_ms,
end_time_ms=timestamp_ms + 500
)
print(f"[成功] {data_type} 取得成功 (試行