← Alle Insights

Positionsabgleich für Trading-Bots bei unklarem Order-Status.

Endet eine Order-Anfrage mit Timeout oder Serverfehler, sollte Ihr Trading-Bot sie weder als gescheitert behandeln noch blind erneut senden. Sicherer ist es, die Order als „unbekannt“ zu markieren, per eigener Order-ID beim Broker nachzufragen und erst nach einem Positionsabgleich weiterzuhandeln. Binance schreibt in seiner API-Dokumentation ausdrücklich, dass der Status bei 5XX-Antworten unbekannt ist und die Order trotzdem ausgeführt sein kann. Dieser Artikel zeigt broker-übergreifend, wie Sie mit Client Order IDs doppelte Orders vermeiden, wie Binance, Alpaca und Interactive Brokers eigene Kennungen umsetzen, wie ein Abgleich beim Start und im laufenden Betrieb aussieht und wann eine Abweichung den Kill-Switch auslösen sollte. Dazu kommen Python-Pseudocode und eine Liste von Testfällen. Die API-Angaben entsprechen dem Stand Oktober 2026.

Warum bedeutet ein Timeout nicht „nicht ausgeführt“?

Eine Order-Anfrage durchläuft mehrere Stationen: Ihr Programm, das Netzwerk, das API-Gateway des Brokers, die Order-Verwaltung und schließlich die Börse oder das Matching-System, also die Stelle, an der Kauf- und Verkaufsaufträge zusammengeführt werden. Ein Timeout sagt nur, dass Ihr Programm innerhalb der eingestellten Wartezeit keine Antwort bekommen hat. Ob die Anfrage unterwegs verloren ging oder nur die Antwort, bleibt offen.

Binance formuliert das in der Spot-API-Dokumentation ausdrücklich: HTTP-Statuscodes der 5XX-Reihe stehen für interne Fehler auf Binance-Seite, und man soll sie nicht als Fehlschlag behandeln, denn der Ausführungsstatus ist unbekannt und kann erfolgreich gewesen sein. Zusätzlich nennt die Doku ein internes Zeitlimit von 10 Sekunden; dauert die Antwort des Matching-Systems länger, kommt eine Timeout-Meldung mit dem Hinweis, der Status sei unbekannt. Empfohlen wird, erst den User Data Stream (einen laufenden Ereignis-Stream mit Kontodaten) und dann per API den Status zu prüfen.

Die naheliegende Reaktion, einfach noch einmal zu senden, ist deshalb die gefährlichste. War die erste Order angekommen, hält der Bot jetzt die doppelte Position. Bei gehebelten Produkten wie Futures oder CFDs verdoppelt sich damit auch das Verlustrisiko. Der Rest dieses Artikels beschreibt, wie man diese Lücke technisch schließt, ohne zu raten.

Eigene Order-IDs: wie Binance, Alpaca und IBKR das lösen.

Die Grundlage jedes Abgleichs ist eine Kennung, die Ihr Bot vor dem Senden selbst vergibt. Nur so lässt sich nach einem Timeout fragen: „Gibt es die Order mit dieser ID?“ Die Broker-eigene Order-Nummer hilft dann nicht, denn die kommt ja mit der Antwort, die gerade fehlt. Die drei verbreiteten APIs lösen das unterschiedlich:

APIEigene KennungWas die Doku sagtNachfragen per
Binance SpotnewClientOrderIdEindeutig unter offenen Orders, wird ohne Angabe automatisch erzeugt; eine Order mit gleicher ID wird nur angenommen, wenn die vorherige gefüllt ist, sonst abgelehntGET /api/v3/order mit origClientOrderId
Alpacaclient_order_idEindeutige Kennung, höchstens 128 Zeichen, automatisch erzeugt, wenn sie fehltGET /v2/orders:by_client_order_id
Interactive Brokers (TWS API)orderId (Ganzzahl)Vom Client verwaltet, muss strikt steigen; die nächste gültige ID liefern nextValidId() bzw. reqIds(); Orders sind an die Client-ID gebundenreqOpenOrders(), reqAllOpenOrders(), reqCompletedOrders()

