Real-time cryptocurrency market data powers trading strategies, risk management systems, and financial analytics. When that data arrives late, incomplete, or corrupted, the consequences can be devastating—missed trade executions, inaccurate portfolio valuations, or worse, catastrophic losses from stale quotes. This comprehensive guide walks you through building a production-grade data quality monitoring system using HolySheep AI's Tardis.dev relay, designed specifically for beginners with zero API experience.

HolySheep AI provides unified access to raw exchange feeds including Binance, Bybit, OKX, and Deribit with sub-50ms latency. Sign up here to receive free credits and start monitoring your data quality today.

What You Will Learn

Understanding Tardis.dev Data Streams

Tardis.dev, integrated into HolySheep AI's infrastructure, captures every market event from supported exchanges. Think of it as a continuous video feed of market activity—each message represents a single moment in time: a trade executed, an order book updated, a funding rate changed, or a liquidation triggered.

Before diving into monitoring, let's understand the four primary message types you'll encounter:

Who This Tutorial Is For

This Guide Is Perfect For This Guide Is NOT For
Developers new to cryptocurrency APIs Experienced HFT firms with proprietary monitoring
Trading strategy developers needing reliable data Those seeking historical backtesting data only
Risk management teams monitoring data quality Casual hobbyists with no production systems
Quantitative researchers building analytics pipelines Developers unwilling to write any code

Setting Up Your HolySheep AI Environment

The first step is obtaining your API credentials. HolySheep AI offers a streamlined onboarding process with support for WeChat and Alipay payments, making it particularly convenient for users in Asia-Pacific regions. New registrations receive complimentary credits—enough to run substantial monitoring tests before committing to a paid plan.

Access the HolySheep AI dashboard by navigating to the API keys section. You'll receive two critical pieces of information:

Your First Data Quality Check: Hello World Example

Let's start with the simplest possible example—connecting to the market data stream and verifying you receive messages. This foundational code will become the skeleton for all advanced monitoring we'll build later.

#!/usr/bin/env python3
"""
HolySheep AI - Tardis API Data Quality Monitor
Minimal working example for complete beginners
"""

import requests
import json
import time
from datetime import datetime

============================================

CONFIGURATION - Replace with your credentials

============================================

BASE_URL = "https://api.holysheep.ai/v1" API_KEY = "YOUR_HOLYSHEEP_API_KEY" # Get from https://www.holysheep.ai/register

Supported exchanges: binance, bybit, okx, deribit

