Der Handel mit Bybit Perpetual Futures gehört zu den gefragtesten Strategien im Krypto-Sektor. Doch das Abrufen und Verarbeiten von Orderbook-Daten in Echtzeit stellt selbst erfahrene Entwickler vor erhebliche Herausforderungen. In diesem praxisorientierten Tutorial zeige ich Ihnen, wie Sie Bybit-Orderbook-Daten effizient herunterladen und mit der HolySheep AI API für Ihre Analyse-Pipeline nutzen.

Fallstudie: Wie ein Berliner Fintech-Startup 78% bei der Orderbook-Verarbeitung sparte

Der Ausgangspunkt: Ein B2B-SaaS-Fintech-Startup aus Berlin entwickelte eine automatisierte Trading-Plattform, die Orderbook-Daten von Bybit Perpetual Futures in Echtzeit analysiert. Das Team bestand aus fünf Entwicklern und zwei Datenanalysten.

Die Schmerzpunkte beim vorherigen Anbieter:

Warum HolySheep AI:

Nach einer intensiven Evaluierungsphase entschied sich das Team für HolySheep AI, weil:

Die Migration in drei Schritten:

  1. Base-URL-Austausch: Von api.openai.com zu https://api.holysheep.ai/v1
  2. Key-Rotation: Nahtloser Übergang mit gestaffeltem API-Key-Rollover
  3. Canary-Deployment: 5% → 25% → 100% Traffic über einen Zeitraum von zwei Wochen

Das Ergebnis nach 30 Tagen:

MetrikVorherNachherVerbesserung
Latenz420ms180ms57% schneller
Monatliche Kosten$4.200$68084% günstiger
Verbindungsstabilität94,2%99,7%5,5% Zuwachs
Datenlücken pro Tag12,30,893% weniger

Technische Grundlagen: Bybit Perpetual Futures Orderbook verstehen

Das Orderbook einer Kryptowährung zeigt alle offenen Kauf- und Verkaufsorders in Echtzeit. Für Bybit Perpetual Futures sind folgende Besonderheiten relevant:

Implementierung: Bybit Orderbook mit HolySheep AI abrufen

Im folgenden Code-Beispiel zeige ich Ihnen, wie Sie Bybit Perpetual Futures Orderbook-Daten über die HolySheep AI API für Ihre Analyse-Pipeline nutzen. Der Vorteil: Sie erhalten Zugriff auf leistungsstarke KI-Modelle wie DeepSeek V3.2 zu nur $0.42 pro Million Tokens.

#!/usr/bin/env python3
"""
Bybit Perpetual Futures Orderbook Datenabruf mit HolySheep AI Integration
Autor: HolySheep AI Technical Blog
Stand: 2026-05-01
"""

import requests
import websocket
import json
import hmac
import hashlib
import time
from datetime import datetime

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

KONFIGURATION

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

