# IBKR-Anbindung (TWS API via IB Gateway) **Entscheidung:** Der `IbkrBrokerClient` (Alternative zum `NullBrokerClient`) nutzt die **TWS API** über das **IB Gateway** – native C#-Lib, robusteste Order-Ausführung, region-agnostisch. > **Stand 2026-07-31:** Der Adapter ist implementiert (`src/IBKRTrader.Core/Trading/Ibkr/`) und wird > über `IBKRSettings.UseTwsApi` aktiviert. Gegen das Paper-Konto **DUR371528** verifiziert sind > Verbindung, `GetAccountStateAsync` und `GetQuoteAsync` (verzögerte Kurse, siehe unten) sowie der > Fehlerpfad bei unbekanntem Symbol und nicht erreichbarer TWS. > **Noch nicht verifiziert: `PlaceOrderAsync`** – dafür ist eine echte Order auf dem Paper-Konto nötig. ## Regionen (US ↔ IE) Gleiche API, gleiche Gateway-Software, **eine Codebasis**. Unterschied nur: Login/Entity (Paper: IBKR Ireland, Live später: IBKR LLC US), Marktdaten-Abos, Reports – **kein Code-Fork**. Paper vs. Live = Konto + Port, kein Code-Unterschied. ## Betrieb (operativ) - **Setup auf neuem System:** alle nötigen TWS-/Gateway-Einstellungen Schritt für Schritt in der [TWS-Setup-Checkliste](TWS-Setup-Checkliste.md). - **IB Gateway** (schlank, statt TWS) muss laufen und eingeloggt sein. - **Ports:** Paper **4002**, Live **4001** (Auswahl über `TradingSettings.Mode`). → passt exakt zu den bestehenden `IBKRSettings` (Host `127.0.0.1`, Port, `ClientId`). - **2FA / Dauerbetrieb:** IBKR erzwingt 2FA und täglichen Neustart. Für unbeaufsichtigten Server-Betrieb **IBC/IBController** (Auto-Login + geplanter Neustart). ## Bibliothek Offizielle C#-API als NuGet-Mirror **`IB.TWS.CSharpApi` 9.76.1**, referenziert im Core und in der NuGet-Allowlist (`NuGet.config`) freigegeben. Das Paket zielt auf .NET Framework, ist aber reiner managed Code und läuft auf net10 – `NU1701` ist in der `.csproj` bewusst unterdrückt. ## Umsetzung (`src/IBKRTrader.Core/Trading/Ibkr/`) Die TWS API ist **callback-basiert** (`EClientSocket` sendet, `EWrapper` empfängt Events). Das ist hinter dem bestehenden async-Seam `IBrokerClient` gekapselt, aufgeteilt in drei Dateien: | Datei | Aufgabe | |---|---| | `IbkrMapping.cs` | Reine Abbildung Core ↔ TWS (Kontrakt, Order, Kurs, Port-/Statusregeln) – **unit-getestet** | | `IbkrConnection.cs` | Socket-Lebenszyklus, Reader-Thread, reqId-Korrelation über `TaskCompletionSource` | | `IbkrBrokerClient.cs` | Implementiert `IBrokerClient`, übersetzt Fehler in leere Ergebnisse | **Ablauf je Methode** - **`GetQuoteAsync`** → `reqContractDetails` (Ergebnis wird gecacht) → `reqMktData` als Snapshot → `Quote`. Preis-Reihenfolge: letzter Handelspreis, sonst Bid/Ask-Mitte, sonst Schlusskurs. - **`GetAccountStateAsync`** → `reqAccountSummary` (NetLiquidation, AvailableFunds). - **`PlaceOrderAsync`** → Kontrakt auflösen → `placeOrder`; das Ergebnis kommt über `orderStatus`, die Order-IDs liefert `nextValidId`. **Bewusste Entscheidungen** - **Träges Verbinden mit Wiederholung statt Verbindungsaufbau beim Start.** TWS ist nach einem Neustart minutenlang nicht bereit (erst abgelehnte Verbindungen, dann abgebrochene Handshakes); ein einmaliger Versuch beim Programmstart würde das nicht überleben. - **Port-Prüfung gegen den Handelsmodus.** Paper-Modus auf einem Live-Port (oder umgekehrt) wird abgelehnt, der Broker bleibt dann inaktiv – sonst würde echtes Geld bewegt, wo ein Test erwartet wird. - **Fehler werden nie geworfen, sondern zu leeren Ergebnissen.** Konto 0 lässt die Risikoprüfung jedes Signal ablehnen – die sichere Richtung bei nicht erreichbarem Broker. - **`MarketDataType` standardmäßig 4 (verzögert + Frozen).** Paper-Konten ohne Datenabo bekommen sonst überhaupt keine Kurse, und der `ExecutionService` überspringt jedes Signal mit „kein Kurs". - **Zwei Sicherungen bleiben:** `UseTwsApi` entscheidet über den Adapter, `TradingEnabled` über den Handel. Ohne den zweiten Schalter platziert der `ExecutionService` keine Order. ### Bekannte Grenze: Orders ohne sofortige Ausführung `IBrokerClient.PlaceOrderAsync` ist synchron gedacht (Ausführung oder Fehlschlag). Eine Order, die innerhalb von `OrderTimeoutSeconds` keinen Endstatus erreicht – etwa eine Limit-Order im Orderbuch oder eine Market-Order außerhalb der Handelszeiten –, wird als Fehlschlag zurückgegeben, **kann bei IBKR aber weiterhin aktiv sein**. Die Meldung enthält deshalb Order-ID und letzten Status. Sauber lösen ließe sich das nur mit asynchroner Fill-Verfolgung (Order-Zustand persistieren, `orderStatus` und `execDetails` dauerhaft mitschreiben) – das ändert den Seam und ist eigene Arbeit. ## Marktdaten Das Paper-Konto hat **kein Marktdaten-Abo**. TWS meldet deshalb bei jeder Kursanfrage den Hinweis **10167** („nicht abonniert, es werden verzögerte Marktdaten angezeigt") und liefert danach ganz normal verzögerte Ticks. Das ist ein **Statushinweis, kein Fehler** – wird er als Fehler behandelt, bricht die Kursanfrage ab, bevor die Ticks eintreffen, und jedes Symbol liefert „kein Kurs". `IbkrMapping.IsInformational` deckt den Code deshalb ausdrücklich ab (mit Test). Verifiziert am 2026-07-31 gegen DUR371528: AAPL 302,94 / MSFT 476,88 / NVDA 209,81 (verzögert). ## Optionen (Berechtigung verifiziert 2026-08-04) Das Paper-Konto **DUR371528 ist für den Optionshandel freigeschaltet**. Geprüft ohne jede Ausführung über eine **What-If-Order** (`Order.WhatIf = true`): IBKR rechnet dabei Margin und Gebühren durch die komplette Prüfkette – inklusive Handelsberechtigung – und verwirft die Order anschließend. | Prüfung | Ergebnis | |---|---| | `reqSecDefOptParams` AAPL | 24 Verfallstermine, 127 Strikes (5–600), Multiplier 100, TradingClass AAPL | | Börsen | SMART, CBOE, ISE, EMERALD, NASDAQBX, PHLX, AMEX, MEMX, PSE | | Kontrakt `AAPL 20260812 C302.5` | aufgelöst, ConId 906106141, LocalSymbol `AAPL 260812C00302500` | | What-If BUY 1 Kontrakt | **angenommen**, Init-Margin 0 → 589,52 | | What-If BUY 1 AAPL (Aktie) | **angenommen**, Init-Margin 0 → 87,61, Kommission 1,00 USD | Fehlte die Berechtigung, hätte IBKR die What-If-Order mit einem Berechtigungsfehler abgelehnt statt eine Margin zu liefern. Für **Realtime**-Optionskurse wäre zusätzlich ein OPRA-Abo nötig; ohne Abo kommen verzögerte Daten (siehe Marktdaten unten). Modul-Konzept: [archiv/KONZEPT-Modul-OptionsWheel.md](archiv/KONZEPT-Modul-OptionsWheel.md). > **What-If als Testwerkzeug:** Damit lässt sich der gesamte Orderpfad bis zur Broker-Annahme prüfen, > ohne eine Position zu eröffnen. Der Adapter nutzt es nicht produktiv – für Vorabprüfungen > (Margin-Deckung vor einer echten Order) wäre es aber ein naheliegender Ausbau. Welche Daten die API auf diesem Konto tatsächlich liefert – und welche Strategien das trägt – steht gemessen in [archiv/KONZEPT-Datenlage-und-Strategien.md](archiv/KONZEPT-Datenlage-und-Strategien.md). Kurz: Kurshistorie (30 Jahre), Volatilitätshistorie, Optionsketten und Griechen ja; Fundamentaldaten und Marktscanner nein (Abo nötig). ### Historie: welcher Gateway? Aktuell laufen die Marktdaten-Worker über die **Client Portal Web API** (`IBKRGatewayService`). Später zu entscheiden: - Broker (Quotes/Konto/Orders) → TWS API; Marktdaten-Historie **vorerst auf CP Web API belassen**, oder - Historie ebenfalls auf TWS (`reqHistoricalData`) migrieren → nur noch ein Gateway. ## Konfiguration (`settings.json`, Abschnitt `IBKR`) | Schlüssel | Default | Bedeutung | |---|---|---| | `UseTwsApi` | `false` | Aktiviert den echten Adapter; sonst `NullBrokerClient` | | `Host` / `Port` / `ClientId` | `127.0.0.1` / `4002` / `1` | Verbindung; Port muss zum Handelsmodus passen | | `MarketDataType` | `4` | 1 Realtime, 2 Frozen, 3 verzögert, 4 verzögert+Frozen | | `ConnectTimeoutSeconds` | `15` | Socket-Verbindung und Handshake | | `RequestTimeoutSeconds` | `15` | Kurs-, Kontrakt- und Kontoantworten | | `OrderTimeoutSeconds` | `60` | Wartezeit auf den Endstatus einer Order | ## Testbarkeit - `IbkrMapping` ist vollständig unit-getestet (`tests/.../IbkrMappingTests.cs`): Port-/Modus-Regeln, Kontrakt- und Order-Aufbau, Kursableitung, Tick- und Statusklassifizierung. - Verbindung, Kurse und Orders bleiben **manuelle Verifikation gegen das Paper-Gateway** – siehe [TWS-Setup-Checkliste](TWS-Setup-Checkliste.md), Abschnitt Verifikation. ## Offen Die offenen Punkte dieses Adapters werden seit dem 2026-08-23 in der [Roadmap](ROADMAP.md) gefuehrt, nicht mehr hier – sie haengen mit Aufgaben aus anderen Konzepten zusammen und standen deshalb doppelt. Es sind: | Roadmap | Punkt | |---|---| | **H1** | `PlaceOrderAsync` gegen das Paper-Konto verifizieren (Order → Fill → Buchung) | | **H2** | Asynchrone Fill-Verfolgung, siehe „Bekannte Grenze" oben – zugleich Voraussetzung fuer OptionsWheel | | **H4** | IBC fuer Auto-Login/Neustart einrichten (Server-Betrieb) | | **T1** | Entscheiden, ob die Marktdaten-Historie von der CP Web API auf `reqHistoricalData` wandert | Das **Design** und die **bekannten Grenzen** stehen weiterhin in diesem Dokument – es bleibt die technische Referenz des Adapters.