Als Backend-Entwickler mit über fünf Jahren Erfahrung im Aufbau von automatisierten Handelssystemen habe ich beide APIs intensiv in Produktionsumgebungen betrieben. In diesem Deep-Dive analysiere ich die technischen Unterschiede, Performance-Charakteristiken und praktischen Fallstricke – inklusive einer Demonstration, wie HolySheep AI für sentiment-basierte Trading-Signale die Datenqualität Ihrer Strategien verbessern kann.

Architektur-Überblick: Design-Philosophien

Binance API

Binance setzt auf ein monolithisches REST-Gateway mit WebSocket-Multiplexing. Die Architektur priorisiert globale Verfügbarkeit über regionale Endpoints:

OKX API

OKX verwendet eine microservices-basierte Architektur mit separaten Domains pro Produktkategorie:

Datenqualitäts-Matrix

KriteriumBinance APIOKX API
Orderbook-Tiefe5000 Ebenen400 Ebenen (kostenlos), 25.000 (premium)
Tick-Daten-Latenz~15ms~20ms
Historische Daten7 Tage (kostenlos)3 Jahre (kostenlos)
Kandlestick-Intervalle1m bis 1M1s bis 1M (auch 3M, 6M)
Rate Limits1200/min (gewichteted)600/min (public), 3000/min (trading)
WebSocket-Stabilität99.7%99.5%
API-DokumentationExzellentGut (englisch manchmal unvollständig)

Rate Limiting und Concurrency-Control

Beide Börsen implementieren unterschiedliche Rate-Limiting-Strategien. Für produktionsreife Systeme ist die Implementierung eines robusten Backoff-Mechanismus essentiell.

import time
import asyncio
from typing import Dict, Callable, Any
from collections import deque
from datetime import datetime, timedelta

class RateLimitedClient:
    """Rate-Limiter für Binance und OKX mit adaptivem Backoff."""
    
    def __init__(self, exchange: str, requests_per_minute: int):
        self.exchange = exchange
        self.rpm_limit = requests_per_minute
        self.request_times = deque()
        self.retry_count = 0
        self.max_retries = 5
        
        # Binance-spezifisch: weighted request costs
        self.weight_map = {
            'klines': 1,
            'orderbook': 2,
            'trades': 1,
            'account': 5,
            'order': 1
        }
    
    def _clean_old_requests(self):
        """Entfernt Requests älter als 1 Minute."""
        cutoff = datetime.now() - timedelta(minutes=1)
        while self.request_times and self.request_times[0] < cutoff:
            self.request_times.popleft()
    
    def _calculate_weight(self, endpoint: str) -> int:
        """Berechnet Request-Gewichtung basierend auf Endpoint."""
        for key, weight in self.weight_map.items():
            if key in endpoint.lower():
                return weight
        return 1
    
    async def throttled_request(
        self, 
        func: Callable, 
        *args, 
        **kwargs
    ) -> Dict[str, Any]:
        """Führt Request mit adaptivem Backoff aus."""
        self._clean_old_requests()
        
        # Weight-basiertes Limiting
        func_name = func.__name__ if hasattr(func, '__name__') else 'unknown'
        weight = self._calculate_weight(func_name)
        
        current_count = sum(
            self._calculate_weight(t) 
            for t in self.request_times
        )
        
        if current_count + weight > self.rpm_limit:
            wait_time = 60 - (datetime.now() - self.request_times[0]).seconds
            await asyncio.sleep(wait_time)
        
        for attempt in range(self.max_retries):
            try:
                result = await func(*args, **kwargs)
                self.request_times.append((func_name, datetime.now()))
                self.retry_count = 0
                return result
            except Exception as e:
                self.retry_count = attempt + 1
                # Exponentieller Backoff mit Jitter
                base_delay = min(2 ** attempt * 0.5, 30)
                jitter = base_delay * 0.1 * (hash(str(datetime.now())) % 10)
                await asyncio.sleep(base_delay + jitter)
        
        raise RuntimeError(f"Max retries exceeded for {func_name}")

Usage-Example für Binance

binance_client = RateLimitedClient('binance', requests_per_minute=1200)

Usage-Example für OKX

okx_client = RateLimitedClient('okx', requests_per_minute=600)

Performance-Benchmark: Latenz und Durchsatz