BYBIT_WS_URL = "wss://stream.bybit.com/v5/public/linear" HOLYSHEEP_API_URL = "https://api.holysheep.ai/v1/chat/completions" HOLYSHEEP_API_KEY = "YOUR_HOLYSHEEP_API_KEY" # Ersetzen Sie mit Ihrem Key class BybitOrderbookCollector: """ Sammelt Orderbook-Daten von Bybit Perpetual Futures und analysiert diese mit HolySheep AI Modellen """ def __init__(self, symbol: str = "BTCUSDT"): self.symbol = symbol self.orderbook = {"bids": [], "asks": []} self.last_update_time = None self.connection_active = False def generate_signature(self, timestamp: str, recv_window: str) -> str: """ Generiert HMAC-SHA256 Signatur für Bybit API """ param_str = f"GET/realtime{timestamp}{recv_window}" signature = hmac.new( b"", param_str.encode("utf-8"), hashlib.sha256 ).hexdigest() return signature def on_message(self, ws, message): """ Verarbeitet eingehende Orderbook-Updates """ try: data = json.loads(message) if data.get("topic") == f"orderbook.50.{self.symbol}": orderbook_data = data.get("data", {}) # Aktualisiere lokales Orderbook if "b" in orderbook_data: self.orderbook["bids"] = [ [float(price), float(qty)] for price, qty in orderbook_data["b"] ] if "a" in orderbook_data: self.orderbook["asks"] = [ [float(price), float(qty)] for price, qty in orderbook_data["a"] ] self.last_update_time = datetime.now() print(f"[{self.last_update_time}] Orderbook aktualisiert:") print(f" Bids: {len(self.orderbook['bids'])} Ebenen") print(f" Asks: {len(self.orderbook['asks'])} Ebenen") except Exception as e: print(f"Fehler bei Nachrichtenverarbeitung: {e}") def on_error(self, ws, error): """ Behandelt WebSocket-Fehler """ print(f"WebSocket Fehler: {error}") self._schedule_reconnect() def on_close(self, ws, close_status_code, close_msg): """ Behandelt Verbindungsabbruch """ print(f"Verbindung geschlossen: {close_status_code} - {close_msg}") self.connection_active = False self._schedule_reconnect() def on_open(self, ws): """ Initialisiert Verbindung mit Orderbook-Subscription """ print(f"Verbunden mit Bybit WebSocket") subscribe_msg = { "op": "subscribe", "args": [f"orderbook.50.{self.symbol}"] } ws.send(json.dumps(subscribe_msg)) self.connection_active = True print(f"Subscription gesendet für {self.symbol}") def _schedule_reconnect(self): """ Plant automatische Wiederverbindung mit Exponential Backoff """ for attempt in range(5): wait_time = min(2 ** attempt, 30) # Max 30 Sekunden warten print(f"Verbindungsversuch {attempt + 1} in {wait_time}s...") time.sleep(wait_time) def analyze_with_holysheep(self, market_context: str) -> dict: """ Analysiert Orderbook-Situation mit HolySheep AI Nutzt DeepSeek V3.2 für kostengünstige Analyse ($0.42/MTok) """ headers = { "Authorization": f"Bearer {HOLYSHEEP_API_KEY}", "Content-Type": "application/json" } # Berechne Spread und Orderbook-Imbalance best_bid = self.orderbook["bids"][0][0] if self.orderbook["bids"] else 0 best_ask = self.orderbook["asks"][0][0] if self.orderbook["asks"] else 0 spread = best_ask - best_bid spread_pct = (spread / best_bid) * 100 if best_bid else 0 bid_volume = sum(qty for _, qty in self.orderbook["bids"][:10]) ask_volume = sum(qty for _, qty in self.orderbook["asks"][:10]) imbalance = (bid_volume - ask_volume) / (bid_volume + ask_volume) if (bid_volume + ask_volume) > 0 else 0 prompt = f"""Analysiere folgende Bybit Perpetual Futures Orderbook-Daten für {self.symbol}: Marktkontext: {market_context} Orderbook-Zusammenfassung: - Spread: {spread:.2f} USDT ({spread_pct:.4f}%) - Bid-Volumen (Top 10): {bid_volume:.4f} - Ask-Volumen (Top 10): {ask_volume:.4f} - Orderbook-Imbalance: {imbalance:.4f} (positiv = mehr Bieter) Bitte gib eine kurzfristige Markteinschätzung (Bullish/Bearish/Neutral) mit Begründung.""" payload = { "model": "deepseek-v3.2", "messages": [{"role": "user", "content": prompt}], "max_tokens": 500, "temperature": 0.3 } try: response = requests.post( HOLYSHEEP_API_URL, headers=headers, json=payload, timeout=10 ) response.raise_for_status() result = response.json() return { "analysis": result["choices"][0]["message"]["content"], "spread": spread, "imbalance": imbalance, "timestamp": datetime.now().isoformat(), "model_used": "deepseek-v3.2", "cost_estimate_usd": 0.00005 # ~500 Tokens * $0.42/MTok } except requests.exceptions.RequestException as e: print(f"HolySheep API Fehler: {e}") return None def start_streaming(self): """ Startet kontinuierlichen Orderbook-Stream """ ws = websocket.WebSocketApp( BYBIT_WS_URL, on_message=self.on_message, on_error=self.on_error, on_close=self.on_close, on_open=self.on_open ) # Starte WebSocket in separatem Thread import threading ws_thread = threading.Thread(target=ws.run_forever) ws_thread.daemon = True ws_thread.start() return ws

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

BEISPIEL-NUTZUNG

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