EXCHANGE = "binance" SYMBOL = "BTC-USDT" def get_server_time(): """Check API connectivity and measure response latency""" headers = {"X-API-Key": API_KEY} start = time.perf_counter() response = requests.get( f"{BASE_URL}/time", headers=headers, timeout=10 ) latency_ms = (time.perf_counter() - start) * 1000 if response.status_code == 200: data = response.json() print(f"✓ Connected to HolySheep API") print(f"✓ Server time: {data.get('server_time')}") print(f"✓ Round-trip latency: {latency_ms:.2f}ms") return True, latency_ms else: print(f"✗ Connection failed: {response.status_code}") print(f" Response: {response.text}") return False, latency_ms def subscribe_to_trades(): """Subscribe to real-time trade stream""" headers = { "X-API-Key": API_KEY, "Content-Type": "application/json" } payload = { "exchange": EXCHANGE, "symbol": SYMBOL, "channel": "trades", "limit": 10 # Receive last 10 trades } print(f"\n📡 Subscribing to {EXCHANGE}/{SYMBOL} trade stream...") response = requests.post( f"{BASE_URL}/subscribe", headers=headers, json=payload, timeout=10 ) if response.status_code == 200: data = response.json() trades = data.get('trades', []) print(f"✓ Subscribed successfully") print(f"✓ Received {len(trades)} recent trades") for trade in trades[:3]: # Show first 3 print(f" {trade.get('timestamp')} | " f"Price: {trade.get('price')} | " f"Size: {trade.get('size')}") return data else: print(f"✗ Subscription failed: {response.status_code}") return None

Main execution

if __name__ == "__main__": print("=" * 50) print("HolySheep AI - Data Quality Monitor") print("=" * 50) connected, latency = get_server_time() if connected: subscribe_to_trades() print("\n✅ Basic connectivity test complete!")

What to expect when you run this: After replacing YOUR_HOLYSHEEP_API_KEY with your actual key, you should see output confirming connection to HolySheep's servers with sub-50ms latency (HolySheep guarantees <50ms globally). The terminal will display recent BTC-USDT trades from Binance with timestamps.

Building the Data Quality Monitor Class

Now we'll build a comprehensive monitoring system that tracks three critical metrics: latency (time between exchange event and your receipt), completeness (no missing sequence numbers), and validity (data falls within expected ranges).

#!/usr/bin/env python3
"""
HolySheep AI - Production Data Quality Monitor
Tracks latency, completeness, and data validity in real-time
"""

import requests
import json
import time
import threading
from datetime import datetime, timezone
from collections import deque
from dataclasses import dataclass, field
from typing import Optional, Dict, List
import statistics

============================================

CONFIGURATION

============================================

BASE_URL = "https://api.holysheep.ai/v1" API_KEY = "YOUR_HOLYSHEEP_API_KEY" @dataclass class QualityMetrics: """Stores aggregated quality metrics""" latency_samples: deque = field(default_factory=lambda: deque(maxlen=100)) sequence_gaps: List[int] = field(default_factory=list) invalid_messages: List[str] = field(default_factory=list) total_messages: int = 0 last_sequence: Optional[int] = None last_timestamp: Optional[int] = None @property def avg_latency_ms(self) -> float: return statistics.mean(self.latency_samples) if self.latency_samples else 0 @property def p99_latency_ms(self) -> float: if not self.latency_samples: return 0 sorted_latencies = sorted(self.latency_samples) idx = int(len(sorted_latencies) * 0.99) return sorted_latencies[min(idx, len(sorted_latencies) - 1)] @property def gap_count(self) -> int: return len(self.sequence_gaps) @property def completeness_rate(self) -> float: if self.total_messages == 0: return 100.0 return ((self.total_messages - self.gap_count) / self.total_messages) * 100 class DataQualityMonitor: """ Monitors Tardis API data streams for quality issues. Tracks latency, sequence integrity, and message validity. """ def __init__(self, api_key: str, base_url: str = BASE_URL): self.api_key = api_key self.base_url = base_url self.headers = {"X-API-Key": api_key} self.metrics = QualityMetrics() self.alerts = [] self._lock = threading.Lock() # Thresholds for alerting (customize based on requirements) self.latency_threshold_ms = 100 # Alert if avg latency exceeds 100ms self.p99_threshold_ms = 200 # Alert if P99 latency exceeds 200ms self.completeness_threshold = 99.0 # Alert if completeness drops below 99% def process_trade(self, trade: Dict) -> None: """Process a single trade message and update metrics""" with self._lock: self.metrics.total_messages += 1 # 1. LATENCY MEASUREMENT exchange_timestamp = trade.get('timestamp', 0) receive_timestamp = int(time.time() * 1000) # If exchange provides millisecond timestamp if exchange_timestamp > 1_000_000_000_000: latency = receive_timestamp - exchange_timestamp elif exchange_timestamp > 1_000_000_000: latency = receive_timestamp - (exchange_timestamp * 1000) else: latency = receive_timestamp - exchange_timestamp self.metrics.latency_samples.append(max(0, latency)) # 2. SEQUENCE COMPLETENESS CHECK sequence = trade.get('sequence') if sequence is not None and self.metrics.last_sequence is not None: expected = self.metrics.last_sequence + 1 if sequence != expected: gap = sequence - expected self.metrics.sequence_gaps.append(gap) self._create_alert( "SEQUENCE_GAP", f"Gap of {gap} sequences detected (expected {expected}, got {sequence})", severity="HIGH" ) if sequence is not None: self.metrics.last_sequence = sequence # 3. DATA VALIDITY CHECKS price = trade.get('price') size = trade.get('size') if price is None or price <= 0: self._create_alert("INVALID_PRICE", f"Invalid price: {price}", severity="HIGH") if size is None or size <= 0: self._create_alert("INVALID_SIZE", f"Invalid size: {size}", severity="MEDIUM") # Check for stale data (more than 5 seconds old) if exchange_timestamp: age_ms = receive_timestamp - (exchange_timestamp if exchange_timestamp > 1_000_000_000_000 else exchange_timestamp * 1000) if age_ms > 5000: self._create_alert("STALE_DATA", f"Data is {age_ms}ms old", severity="HIGH") def _create_alert(self, alert_type: str, message: str, severity: str = "LOW") -> None: """Create and store an alert""" alert = { "type": alert_type, "message": message, "severity": severity, "timestamp": datetime.now(timezone.utc).isoformat() } self.alerts.append(alert) print(f"🚨 ALERT [{severity}] {alert_type}: {message}") def check_thresholds(self) -> List[str]: """Check if any metrics exceed configured thresholds""" warnings = [] if self.metrics.avg_latency_ms > self.latency_threshold_ms: warnings.append(f"High average latency: {self.metrics.avg_latency_ms:.1f}ms") if self.metrics.p99_latency_ms > self.p99_threshold_ms: warnings.append(f"High P99 latency: {self.metrics.p99_latency_ms:.1f}ms") if self.metrics.completeness_rate < self.completeness_threshold: warnings.append(f"Low completeness: {self.metrics.completeness_rate:.2f}%") return warnings def get_report(self) -> Dict: """Generate current quality report""" with self._lock: return { "total_messages": self.metrics.total_messages, "latency": { "avg_ms": round(self.metrics.avg_latency_ms, 2), "p99_ms": round(self.metrics.p99_latency_ms, 2), "samples": len(self.metrics.latency_samples) }, "completeness": { "rate_percent": round(self.metrics.completeness_rate, 4), "gap_count": self.metrics.gap_count }, "alerts": { "total": len(self.alerts), "recent": self.alerts[-5:] # Last 5 alerts }, "status": "HEALTHY" if not self.check_thresholds() else "DEGRADED" } def stream_trades(self, exchange: str, symbol: str, duration_seconds: int = 60): """ Stream and monitor trades for specified duration. This is a polling implementation - for production, use WebSocket. """ print(f"📡 Starting {duration_seconds}s monitoring session...") print(f" Exchange: {exchange}") print(f" Symbol: {symbol}") print("-" * 50) start_time = time.time() poll_interval = 0.5 # Poll every 500ms while time.time() - start_time < duration_seconds: try: response = requests.post( f"{self.base_url}/subscribe", headers=self.headers, json={ "exchange": exchange, "symbol": symbol, "channel": "trades", "limit": 100 }, timeout=5 ) if response.status_code == 200: data = response.json() trades = data.get('trades', []) for trade in trades: self.process_trade(trade) if trades: print(f"\r Progress: {time.time() - start_time:.0f}s | " f"Msgs: {self.metrics.total_messages} | " f"Latency: {self.metrics.avg_latency_ms:.1f}ms | " f"Complete: {self.metrics.completeness_rate:.2f}%", end="") except Exception as e: print(f"\n⚠️ Stream error: {e}") time.sleep(poll_interval) print("\n" + "=" * 50) print("📊 FINAL QUALITY REPORT") print("=" * 50) report = self.get_report() print(json.dumps(report, indent=2)) return report

============================================

USAGE EXAMPLE

============================================

if __name__ == "__main__": # Initialize monitor monitor = DataQualityMonitor( api_key=API_KEY, base_url=BASE_URL ) # Run 30-second monitoring session report = monitor.stream_trades( exchange="binance", symbol="BTC-USDT", duration_seconds=30 ) # Check for threshold violations warnings = monitor.check_thresholds() if warnings: print("\n⚠️ THRESHOLD WARNINGS:") for warning in warnings: print(f" - {warning}")

Running this monitor provides: Real-time visibility into your data quality with millisecond-precision latency tracking, automatic detection of sequence gaps that indicate missing data, and configurable alerting when metrics breach your defined thresholds. HolySheep's sub-50ms infrastructure means your latency readings should consistently stay well within acceptable ranges.

Building a Webhook Alerting System

For production deployments, you need alerts delivered to your incident management platform—Slack, PagerDuty, Discord, or custom webhooks. This section implements a flexible alerting pipeline that integrates with any notification system.

#!/usr/bin/env python3
"""
HolySheep AI - Webhook Alert System for Data Quality Monitoring
Integrates with Slack, PagerDuty, Discord, or custom endpoints
"""

import requests
import json
import hmac
import hashlib
import time
from datetime import datetime, timezone
from typing import Dict, List, Optional, Callable
from dataclasses import dataclass
from enum import Enum

class AlertSeverity(Enum):
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    CRITICAL = "critical"

@dataclass
class Alert:
    """Represents a data quality alert"""
    severity: AlertSeverity
    title: str
    description: str
    metrics: Dict = None
    timestamp: str = None
    
    def __post_init__(self):
        if self.timestamp is None:
            self.timestamp = datetime.now(timezone.utc).isoformat()

class WebhookAlertManager:
    """
    Manages alert delivery to multiple webhook endpoints.
    Supports Slack, Discord, generic webhooks with signature verification.
    """
    
    def __init__(self):
        self.webhooks: List[Dict] = []
        self.alert_history: List[Alert] = []
        self.alert_callbacks: List[Callable] = []
        
        # Rate limiting (prevent alert storms)
        self.min_alert_interval_seconds = 60
        self.last_alert_times: Dict[str, float] = {}
    
    def add_slack_webhook(self, url: str, channel: str = None, mention_user: str = None):
        """Add a Slack incoming webhook"""
        self.webhooks.append({
            "type": "slack",
            "url": url,
            "channel": channel,
            "mention_user": mention_user
        })
        print(f"✓ Added Slack webhook for channel: {channel or 'default'}")
    
    def add_discord_webhook(self, url: str, username: str = "Data Monitor"):
        """Add a Discord webhook"""
        self.webhooks.append({
            "type": "discord",
            "url": url,
            "username": username
        })
        print(f"✓ Added Discord webhook: {username}")
    
    def add_generic_webhook(self, url: str, secret: str = None, headers: Dict = None):
        """Add a generic webhook with optional HMAC signature"""
        self.webhooks.append({
            "type": "generic",
            "url": url,
            "secret": secret,
            "headers": headers or {}
        })
        print(f"✓ Added generic webhook: {url}")
    
    def add_alert_callback(self, callback: Callable[[Alert], None]):
        """Add a Python callback function to be called on each alert"""
        self.alert_callbacks.append(callback)
    
    def _create_slack_payload(self, alert: Alert) -> Dict:
        """Format alert for Slack"""
        color_map = {
            AlertSeverity.LOW: "#36a64f",
            AlertSeverity.MEDIUM: "#ff9800",
            AlertSeverity.HIGH: "#f44336",
            AlertSeverity.CRITICAL: "#9c27b0"
        }
        
        fields = [
            {"title": "Severity", "value": alert.severity.value.upper(), "short": True},
            {"title": "Timestamp", "value": alert.timestamp, "short": True}
        ]
        
        if alert.metrics:
            if "latency_ms" in alert.metrics:
                fields.append({
                    "title": "Latency",
                    "value": f"{alert.metrics['latency_ms']}ms",
                    "short": True
                })
            if "completeness" in alert.metrics:
                fields.append({
                    "title": "Completeness",
                    "value": f"{alert.metrics['completeness']}%",
                    "short": True
                })
        
        return {
            "attachments": [{
                "color": color_map.get(alert.severity, "#808080"),
                "title": f"🚨 {alert.title}",
                "text": alert.description,
                "fields": fields,
                "footer": "HolySheep Data Quality Monitor",
                "ts": int(time.time())
            }]
        }
    
    def _create_discord_payload(self, alert: Alert) -> Dict:
        """Format alert for Discord"""
        emoji_map = {
            AlertSeverity.LOW: "ℹ️",
            AlertSeverity.MEDIUM: "⚠️",
            AlertSeverity.HIGH: "🚨",
            AlertSeverity.CRITICAL: "💀"
        }
        
        description = f"**{alert.description}**"
        if alert.metrics:
            metrics_str = " | ".join([
                f"{k}: {v}" for k, v in alert.metrics.items()
            ])
            description += f"\n\n``\n{metrics_str}\n``"
        
        return {
            "username": "HolySheep Monitor",
            "content": f"{emoji_map.get(alert.severity, '📊')} **{alert.title}**",
            "embeds": [{
                "description": description,
                "timestamp": alert.timestamp,
                "color": {
                    AlertSeverity.LOW: 0x36a64f,
                    AlertSeverity.MEDIUM: 0xff9800,
                    AlertSeverity.HIGH: 0xf44336,
                    AlertSeverity.CRITICAL: 0x9c27b0
                }.get(alert.severity, 0x808080)
            }]
        }
    
    def _sign_payload(self, payload: str, secret: str) -> str:
        """Create HMAC-SHA256 signature for webhook verification"""
        signature = hmac.new(
            secret.encode(),
            payload.encode(),
            hashlib.sha256
        ).hexdigest()
        return f"sha256={signature}"
    
    def send_alert(self, alert: Alert, force: bool = False) -> bool:
        """
        Send alert to all configured webhooks.
        Set force=True to bypass rate limiting.
        """
        # Rate limiting check
        if not force:
            if alert.title in self.last_alert_times:
                elapsed = time.time() - self.last_alert_times[alert.title]
                if elapsed < self.min_alert_interval_seconds:
                    return False
        
        self.last_alert_times[alert.title] = time.time()
        self.alert_history.append(alert)
        
        # Execute callbacks
        for callback in self.alert_callbacks:
            try:
                callback(alert)
            except Exception as e:
                print(f"⚠️ Callback error: {e}")
        
        # Send to webhooks
        success_count = 0
        for webhook in self.webhooks:
            try:
                if webhook["type"] == "slack":
                    payload = self._create_slack_payload(alert)
                elif webhook["type"] == "discord":
                    payload = self._create_discord_payload(alert)
                else:
                    payload = {"alert": {
                        "title": alert.title,
                        "description": alert.description,
                        "severity": alert.severity.value,
                        "timestamp": alert.timestamp,
                        "metrics": alert.metrics
                    }}
                
                response = requests.post(
                    webhook["url"],
                    json=payload,
                    timeout=10
                )
                
                if response.status_code in (200, 204):
                    success_count += 1
                else:
                    print(f"⚠️ Webhook failed ({webhook['type']}): {response.status_code}")
            
            except Exception as e:
                print(f"⚠️ Webhook error ({webhook['type']}): {e}")
        
        return success_count > 0

============================================

INTEGRATION EXAMPLE

============================================

def create_data_quality_alert(monitor, alert_manager): """Generate alerts based on monitor thresholds""" report = monitor.get_report() warnings = monitor.check_thresholds() if not warnings: return # Determine severity based on warning count severity = AlertSeverity.LOW if len(warnings) >= 2: severity = AlertSeverity.HIGH elif warnings: severity = AlertSeverity.MEDIUM alert = Alert( severity=severity, title="Data Quality Threshold Exceeded", description="; ".join(warnings), metrics={ "latency_ms": report["latency"]["avg_ms"], "p99_latency_ms": report["latency"]["p99_ms"], "completeness": report["completeness"]["rate_percent"], "total_messages": report["total_messages"] } ) alert_manager.send_alert(alert)

Example usage:

if __name__ == "__main__": # Initialize alert manager manager = WebhookAlertManager() # Add your webhooks here: # manager.add_slack_webhook("https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK", "#alerts") # manager.add_discord_webhook("https://discord.com/api/webhooks/YOUR/DISCORD/WEBHOOK") # Add custom callback def log_alert(alert: Alert): print(f"📝 Custom log: {alert.title} - {alert.description}") manager.add_alert_callback(log_alert) # Test alert test_alert = Alert( severity=AlertSeverity.MEDIUM, title="Test Alert", description="This is a test alert from the monitoring system", metrics={"latency_ms": 45.2, "completeness": 99.95} ) print("\n" + "=" * 50) print("Testing alert system...") print("=" * 50) # Note: Webhooks not configured, so only callback will fire manager.send_alert(test_alert, force=True) print("\n✓ Alert system initialized successfully")

Monitoring Multiple Exchanges Simultaneously

Production systems typically ingest data from multiple exchanges for arbitrage, cross-exchange analysis, or redundancy. This example demonstrates coordinated monitoring across Binance, Bybit, OKX, and Deribit with unified alerting.

#!/usr/bin/env python3
"""
HolySheep AI - Multi-Exchange Data Quality Monitor
Monitors Binance, Bybit, OKX, and Deribit simultaneously
"""

import requests
import json
import time
import threading
from datetime import datetime, timezone
from dataclasses import dataclass, field
from typing import Dict, List, Optional
from concurrent.futures import ThreadPoolExecutor, as_completed

BASE_URL = "https://api.holysheep.ai/v1"
API_KEY = "YOUR_HOLYSHEEP_API_KEY"

@dataclass
class ExchangeHealth:
    """Health status for a single exchange"""
    name: str
    is_connected: bool = False
    messages_received: int = 0
    last_message_time: Optional[float] = None
    avg_latency_ms: float = 0.0
    errors: List[str] = field(default_factory=list)
    
    @property
    def stale_seconds(self) -> float:
        if self.last_message_time is None:
            return float('inf')
        return time.time() - self.last_message_time

class MultiExchangeMonitor:
    """
    Coordinates data quality monitoring across multiple exchanges.
    Provides unified view and cross-exchange comparisons.
    """
    
    SUPPORTED_EXCHANGES = {
        "binance": {"name": "Binance", "has_trades": True, "has_orderbook": True},
        "bybit": {"name": "Bybit", "has_trades": True, "has_orderbook": True},
        "okx": {"name": "OKX", "has_trades": True, "has_orderbook": True},
        "deribit": {"name": "Deribit", "has_trades": True, "has_orderbook": False}
    }
    
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.headers = {"X-API-Key": api_key}
        self.exchanges: Dict[str, ExchangeHealth] = {
            name: ExchangeHealth(name=name) 
            for name in self.SUPPORTED_EXCHANGES
        }
        self._lock = threading.Lock()
        self.monitoring = False
        self.poll_thread: Optional[threading.Thread] = None
    
    def check_exchange(self, exchange: str, symbol: str = "BTC-USDT") -> Dict:
        """Check connectivity and latency for a single exchange"""
        start = time.perf_counter()
        
        try:
            response = requests.post(
                f"{BASE_URL}/subscribe",
                headers=self.headers,
                json={
                    "exchange": exchange,
                    "symbol": symbol,
                    "channel": "trades",
                    "limit": 10
                },
                timeout=5
            )
            
            latency_ms = (time.perf_counter() - start) * 1000
            
            if response.status_code == 200:
                data = response.json()
                trades = data.get('trades', [])
                
                with self._lock:
                    self.exchanges[exchange].is_connected = True
                    self.exchanges[exchange].messages_received += len(trades)
                    self.exchanges[exchange].last_message_time = time.time()
                    
                    # Update rolling average latency
                    current_avg = self.exchanges[exchange].avg_latency_ms
                    count = self.exchanges[exchange].messages_received
                    new_avg = ((current_avg * (count - len(trades)) + 
                               latency_ms * len(trades)) / count) if count > 0 else latency_ms
                    self.exchanges[exchange].avg_latency_ms = new_avg
                
                return {
                    "exchange": exchange,
                    "status": "OK",
                    "latency_ms": round(latency_ms, 2),
                    "trades_received": len(trades)
                }
            else:
                with self._lock:
                    self.exchanges[exchange].is_connected = False
                    self.exchanges[exchange].errors.append(
                        f"HTTP {response.status_code}"
                    )
                return {
                    "exchange": exchange,
                    "status": "ERROR",
                    "error": f"HTTP {response.status_code}"
                }
        
        except requests.exceptions.Timeout:
            with self._lock:
                self.exchanges[exchange].is_connected = False
                self.exchanges[exchange].errors.append("Timeout")
            return {
                "exchange": exchange,
                "status": "TIMEOUT",
                "error": "Connection timed out"
            }
        
        except Exception as e:
            with self._lock:
                self.exchanges[exchange].is_connected = False
                self.exchanges[exchange].errors.append(str(e))
            return {
                "exchange": exchange,
                "status": "ERROR",
                "error": str(e)
            }
    
    def check_all_exchanges(self, symbol: str = "BTC-USDT") -> List[Dict]:
        """Check all exchanges in parallel"""
        results = []
        
        with ThreadPoolExecutor(max_workers=4) as executor:
            futures = {
                executor.submit(self.check_exchange, exchange, symbol): exchange
                for exchange in self.SUPPORTED_EXCHANGES
            }
            
            for future in as_completed(futures):
                exchange = futures[future]
                try:
                    result = future.result()
                    results.append(result)
                except Exception as e:
                    results.append({
                        "exchange": exchange,
                        "status": "ERROR",
                        "error": str(e)
                    })
        
        return results
    
    def get_unified_report(self) -> Dict:
        """Generate unified health report across all exchanges"""
        with self._lock:
            exchange_status = {}
            all_latencies = []
            
            for name, health in self.exchanges.items():
                exchange_status[name] = {
                    "connected": health.is_connected,
                    "messages": health.messages_received,
                    "latency_ms": round(health.avg_latency_ms, 2),
                    "stale_seconds": round(health.stale_seconds, 1),
                    "errors": health.errors[-3:]  # Last 3 errors
                }
                
                if health.is_connected:
                    all_latencies.append(health.avg_latency_ms)
            
            return {
                "timestamp": datetime.now(timezone.utc).isoformat(),
                "exchanges": exchange_status,
                "summary": {
                    "total_connected": sum(1 for h in self.exchanges.values() if h.is_connected),
                    "total_exchanges": len(self.exchanges),
                    "avg_latency_ms": round(sum(all_latencies) / len(all_latencies), 2) if all_latencies else 0,
                    "max_latency_ms": round(max(all_latencies), 2) if all_latencies else 0
                }
            }
    
    def start_monitoring(self, interval_seconds: int = 10):
        """Start continuous monitoring in background thread"""
        self.monitoring = True
        
        def monitor_loop():
            while self.monitoring:
                results = self.check_all_exchanges()
                
                # Check for issues
                issues = [r for r in results if r["status"] != "OK"]
                if issues:
                    print(f"\n⚠️ Issues detected:")
                    for issue in issues:
                        print(f"   {issue['exchange']}: {issue.get('error', issue['status'])}")
                
                # Print status
                report = self.get_unified_report()
                print(f"\r[{datetime.now().strftime('%H:%M:%S')}] "
                      f"Connected: {report['summary']['total_connected']}/"
                      f"{report['summary']['total_exchanges']} | "
                      f"Avg Latency: {report['summary']['avg_latency_ms']}ms", end="")
                
                time.sleep(interval_seconds)
        
        self.poll_thread = threading.Thread(target=monitor_loop, daemon=True)
        self.poll_thread.start()
        print("✓ Started multi-exchange monitoring")
    
    def stop_monitoring(self):
        """Stop continuous monitoring"""
        self.monitoring = False
        if self.poll_thread:
            self.poll_thread.join(timeout=5)
        print("✓ Stopped monitoring")

============================================

USAGE EXAMPLE

============================================

if __name__ == "__main__": monitor = MultiExchangeMonitor(api_key=API_KEY) print("=" * 60) print("HolySheep AI - Multi-Exchange Data Quality Monitor") print("=" * 60) # Run one-time check print("\n📡 Checking all exchanges...") results =