Last updated: May 2026 | Difficulty: Beginner to Intermediate | Reading time: 15 minutes

What This Tutorial Covers

When you build trading algorithms or backtest strategies using historical cryptocurrency market data, you rely on datasets from exchanges like Binance, Bybit, OKX, and Deribit. But here's what most beginners don't know: exchanges regularly correct historical data—and those corrections can silently invalidate your backtesting results.

In this guide, you'll learn how to use Tardis.dev (a professional crypto market data relay service) combined with HolySheep AI (which offers AI-powered data processing at ¥1=$1 with less than 50ms latency and supports WeChat/Alipay) to implement proper dataset version governance. By the end, you'll be able to track exchange corrections, identify data gaps, and understand exactly how these changes impact your backtesting outcomes.

💡 HolySheep AI Quick Facts (2026 Pricing):
• Rate: ¥1=$1 (saves 85%+ vs traditional ¥7.3 pricing)
• Latency: <50ms
• Payment: WeChat, Alipay, credit card
• Output models: GPT-4.1 ($8/Mtok), Claude Sonnet 4.5 ($15/Mtok), Gemini 2.5 Flash ($2.50/Mtok), DeepSeek V3.2 ($0.42/Mtok)
Sign up here for free credits on registration

Who This Tutorial Is For

✅ Perfect For❌ Not Ideal For
Quantitative traders building backtesting systemsPeople looking for real-time trading signals only
Developers working with crypto exchange APIsThose with no programming experience whatsoever
Data engineers managing historical market datasetsTeams without budget for data infrastructure
Algorithmic trading researchers validating resultsCasual investors who don't backtest strategies
Compliance teams auditing trading decisionsUsers who only need spot price data

Why Dataset Version Governance Matters

The Hidden Problem: Silent Data Corrections

Imagine you've spent three months developing a mean-reversion strategy on Binance futures data. Your backtest shows a Sharpe ratio of 2.3 with 40% annual returns. You go live—and lose money. What went wrong?

Chances are, the exchange corrected historical data after you downloaded it. Common corrections include:

Tardis.dev solves the first problem by providing structured, reliable data feeds including trades, order books, liquidations, and funding rates. HolySheep AI then adds an intelligence layer to track when those feeds change and what your backtesting results looked like before versus after.

Understanding Tardis.dev Data Architecture

Tardis.dev provides normalized market data from major exchanges. Here's the data structure you'll work with:

Core Data Types Available

Data TypeDescriptionUse CaseHolySheep Processing Cost
TradesIndividual executed ordersPrice action analysis$0.004/1K events
Order BookBid/ask depth snapshotsLiquidity analysis$0.008/1K snapshots
LiquidationsForced position closuresLeverage sentiment$0.003/1K events
Funding RatesPeriodic funding paymentsSwap pricing$0.002/1K rates

Step 1: Setting Up Your Environment

Before we start, you'll need three things:

  1. A Tardis.dev account (free tier available)
  2. A HolySheep AI account (get free credits on signup)
  3. Python 3.9+ installed on your machine

Installing Required Libraries

Open your terminal and run:

# Create a virtual environment
python -m venv crypto-env
source crypto-env/bin/activate  # On Windows: crypto-env\Scripts\activate

Install dependencies

pip install requests pandas python-dotenv tardis-client pip install "holy-sheep-sdk>=1.0.0" # HolySheep official SDK

Verify installation

python -c "import holy_sheep; print('HolySheep SDK ready')"

💡 Screenshot hint: Your terminal should show successful installation with no error messages.

Step 2: Configuring API Credentials

Create a file named .env in your project root:

# Tardis.dev credentials
TARDIS_API_KEY=your_tardis_api_key_here
TARDIS_EXCHANGE=binance

HolySheep AI credentials (base_url is fixed)

Rate: ¥1=$1 — 85%+ savings vs ¥7.3 market rate

HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY HOLYSHEEP_BASE_URL=https://api.holysheep.ai/v1

Data storage paths

DATA_DIR=./crypto_data VERSIONS_DIR=./version_history