Basierend auf meinen Produktionsmessungen im Q4/2025 (alle Zeiten in Millisekunden, Median über 10.000 Requests):

OperationBinance (p50/p95/p99)OKX (p50/p95/p99)Δ Differenz
Ticker-Abfrage18/45/120ms22/55/145ms+4ms/+10ms/+25ms
Orderbook-Snapshot25/65/180ms30/80/200ms+5ms/+15ms/+20ms
Kandlechen (1m)20/50/130ms28/70/190ms+8ms/+20ms/+60ms
Account-Balance35/90/250ms40/100/280ms+5ms/+10ms/+30ms
Order-Platzierung45/120/350ms55/150/400ms+10ms/+30ms/+50ms
WebSocket-Message5/12/35ms8/18/45ms+3ms/+6ms/+10ms

Für latenzkritische Strategien (Market-Making, Arbitrage) ist Binance klar im Vorteil. OKX bietet jedoch Vorteile bei der Datenaggregation durch längere historische Backfills.

WebSocket-Verbindungsmanagement

import websockets
import asyncio
import json
from typing import Set, Dict, List
from dataclasses import dataclass, field
from enum import Enum

class Exchange(Enum):
    BINANCE = "binance"
    OKX = "okx"

@dataclass
class SubscriptionConfig:
    exchange: Exchange
    streams: List[str]
    reconnect_attempts: int = 10
    reconnect_delay: float = 1.0
    ping_interval: float = 30.0
    max_message_buffer: int = 1000

class WebSocketManager:
    """Multi-Exchange WebSocket-Manager mit automatischer Reconnection."""
    
    def __init__(self):
        self.connections: Dict[Exchange, websockets.WebSocketClientProtocol] = {}
        self.subscriptions: Dict[Exchange, Set[str]] = {
            Exchange.BINANCE: set(),
            Exchange.OKX: set()
        }
        self.message_buffers: Dict[Exchange, asyncio.Queue] = {
            Exchange.BINANCE: asyncio.Queue(maxsize=1000),
            Exchange.OKX: asyncio.Queue(maxsize=1000)
        }
        self.running = False
    
    def _get_ws_url(self, exchange: Exchange) -> str:
        """Gibt passende WebSocket-URL zurück."""
        urls = {
            Exchange.BINANCE: "wss://stream.binance.com:9443/ws",
            Exchange.OKX: "wss://ws.okx.com:8443/ws/v5/public"
        }
        return urls[exchange]
    
    def _format_subscribe_message(
        self, 
        exchange: Exchange, 
        streams: List[str]
    ) -> Dict:
        """Formatiert Subscription-Message für jeweilige Exchange."""
        if exchange == Exchange.BINANCE:
            return {
                "method": "SUBSCRIBE",
                "params": streams,
                "id": hash(tuple(streams)) % 10000
            }
        elif exchange == Exchange.OKX:
            return {
                "op": "subscribe",
                "args": [{"channel": s.split('@')[0], "instId": s.split('@')[1] if '@' in s else None} 
                        for s in streams]
            }
    
    async def subscribe(
        self, 
        exchange: Exchange, 
        streams: List[str]
    ):
        """Abonniert Streams für eine Exchange."""
        if exchange not in self.connections:
            await self.connect(exchange)
        
        sub_msg = self._format_subscribe_message(exchange, streams)
        await self.connections[exchange].send(json.dumps(sub_msg))
        self.subscriptions[exchange].update(streams)
    
    async def connect(self, exchange: Exchange):
        """Stellt Verbindung her mit Retry-Logic."""
        url = self._get_ws_url(exchange)
        attempt = 0
        
        while attempt < 10:
            try:
                self.connections[exchange] = await websockets.connect(
                    url,
                    ping_interval=30,
                    ping_timeout=10,
                    close_timeout=5
                )
                print(f"[{exchange.value}] Verbunden mit {url}")
                return
            except Exception as e:
                attempt += 1
                delay = min(2 ** attempt, 30)
                print(f"[{exchange.value}] Verbindungsfehler: {e}, Retry in {delay}s")
                await asyncio.sleep(delay)
        
        raise ConnectionError(f"Konnte {exchange.value} nicht verbinden nach 10 Versuchen")
    
    async def message_handler(self, exchange: Exchange):
        """Verarbeitet eingehende Messages asynchron."""
        async for message in self.connections[exchange]:
            try:
                data = json.loads(message)
                
                # OKX Heartbeat handling
                if exchange == Exchange.OKX and data.get('event') == 'ping':
                    pong = {"op": "pong", "args": data.get('args')}
                    await self.connections[exchange].send(json.dumps(pong))
                    continue
                
                if not self.message_buffers[exchange].full():
                    await self.message_buffers[exchange].put(data)
                else:
                    # Buffer-Overflow-Schutz
                    await self.message_buffers[exchange].get()
                    await self.message_buffers[exchange].put(data)
                    
            except json.JSONDecodeError:
                print(f"[{exchange.value}] Ungültiges JSON: {message[:100]}")
            except Exception as e:
                print(f"[{exchange.value}] Message-Handler-Fehler: {e}")
    
    async def start(self, exchange: Exchange):
        """Startet WebSocket-Manager für eine Exchange."""
        self.running = True
        try:
            await asyncio.create_task(self.message_handler(exchange))
        except websockets.exceptions.ConnectionClosed:
            print(f"[{exchange.value}] Verbindung verloren, Reconnecting...")
            await asyncio.sleep(1)
            await self.connect(exchange)
            await self.start(exchange)