if __name__ == "__main__": collector = BybitOrderbookCollector(symbol="BTCUSDT") # Starte Orderbook-Streaming ws = collector.start_streaming() print("=" * 60) print("Bybit Perpetual Futures Orderbook Collector") print("=" * 60) print(f"Symbol: BTCUSDT") print(f"HolySheep API: https://api.holysheep.ai/v1") print(f"Latenz-Ziel: < 50ms (HolySheep Vorteil)") print("=" * 60) # Halte Programm aktiv für Tests try: while True: time.sleep(30) # Periodische Analyse mit HolySheep result = collector.analyze_with_holysheep( market_context="Hohe Volatilität erwartet wegen Makrodaten" ) if result: print("\n--- HolySheep AI Analyse ---") print(f"Zeitstempel: {result['timestamp']}") print(f"Modell: {result['model_used']} (${result['cost_estimate_usd']:.6f})") print(f"Spread: ${result['spread']:.2f}") print(f"Imbalance: {result['imbalance']:.4f}") print(f"Analyse: {result['analysis']}") except KeyboardInterrupt: print("\nStream beendet.")

Erweiterte Konfiguration: Orderbook-Tiefe und Filter

Je nach Anwendungsfall benötigen Sie unterschiedliche Orderbook-Tiefen. Im folgenden Beispiel zeige ich erweiterte Filteroptionen und die Integration mit mehreren Symbolen gleichzeitig.

#!/usr/bin/env python3
"""
Erweiterte Bybit Orderbook-Konfiguration
Multi-Symbol Support mit gefilterter Orderbook-Tiefe
"""

import asyncio
import json
from dataclasses import dataclass
from typing import List, Dict, Optional
from enum import Enum

class OrderbookDepth(Enum):
    """Verfügbare Orderbook-Tiefen bei Bybit"""
    LEVEL_50 = 50    # 50 Ebenen (Standard)
    LEVEL_200 = 200  # 200 Ebenen
    LEVEL_500 = 500  # 500 Ebenen (nur für VIP)

class OrderbookFilter:
    """
    Filter-Konfiguration für Orderbook-Updates
    Reduziert Datenmenge und Verarbeitungslast
    """
    
    def __init__(
        self,
        min_price_change: float = 0.01,
        min_volume: float = 0.001,
        max_entries: int = 100,
        price_precision: int = 2
    ):
        self.min_price_change = min_price_change
        self.min_volume = min_volume
        self.max_entries = max_entries
        self.price_precision = price_precision
    
    def apply(self, orderbook_data: Dict) -> Dict:
        """
        Wendet Filter auf Orderbook-Daten an
        """
        filtered = {"bids": [], "asks": []}
        
        for side in ["bids", "asks"]:
            entries = orderbook_data.get(side, [])
            
            # Filter nach Mindestvolumen
            filtered_entries = [
                entry for entry in entries
                if float(entry[1]) >= self.min_volume
            ]
            
            # Limit auf maximale Einträge
            filtered_entries = filtered_entries[:self.max_entries]
            
            # Preise runden
            for price, volume in filtered_entries:
                rounded_price = round(float(price), self.price_precision)
                filtered[side].append([rounded_price, float(volume)])
            
            # Sortieren: Bids absteigend, Asks aufsteigend
            if side == "bids":
                filtered[side].sort(key=lambda x: x[0], reverse=True)
            else:
                filtered[side].sort(key=lambda x: x[0])
        
        return filtered


@dataclass
class SymbolConfig:
    """Konfiguration für einzelnes Trading-Symbol"""
    symbol: str
    depth: OrderbookDepth
    filters: Optional[OrderbookFilter] = None