Important: Never commit this file to version control. Add it to your .gitignore:

echo ".env" >> .gitignore
echo "__pycache__/" >> .gitignore
echo "*.csv" >> .gitignore

Step 3: Building the Dataset Version Tracker

Now let's create a Python module that handles version governance. I'll walk you through each component.

3.1 Initialize the HolySheep Client

# version_tracker.py
import os
import hashlib
import json
from datetime import datetime
from pathlib import Path
from typing import Dict, List, Optional

import requests
import pandas as pd
from dotenv import load_dotenv

Load environment variables

load_dotenv() class CryptoVersionTracker: """ Tracks cryptocurrency dataset versions using Tardis.dev feeds and HolySheep AI for intelligent change detection. HolySheep Benefits: - Rate: ¥1=$1 (85%+ savings vs ¥7.3) - Latency: <50ms API responses - Payment: WeChat/Alipay supported """ def __init__(self): self.base_url = "https://api.holysheep.ai/v1" self.api_key = os.getenv("HOLYSHEEP_API_KEY") self.tardis_key = os.getenv("TARDIS_API_KEY") self.exchange = os.getenv("TARDIS_EXCHANGE", "binance") if not self.api_key: raise ValueError("HOLYSHEEP_API_KEY not found in environment") if not self.tardis_key: raise ValueError("TARDIS_API_KEY not found in environment") # Setup directories self.data_dir = Path(os.getenv("DATA_DIR", "./crypto_data")) self.versions_dir = Path(os.getenv("VERSIONS_DIR", "./version_history")) self.data_dir.mkdir(exist_ok=True) self.versions_dir.mkdir(exist_ok=True) # Initialize HolySheep client headers self.headers = { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json" } print("✅ CryptoVersionTracker initialized") print(f" - HolySheep rate: ¥1=$1 (<50ms latency)") print(f" - Exchange: {self.exchange}") def analyze_backtest_impact(self, old_results: Dict, new_results: Dict) -> str: """ Uses HolySheep AI to analyze what changed between two backtest versions. This helps identify which exchange corrections impacted your strategy. """ prompt = f""" Analyze the impact of exchange data corrections on backtesting results: PREVIOUS RESULTS: {json.dumps(old_results, indent=2)} CURRENT RESULTS: {json.dumps(new_results, indent=2)} Identify: 1. Which metrics changed significantly 2. Likely cause (trade correction, funding rate change, gap fill) 3. Whether the strategy is still valid 4. Recommended actions """ payload = { "model": "deepseek-v3.2", # $0.42/Mtok - cost effective "messages": [ {"role": "system", "content": "You are a quantitative trading analyst specializing in data quality assessment."}, {"role": "user", "content": prompt} ], "temperature": 0.3 } response = requests.post( f"{self.base_url}/chat/completions", headers=self.headers, json=payload, timeout=30 # HolySheep responds in <50ms ) if response.status_code == 200: return response.json()["choices"][0]["message"]["content"] else: raise Exception(f" HolySheep API error: {response.status_code} - {response.text}")

Usage example

tracker = CryptoVersionTracker()

3.2 Fetching Data from Tardis.dev with Version Hashing

# Continuing in version_tracker.py

import asyncio
from tardis_client import TardisClient, MessageType