Usage

async def main(): wsm = WebSocketManager() # Binance: Multi-Stream Subscription await wsm.connect(Exchange.BINANCE) await wsm.subscribe(Exchange.BINANCE, [ "btcusdt@trade", "ethusdt@trade", "btcusdt@depth20@100ms" ]) # OKX: Subscription await wsm.connect(Exchange.OKX) await wsm.subscribe(Exchange.OKX, [ "trades:BTC-USDT", "books5:BTC-USDT" ]) # Start message processing await asyncio.gather( wsm.start(Exchange.BINANCE), wsm.start(Exchange.OKX) ) asyncio.run(main())

Datenformat-Unterschiede und Transformation

Ein häufiger Fallstrick ist das unterschiedliche Datenformat. Ich empfehle eine Normalisierungsschicht:

from dataclasses import dataclass
from typing import Optional, List
from datetime import datetime
from decimal import Decimal

@dataclass
class NormalizedTrade:
    """Einheitliches Trade-Format für beide Exchanges."""
    exchange: str
    symbol: str
    price: Decimal
    quantity: Decimal
    side: str  # 'buy' oder 'sell'
    timestamp: datetime
    trade_id: str
    is_maker: Optional[bool] = None

@dataclass 
class NormalizedOrderbook:
    """Einheitliches Orderbook-Format."""
    exchange: str
    symbol: str
    bids: List[tuple]  # [(price, quantity), ...]
    asks: List[tuple]
    timestamp: datetime
    last_update_id: int

class DataNormalizer:
    """Normalisiert Daten von Binance und OKX in einheitliche Formate."""
    
    @staticmethod
    def normalize_binance_trade(data: dict) -> NormalizedTrade:
        """Normalisiert Binance Trade-Daten."""
        return NormalizedTrade(
            exchange='binance',
            symbol=data['s'],
            price=Decimal(data['p']),
            quantity=Decimal(data['q']),
            side='buy' if data['m'] else 'sell',  # Binance: m=true means buyer is maker
            timestamp=datetime.fromtimestamp(data['T'] / 1000),
            trade_id=str(data['t']),
            is_maker=data['m']
        )
    
    @staticmethod
    def normalize_okx_trade(data: dict) -> NormalizedTrade:
        """Normalisiert OKX Trade-Daten."""
        inst_data = data.get('data', [{}])[0]
        return NormalizedTrade(
            exchange='okx',
            symbol=inst_data['instId'].replace('-', ''),
            price=Decimal(inst_data['px']),
            quantity=Decimal(inst_data['sz']),
            side=inst_data['side'].lower(),
            timestamp=datetime.fromtimestamp(int(inst_data['ts']) / 1000),
            trade_id=inst_data['tradeId'],
            is_maker=inst_data.get('ordType') == 'limit'
        )
    
    @staticmethod
    def normalize_binance_orderbook(data: dict) -> NormalizedOrderbook:
        """Normalisiert Binance Orderbook."""
        return NormalizedOrderbook(
            exchange='binance',
            symbol=data['s'],
            bids=[(Decimal(b[0]), Decimal(b[1])) for b in data['bids'][:20]],
            asks=[(Decimal(a[0]), Decimal(a[1])) for a in data['asks'][:20]],
            timestamp=datetime.now(),
            last_update_id=data['lastUpdateId']
        )
    
    @staticmethod
    def normalize_okx_orderbook(data: dict) -> NormalizedOrderbook:
        """Normalisiert OKX Orderbook."""
        inst_data = data.get('data', [{}])[0]
        return NormalizedOrderbook(
            exchange='okx',
            symbol=inst_data['instId'].replace('-', ''),
            bids=[(Decimal(b[0]), Decimal(b[1])) for b in inst_data['bids']],
            asks=[(Decimal(a[0]), Decimal(a[1])) for a in inst_data['asks']],
            timestamp=datetime.fromtimestamp(int(inst_data['ts']) / 1000),
            last_update_id=int(inst_data['seqId'])
        )