class MultiSymbolOrderbookCollector:
    """
    Sammelt Orderbook-Daten von mehreren Bybit Perpetual Symbols
    mit individueller Konfiguration pro Symbol
    """
    
    def __init__(self):
        self.symbols: Dict[str, SymbolConfig] = {}
        self.orderbooks: Dict[str, Dict] = {}
        self.subscribed = False
    
    def add_symbol(
        self,
        symbol: str,
        depth: OrderbookDepth = OrderbookDepth.LEVEL_50,
        filters: Optional[OrderbookFilter] = None
    ):
        """
        Fügt ein Symbol zur Überwachung hinzu
        """
        self.symbols[symbol] = SymbolConfig(
            symbol=symbol,
            depth=depth,
            filters=filters
        )
        
        # Initialisiere leeres Orderbook
        self.orderbooks[symbol] = {
            "bids": [],
            "asks": [],
            "last_update": None
        }
        
        print(f"Symbol {symbol} hinzugefügt (Tiefe: {depth.value})")
    
    def remove_symbol(self, symbol: str):
        """
        Entfernt ein Symbol aus der Überwachung
        """
        if symbol in self.symbols:
            del self.symbols[symbol]
            del self.orderbooks[symbol]
            print(f"Symbol {symbol} entfernt")
    
    def generate_subscription_message(self) -> List[Dict]:
        """
        Generiert Subscribe-Nachrichten für alle konfigurierten Symbole
        """
        subscriptions = []
        
        for symbol, config in self.symbols.items():
            # Bybit Topic-Format: orderbook.{depth}.{symbol}
            topic = f"orderbook.{config.depth.value}.{symbol}"
            
            subscriptions.append({
                "op": "subscribe",
                "args": [topic]
            })
        
        return subscriptions
    
    def process_update(self, symbol: str, data: Dict):
        """
        Verarbeitet ein Orderbook-Update und wendet Filter an
        """
        if symbol not in self.symbols:
            return
        
        config = self.symbols[symbol]
        raw_data = {"bids": [], "asks": []}
        
        # Extrahiere Daten aus Bybit-Format
        if "b" in data:
            raw_data["bids"] = data["b"]
        if "a" in data:
            raw_data["asks"] = data["a"]
        
        # Wende Filter an falls konfiguriert
        if config.filters:
            processed = config.filters.apply(raw_data)
        else:
            processed = raw_data
        
        # Speichere verarbeitete Daten
        self.orderbooks[symbol] = {
            "bids": processed["bids"],
            "asks": processed["asks"],
            "last_update": asyncio.get_event_loop().time()
        }
    
    def get_spread_info(self, symbol: str) -> Optional[Dict]:
        """
        Berechnet Spread-Informationen für ein Symbol
        """
        if symbol not in self.orderbooks:
            return None
        
        orderbook = self.orderbooks[symbol]
        
        if not orderbook["bids"] or not orderbook["asks"]:
            return None
        
        best_bid = float(orderbook["bids"][0][0])
        best_ask = float(orderbook["asks"][0][0])
        spread = best_ask - best_bid
        spread_pct = (spread / best_bid) * 100
        
        return {
            "symbol": symbol,
            "best_bid": best_bid,
            "best_ask": best_ask,
            "spread": spread,
            "spread_pct": spread_pct
        }
    
    def get_market_depth(self, symbol: str, levels: int = 10) -> Optional[Dict]:
        """
        Berechnet Markttiefe (kumuliertes Volumen) für ein Symbol
        """
        if symbol not in self.orderbooks:
            return None
        
        orderbook = self.orderbooks[symbol]
        
        bid_depth = []
        ask_depth = []
        cum_bid = 0
        cum_ask = 0
        
        for price, volume in orderbook["bids"][:levels]:
            cum_bid += float(volume)
            bid_depth.append({"price": float(price), "volume": float(volume), "cum_volume": cum_bid})
        
        for price, volume in orderbook["asks"][:levels]:
            cum_ask += float(volume)
            ask_depth.append({"price": float(price), "volume": float(volume), "cum_volume": cum_ask})
        
        return {
            "symbol": symbol,
            "bid_depth": bid_depth,
            "ask_depth": ask_depth,
            "total_bid_volume": cum_bid,
            "total_ask_volume": cum_ask,
            "depth_ratio": cum_bid / cum_ask if cum_ask > 0 else 0
        }


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

KONFIGURATIONS-BEISPIEL

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

if __name__ == "__main__": # Initialisiere Multi-Symbol Collector collector = MultiSymbolOrderbookCollector() # Füge Symbols mit verschiedenen Konfigurationen hinzu collector.add_symbol( symbol="BTCUSDT", depth=OrderbookDepth.LEVEL_50, filters=OrderbookFilter( min_volume=0.01, max_entries=50, price_precision=2 ) ) collector.add_symbol( symbol="ETHUSDT", depth=OrderbookDepth.LEVEL_200, filters=OrderbookFilter( min_volume=0.1, max_entries=100 ) ) collector.add_symbol( symbol="SOLUSDT", depth=OrderbookDepth.LEVEL_50 ) # Generiere Subscription-Nachrichten subscriptions = collector.generate_subscription_message() print("\n" + "=" * 60) print("Subscription-Nachrichten für Bybit WebSocket:") print("=" * 60) for sub in subscriptions: print(json.dumps(sub, indent=2)) # Simuliere Orderbook-Update collector.process_update("BTCUSDT", { "b": [["65000.00", "1.5"], ["64999.50", "2.3"]], "a": [["65001.00", "1.2"], ["65002.00", "0.8"]] }) # Zeige Spread-Informationen spread_info = collector.get_spread_info("BTCUSDT") if spread_info: print("\n" + "=" * 60) print(f"Spread für {spread_info['symbol']}:") print("=" * 60) print(f" Bid: ${spread_info['best_bid']:.2f}") print(f" Ask: ${spread_info['best_ask']:.2f}") print(f" Spread: ${spread_info['spread']:.2f} ({spread_info['spread_pct']:.4f}%)") # Zeige Markttiefe depth_info = collector.get_market_depth("BTCUSDT", levels=5) if depth_info: print("\n" + "=" * 60) print(f"Markttiefe für {depth_info['symbol']}:") print("=" * 60) print(f" Bid/Ask Ratio: {depth_info['depth_ratio']:.2f}") print(f" Bid Volumen (Top 5): {depth_info['total_bid_volume']:.4f}") print(f" Ask Volumen (Top 5): {depth_info['total_ask_volume']:.4f}")