class CryptoVersionTracker:
    # ... previous code ...
    
    async def fetch_trades_with_version(
        self, 
        symbol: str, 
        start_date: datetime, 
        end_date: datetime
    ) -> Dict:
        """
        Fetches trades from Tardis.dev and creates a versioned snapshot.
        Includes cryptographic hash to detect any changes.
        """
        client = TardisClient(self.tardis_key)
        
        trades_data = []
        version_hash_components = []
        
        # Async iterator for trades
        async for entry in client.as_iter(
            exchange=self.exchange,
            symbols=[symbol],
            from_time=int(start_date.timestamp() * 1000),
            to_time=int(end_date.timestamp() * 1000),
            channels=[MessageType.trade]
        ):
            if entry.type == MessageType.trade:
                trade = {
                    "id": entry.id,
                    "timestamp": entry.timestamp,
                    "price": float(entry.price),
                    "amount": float(entry.amount),
                    "side": entry.side
                }
                trades_data.append(trade)
                version_hash_components.append(f"{entry.id}:{entry.price}:{entry.amount}")
        
        # Create deterministic hash for version tracking
        combined = "|".join(sorted(version_hash_components))
        version_hash = hashlib.sha256(combined.encode()).hexdigest()[:16]
        
        # Save with version metadata
        version_info = {
            "version": version_hash,
            "fetched_at": datetime.now().isoformat(),
            "exchange": self.exchange,
            "symbol": symbol,
            "start_date": start_date.isoformat(),
            "end_date": end_date.isoformat(),
            "trade_count": len(trades_data),
            "data_file": f"trades_{symbol}_{version_hash}.parquet"
        }
        
        # Save data as parquet for efficiency
        df = pd.DataFrame(trades_data)
        data_path = self.data_dir / version_info["data_file"]
        df.to_parquet(data_path, index=False)
        
        # Save version metadata
        version_path = self.versions_dir / f"version_{version_hash}.json"
        with open(version_path, "w") as f:
            json.dump(version_info, f, indent=2)
        
        print(f"✅ Fetched {len(trades_data)} trades")
        print(f"   Version hash: {version_hash}")
        print(f"   Saved to: {data_path}")
        
        return version_info
    
    async def fetch_orderbook_snapshots(
        self, 
        symbol: str, 
        start_date: datetime, 
        end_date: datetime,
        interval_ms: int = 1000  # Snapshot every 1 second
    ) -> Dict:
        """
        Fetches order book snapshots with version tracking.
        Order book changes are critical for slippage and liquidity analysis.
        """
        client = TardisClient(self.tardis_key)
        
        snapshots = []
        version_components = []
        
        async for entry in client.as_iter(
            exchange=self.exchange,
            symbols=[symbol],
            from_time=int(start_date.timestamp() * 1000),
            to_time=int(end_date.timestamp() * 1000),
            channels=[MessageType.order_book_snapshot]
        ):
            if entry.type == MessageType.order_book_snapshot:
                snapshot = {
                    "timestamp": entry.timestamp,
                    "asks": [[float(p), float(a)] for p, a in entry.asks[:10]],
                    "bids": [[float(p), float(a)] for p, a in entry.bids[:10]],
                    "mid_price": (float(entry.asks[0][0]) + float(entry.bids[0][0])) / 2
                }
                snapshots.append(snapshot)
                version_components.append(
                    f"{entry.timestamp}:{snapshot['mid_price']}"
                )
        
        combined = "|".join(version_components)
        version_hash = hashlib.sha256(combined.encode()).hexdigest()[:16]
        
        version_info = {
            "version": version_hash,
            "fetched_at": datetime.now().isoformat(),
            "type": "orderbook_snapshots",
            "exchange": self.exchange,
            "symbol": symbol,
            "snapshot_count": len(snapshots),
            "data_file": f"orderbook_{symbol}_{version_hash}.parquet"
        }
        
        df = pd.DataFrame(snapshots)
        data_path = self.data_dir / version_info["data_file"]
        df.to_parquet(data_path, index=False)
        
        version_path = self.versions_dir / f"version_{version_hash}.json"
        with open(version_path, "w") as f:
            json.dump(version_info, f, indent=2)
        
        print(f"✅ Fetched {len(snapshots)} order book snapshots")
        print(f"   Version hash: {version_hash}")
        
        return version_info

Run the async fetch

async def main(): tracker = CryptoVersionTracker() # Fetch 1 hour of BTCUSDT trades from Binance end_time = datetime(2026, 5, 4, 0, 0) start_time = datetime(2026, 5, 3, 23, 0) version = await tracker.fetch_trades_with_version( symbol="BTCUSDT", start_date=start_time, end_date=end_time ) print(f"\n📋 Version Summary:") print(json.dumps(version, indent=2)) if __name__ == "__main__": asyncio.run(main())

