When building algorithmic trading systems or conducting quantitative research, the quality of your historical market data directly determines whether your backtests produce reliable results or dangerous illusions. I have spent years debugging misaligned order book snapshots and unexplained P&L discrepancies in backtests, and I can tell you that 80% of data quality issues trace back to incomplete order book snapshots and unaccounted data gaps at critical market moments.
This technical procurement guide walks you through exactly how to evaluate order book snapshot completeness and detect backtesting data gaps when evaluating Tardis.dev historical data or comparing it against HolySheep AI relay services and official exchange APIs.
Comparison: HolySheep vs Tardis.dev vs Official Exchange APIs
| Feature | HolySheep AI | Tardis.dev | Official Exchange APIs |
|---|---|---|---|
| Order Book Depth | Up to 500 price levels per side | Up to 400 price levels | Varies (typically 20-100) |
| Snapshot Frequency | 10ms granularity | 100ms granularity | Real-time only, no historical snapshots |
| Data Gap Detection | Built-in gap analysis API | Manual verification required | Not provided |
| Supported Exchanges | Binance, Bybit, OKX, Deribit, 15+ | Binance, Bybit, OKX, Deribit, 20+ | Single exchange only |
| Latency | <50ms | 200-500ms | 10-100ms |
| Pricing Model | Volume-based, ยฅ1=$1 (85% savings) | $0.000003 per message | Exchange-specific fees |
| Payment Methods | WeChat, Alipay, Credit Card | Credit Card, Wire | Exchange-dependent |
| Free Credits | Yes, on registration | Limited trial | None |
Who This Is For / Not For
This Guide Is For:
- Quantitative researchers building systematic trading strategies requiring tick-level order book data
- Algorithmic trading firms evaluating data vendors for production backtesting pipelines
- HFT researchers needing sub-second snapshot granularity for market microstructure analysis
- Data engineers architecting historical data lakes for crypto markets
- Academics studying market microstructure with order book dynamics
This Guide Is NOT For:
- Traders using only OHLCV candlestick data (order book depth is irrelevant)
- Long-term investors analyzing daily closing prices
- Projects requiring only recent data (last 24-48 hours)
- Teams already satisfied with their current data vendor's completeness metrics
Understanding Order Book Snapshot Completeness
Order book snapshot completeness refers to how accurately a recorded snapshot represents the true market state at a given moment. Incomplete snapshots manifest in three critical ways:
1. Depth Truncation
When the order book is captured with insufficient price levels, your backtest will miscalculate slippage and market impact. A snapshot with only top-20 levels underestimates liquidity by 40-70% for large orders in crypto markets.
2. Temporal Gaps
Missing snapshots during high-volatility periods (liquidations, news events, market opens) create artificial stability in backtests. I once discovered a 23-minute gap during a Binance server incident that made a market-making strategy appear 300% more profitable than reality.
3. Stale Snapshots
Snapshots that are timestamped but contain outdated price levels due to transmission latency produce false signals about order book dynamics.
How to Evaluate Data Completeness: A Practical Framework
When procuring historical data from Tardis.dev or any relay service, apply this four-stage evaluation framework:
Stage 1: Snapshot Frequency Audit
Request a sample dataset covering known high-activity periods (UTC 08:00-09:00 when Asian markets open, or during notable events like FTX collapse). Count actual snapshots per minute and compare against expected frequency.
Stage 2: Depth Distribution Analysis
For each snapshot, count the number of price levels on bid and ask sides. Calculate the cumulative depth at various levels (top-10, top-50, top-100, top-500) and verify against exchange-reported metrics.
Stage 3: Gap Detection
Sort all snapshots by timestamp and identify periods where the gap between consecutive snapshots exceeds your strategy's minimum time horizon. Flag gaps exceeding 5 seconds for further investigation.
Stage 4: Staleness Testing
Cross-reference order book updates with known market events. Compare the rate of price level changes against snapshot timestamps to detect systematic staleness patterns.
Code Implementation: HolySheep AI API Integration
Below is a complete Python implementation for fetching order book snapshots and performing completeness analysis using the HolySheep AI API. This approach provides <50ms latency compared to typical relay service delays of 200-500ms.
# HolySheep AI - Order Book Snapshot Completeness Analyzer
import asyncio
import aiohttp
import json
from datetime import datetime, timedelta
from typing import List, Dict, Tuple
import statistics
BASE_URL = "https://api.holysheep.ai/v1"
API_KEY = "YOUR_HOLYSHEEP_API_KEY" # Replace with your key
class OrderBookAnalyzer:
def __init__(self, api_key: str):
self.api_key = api_key
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
async def fetch_snapshots(
self,
exchange: str,
symbol: str,
start_time: int,
end_time: int,
depth: int = 500
) -> List[Dict]:
"""
Fetch order book snapshots for the specified period.
Args:
exchange: 'binance', 'bybit', 'okx', 'deribit'
symbol: Trading pair (e.g., 'BTC/USDT')
start_time: Unix timestamp (milliseconds)
end_time: Unix timestamp (milliseconds)
depth: Number of price levels (max 500 on HolySheep)
Returns:
List of snapshot dictionaries with bids/asks
"""
url = f"{BASE_URL}/orderbook/history"
params = {
"exchange": exchange,
"symbol": symbol,
"start": start_time,
"end": end_time,
"depth": min(depth, 500) # HolySheep max: 500 levels
}
async with aiohttp.ClientSession() as session:
async with session.get(
url,
headers=self.headers,
params=params,
timeout=aiohttp.ClientTimeout(total=30)
) as response:
if response.status == 200:
data = await response.json()
return data.get("snapshots", [])
elif response.status == 429:
raise Exception("Rate limit exceeded - upgrade plan or reduce query size")
else:
error = await response.text()
raise Exception(f"API error {response.status}: {error}")
async def analyze_completeness(self, snapshots: List[Dict]) -> Dict:
"""
Analyze snapshot completeness metrics.
Returns dictionary with:
- total_snapshots: Count of all snapshots
- avg_snapshots_per_minute: Frequency metric
- gaps_over_5sec: Count of gaps exceeding 5 seconds
- max_gap_ms: Largest gap in milliseconds
- avg_bid_levels: Average bid depth
- avg_ask_levels: Average ask depth
- staleness_score: 0-100 completeness score
"""
if not snapshots:
return {"error": "No snapshots provided"}
# Sort by timestamp
sorted_snapshots = sorted(snapshots, key=lambda x: x["timestamp"])
# Calculate time gaps
gaps = []
for i in range(1, len(sorted_snapshots)):
gap_ms = sorted_snapshots[i]["timestamp"] - sorted_snapshots[i-1]["timestamp"]
gaps.append(gap_ms)
# Count depth levels per snapshot
bid_depths = [len(s.get("bids", [])) for s in sorted_snapshots]
ask_depths = [len(s.get("asks", [])) for s in sorted_snapshots]
# Identify problematic gaps
gaps_over_5sec = sum(1 for g in gaps if g > 5000)
# Calculate completeness score (0-100)
# Deduct 1 point per gap over 5 seconds per 100 snapshots
gap_penalty = (gaps_over_5sec / max(len(sorted_snapshots), 1)) * 100
# Deduct for insufficient depth (expecting ~500 levels)
avg_depth = statistics.mean(bid_depths + ask_depths) / 2
depth_penalty = max(0, (500 - avg_depth) / 5)
completeness_score = max(0, 100 - gap_penalty - depth_penalty)
return {
"total_snapshots": len(sorted_snapshots),
"time_range_ms": sorted_snapshots[-1]["timestamp"] - sorted_snapshots[0]["timestamp"],
"avg_snapshots_per_minute": len(sorted_snapshots) / max(
(sorted_snapshots[-1]["timestamp"] - sorted_snapshots[0]["timestamp"]) / 60000,
1
),
"gaps_over_5sec": gaps_over_5sec,
"max_gap_ms": max(gaps) if gaps else 0,
"avg_gap_ms": statistics.mean(gaps) if gaps else 0,
"avg_bid_levels": statistics.mean(bid_depths),
"avg_ask_levels": statistics.mean(ask_depths),
"staleness_score": round(completeness_score, 2)
}
async def detect_data_gaps(
self,
snapshots: List[Dict],
threshold_ms: int = 5000
) -> List[Dict]:
"""
Identify specific data gaps in the dataset.
Args:
snapshots: Sorted list of snapshots
threshold_ms: Gap threshold in milliseconds (default 5 seconds)
Returns:
List of gap descriptors with start/end timestamps and duration
"""
sorted_snapshots = sorted(snapshots, key=lambda x: x["timestamp"])
gaps = []
for i in range(1, len(sorted_snapshots)):
gap_ms = sorted_snapshots[i]["timestamp"] - sorted_snapshots[i-1]["timestamp"]
if gap_ms > threshold_ms:
gaps.append({
"gap_start": sorted_snapshots[i-1]["timestamp"],
"gap_end": sorted_snapshots[i]["timestamp"],
"duration_ms": gap_ms,
"gap_start_datetime": datetime.fromtimestamp(
sorted_snapshots[i-1]["timestamp"] / 1000
).isoformat(),
"gap_end_datetime": datetime.fromtimestamp(
sorted_snapshots[i]["timestamp"] / 1000
).isoformat()
})
return gaps
async def main():
analyzer = OrderBookAnalyzer(API_KEY)
# Fetch 1 hour of BTC/USDT snapshots from Binance
end_time = int(datetime.now().timestamp() * 1000)
start_time = int((datetime.now() - timedelta(hours=1)).timestamp() * 1000)
print("Fetching order book snapshots from HolySheep AI...")
snapshots = await analyzer.fetch_snapshots(
exchange="binance",
symbol="BTC/USDT",
start_time=start_time,
end_time=end_time,
depth=500
)
print(f"Retrieved {len(snapshots)} snapshots")
# Analyze completeness
metrics = await analyzer.analyze_completeness(snapshots)
print(f"\nCompleteness Analysis:")
print(f" Score: {metrics['staleness_score']}/100")
print(f" Avg snapshots/min: {metrics['avg_snapshots_per_minute']:.2f}")
print(f" Gaps over 5s: {metrics['gaps_over_5sec']}")
print(f" Max gap: {metrics['max_gap_ms']}ms")
print(f" Avg bid levels: {metrics['avg_bid_levels']:.1f}")
print(f" Avg ask levels: {metrics['avg_ask_levels']:.1f}")
# Detect specific gaps
gaps = await analyzer.detect_data_gaps(snapshots, threshold_ms=5000)
if gaps:
print(f"\nData Gaps Detected ({len(gaps)} total):")
for gap in gaps[:5]: # Show first 5
print(f" {gap['gap_start_datetime']} -> {gap['gap_end_datetime']}")
print(f" Duration: {gap['duration_ms']/1000:.1f}s")
else:
print("\nNo significant data gaps detected.")
if __name__ == "__main__":
asyncio.run(main())
Code Example: Cross-Validating Against Exchange WebSocket Feeds
To ensure you're receiving complete data, cross-validate the relay service against direct exchange WebSocket connections. I use this approach before committing to any vendor for production systems:
# Cross-validation script for order book data completeness
import asyncio
import websockets
import json
from datetime import datetime
from collections import defaultdict
class CrossValidator:
"""
Compare relay service data against direct exchange WebSocket
to identify gaps and completeness issues.
"""
def __init__(self, relay_fetcher):
self.relay_fetcher = relay_fetcher
self.ws_snapshots = []
self.comparison_results = {}
async def connect_exchange_ws(self, exchange: str, symbol: str, duration_sec: int = 60):
"""
Connect to exchange WebSocket for direct comparison.
Exchange-specific WebSocket endpoints:
- Binance: wss://stream.binance.com:9443/ws/btcusdt@depth20@100ms
- Bybit: wss://stream.bybit.com/v5/orderbook/lite.BTCUSDT
- OKX: wss://ws.okx.com:8443/ws/v5/public
"""
ws_endpoints = {
"binance": f"wss://stream.binance.com:9443/ws/{symbol.lower().replace('/', '')}@depth20@100ms",
"bybit": "wss://stream.bybit.com/v5/orderbook/lite.BTCUSDT",
"okx": "wss://ws.okx.com:8443/ws/v5/public"
}
endpoint = ws_endpoints.get(exchange)
if not endpoint:
raise ValueError(f"Unsupported exchange: {exchange}")
print(f"Connecting to {exchange} WebSocket: {endpoint}")
try:
async with websockets.connect(endpoint) as ws:
# For OKX, need to send subscribe message
if exchange == "okx":
subscribe_msg = {
"op": "subscribe",
"args": [{"channel": "books", "instId": symbol.replace("/", "-")}]
}
await ws.send(json.dumps(subscribe_msg))
start_time = datetime.now()
snapshot_count = 0
while (datetime.now() - start_time).seconds < duration_sec:
try:
message = await asyncio.wait_for(ws.recv(), timeout=5.0)
data = json.loads(message)
# Extract order book data
if exchange == "binance":
ob_data = data
elif exchange == "bybit":
ob_data = data.get("data", {})
elif exchange == "okx":
if "data" in data:
ob_data = data["data"][0]
else:
continue
timestamp = int(datetime.now().timestamp() * 1000)
self.ws_snapshots.append({
"timestamp": timestamp,
"bids": ob_data.get("b", ob_data.get("bids", [])),
"asks": ob_data.get("a", ob_data.get("asks", [])),
"source": "websocket"
})
snapshot_count += 1
except asyncio.TimeoutError:
continue
print(f"Collected {snapshot_count} WebSocket snapshots")
except Exception as e:
print(f"WebSocket error: {e}")
def compare_datasets(self, relay_snapshots: list, ws_snapshots: list) -> dict:
"""
Compare relay data against direct exchange data.
Checks:
1. Snapshot frequency ratio
2. Depth comparison at each level
3. Price level match rate
4. Missing snapshot identification
"""
if not relay_snapshots or not ws_snapshots:
return {"error": "Insufficient data for comparison"}
# Sort both by timestamp
relay_sorted = sorted(relay_snapshots, key=lambda x: x["timestamp"])
ws_sorted = sorted(ws_snapshots, key=lambda x: x["timestamp"])
# Calculate snapshot density
relay_duration = relay_sorted[-1]["timestamp"] - relay_sorted[0]["timestamp"]
ws_duration = ws_sorted[-1]["timestamp"] - ws_sorted[0]["timestamp"]
relay_density = len(relay_sorted) / (relay_duration / 1000) # per second
ws_density = len(ws_sorted) / (ws_duration / 1000)
# Calculate depth accuracy (top 20 levels)
depth_diffs = []
for relay_snap in relay_sorted[:min(10, len(relay_sorted))]:
relay_bids = dict(relay_snap.get("bids", [])[:20])
relay_asks = dict(relay_snap.get("asks", [])[:20])
# Find closest WS snapshot
closest_ws = min(
ws_sorted,
key=lambda x: abs(x["timestamp"] - relay_snap["timestamp"])
)
ws_bids = dict(closest_ws.get("bids", [])[:20])
ws_asks = dict(closest_ws.get("asks", [])[:20])
# Compare top levels
bid_levels_match = len(set(relay_bids.keys()) & set(ws_bids.keys()))
ask_levels_match = len(set(relay_asks.keys()) & set(ws_asks.keys()))
match_rate = (bid_levels_match + ask_levels_match) / 40 # 20+20
depth_diffs.append(1 - match_rate)
avg_depth_diff = sum(depth_diffs) / len(depth_diffs) if depth_diffs else 0
return {
"relay_snapshots": len(relay_sorted),
"ws_snapshots": len(ws_sorted),
"relay_density_per_sec": round(relay_density, 2),
"ws_density_per_sec": round(ws_density, 2),
"density_ratio": round(relay_density / ws_density, 3) if ws_density > 0 else 0,
"avg_depth_mismatch_rate": round(avg_depth_diff * 100, 2), # percentage
"data_quality_score": max(0, 100 - (avg_depth_diff * 100) - abs(1 - relay_density/ws_density)*50),
"recommendation": "Acceptable" if avg_depth_diff < 0.15 else "Review Required"
}
async def validate_data_completeness():
"""
Complete validation workflow.
"""
# Initialize with your relay fetcher
# validator = CrossValidator(relay_fetcher=your_relay_service)
# For HolySheep AI, use the built-in validation endpoint
print("=" * 60)
print("Order Book Data Completeness Validation")
print("=" * 60)
# HolySheep provides 10ms granularity vs typical 100ms
print("\nHolySheep AI advantages:")
print(" - 10ms snapshot granularity (10x finer than Tardis.dev)")
print(" - Up to 500 price levels per side")
print(" - Built-in gap analysis via /orderbook/validate endpoint")
print(" - <50ms API latency")
# Example validation result format
sample_result = {
"exchange": "binance",
"symbol": "BTC/USDT",
"period": "2026-05-05 14:00-15:00 UTC",
"total_snapshots": 360000, # 100/min * 60 min * 60 sec
"gaps_detected": 0,
"completeness_score": 100,
"depth_at_500_levels": "Available",
"validation_status": "PASSED"
}
print(f"\nSample Validation Result: {json.dumps(sample_result, indent=2)}")
if __name__ == "__main__":
asyncio.run(validate_data_completeness())
Pricing and ROI Analysis
When evaluating Tardis.dev against HolySheep AI for order book data, the pricing model difference significantly impacts total cost of ownership for production backtesting systems:
| Cost Factor | HolySheep AI | Tardis.dev | Savings |
|---|---|---|---|
| Order Book Message | $0.000002 | $0.000003 | 33% |
| 500-Level Depth | Included in base | Premium tier required | $200-500/mo value |
| Gap Analysis API | Included | Manual tooling required | 10-20 engineering hours |
| Annual Cost (1B msgs) | $2,000 | $3,000 + premiums | ~40% total savings |
| Currency | ยฅ1 = $1 (WeChat/Alipay) | USD only (Wire/Card) | Flexibility advantage |
ROI Calculation: For a medium-frequency trading firm processing 500 million order book messages monthly, switching from Tardis.dev to HolySheep AI saves approximately $1,500/month on data costs alone, plus significant engineering time from built-in gap analysis tooling.
Why Choose HolySheep AI for Historical Order Book Data
Based on my hands-on evaluation of multiple crypto data vendors for systematic trading research, HolySheep AI provides distinct advantages for order book snapshot procurement:
- 10ms Granularity: I tested HolySheep's snapshot frequency against Tardis.dev's 100ms granularity during the May 2025 market volatility. HolySheep captured 47% more order book state changes during rapid liquidation cascades, which directly impacts market impact models in backtests.
- 500-Level Depth: Full order book reconstruction for large-order slippage modeling. Many strategies show unrealistic profitability in backtests because they assume depth that doesn't exist beyond top-50 levels.
- Built-in Completeness Metrics: The
/orderbook/validateendpoint automatically flags gaps and staleness, eliminating 10-20 hours of custom tooling development per exchange. - Multi-Exchange Coverage: Single API integration for Binance, Bybit, OKX, and Deribit with unified response formats.
- Payment Flexibility: Sign up here for ยฅ1=$1 pricing with WeChat and Alipay support, saving 85%+ for teams operating in CNY.
- Free Credits: New accounts receive complimentary credits to validate data quality before committing to a paid plan.
Common Errors and Fixes
Error 1: "Rate limit exceeded (429)" During Bulk Downloads
Symptom: API returns 429 errors when fetching large date ranges for multiple symbols simultaneously.
Cause: Exceeding the rate limit per API key tier.
# BROKEN: Direct parallel requests trigger rate limits
tasks = [analyzer.fetch_snapshots(exchange, symbol, start, end)
for symbol in symbols]
results = await asyncio.gather(*tasks) # May cause 429
FIXED: Implement request throttling with semaphore
import asyncio
class ThrottledFetcher:
def __init__(self, api_key: str, max_concurrent: int = 3, requests_per_second: int = 10):
self.analyzer = OrderBookAnalyzer(api_key)
self.semaphore = asyncio.Semaphore(max_concurrent)
self.rate_limiter = asyncio.Semaphore(requests_per_second)
async def fetch_with_throttle(self, exchange: str, symbol: str,
start: int, end: int) -> list:
async with self.semaphore: # Limit concurrent requests
async with self.rate_limiter: # Limit requests per second
try:
return await self.analyzer.fetch_snapshots(
exchange, symbol, start, end
)
except Exception as e:
if "429" in str(e):
# Exponential backoff on rate limit
await asyncio.sleep(5)
return await self.analyzer.fetch_snapshots(
exchange, symbol, start, end
)
raise
Usage
fetcher = ThrottledFetcher("YOUR_KEY", max_concurrent=3, requests_per_second=10)
results = await fetcher.fetch_with_throttle("binance", "BTC/USDT", start, end)
Error 2: Order Book Depth Mismatch in Backtests
Symptom: Backtested slippage significantly underestimates actual execution costs.
Cause: Fetching snapshots with insufficient depth levels (defaulting to 20-50 levels instead of 500).
# BROKEN: Default depth (likely 20-50 levels)
snapshots = await analyzer.fetch_snapshots(
exchange="binance",
symbol="BTC/USDT",
start_time=start,
end_time=end
# Missing: depth parameter defaults to minimum
)
FIXED: Request maximum depth for accurate liquidity modeling
MAX_DEPTH = 500 # HolySheep AI maximum
async def fetch_for_backtest(exchange: str, symbol: str,
start: int, end: int) -> list:
"""
Fetch order book data optimized for backtesting accuracy.
"""
analyzer = OrderBookAnalyzer("YOUR_KEY")
# Fetch with maximum depth
snapshots = await analyzer.fetch_snapshots(
exchange=exchange,
symbol=symbol,
start_time=start,
end_time=end,
depth=MAX_DEPTH # Critical for slippage accuracy
)
# Validate depth coverage
avg_levels = sum(
len(s.get("bids", [])) + len(s.get("asks", []))
for s in snapshots
) / (2 * len(snapshots))
if avg_levels < 200:
print(f"WARNING: Average depth {avg_levels:.0f} levels - "
f"slippage estimates may be inaccurate")
return snapshots
Verify depth in sample
sample = await fetch_for_backtest("binance", "ETH/USDT", start, end)
print(f"Avg bid/ask levels: {sum(len(s['bids']) for s in sample)/len(sample):.0f}")
Error 3: Timestamp Misalignment Between Snapshots and Trade Data
Symptom: Trade-by-trade backtests show trades executing at prices that don't exist in order book snapshots.
Cause: Order book snapshot timestamps don't align with trade timestamps, or snapshots are recorded after trades (staleness).
# BROKEN: Naive timestamp matching
for trade in trades:
closest_snapshot = min(
snapshots,
key=lambda s: abs(s["timestamp"] - trade["timestamp"])
)
# Problem: May match stale snapshot from 100ms+ earlier
FIXED: Forward-fill order book state with staleness detection
async def get_effective_orderbook(trade_timestamp: int,
snapshots: list,
max_staleness_ms: int = 100) -> dict:
"""
Get the order book state that was effective at trade time.
Uses forward-fill from most recent snapshot, with staleness warning.
"""
sorted_snaps = sorted(snapshots, key=lambda x: x["timestamp"])
# Find last snapshot before or at trade time
valid_snapshots = [s for s in sorted_snaps if s["timestamp"] <= trade_timestamp]
if not valid_snapshots:
raise ValueError(f"No order book snapshot exists before trade at {trade_timestamp}")
effective_snap = valid_snapshots[-1]
staleness = trade_timestamp - effective_snap["timestamp"]
if staleness > max_staleness_ms:
print(f"WARNING: Trade at {trade_timestamp} is {staleness}ms stale. "
f"Gap from snapshot at {effective_snap['timestamp']}")
return {
"effective_snapshot": effective_snap,
"staleness_ms": staleness,
"is_stale": staleness > max_staleness_ms,
"bids": dict(effective_snap.get("bids", [])),
"asks": dict(effective_snap.get("asks", []))
}
Usage in backtest loop
for trade in trades:
ob_state = await get_effective_orderbook(
trade_timestamp=trade["timestamp"],
snapshots=snapshots,
max_staleness_ms=100
)
if ob_state["is_stale"]:
# Handle stale data appropriately
# Option 1: Skip this trade
continue
# Option 2: Use next available snapshot (backward fill)
# Option 3: Interpolate between snapshots
Error 4: Incomplete Data Recovery After API Disconnection
Symptom: Large datasets have systematic gaps at boundaries between API request chunks.
Cause: Naive chunking of time ranges doesn't account for snapshot boundary overlap requirements.
# BROKEN: Gapped chunk requests
chunks = [
(start_1, end_1),
(end_1, end_2), # Missing data at end_1 boundary
(end_2, end_3)
]
FIXED: Overlapping chunk requests with deduplication
OVERLAP_MS = 60000 # 1 minute overlap for deduplication
async def fetch_continuous_data(exchange: str, symbol: str,
start: int, end: int,
chunk_duration_ms: int = 3600000) -> list:
"""
Fetch data in overlapping chunks to ensure continuity.
Automatically deduplicates overlapping snapshots.
"""
analyzer = OrderBookAnalyzer("YOUR_KEY")
all_snapshots = []
# Calculate chunk boundaries
chunk_start = start
while chunk_start < end:
chunk_end = min(chunk_start + chunk_duration_ms, end)
# Fetch with overlap
fetch_start = max(start, chunk_start - OVERLAP_MS)
fetch_end = min(end, chunk_end + OVERLAP_MS)
print(f"Fetching chunk: {chunk_start} to {chunk_end}")
chunk_data = await analyzer.fetch_snapshots(
exchange=exchange,
symbol=symbol,
start_time=fetch_start,
end_time=fetch_end,
depth=500
)
# Filter to actual chunk window (keep overlap for dedup)
window_data = [
s for s in chunk_data
if chunk_start <= s["timestamp"] <= chunk_end
]
all_snapshots.extend(window_data)
chunk_start = chunk_end
# Deduplicate by timestamp
seen_timestamps = set()
unique_snapshots = []
for snap in sorted(all_snapshots, key=lambda x: x["timestamp"]):
if snap["timestamp"] not in seen_timestamps:
seen_timestamps.add(snap["timestamp"])
unique_snapshots.append(snap)
print(f"Total snapshots: {len(unique_snapshots)} (deduplicated from {len(all