Interactive Brokers API mit Python: Praxis-Leitfaden.

Die IBKR-API ist mächtig — und gleichzeitig die unfreundlichste API, die ein Retail- oder Pro-Trader heute findet. Wer den Sprung schafft, bekommt Zugriff auf Börsen weltweit, sämtliche Asset-Klassen und institutionelle Execution. Dieser Leitfaden zeigt, wie Sie ohne Frust an dieses Ziel kommen.

Die Architektur verstehen.

Anders als moderne REST-APIs liegt zwischen Ihrem Python-Code und den IBKR-Servern immer eine lokale Gateway-Applikation: entweder die Trader Workstation (TWS) oder das schlankere IB Gateway. Beide sprechen Socket-Protokoll auf Port 7497 (Paper) bzw. 7496 (Live) für TWS, 4002/4001 für das Gateway. Erst diese Gateway-Apps halten den authentifizierten Login zur IBKR-Infrastruktur.

Für produktive Setups ist das IB Gateway die richtige Wahl — laut IBKR rund 40 Prozent weniger Ressourcenbedarf als TWS, schlankere Oberfläche, läuft gut auf einer VPS. Eine Anmeldung ohne grafische Oberfläche (headless) unterstützt IBKR allerdings ausdrücklich nicht: Auch das Gateway braucht ein Login-Fenster, auf einem Server erreichen Sie es typischerweise per Remote-Desktop oder VNC. TWS ist gut für Entwicklung und manuelles Eingreifen.

ibapi, ib_insync oder ib_async — die ehrliche Empfehlung.

Die offizielle Python-Library ibapi ist in ihrer klassischen Form callback-basiert, threadlastig und für Anfänger ein Albtraum. Viele produktive Python-Stacks nutzten deshalb jahrelang ib_insync von Ewald de Wit — eine asyncio-basierte Wrapper-Bibliothek, die den Code deutlich verkürzt. ib_insync wird jedoch nicht mehr gepflegt: Die letzte Version 0.9.86 stammt vom Juli 2023, das Repository ist archiviert. Frühere Mitstreiter führen die Bibliothek seit 2024 unter dem Namen ib_async weiter, mit weitgehend gleicher Struktur und gleichen Begriffen. Die Beispiele in diesem Leitfaden nutzen deshalb ib_async.

from ib_async import IB, Stock, MarketOrder, util

ib = IB()
ib.connect('127.0.0.1', 7497, clientId=1)

# Kontrakt definieren
aapl = Stock('AAPL', 'SMART', 'USD')
ib.qualifyContracts(aapl)

# Marktdaten anfordern (Snapshot)
ticker = ib.reqMktData(aapl, '', False, False)
ib.sleep(2)
print(f"AAPL bid={ticker.bid} ask={ticker.ask} last={ticker.last}")

# Marktorder über 10 Aktien
order = MarketOrder('BUY', 10)
trade = ib.placeOrder(aapl, order)
ib.sleep(1)
print(f"Status: {trade.orderStatus.status}")

ib.disconnect()

Der gleiche Code im klassischen Callback-Modell von ibapi würde drei Klassen, einen eigenen Event-Loop und etwa 80 Zeilen Boilerplate benötigen. Für bestehenden ib_insync-Code ist ib_async der kürzeste Weg: Import umstellen, Tests laufen lassen, Änderungshistorie lesen. ib_async 2.1.0 setzt Python 3.10 oder neuer voraus. Interactive Brokers nennt ib_async selbst als Weg für alle, die die ib_insync-Struktur behalten wollen, leistet für beide Pakete aber keine Programmierhilfe und empfiehlt grundsätzlich die direkte TWS API.

Die offizielle API ist inzwischen zugänglicher geworden: Seit TWS API 10.40 gibt es mit TWSSyncWrapper einen synchronen Python-Wrapper, der Ergebnisse direkt zurückgibt statt über Callbacks. Seit 10.49 steht die TWS API unter der GPL, was vor allem für weitergegebene Software zu prüfen ist. Wann sich welcher Weg lohnt und wie Sie alte Skripte migrieren, beschreibt der Artikel ib_insync-Alternative: ib_async, Sync-Wrapper und GPL.