3.3 Detecting Data Gaps and Corrections

# gap_detector.py - Detects missing data and exchange corrections

import requests
import pandas as pd
from datetime import datetime, timedelta
from typing import List, Tuple, Dict

class DataGapDetector:
    """
    Identifies gaps in historical data and detects when exchanges
    make corrections that affect backtesting validity.
    
    Powered by HolySheep AI for intelligent gap analysis.
    """
    
    def __init__(self, holy_sheep_api_key: str):
        self.api_key = holy_sheep_api_key
        self.base_url = "https://api.holysheep.ai/v1"
        self.headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
    
    def detect_timestamp_gaps(
        self, 
        df: pd.DataFrame, 
        expected_interval_ms: int = 1000
    ) -> List[Dict]:
        """
        Finds gaps in timestamp sequences.
        Common cause: Exchange downtime or data relay issues.
        """
        if "timestamp" not in df.columns:
            raise ValueError("DataFrame must have 'timestamp' column")
        
        gaps = []
        df = df.sort_values("timestamp").reset_index(drop=True)
        
        for i in range(1, len(df)):
            time_diff = df.loc[i, "timestamp"] - df.loc[i-1, "timestamp"]
            
            if time_diff > expected_interval_ms * 1.5:  # 50% tolerance
                gaps.append({
                    "gap_id": i,
                    "before_timestamp": df.loc[i-1, "timestamp"],
                    "after_timestamp": df.loc[i, "timestamp"],
                    "gap_duration_ms": time_diff,
                    "gap_duration_hours": time_diff / (1000 * 3600),
                    "data_loss_percent": (time_diff / expected_interval_ms - 1) * 100
                })
        
        return gaps
    
    def detect_volume_anomalies(
        self, 
        df: pd.DataFrame, 
        z_score_threshold: float = 3.0
    ) -> List[Dict]:
        """
        Identifies unusual volume spikes that might indicate data errors
        or require special handling in backtests.
        """
        if "amount" not in df.columns:
            raise ValueError("DataFrame must have 'amount' column")
        
        mean_volume = df["amount"].mean()
        std_volume = df["amount"].std()
        
        anomalies = []
        for idx, row in df.iterrows():
            z_score = abs(row["amount"] - mean_volume) / std_volume if std_volume > 0 else 0
            
            if z_score > z_score_threshold:
                anomalies.append({
                    "timestamp": row.get("timestamp", idx),
                    "volume": row["amount"],
                    "z_score": z_score,
                    "deviation_from_mean": f"{(row['amount']/mean_volume - 1)*100:.1f}%",
                    "severity": "high" if z_score > 5 else "medium"
                })
        
        return anomalies
    
    def analyze_correction_impact(
        self, 
        old_df: pd.DataFrame, 
        new_df: pd.DataFrame,
        strategy_params: Dict
    ) -> Dict:
        """
        Uses HolySheep AI to intelligently assess how exchange corrections
        impact specific backtesting strategy parameters.
        
        HolySheep Pricing (2026):
        - DeepSeek V3.2: $0.42/Mtok (most cost-effective for this)
        - GPT-4.1: $8/Mtok (most capable)
        - Claude Sonnet 4.5: $15/Mtok
        - Gemini 2.5 Flash: $2.50/Mtok
        """
        
        old_stats = {
            "trade_count": len(old_df),
            "avg_price": old_df["price"].mean() if "price" in old_df else 0,
            "total_volume": old_df["amount"].sum() if "amount" in old_df else 0,
            "price_std": old_df["price"].std() if "price" in old_df else 0
        }
        
        new_stats = {
            "trade_count": len(new_df),
            "avg_price": new_df["price"].mean() if "price" in new_df else 0,
            "total_volume": new_df["amount"].sum() if "amount" in new_df else 0,
            "price_std": new_df["price"].std() if "price" in new_df else 0
        }
        
        prompt = f"""
        Analyze this backtesting dataset correction impact:
        
        STRATEGY PARAMETERS:
        {json.dumps(strategy_params, indent=2)}
        
        OLD DATASET STATS:
        {json.dumps(old_stats, indent=2)}
        
        NEW DATASET STATS:
        {json.dumps(new_stats, indent=2)}
        
        Changes detected:
        - Trade count change: {len(new_df) - len(old_df)} ({(len(new_df)/len(old_df)-1)*100 if len(old_df) > 0 else 0:+.2f}%)
        - Average price change: {new_stats['avg_price'] - old_stats['avg_price']:+.6f}
        - Volume change: {new_stats['total_volume'] - old_stats['total_volume']:+.2f}
        
        Provide a detailed impact analysis focusing on:
        1. Which strategy parameters are most affected
        2. Should the backtest be re-run?
        3. Risk assessment for live trading
        4. Specific data points that changed (if identifiable)
        """
        
        payload = {
            "model": "deepseek-v3.2",  # $0.42/Mtok - excellent value
            "messages": [
                {
                    "role": "system", 
                    "content": "You are an expert quantitative analyst specializing in crypto data quality and backtesting validation."
                },
                {"role": "user", "content": prompt}
            ],
            "temperature": 0.2,
            "max_tokens": 1000
        }
        
        response = requests.post(
            f"{self.base_url}/chat/completions",
            headers=self.headers,
            json=payload,
            timeout=30
        )
        
        if response.status_code == 200:
            analysis = response.json()["choices"][0]["message"]["content"]
            return {
                "status": "success",
                "analysis": analysis,
                "old_stats": old_stats,
                "new_stats": new_stats,
                "cost_estimate_usd": response.json().get("usage", {}).get("total_tokens", 0) * 0.00042
            }
        else:
            raise Exception(f"Analysis failed: {response.status_code}")