Zwei Feinheiten werden oft übersehen. Erstens schützt die Binance-ID nicht vollständig vor Doppelungen: Ist die erste Order bereits gefüllt, wird eine neue Order mit derselben ID laut Doku angenommen. Ein blindes Wiederholen mit gleicher ID ist also nicht automatisch harmlos. Zweitens trägt die IBKR-orderId keine Bedeutung, sie ist nur eine steigende Zahl. Ihr Bot muss deshalb selbst speichern, welche ID zu welchem Signal gehört, und nach einem Neustart mit derselben Client-ID verbinden, sonst kann er seine eigenen Orders weder ändern noch sauber zuordnen.

Praktikabel ist eine sprechende, deterministische Kennung aus Strategie, Signalzeitpunkt und laufender Nummer, etwa s1-20261007-1530-0042. Kommt dasselbe Signal zweimal an, zum Beispiel weil ein Webhook, also eine automatische Benachrichtigung etwa von TradingView, doppelt zugestellt wurde, entsteht dieselbe ID, und der Bot erkennt die Wiederholung schon lokal.

Der Zustand „unbekannt“ im Order-Lebenszyklus.

Viele Bots kennen für eine Order nur „offen“, „gefüllt“ und „Fehler“. Das reicht nicht. Robuster ist ein Zustandsmodell, in dem „unbekannt“ ein eigener, gleichberechtigter Zustand ist, aus dem nur eine Antwort des Brokers herausführt:

Entscheidend ist die Regel dahinter: Solange für ein Instrument eine Order im Zustand „unbekannt“ steht, trifft der Bot für dieses Instrument keine neuen Handelsentscheidungen. Das kostet im Zweifel einen Trade. Eine doppelte Position kostet im Zweifel deutlich mehr. Den Zustand sollten Sie außerdem dauerhaft speichern, etwa in SQLite oder einer Journal-Datei, und zwar bevor die Anfrage das Programm verlässt. Stürzt der Bot genau zwischen Senden und Antwort ab, findet er beim Neustart den Eintrag „gesendet“ und weiß, dass er nachfragen muss.

Nachfragen statt erneut senden: Ablauf bei Timeout und 5XX.

Ein klarer, vorher festgelegter Ablauf verhindert Improvisation unter Zeitdruck. Für REST-APIs wie Binance oder Alpaca sieht er typischerweise so aus:

  1. Order-Anfrage endet mit Timeout, 5XX oder abgebrochener Verbindung: Zustand auf „unbekannt“ setzen, Ereignis protokollieren.
  2. Kurz warten, dann gezielt per eigener ID nachfragen, bei Binance über origClientOrderId, bei Alpaca über den Endpunkt orders:by_client_order_id. Wenn ein Ereignis-Stream läuft (bei Binance der User Data Stream, bei Alpaca der WebSocket-Stream trade_updates), zuerst dort nachsehen.
  3. Order gefunden: Status und Füllmenge übernehmen, normal weiterarbeiten.
  4. Order nicht gefunden: mit wachsenden Abständen mehrfach wiederholen. Ein einzelnes „nicht gefunden“ direkt nach einer Störung ist kein Beweis, dass die Order nie ankam.
  5. Nach Ablauf der Versuche zusätzlich Positionen und die Liste ausgeführter Trades prüfen. Erst wenn alle drei Quellen übereinstimmen, gilt die Order als nicht angekommen.
  6. Ob dann neu gesendet wird, entscheidet eine feste Regel, nicht der Zufall: Ist das Signal noch gültig und der Preis noch im erlaubten Rahmen? Sonst verwerfen.