Verbindung, Client-IDs und Reconnect-Logik.

Jede Verbindung zur Gateway-App braucht eine Client-ID — eine ganze Zahl; TWS und IB Gateway erlauben bis zu 32 gleichzeitige API-Verbindungen. Die Client-ID 0 hat eine Sonderrolle: Sie kann auch manuell in TWS erteilte Orders übernehmen. Welche ID die Orders aller API-Clients sieht, legen Sie in den API-Einstellungen als „Master API client ID“ fest. Für jeden parallelen Prozess vergeben Sie eine eindeutige ID, ansonsten kickt Sie der Gateway sofort raus.

In Produktion brauchen Sie unbedingt Reconnect-Logik. Die Gateway-App wird täglich neu gestartet oder abgemeldet, je nach Einstellung „Auto restart“ oder „Auto log off“, und WLAN-Drops kommen vor. Ein Minimal-Wrapper:

import asyncio
from ib_async import IB

async def ensure_connected(ib: IB, host='127.0.0.1', port=4002, client_id=42):
    while True:
        try:
            if not ib.isConnected():
                await ib.connectAsync(host, port, clientId=client_id, timeout=10)
                print("[ok] verbunden")
            await asyncio.sleep(5)
        except Exception as e:
            print(f"[warn] reconnect-versuch fehlgeschlagen: {e}")
            await asyncio.sleep(15)

ib = IB()
ib.errorEvent += lambda reqId, code, msg, _: print(f"err {code}: {msg}")
asyncio.run(ensure_connected(ib))

Wichtig: vor jeder kritischen Order prüfen Sie ib.isConnected() und cachen offene Orders lokal. Wenn der Gateway während eines Fills disconnected, müssen Sie nach Reconnect den Zustand abgleichen — IB sendet alte Events nicht erneut.

Marktdaten, Subscriptions und Limits.

Marktdaten kosten bei IBKR pro Exchange-Paket. Wer nur Paper-Trading macht, kommt mit verzögerten Daten aus oder nutzt per Data Sharing die Abos des Live-Benutzers; das „US Securities Snapshot and Futures Value Bundle“ kostet laut Preisseite 10 USD im Monat und entfällt ab 30 USD Monatskommission (Stand Oktober 2026). Jeder Benutzer hat mindestens 100 gleichzeitige Marktdatenlinien für TWS und API zusammen; ab dem zweiten Monat richtet sich die Zahl nach Kommission und Equity, zusätzliche Linien gibt es per Quote Booster (30 USD je 100 Linien).

Historische Bars werden über ib.reqHistoricalData() abgerufen. Für Balken von 30 Sekunden oder kleiner gelten feste Pacing-Grenzen: höchstens 60 Anfragen in zehn Minuten, keine identische Anfrage innerhalb von 15 Sekunden, nicht sechs oder mehr Anfragen für denselben Kontrakt, dieselbe Börse und denselben Datentyp innerhalb von zwei Sekunden; BID_ASK zählt doppelt. Für Backtest-Datensätze besser einmal pullen und lokal in Parquet ablegen, statt jedes Mal abzufragen.

Wer Tick-Daten braucht (Trades und Quotes auf höchster Granularität), nutzt reqTickByTickData() — limitiert auf 5 Prozent der Marktdatenlinien des Benutzers, bei den standardmäßigen 100 Linien also 5 gleichzeitige Abos. Das ist die wichtigste Einschränkung für HFT-artige Setups: für mehr als eine Handvoll Live-Symbole müssen Sie aggregieren oder einen anderen Datenfeed dazuziehen.

Order-Typen, die Sie wirklich nutzen werden.

Multi-Currency und Cross-Border.

Hier wird es interessant — und unangenehm. IBKR rechnet jede Order in die jeweilige Settlement-Währung ab. Kaufen Sie an der LSE eine GBP-denominated Aktie mit einem EUR-Konto, entsteht ein negativer GBP-Cash-Saldo, den IBKR per Margin-Kredit ausgleicht. Sie zahlen Zinsen darauf, solange Sie nicht konvertieren.

Konvertieren geht über das Cash-Forex-Paar:

from ib_async import IB, Forex, MarketOrder

ib = IB()
ib.connect('127.0.0.1', 4002, clientId=7)

# 5000 GBP von EUR-Cash kaufen — settled in IBKR Cash-Forex
gbpeur = Forex('GBPEUR')
ib.qualifyContracts(gbpeur)
order = MarketOrder('BUY', 5000)
trade = ib.placeOrder(gbpeur, order)
ib.sleep(2)
print(trade.orderStatus.status, trade.orderStatus.avgFillPrice)
ib.disconnect()

Ob Sie einen negativen Fremdwährungssaldo konvertieren oder als Kredit stehen lassen, hängt von Zinsen, Gebühren und Ihrem Vorgehen ab. Eine pauschale Regel gibt es nicht; maßgeblich sind die aktuellen Konditionen von IBKR.

Typische Fehler und ihre Ursachen.

  1. Error 502: „Couldn't connect to TWS“ — die Gateway-App läuft nicht oder API-Verbindungen sind deaktiviert. In TWS unter Configure → API → Settings die Checkbox „Enable ActiveX and Socket Clients“ prüfen.
  2. Error 200: „No security definition“ — der Contract ist falsch spezifiziert. Vor jeder Order ib.qualifyContracts() aufrufen.
  3. Error 354: „Requested market data is not subscribed“ — Sie brauchen entweder ein Subscription-Paket oder müssen mit Delayed-Daten arbeiten (ib.reqMarketDataType(3)).
  4. Error 10197: „No market data during competing session“ — laut IBKR sind Live- und Paper-Benutzer gleichzeitig angemeldet und fordern über dasselbe geteilte Marktdatenabo Echtzeitdaten an. Vorrang hat dann der Live-Benutzer.
  5. Stiller Order-Reject: prüfen Sie immer trade.log — manche Rejects kommen als Log-Event statt als Exception.

Produktiv-Setup, das funktioniert.

Mein empfohlener Stack für IBKR-Live-Trading:

  1. IB Gateway mit eingebautem „Auto restart“ und „Never lock Trader Workstation“ (Global Configuration → Lock and Exit); einmal pro Woche manuelle Anmeldung mit zweitem Faktor. Das früher übliche IBC (hervorgegangen aus IBController) ist seit dem 01.09.2026 eingestellt.
  2. Python-Service mit ib_async, asyncio-Eventloop, zentralem State-Store (Redis oder Postgres) für Order-Tracking.
  3. Heartbeat-Monitor: separater Prozess, der alle 30 Sekunden den Connection-State prüft und bei mehrfacher Fehlmeldung Alerts schickt.
  4. Order-Reconciliation: täglich nach Settlement Soll/Ist-Abgleich zwischen internem State und IBKR-Account-Statements.
  5. Paper-Mirror: parallel zur Live-Engine eine Paper-Instanz mit gleichem Code laufen lassen, Divergenzen automatisch protokollieren.

Mit dieser Infrastruktur ist ein stabiler Live-Betrieb realistisch — auch für Multi-Asset-Strategien über mehrere Kontinente, sofern die wöchentliche Anmeldung fest eingeplant ist. Ohne sie läuft das Gateway höchstens eine Woche. Was nach dem Ende von IBC offiziell gilt, welche 2FA-Methoden mit der API funktionieren und warum Community-Nachfolger für Live-Konten derzeit keine Empfehlung sind, beschreibt der Artikel IB Gateway im Dauerbetrieb: was nach dem Ende von IBC gilt. Die initialen 2–4 Wochen Aufwand, das Setup sauber aufzubauen, sind die beste Investition im gesamten Quant-Stack.

Stand: Mai 2026, überarbeitet 22. Oktober 2026. Angaben zu Produkten, Preisen, Gesetzen und Fristen können sich seitdem geändert haben; maßgeblich sind die aktuellen Angaben der Anbieter und Behörden.

Sie planen einen IBKR-Live-Betrieb oder kämpfen mit Reconnect- und Order-State- Problemen? Unverbindlich anfragen — wir setzen den Stack auf, der auch um 3 Uhr morgens noch läuft. Mehr zu meinem Angebot: Trading-Systeme entwickeln lassen.