Usage example

detector = DataGapDetector("YOUR_HOLYSHEEP_API_KEY")

Detect gaps in fetched data

df = pd.read_parquet("./crypto_data/trades_BTCUSDT_abc123.parquet") gaps = detector.detect_timestamp_gaps(df) print(f"🔍 Found {len(gaps)} gaps in the data") for gap in gaps[:5]: # Show first 5 print(f" Gap at {gap['before_timestamp']}: {gap['gap_duration_hours']:.2f} hours missing")

Step 4: Implementing Complete Version Governance

# main_backtest_governance.py - Complete implementation

import asyncio
import json
from datetime import datetime, timedelta
from pathlib import Path
from typing import Dict, List

import pandas as pd
import requests
from dotenv import load_dotenv

from version_tracker import CryptoVersionTracker
from gap_detector import DataGapDetector

load_dotenv()

class BacktestVersionManager:
    """
    Complete version governance system for crypto backtesting.
    
    Features:
    - Automatic version hashing of all data sources
    - Gap detection and reporting
    - Exchange correction impact analysis
    - Backtest result diffing with HolySheep AI
    
    HolySheep Benefits:
    - Rate: ¥1=$1 (85%+ savings vs ¥7.3)
    - Latency: <50ms per API call
    - Payment: WeChat/Alipay
    """
    
    def __init__(self):
        self.tracker = CryptoVersionTracker()
        self.detector = DataGapDetector(os.getenv("HOLYSHEEP_API_KEY"))
        self.version_history = []
        
    def run_backtest(self, version_hash: str, params: Dict) -> Dict:
        """
        Simulates running a backtest with a specific data version.
        In production, replace with your actual backtesting engine.
        """
        # Load the version's data
        data_file = self.tracker.data_dir / f"trades_BTCUSDT_{version_hash}.parquet"
        
        if not data_file.exists():
            raise FileNotFoundError(f"Data file not found: {data_file}")
        
        df = pd.read_parquet(data_file)
        
        # Simulated backtest results (replace with real backtest)
        results = {
            "version_hash": version_hash,
            "run_timestamp": datetime.now().isoformat(),
            "total_trades": len(df),
            "avg_slippage_bps": abs(df["price"].pct_change().std() * 10000) if len(df) > 1 else 0,
            "win_rate": 0.58,  # Simulated
            "sharpe_ratio": 2.1,  # Simulated
            "max_drawdown": 0.12,  # Simulated
            "profit_factor": 1.45  # Simulated
        }
        
        return results
    
    async def fetch_and_version_data(
        self, 
        symbol: str, 
        hours: int = 24
    ) -> Dict:
        """Fetches fresh data and creates new version."""
        end_time = datetime.now()
        start_time = end_time - timedelta(hours=hours)
        
        print(f"📥 Fetching {symbol} data from {start_time} to {end_time}")
        
        # Fetch from Tardis.dev
        version_info = await self.tracker.fetch_trades_with_version(
            symbol=symbol,
            start_date=start_time,
            end_date=end_time
        )
        
        # Analyze for gaps
        data_file = self.tracker.data_dir / version_info["data_file"]
        df = pd.read_parquet(data_file)
        
        gaps = self.detector.detect_timestamp_gaps(df)
        anomalies = self.detector.detect_volume_anomalies(df)
        
        version_info["gaps_detected"] = len(gaps)
        version_info["anomalies_detected"] = len(anomalies)
        version_info["gap_details"] = gaps[:10]  # Store top 10
        version_info["anomaly_details"] = anomalies[:10]
        
        return version_info
    
    def compare_versions(
        self, 
        old_version: Dict, 
        new_version: Dict
    ) -> Dict:
        """
        Compares two versions using HolySheep AI analysis.
        """
        print(f"🔄 Comparing versions:")
        print(f"   Old: {old_version['version']} ({old_version.get('trade_count', 'N/A')} trades)")
        print(f"   New: {new_version['version']} ({new_version.get('trade_count', 'N/A')} trades)")
        
        # Run backtests for both versions
        old_results = self.run_backtest(old_version["version"], {})
        new_results = self.run_backtest(new_version["version"], {})
        
        # Use HolySheep AI for intelligent comparison
        analysis = self.tracker.analyze_backtest_impact(old_results, new_results)
        
        comparison = {
            "old_version": old_version["version"],
            "new_version": new_version["version"],
            "trade_count_delta": new_version.get("trade_count", 0) - old_version.get("trade_count", 0),
            "gap_change": new_version.get("gaps_detected", 0) - old_version.get("gaps_detected", 0),
            "backtest_comparison": {
                "old_results": old_results,
                "new_results": new_results
            },
            "holy_sheep_analysis": analysis
        }
        
        return comparison
    
    def generate_version_report(self) -> str:
        """
        Generates a comprehensive version governance report using HolySheep.
        """
        prompt = f"""
        Generate a dataset version governance report for cryptocurrency backtesting.
        
        Total versions tracked: {len(self.version_history)}
        
        {json.dumps(self.version_history[:10], indent=2) if self.version_history else "No versions yet"}
        
        Include:
        1. Data quality summary
        2. Trend analysis (are gaps increasing/decreasing?)
        3. Recommendations for improving data reliability
        4. Risk assessment for production deployment
        """
        
        payload = {
            "model": "gpt-4.1",  # $8/Mtok - best for comprehensive reports
            "messages": [
                {
                    "role": "system",
                    "content": "You are a senior data engineering analyst creating executive summaries for quantitative trading teams."
                },
                {"role": "user", "content": prompt}
            ],
            "temperature": 0.3
        }
        
        response = requests.post(
            f"https://api.holysheep.ai/v1/chat/completions",
            headers=self.tracker.headers,
            json=payload,
            timeout=45
        )
        
        if response.status_code == 200:
            return response.json()["choices"][0]["message"]["content"]
        else:
            return f"Report generation failed: {response.status_code}"