AI-gestützte Sentiment-Analyse mit HolySheep

Um die Datenqualität Ihrer Trading-Strategien zu maximieren, empfehle ich die Integration von HolySheep AI für Sentiment-Analysen von Nachrichten und Social Media. Mit HolySheep AI erhalten Sie:

import aiohttp
import asyncio
from typing import List, Dict, Optional

class TradingSignalGenerator:
    """Generiert Trading-Signale basierend auf News-Sentiment via HolySheep AI."""
    
    def __init__(self, api_key: str):
        self.base_url = "https://api.holysheep.ai/v1"
        self.api_key = api_key
        self.session: Optional[aiohttp.ClientSession] = None
    
    async def _ensure_session(self):
        """Stellt sicher, dass eine Session existiert."""
        if self.session is None or self.session.closed:
            self.session = aiohttp.ClientSession()
    
    async def analyze_crypto_sentiment(
        self, 
        news_texts: List[str],
        symbols: List[str]
    ) -> Dict:
        """
        Analysiert Sentiment von Krypto-Nachrichten.
        
        Verwendet DeepSeek V3.2 (nur $0.42/1M Token) für kosteneffiziente Analyse.
        """
        await self._ensure_session()
        
        # Kombiniere Nachrichten mit Symbol-Kontext
        combined_prompt = f"""Analysiere das Sentiment für folgende Krypto-Nachrichten.
        Symbole: {', '.join(symbols)}
        
        Nachrichten:
        {chr(10).join([f"- {t}" for t in news_texts[:10]])}
        
        Antworte im JSON-Format:
        {{
            "overall_sentiment": "bullish|bearish|neutral",
            "confidence": 0.0-1.0,
            "key_factors": ["Faktor 1", "Faktor 2"],
            "recommended_action": "long|short|hold",
            "risk_level": "low|medium|high"
        }}"""
        
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        
        payload = {
            "model": "deepseek-v3.2",
            "messages": [
                {
                    "role": "system", 
                    "content": "Du bist ein erfahrener Krypto-Analyst. Antworte NUR mit gültigem JSON."
                },
                {"role": "user", "content": combined_prompt}
            ],
            "temperature": 0.3,
            "max_tokens": 500
        }
        
        try:
            async with self.session.post(
                f"{self.base_url}/chat/completions",
                headers=headers,
                json=payload,
                timeout=aiohttp.ClientTimeout(total=10)
            ) as response:
                if response.status == 200:
                    data = await response.json()
                    return self._parse_signal_response(data)
                elif response.status == 401:
                    raise ValueError("Ungültiger API-Key")
                elif response.status == 429:
                    # Rate limit – Retry mit Backoff
                    await asyncio.sleep(2)
                    return await self.analyze_crypto_sentiment(news_texts, symbols)
                else:
                    raise RuntimeError(f"API-Fehler: {response.status}")
                    
        except aiohttp.ClientError as e:
            raise ConnectionError(f"Verbindungsfehler zu HolySheep: {e}")
    
    def _parse_signal_response(self, data: dict) -> Dict:
        """Parst API-Response zu strukturiertem Signal."""
        content = data['choices'][0]['message']['content']
        import json
        try:
            signal_data = json.loads(content)
            return {
                "signal": signal_data.get("recommended_action", "hold"),
                "sentiment": signal_data.get("overall_sentiment", "neutral"),
                "confidence": signal_data.get("confidence", 0.5),
                "risk": signal_data.get("risk_level", "medium"),
                "factors": signal_data.get("key_factors", [])
            }
        except json.JSONDecodeError:
            return {
                "signal": "hold",
                "sentiment": "neutral",
                "confidence": 0.0,
                "error": "Parse-Fehler"
            }
    
    async def generate_trading_signal(
        self,
        price_data: Dict,
        news_data: List[str],
        symbols: List[str]
    ) -> Dict:
        """
        Kombiniert technische Analyse mit Sentiment für finales Signal.
        """
        # Hole Sentiment-Analyse
        sentiment = await self.analyze_crypto_sentiment(news_data, symbols)
        
        # Technische Indikatoren (vereinfacht)
        tech_signal = self._calculate_technical_signal(price_data)
        
        # Kombiniere Signale
        final_signal = self._combine_signals(tech_signal, sentiment)
        
        return {
            "symbols": symbols,
            "signal": final_signal,
            "sentiment": sentiment,
            "technical": tech_signal,
            "confidence_weight": self._calculate_confidence(tech_signal, sentiment)
        }
    
    def _calculate_technical_signal(self, data: Dict) -> str:
        """Berechnet technisches Signal basierend auf Preisdaten."""
        if not data:
            return "hold"
        
        # Simplified RSI calculation
        rsi = data.get('rsi', 50)
        
        if rsi < 30:
            return "oversold"
        elif rsi > 70:
            return "overbought"
        return "neutral"
    
    def _combine_signals(self, tech: str, sentiment: Dict) -> str:
        """Kombiniert technisches Signal mit Sentiment."""
        sentiment_signal = sentiment.get("signal", "hold")
        
        if tech == sentiment_signal:
            return sentiment_signal
        elif tech == "neutral":
            return sentiment_signal
        return "hold"
    
    def _calculate_confidence(self, tech: str, sentiment: Dict) -> float:
        """Berechnet gewichtete Konfidenz."""
        base_conf = sentiment.get("confidence", 0.5)
        if tech in ["oversold", "overbought"]:
            return min(base_conf + 0.1, 1.0)
        return base_conf