Bei Binance hilft zusätzlich der Parameter recvWindow: Signierte Anfragen prüft Binance laut Doku beim Eingang und noch einmal vor der Weitergabe an das Matching-System gegen dieses Zeitfenster; liegt eine Anfrage außerhalb, wird sie abgelehnt. Standard sind 5.000 ms, maximal 60.000 ms, empfohlen 5.000 ms oder weniger. Ein kleines Fenster begrenzt, wie lange eine hängende Anfrage noch zur Ausführung kommen kann. Bei der IBKR TWS API ist die Lage anders, weil Orders über eine dauerhafte Socket-Verbindung laufen: Reißt sie ab, ruft die API connectionClosed() auf. Nach dem Wiederverbinden fragen Sie mit derselben Client-ID offene Orders über reqOpenOrders() und abgeschlossene über reqCompletedOrders() ab, bevor der Bot wieder handelt.

Positionsabgleich beim Start und im laufenden Betrieb.

Der gezielte Abgleich einer einzelnen Order reicht nicht. Zusätzlich braucht jeder Bot einen vollständigen Positionsabgleich (Reconciliation): Er vergleicht, was er selbst zu halten glaubt, mit dem, was der Broker meldet. Dabei gilt eine einfache Hierarchie: Die Position beim Broker ist die Wahrheit, das eigene Journal ist die Erwartung.

Beim Start läuft der Abgleich, bevor die Strategie das erste Signal verarbeiten darf. Er umfasst Positionen je Instrument, offene Orders, die seit dem letzten Lauf abgeschlossenen Orders und die Ausführungen. Bei IBKR liefert reqPositions() alle Positionen der verbundenen Konten und danach laufende Änderungen. Für Ausführungen gibt es eine wichtige Einschränkung: reqExecutions() liefert laut Doku standardmäßig nur Ausführungen seit Mitternacht. In der TWS lässt sich das über die Trade-Log-Einstellung auf bis zu sieben Tage erweitern, das IB Gateway bleibt auf den aktuellen Handelstag beschränkt. Auch reqCompletedOrders() liefert nur die nicht mehr änderbaren Orders des Tages. War der Bot über Nacht aus, lässt sich der Vortag über die API deshalb oft nicht vollständig rekonstruieren. Umso wichtiger sind das lokale Journal und der Vergleich der Endbestände.

Im laufenden Betrieb wiederholt sich der Abgleich in festen Abständen, zum Beispiel jede Minute oder nach jeder abgeschlossenen Order, und zusätzlich nach jedem Wiederverbinden. Der Abstand richtet sich nach Handelsfrequenz und den Rate-Limits, also den Abfragegrenzen der jeweiligen API. Ergänzend lohnt der Blick auf fremde Orders: Taucht beim Broker eine offene Order auf, deren ID der Bot nicht kennt, hat jemand manuell eingegriffen, oder eine zweite Instanz läuft auf demselben Konto. Beides muss der Bot bemerken. Typische Stolpersteine bei Teilfüllungen und Verbindungsabbrüchen beschreibt der Artikel zu API-Edge-Cases bei Brokern.

Abweichungen behandeln: Alarm, Handelsstopp, Kill-Switch.

Eine gefundene Abweichung sollte der Bot nicht selbst „reparieren“, indem er die Differenz einfach glattstellt oder nachkauft. Er kennt die Ursache nicht. Vielleicht hat der Abgleich nur einen Zwischenstand gesehen, während eine Teilfüllung noch eintrifft. Sinnvoll ist eine Eskalation in Stufen:

BefundReaktion
Kleine Differenz unter einer festen Toleranz, z. B. Rundung bei Krypto-MengenProtokollieren, beim nächsten Abgleich erneut prüfen
Order im Zustand „unbekannt“ länger als die festgelegte FristAlarm, keine neuen Orders für dieses Instrument
Positionsdifferenz über der Toleranz oder unbekannte Order beim BrokerHandelsstopp für die ganze Strategie, Alarm an den Betreiber
Abweichung wächst weiter oder betrifft mehrere InstrumenteKill-Switch: offene Orders stornieren, keine neuen Orders, Entscheidung über Positionen durch einen Menschen

Die Schwellen legen Sie vorher fest und dokumentieren sie, nicht im Ernstfall. Wie ein Kill-Switch aufgebaut ist und welche weiteren Auslöser sinnvoll sind, steht im Artikel zum Kill-Switch für Trading-Bots. Wichtig ist hier nur: Eine Positionsabweichung eignet sich gut als Auslöser, weil sie unabhängig davon greift, welcher Fehler sie verursacht hat.