Häufige Fehler und Lösungen

Fehler 1: Rate-Limit Überschreitung (HTTP 429)

Problem: Bei zu häufigen API-Aufrufen 返回iert Bybit einen 429-Fehler mit "Too many requests".

# FEHLERHAFT - Führt zu Rate-Limit
for symbol in symbols:
    response = requests.get(f"{BYBIT_API_URL}/{symbol}/orderbook")  # Alle gleichzeitig!

LÖSUNG: Exponential Backoff mit gestaffelten Requests

import time from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry class RateLimitHandler: """ Behandelt Bybit Rate-Limits mit Exponential Backoff """ def __init__(self, max_retries: int = 5): self.max_retries = max_retries self.session = self._create_session() self.request_times = {} # Track pro Symbol def _create_session(self) -> requests.Session: """Erstellt Session mit Retry-Strategie""" session = requests.Session() retry_strategy = Retry( total=5, backoff_factor=1, status_forcelist=[429, 500, 502, 503, 504], allowed_methods=["GET"] ) adapter = HTTPAdapter(max_retries=retry_strategy) session.mount("https://", adapter) session.mount("http://", adapter) return session def wait_if_needed(self, symbol: str, min_interval: float = 0.1): """ Wartet zwischen Requests für dasselbe Symbol Verhindert Burst-Requests """ current_time = time.time() if symbol in self.request_times: elapsed = current_time - self.request_times[symbol] if elapsed < min_interval: time.sleep(min_interval - elapsed) self.request_times[symbol] = time.time() def fetch_with_retry(self, url: str, symbol: str) -> Optional[Dict]: """ Führt Request mit automatischem Retry bei Rate-Limits durch """ self.wait_if_needed(symbol) for attempt in range(self.max_retries): try: response = self.session.get(url, timeout=10) if response.status_code == 200: return response.json() elif response.status_code == 429: # Rate-Limit: Warte länger und wiederhole wait_time = 2 ** attempt # Exponential: 2, 4, 8, 16, 32s print(f"Rate-Limit für {symbol}, warte {wait_time}s...") time.sleep(wait_time) else: response.raise_for_status() except requests.exceptions.RequestException as e: if attempt == self.max_retries - 1: print(f"Request fehlgeschlagen nach {self.max_retries} Versuchen: {e}") return None time.sleep(2 ** attempt) return None

Nutzung:

handler = RateLimitHandler() result = handler.fetch_with_retry( f"{BYBIT_API_URL}/v5/market/orderbook?category=linear&symbol=BTCUSDT", "BTCUSDT" )

Fehler 2: WebSocket Reconnection Loop

Problem: Nach einem Verbindungsabbruch versucht das System sofortige Neuverbindung ohne Pause, was zu permanentem Reconnect führt.

# FEHLERHAFT - Endlosschleife ohne Pause
def on_close(ws):
    while True:
        try:
            ws.run_forever()  # Sofortiger Reconnect!
        except:
            pass

LÖSUNG: Controlled Reconnection mit Backoff