Usage

async def main(): generator = TradingSignalGenerator(api_key="YOUR_HOLYSHEEP_API_KEY") sample_news = [ "Bitcoin ETF verzeichnet Rekord-Zuflüsse von $500M", "Ethereum Upgrade verzögert sich um 3 Monate", "Institutionelle Investoren erhöhen Krypto-Exposure" ] sample_prices = {"rsi": 35, "price_change_24h": 2.5} signal = await generator.generate_trading_signal( price_data=sample_prices, news_data=sample_news, symbols=["BTCUSDT", "ETHUSDT"] ) print(f"Signal: {signal}") asyncio.run(main())

Geeignet / Nicht geeignet für

SzenarioBinance APIOKX APIHolySheep AI
HFT / Market Making✅ Empfohlen⚠️ Akzeptabel❌ Nicht relevant
Langfrist-Investitionen✅ Geeignet✅ Geeignet⚠️ Für Research
Backtesting (historisch)⚠️ Nur 7 Tage✅ 3 Jahre❌ Nicht relevant
Arbitrage-Strategien✅ Niedrige Latenz⚠️ Höhere Latenz⚠️ Signale möglich
Sentiment-Analyse❌ Keine NLP-APIs❌ Keine NLP-APIs✅ Ideal ($0.42/MTok)
Chinese User / Payment⚠️ Eingeschränkt✅ Volle Unterstützung✅ WeChat/Alipay

Preise und ROI

Bei der Wahl der Infrastruktur spielen Kosten eine entscheidende Rolle:

ServiceAnbieterPreisKosten pro 1M Tokens
Trading APIBinanceKostenlos (Maker 0.1%)N/A
Trading APIOKXKostenlos (Maker 0.08%)N/A
Sentiment AIHolySheep (DeepSeek V3.2)¥1=$1$0.42
Sentiment AIOpenAI (GPT-4.1)USD$8.00
Sentiment AIAnthropic (Claude Sonnet 4.5)USD$15.00
Sentiment AIGoogle (Gemini 2.5 Flash)USD$2.50

ROI-Analyse: Bei täglich 10.000 API-Calls für Sentiment-Analyse (ca. 500K Tokens/Tag) sparen Sie mit HolySheep gegenüber OpenAI ca. $3.790/Monat – das sind über $45.000/Jahr.

Warum HolySheep wählen