Pseudocode und Testfälle für den Abgleich.

Der folgende Python-Pseudocode zeigt das Zusammenspiel aus eigener ID, Journal, Nachfragen und Abgleich. Er ist bewusst broker-neutral; die Methoden place_order, get_order und get_positions stehen für die jeweiligen API-Aufrufe.

# Pseudocode, broker-neutral. Zustände: GEPLANT, GESENDET, UNBEKANNT,
# OFFEN, TEILGEFUELLT, GEFUELLT, STORNIERT, ABGELEHNT

def submit(intent):
    coid = make_client_order_id(intent)        # z. B. "s1-20261007-1530-0042"
    journal.save(coid, intent, state="GESENDET")   # VOR dem Senden speichern
    try:
        ack = broker.place_order(intent, client_order_id=coid, timeout=5)
        journal.update(coid, state="OFFEN", broker_id=ack.id)
    except (Timeout, ServerError5xx, ConnectionLost):
        journal.update(coid, state="UNBEKANNT")
        resolve_unknown(coid)

def resolve_unknown(coid, versuche=5):
    for i in range(versuche):
        sleep(backoff(i))                       # 1 s, 2 s, 4 s ...
        order = broker.get_order(client_order_id=coid)
        if order is not None:
            journal.update(coid, state=map_status(order), broker_id=order.id)
            return
    # Nicht automatisch neu senden: Handel anhalten, Mensch entscheidet
    trading_halt(grund=f"Order {coid} nach {versuche} Abfragen unbekannt")
    alert(coid)

def reconcile():
    ist_pos = broker.get_positions()            # Wahrheit liegt beim Broker
    ist_orders = {o.client_order_id: o for o in broker.get_open_orders()}
    soll_pos = journal.expected_positions()
    abweichungen = []
    for symbol in set(ist_pos) | set(soll_pos):
        diff = ist_pos.get(symbol, 0) - soll_pos.get(symbol, 0)
        if abs(diff) > toleranz(symbol):
            abweichungen.append((symbol, soll_pos.get(symbol, 0), ist_pos.get(symbol, 0)))
    fremde_orders = [c for c in ist_orders if c not in journal]
    for coid in journal.open_ids():
        if coid not in ist_orders:              # gefüllt, storniert oder nie angekommen?
            journal.update_from(broker.get_order(client_order_id=coid))
    # Stufe je nach Befund, siehe Eskalationstabelle: Alarm, Handelsstopp, Kill-Switch
    if abweichungen or fremde_orders or journal.has_state("UNBEKANNT"):
        eskalieren(abweichungen, fremde_orders, journal.ids_in_state("UNBEKANNT"))

Wenn ich Trading-Systeme entwickle, schreibe ich diese Fälle als automatisierte Tests gegen einen simulierten Broker, bevor der Bot ein echtes Konto sieht. Ein Paper-Konto ersetzt das nicht, weil sich Timeouts und Serverfehler dort in der Regel nicht gezielt auslösen lassen. Mindestens diese Fälle sollten abgedeckt sein:

Jeder Test prüft am Ende dasselbe: Stimmt das Journal mit dem simulierten Broker überein, und hat der Bot in keinem Fall eine zweite Order gesendet, ohne dass die Regel es erlaubte?

Grenzen und Risiken des Positionsabgleichs.

Ein sauberer Abgleich senkt das Risiko doppelter oder vergessener Orders deutlich, beseitigt es aber nicht. Die wichtigsten Grenzen:

Was Sie jetzt konkret tun können.