async def main():
    """Main execution example."""
    print("🚀 Starting Crypto Dataset Version Governance\n")
    
    manager = BacktestVersionManager()
    
    # Step 1: Fetch current data
    current_version = await manager.fetch_and_version_data("BTCUSDT", hours=1)
    print(f"\n✅ Current version created: {current_version['version']}")
    
    # Step 2: If we have a previous version, compare
    if manager.version_history:
        previous_version = manager.version_history[-1]
        comparison = manager.compare_versions(previous_version, current_version)
        
        print(f"\n📊 Comparison Results:")
        print(f"   Trade count change: {comparison['trade_count_delta']:+d}")
        print(f"   Gap change: {comparison['gap_change']:+d}")
        print(f"\n💡 HolySheep AI Analysis:")
        print(comparison['holy_sheep_analysis'])
    
    # Step 3: Add to history
    manager.version_history.append(current_version)
    
    # Step 4: Generate governance report
    print(f"\n📋 Generating version governance report...")
    report = manager.generate_version_report()
    print(f"\n{report}")
    
    print(f"\n✨ Done! Version {current_version['version']} is now tracked.")
    print(f"   HolySheep latency: <50ms | Rate: ¥1=$1")

if __name__ == "__main__":
    asyncio.run(main())

Step 5: Visualizing Version History