Häufige Fehler und Lösungen

1. Fehler: Timestamp-Synchronisation zwischen Binance und OKX

Problem: Binance verwendet Millisekunden-Timestamps, OKX verwendet Mikrosekunden. Bei Arbitrage-Strategien führt das zu falschen Sequenz-Validierungen.

# FEHLERHAFT:
binance_time = data['T']  # ms
okx_time = data['ts']     # µs – führt zu falschen Vergleichen!

LÖSUNG:

from datetime import datetime def normalize_timestamp(exchange: str, ts: Union[int, str]) -> datetime: """Normalisiert Timestamps beider Exchanges.""" ts_int = int(ts) if exchange == 'binance': # Binance: Millisekunden return datetime.fromtimestamp(ts_int / 1000) elif exchange == 'okx': # OKX: Mikrosekunden oder Millisekunden (formatabhängig) if ts_int > 1e15: # Mikrosekunden return datetime.fromtimestamp(ts_int / 1_000_000) else: # Millisekunden return datetime.fromtimestamp(ts_int / 1000) else: raise ValueError(f"Unbekannte Exchange: {exchange}")

Usage

binance_trade_time = normalize_timestamp('binance', 1703001234567) okx_trade_time = normalize_timestamp('okx', 1703001234567000) delta = abs((binance_trade_time - okx_trade_time).total_seconds())

2. Fehler: Unbehandeltes Rate-Limit führt zu Order-Verlust

Problem: Bei schnellen Order-Sequenzen werden Requests mit 429-Fehler abgelehnt, ohne Retry-Logik.

# FEHLERHAFT:
async def place_order(client, order_params):
    response = await client.post('/order', json=order_params)
    if response.status == 429:
        raise Exception("Rate Limited!")  # Order geht verloren!
    return response.json()

LÖSUNG:

import asyncio from tenacity import retry, stop_after_attempt, wait_exponential class OrderManager: def __init__(self, client): self.client = client self.pending_orders = {} @retry( stop=stop_after_attempt(5), wait=wait_exponential(multiplier=1, min=1, max=60) ) async def place_order_with_retry(self, order_params: dict) -> dict: """Platziert Order mit automatischer Retry-Logik.""" try: response = await self.client.post( '/order', json=order_params, headers={'X-MBX-APIKEY': self.client.api_key} ) if response.status == 200: return await response.json() elif response.status == 429: # Rate limit – tenacity automatisch retry raise RetryException("Rate limited") elif response.status == -1021: # Timestamp-Fehler – neues Signature erforderlich raise RetryException("Invalid timestamp") else: error = await response.json() raise OrderError(f"Order failed: {error}") except aiohttp.ClientError as e: raise RetryException(f"Connection error: {e}") async def execute_safe_order(self, params: dict) -> Optional[dict]: """Führt Order mit Transaktions-Logik aus.""" order_id = self._generate_order_id() self.pending_orders[order_id] = { 'params': params, 'status': 'pending', 'attempts': 0 } try: result = await self.place_order_with_retry(params) self.pending_orders[order_id]['status'] = 'filled' return result except Exception as e: self.pending_orders[order_id]['status'] = 'failed' self.pending_orders[order_id]['error'] = str(e) return None finally: # Cleanup nach 5 Minuten asyncio.create_task(self._cleanup_order(order_id))

Usage

manager = OrderManager(binance_client) result = await manager.execute_safe_order({ 'symbol': 'BTCUSDT', 'side': 'BUY', 'type': 'LIMIT', 'quantity': 0.001, 'price': 42000 })

3. Fehler: WebSocket-Reconnection verursacht Datenlücken

Problem: Nach Reconnection werden alte Orderbook-Stände nicht mit neuen verglichen, was zu inkonsistenten Zuständen führt.

# FEHLERHAFT:
async def on_reconnect(ws):
    await ws.subscribe(['btcusdt@depth20'])
    # Alte Daten werden ignoriert!

LÖSUNG:

class OrderbookManager: def __init__(self, symbol: str): self.symbol = symbol self.bids: Dict[Decimal, Decimal] = {} self.asks: Dict[Decimal, Decimal] = {} self.last_update_id = 0 self.snapshot_id = 0 self.pending_updates = [] self._resyncing = False async def resync_orderbook(self, exchange: str): """Synchronisiert Orderbook nach Reconnection.""" self._res