WebSocket-APIs für Echtzeit-Marktdaten: was bei der Integration schiefgeht.
REST-Polling fühlt sich einfach an, ist aber für Live-Trading meist die falsche Wahl. WebSocket-APIs liefern Marktdaten in Echtzeit per persistent connection — bringen dafür eine eigene Klasse von Bugs mit, die in keiner Broker-Doku stehen.
Ich habe in den letzten Jahren Dutzende WebSocket-Integrationen gegen IBKR, Binance, Polygon, Alpaca und kleinere Datenanbieter geschrieben. Jede einzelne hat mich mindestens einmal überrascht — meistens nachts, meistens während eines Marktevents. Dieser Artikel ist die Sammlung der Lektionen.
WebSocket vs. REST: wann lohnt sich der Wechsel?
REST ist Request–Response: Sie fragen, der Server antwortet, die Verbindung schließt. Für Quote-Updates bedeutet das Polling — alle 100 ms oder 500 ms eine neue Anfrage, mit allem Overhead (TCP-Handshake, TLS-Handshake, HTTP-Header). WebSocket dagegen ist eine persistent connection: ein Handshake am Anfang, danach fließen Updates server-pushed, mit minimalem Frame-Overhead.
Konkret: ein typischer REST-Poll auf Binance kostet 200–400 ms pro Quote. Per WebSocket bekomme ich dasselbe Update in 5–20 ms, ohne Polling-Overhead. Für jede Strategie unter H1 ist das nicht optional — bei M1- oder Tick-Strategien entscheidet es über Profitabilität.
- REST nutzen für: Orders, Account-Calls, einmalige Snapshots, niedrig-frequente Daten
- WebSocket nutzen für: Quotes, Trades, Order-Book-Updates, Order-Status-Events
Bibliotheken: Standard nehmen, nicht selbst bauen.
In Python gibt es zwei Klassiker:
websockets— async/await-basiert, modern, gut für asyncio-Projektewebsocket-client— synchrones Interface mit Callbacks, robust und etabliert
Ich nehme heute fast immer websockets, weil sich async sauber mit dem Rest
meiner Trading-Pipeline (Order-Routing, DB-Writes, Telegram) komponieren lässt.
Für ältere Codebasen oder kleine Skripte ist websocket-client ok.
Was Sie nicht machen sollten: WebSocket-Framing selbst implementieren. Ich habe in einem alten Projekt mal einen rohen TCP-Socket mit eigenem Frame-Parser gehabt — bei jedem zweiten Binance-Update brach er, weil die Bibliothek einen Edge-Case (zerteilte Frames bei großen Order-Books) nicht abbildete.
Reconnect-Logik: das Herzstück jeder Integration.
WebSockets brechen ab. Immer. Punkt. Broker führen Wartungen durch, Netzwerke haben Aussetzer, Load-Balancer rotieren. Wenn Ihr Bot auf eine einzige offene Verbindung baut, ist er nicht produktionsreif.
Der Standard: exponential backoff mit Jitter.
import asyncio, random, websockets
async def connect_forever(url, on_message):
delay = 1
while True:
try:
async with websockets.connect(url, ping_interval=20) as ws:
delay = 1 # reset nach erfolgreichem Connect
async for msg in ws:
await on_message(msg)
except Exception as e:
jitter = random.uniform(0, delay * 0.3)
wait = min(delay + jitter, 60)
await asyncio.sleep(wait)
delay = min(delay * 2, 60)
Wichtig: nach Reconnect müssen Sie alle Subscriptions neu anlegen. Der Server vergisst Ihre Stream-Abos, sobald die Verbindung weg ist. Ein häufiger Bug ist, dass nach Reconnect die Verbindung zwar steht, aber keine Daten mehr fließen, weil die Resubscribe-Logik fehlt.
Message-Ordering und Sequence-Validation.
Jeder ernsthafte Datenanbieter sendet eine Sequence-Number oder einen
Update-Counter pro Stream. Beispiel Binance Spot Diff-Depth: jedes Update enthält
U (first update id) und u (last update id). Wenn zwischen
zwei Messages eine Lücke ist, haben Sie ein Problem — das lokale Order-Book ist
korrupt.
Der korrekte Algorithmus für Binance Order-Book lokal halten:
- WebSocket-Stream öffnen, eingehende Diffs puffern
- REST-Snapshot des Order-Books holen, mit
lastUpdateId - Alle gepufferten Diffs mit
u≤lastUpdateIdverwerfen - Erstes verbleibendes Diff muss
U≤lastUpdateId + 1≤uerfüllen — sonst neu starten - Ab dann jeweils
U= previousu+ 1 prüfen — sonst neu starten
Bei Verletzung der Sequence: hartes Reset. Order-Book verwerfen, neuer Snapshot, neu aufbauen. Klingt brutal, ist aber die einzige saubere Lösung. Strategien, die auf einem inkonsistenten Order-Book handeln, verlieren leise und konstant.
Heartbeats und Stale-Connection-Detection.
Das Heimtückische an WebSocket: eine Verbindung kann „tot" sein, ohne dass das
close-Event ausgelöst wird. TCP merkt eine NAT-Disconnection oft erst
nach Minuten. In der Zwischenzeit hält Ihr Bot eine Verbindung für lebendig, die
längst keine Daten mehr empfängt.
Zwei Gegenmaßnahmen, die ich immer kombiniere:
- Protokoll-Heartbeats:
ping_interval=20, ping_timeout=10in derwebsockets-Lib. Sendet WS-Pings, schließt automatisch bei ausbleibender Pong-Antwort. - Anwendungs-Watchdog: pro Stream ein „last message received"-Timestamp. Wenn länger als X Sekunden (je nach Stream 5–60 s) nichts mehr kommt, Verbindung killen und reconnect erzwingen.
Den zweiten Punkt unterschätzen Anfänger gern. Aber gerade bei Binance ist es Realität, dass die TCP-Verbindung steht, die WS-Pings funktionieren — und trotzdem keine Trade-Updates mehr fließen, weil server-seitig der Stream verloren ging.
Daten-Quality-Checks.
Auch bei intakter Verbindung dürfen Sie den Daten nicht blind vertrauen. Häufige Probleme:
- Out-of-order Trades: Timestamp t+2 erreicht Sie vor t+1. Bei Aggregation für eine Tick-Strategie kann das Signale verfälschen. Lösung: nach Sequence-Number sortieren oder kleine Verzögerungs-Buffer.
- Duplicates: dieselbe Message zweimal. Vor allem nach Reconnect ist das normal. Lösung: Dedupe per Trade-ID oder Sequence-Number.
- Zero-Quotes: Bid oder Ask plötzlich 0 oder NaN. Passiert bei Maintenance-Windows. Lösung: hartes Filter — solche Updates verwerfen, Strategie pausieren.
- Stale-Quotes: Bid und Ask seit 30 Sekunden identisch. Bei volatilen Märkten ein Alarmzeichen.
Konkrete Broker-Eigenheiten.
IBKR WebSocket (TWS / Gateway)
IBKR ist ein Sonderfall: kein klassisches WebSocket gegen die API, sondern eine
proprietäre Socket-Verbindung gegen TWS oder IB Gateway. Die ib_insync-Library
kapselt das gut. Achten Sie auf: 50-Ticker-Limit pro Marktdaten-Subscription
(außer mit teurerem Bundle), Verbindungs-Reset bei jedem TWS-Auto-Restart (täglich!),
und unzuverlässige Reconnect-Events.
Binance Spot
Stabil, gut dokumentiert — aber: Streams werden nach 24h zwangsweise getrennt
(listenKey-Expiry bei User-Streams). Sie müssen alle 30 Minuten den Key
verlängern (PUT /api/v3/userDataStream) und alle 23h proaktiv neu connecten.
Wer das vergisst, verliert Order-Updates lautlos.
Polygon.io
Saubere API, gute Doku. Ein subtiler Punkt: aggregierte Bars (AM) kommen mit
etwa 0,5–1 s Verzögerung nach Bar-Close — wer auf die Bar reagiert, muss das
einplanen. Trades (T) und Quotes (Q) sind hingegen sehr schnell.
Häufige Bugs in der Praxis.
Memory-Leaks durch nicht-geschlossene Subscriptions
Symptom: Bot läuft, Speicher wächst über Stunden, irgendwann OOM-Kill. Ursache:
bei Reconnect wird ein neuer Stream-Handler erzeugt, der alte aber nicht sauber
beendet. Callbacks akkumulieren, Tasks häufen sich. Lösung: jeden Reconnect mit
sauberem Teardown — alle Tasks cancel()en, alle Callbacks deregistrieren.
Buffer-Overflows bei großen Order-Book-Streams
Bei BTC/USDT Diff-Depth fliegen leicht 100+ Messages pro Sekunde. Wenn Ihre
on_message-Funktion synchron in eine DB schreibt, läuft der WebSocket-Buffer
voll, die Lib wirft WebSocketException, alles bricht. Lösung: Producer-Consumer
mit asyncio-Queue. on_message macht nur Queue-Put, ein separater Worker
verarbeitet.
SSL-Zertifikatsfehler nach OS-Update
Klassiker auf älteren Ubuntu-VPS: ca-certificates ist veraltet, Broker
erneuert TLS-Zertifikat, plötzlich SSL-Handshake-Fehler. Lösung: apt update
in Wartungs-Routine, plus Monitoring auf TLS-Errors.
Meine Praxis.
Ich nutze WebSocket für alle Live-Strategien — REST nur für Order-Submissions und gelegentliche Snapshots. Pro Stream baue ich ein dünnes Wrapper-Modul mit: Reconnect-Loop, Resubscribe-Logik, Sequence-Validation, Heartbeat-Watchdog, Dedupe, Quality-Filter. Plus: extensives Logging in eine zentrale Timeseries-DB (Prometheus oder InfluxDB), inklusive Messages/Sek, Lücken-Counter, Reconnect-Counter, Latenz-Histogramm.
Bei jedem Reconnect, jedem Sequence-Bruch, jedem Quality-Filter-Hit landet ein strukturiertes Log-Event in der DB. Wenn nachts eine Strategie auffällig wird, kann ich am nächsten Morgen in 60 Sekunden sehen, ob der WebSocket sauber lief oder ob die Strategie auf korrupten Daten gehandelt hat.
Sie integrieren WebSocket-Datenfeeds für eine eigene Strategie und wollen typische Fehlerquellen ausschließen? Erstgespräch buchen — ich schaue mir Ihr Setup konkret an.