Für einen bestehenden Bot, egal ob privat oder im Unternehmen betrieben, lässt sich das in überschaubaren Schritten nachrüsten:

  1. Suchen Sie im Code jede Stelle, an der eine Order gesendet wird, und prüfen Sie, was bei Timeout, 5XX und Verbindungsabbruch passiert. Jedes automatische „noch einmal senden“ ist ein Kandidat für einen Fehler.
  2. Vergeben Sie eigene, deterministische Order-IDs und speichern Sie sie vor dem Senden dauerhaft.
  3. Führen Sie den Zustand „unbekannt“ ein und sperren Sie für betroffene Instrumente neue Orders, bis der Status geklärt ist.
  4. Bauen Sie einen Start-Abgleich, der vor dem ersten Signal läuft, und einen regelmäßigen Abgleich im Betrieb.
  5. Legen Sie Toleranzen und Eskalationsstufen schriftlich fest und verbinden Sie die höchste Stufe mit Ihrem Kill-Switch.
  6. Schreiben Sie die Testfälle aus dem vorigen Abschnitt gegen einen simulierten Broker und lassen Sie sie bei jeder Änderung laufen.

Wer diese Schicht nicht selbst bauen möchte oder einen bestehenden Bot prüfen lassen will, findet unter Trading-Automatisierung, wie ich Order-Logik, Tests und Betrieb für private Trader und Unternehmen umsetze.

Häufige Fragen.

Was soll ein Trading-Bot tun, wenn die Order-API einen Timeout meldet?

Die Order als unbekannt markieren, keine neue Order für dasselbe Instrument senden und per eigener Client Order ID beim Broker nachfragen. Wird die Order gefunden, übernimmt der Bot Status und Füllmenge. Wird sie auch nach mehreren Abfragen nicht gefunden, prüft er Positionen und ausgeführte Trades. Ob dann neu gesendet wird, entscheidet eine vorher festgelegte Regel.

Wie vermeide ich doppelte Orders bei Binance, Alpaca oder Interactive Brokers?

Vergeben Sie vor dem Senden eine eigene Kennung und speichern Sie sie dauerhaft: newClientOrderId bei Binance, client_order_id bei Alpaca, eine strikt steigende orderId bei der IBKR TWS API. Nach einer Störung fragen Sie mit dieser Kennung nach, statt erneut zu senden. Beachten Sie, dass Binance eine gleiche ID wieder annimmt, sobald die erste Order gefüllt ist.

Was ist Reconciliation beim algorithmischen Trading?

Reconciliation ist der Abgleich zwischen dem, was das Handelssystem zu halten glaubt, und dem, was der Broker tatsächlich meldet: Positionen, offene Orders, abgeschlossene Orders und Ausführungen. Er läuft beim Start vor dem ersten Signal und danach regelmäßig. Abweichungen über einer Toleranz führen zu Alarm oder Handelsstopp.

Warum findet mein Bot nach einem Neustart bei IBKR die Ausführungen von gestern nicht?

Laut IBKR-Dokumentation liefert reqExecutions standardmäßig nur Ausführungen seit Mitternacht, beim IB Gateway nur die des aktuellen Handelstags. In der TWS lässt sich der Zeitraum über die Trade-Log-Einstellung auf bis zu sieben Tage erweitern. Deshalb braucht der Bot ein eigenes, dauerhaft gespeichertes Journal und vergleicht beim Start die Endbestände über reqPositions.

Sollte der Bot eine Positionsabweichung automatisch ausgleichen?

In der Regel nein. Der Bot kennt die Ursache nicht, vielleicht läuft gerade noch eine Teilfüllung ein oder jemand hat manuell eingegriffen. Sicherer ist es, neue Orders zu stoppen, offene Orders je nach Regelwerk zu stornieren und einen Menschen über die bestehenden Positionen entscheiden zu lassen.

Quellen und Stand.

Stand: 7. Oktober 2026. Produkte, Funktionen und Preise ändern sich schnell; maßgeblich sind die Angaben der Anbieter und Behörden.

Sie wollen Ihren Trading-Bot gegen doppelte Orders und unklare Order-Zustände absichern? Unverbindlich anfragen — wir klären Order-Logik, Abgleich mit dem Broker und die Testfälle vor dem Live-Betrieb. Mehr zu meinem Angebot: Trading-Systeme entwickeln lassen.