To complete the governance system, let's add visualization capabilities:

# visualization.py - Track and visualize dataset changes

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import pandas as pd
from datetime import datetime
from pathlib import Path
from typing import List, Dict
import json

def plot_version_timeline(version_history: List[Dict], save_path: str = "version_timeline.png"):
    """
    Creates a timeline visualization of dataset versions and quality metrics.
    
    This helps you quickly spot:
    - Increasing gap frequency (exchange problems)
    - Correction waves (exchange data rebuilds)
    - Data quality trends
    """
    if not version_history:
        print("No version history to plot")
        return
    
    fig, axes = plt.subplots(3, 1, figsize=(14, 10), sharex=True)
    fig.suptitle("Crypto Dataset Version Governance Timeline", fontsize=14, fontweight="bold")
    
    # Extract data
    versions = [v["version"][:8] for v in version_history]  # Short hash
    timestamps = [datetime.fromisoformat(v["fetched_at"]) for v in version_history]
    trade_counts = [v.get("trade_count", 0) for v in version_history]
    gaps = [v.get("gaps_detected", 0) for v in version_history]
    anomalies = [v.get("anomalies_detected", 0) for v in version_history]
    
    # Plot 1: Trade counts
    axes[0].plot(timestamps, trade_counts, 'b-o', linewidth=2, markersize=6)
    axes[0].set_ylabel("Trade Count")
    axes[0].set_title("Data Volume Over Time")
    axes[0].grid(True, alpha=0.3)
    axes[0].fill_between(timestamps, trade_counts, alpha=0.3)
    
    # Plot 2: Gap count
    axes[1].bar(timestamps, gaps, width=0.0005, color='orange', alpha=0.7, label="Gaps")
    axes[1].bar(timestamps, anomalies, width=0.0005, bottom=gaps, color='red', alpha=0.7, label="Anomalies")
    axes[1].set_ylabel("Issue Count")
    axes[1].set_title("Data Quality Issues Detected")
    axes[1].legend()
    axes[1].grid(True, alpha=0.3)
    
    # Plot 3: Cumulative trade count
    cumulative = pd.Series(trade_counts).cumsum()
    axes[2].plot(timestamps, cumulative, 'g-', linewidth=2)
    axes[2].set_ylabel("Cumulative Trades")
    axes[2].set_xlabel("Version Fetch Time")
    axes[2].set_title("Cumulative Data Collection")
    axes[2].grid(True, alpha=0.3)
    
    # Format x-axis
    axes[2].xaxis.set_major_formatter(mdates.DateFormatter('%m-%d %H:%M'))
    plt.xticks(rotation=45)
    
    plt.tight_layout()
    plt.savefig(save_path, dpi=150, bbox_inches='tight')
    print(f"📊 Timeline saved to {save_path}")
    
    return fig

def generate_summary_stats(version_history: List[Dict]) -> Dict:
    """Generate summary statistics from version history."""
    if not version_history:
        return {}
    
    trade_counts = [v.get("trade_count", 0) for v in version_history]
    gaps = [v.get("gaps_detected", 0) for v in version_history]
    anomalies = [v.get("anomal