import random class WebSocketManager: """ Verwaltet WebSocket-Verbindungen mit kontrolliertem Reconnect """ def __init__(self, url: str): self.url = url self.ws = None self.reconnect_attempts = 0 self.max_reconnect_delay = 300 # Max 5 Minuten def should_reconnect(self) -> bool: """Prüft ob Reconnect versucht werden soll""" max_attempts = 100 return self.reconnect_attempts < max_attempts def get_reconnect_delay(self) -> float: """ Berechnet Reconnect-Verzögerung mit Jitter Formel: min(base * 2^attempt, max) + random_jitter """ base_delay = 1 exponential_delay = min(base_delay * (2 ** self.reconnect_attempts), 30) # Jitter: +/- 20% Zufall, um Thundering Herd zu vermeiden jitter = exponential_delay * 0.2 * (random.random() - 0.5) return exponential_delay + jitter def connect(self): """Stellt Verbindung her mit automatischer Verwaltung""" while self.should_reconnect(): delay = self.get_reconnect_delay() print(f"Verbindungsversuch {self.reconnect_attempts + 1} in {delay:.1f}s...") time.sleep(delay) try: self.ws = websocket.create_connection( self.url, timeout=30, ping_interval=20, ping_timeout=10 ) print("Verbindung erfolgreich hergestellt!") self.reconnect_attempts = 0 return True except websocket.WebSocketTimeoutException: print("Verbindung timeout, erneuter Versuch...") self.reconnect_attempts += 1 except websocket.WebSocketException as e: print(f"WebSocket Fehler: {e}") self.reconnect_attempts += 1 print("Maximale Reconnect-Versuche erreicht") return False def handle_disconnect(self): """Behandelt Verbindungsabbruch elegant""" if self.ws: try: self.ws.close() except: pass print("Verbindung verloren, Reconnect wird vorbereitet...") self.connect()

Fehler 3: Orderbook-Dateninkonsistenz

Problem: Bei schnellen Updates kann das Orderbook inkonsistent werden, wenn Updates in falscher Reihenfolge verarbeitet werden.

# FEHLERHAFT - Keine Sequenzprüfung
def process_update(self, bids, asks):
    self.orderbook["bids"] = bids  # Keine Validierung!
    self.orderbook["asks"] = asks

LÖSUNG: Sequenzvalidierung mit Versionskontrolle

from dataclasses import dataclass, field from typing import Optional from collections import deque @dataclass class OrderbookSnapshot: """Strukturierter Orderbook-Stand mit Metadaten""" seq_num: int timestamp: float bids: list asks: list version: int = 0 class ConsistentOrderbookManager: """ Verwaltet konsistentes Orderbook mit Sequenzvalidierung """ def __init__(self, max_history: int = 1000): self.current = OrderbookSnapshot(0, 0, [], []) self.pending_updates = deque(maxlen=max_history) self.last_validated_seq = 0 def validate_sequence(self, new_seq: int) -> bool: """ Validiert Sequenznummer auf Lücken oder Duplikate """ expected_next = self.last_validated_seq + 1 if new_seq < expected_next: # Duplikat oder alte Nachricht print(f"Duplikat/veraltete Nachricht: {new_seq} (erwartet >={expected_next})") return False if new_seq > expected_next: # Lücke erkannt print(f"Sequenzlücke: {new_seq} (erwartet {expected_next})") self._request_snapshot() return False return True def _request_snapshot(self): """ Fordert vollständigen Orderbook-Snapshot an bei Lücken """ print("Anfrage auf vollständigen Snapshot...") # Implementierung abhängig von Bybit API # POST /v5/market/orderbook/snapshot def apply_update(self, seq_num: int, timestamp: float, bids: list, asks: list) -> bool: """ Wendet Orderbook-Update mit Sequenzvalidierung an """ if not self.validate_sequence(seq_num): return False # Verarbeite Update basierend auf Typ if self._is_snapshot(seq_num): # Vollständiger Snapshot self.current = OrderbookSnapshot( seq_num=seq_num, timestamp=timestamp, bids=self._sort_bids(bids), asks=self._sort_asks(asks), version=self.current.version + 1 ) else: # Inkrementelles Update self.current.bids = self._merge_orders(self.current.bids, bids) self.current.asks = self._merge_orders(self.current.asks, asks) self.current.seq_num = seq_num self.current.timestamp = timestamp self.current.version += 1 self.last_validated_seq = seq_num return True def _is_snapshot(self, seq_num: int) -> bool: """Erkennt Snapshots (z.B. seq_num = 0 oder sehr große Sprünge)""" return seq_num == 0 or seq_num > self.last_validated_seq + 100 def _sort_bids(self, bids: list) -> list: """Sortiert Bids absteigend nach Preis""" return sorted(bids, key=lambda x: float(x[0]), reverse=True) def _sort_asks(self, asks: list) -> list: """Sortiert Asks aufsteigend nach Preis""" return sorted(asks, key=lambda x: float(x[0])) def _merge_orders(self, existing: list, updates: list) -> list: """ Führt Order-Updates mit bestehendem Orderbook zusammen Entfernt Orders mit Menge 0 """ order_dict = {float(price): float(qty) for price, qty in existing} for price, qty in updates: price_f = float(price) qty_f = float(qty) if qty_f == 0: order_dict.pop(price_f, None) else: order_dict