R9: Echter IbkrBrokerClient über die TWS API
Broker-Adapter gegen TWS/IB Gateway, aktivierbar über IBKRSettings.UseTwsApi;
NullBrokerClient bleibt Default. TradingEnabled bleibt als zweite, unabhängige
Sicherung bestehen – ohne ihn platziert der ExecutionService keine Order.
Aufteilung (src/IBKRTrader.Core/Trading/Ibkr/):
- IbkrMapping – reine Abbildung Core <-> TWS (Kontrakt, Order, Kurs, Port-
und Statusregeln), vollständig unit-getestet
- IbkrConnection – Socket-Lebenszyklus, Reader-Thread, reqId-Korrelation über
TaskCompletionSource
- IbkrBrokerClient – implementiert IBrokerClient, übersetzt Fehler in leere
Ergebnisse (Konto 0 lässt die Risikoprüfung alles ablehnen)
Bewusste Entscheidungen:
- Träges Verbinden mit Wiederholung statt Verbindungsaufbau beim Start: TWS ist
nach einem Neustart minutenlang nicht bereit.
- Port wird gegen den Handelsmodus geprüft; Paper-Modus auf Live-Port (oder
umgekehrt) lässt den Broker inaktiv, statt auf dem falschen Konto zu handeln.
- MarketDataType Default 4: Paper-Konten ohne Datenabo bekommen sonst keine Kurse.
- Fehlercode 10167 ist ein Statushinweis (verzögerte Daten folgen), kein Fehler.
Als Fehler behandelt scheiterte jede einzelne Kursabfrage.
Verifiziert gegen Paper-Konto DUR371528: Verbindung, Konto (100.105,50 EUR),
Kurse (AAPL/MSFT/NVDA, verzögert), Fehlerpfade. Orderpfad bis zur Broker-Annahme
per What-If-Order geprüft (Aktie + Option, ohne Ausführung); dabei zugleich die
Optionsberechtigung des Kontos bestätigt. Offen: echte Ausführung (Fill ->
Buchung) und asynchrone Fill-Verfolgung – beides in IBKR-Integration.md notiert.
Doku: TWS-Setup-Checkliste.md (Einstellungen für Neuinstallation) neu,
IBKR-Integration.md / ARCHITECTURE.md / README.md nachgezogen.
154/154 Tests grün.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -63,7 +63,36 @@ public class IBKRSettings
|
||||
[Description("Eindeutige Client-ID für die API-Verbindung")]
|
||||
public int ClientId { get; set; } = 1;
|
||||
|
||||
public override string ToString() => $"{Host}:{Port} (Client {ClientId})";
|
||||
[Category("IBKR Gateway")]
|
||||
[DisplayName("TWS-Broker verwenden")]
|
||||
[Description("Aktiviert den echten TWS-Broker. Aus = NullBroker (handelt nie). " +
|
||||
"Der globale Handelsschalter unter Trading bleibt davon unberührt.")]
|
||||
public bool UseTwsApi { get; set; } = false;
|
||||
|
||||
[Category("IBKR Gateway")]
|
||||
[DisplayName("Marktdaten-Typ")]
|
||||
[Description("1 = Realtime, 2 = Frozen, 3 = verzögert, 4 = verzögert+Frozen. " +
|
||||
"Paper-Konten ohne Datenabo brauchen 3 oder 4, sonst kommen keine Kurse.")]
|
||||
public int MarketDataType { get; set; } = 4;
|
||||
|
||||
[Category("IBKR Gateway")]
|
||||
[DisplayName("Verbindungs-Timeout (s)")]
|
||||
[Description("Wartezeit auf Socket-Verbindung und Handshake. TWS braucht nach einem Neustart mehrere Minuten.")]
|
||||
public int ConnectTimeoutSeconds { get; set; } = 15;
|
||||
|
||||
[Category("IBKR Gateway")]
|
||||
[DisplayName("Anfrage-Timeout (s)")]
|
||||
[Description("Wartezeit auf Kurs-, Kontrakt- und Kontoantworten")]
|
||||
public int RequestTimeoutSeconds { get; set; } = 15;
|
||||
|
||||
[Category("IBKR Gateway")]
|
||||
[DisplayName("Order-Timeout (s)")]
|
||||
[Description("Wartezeit auf den Endstatus einer Order. Danach gilt sie als fehlgeschlagen, " +
|
||||
"kann bei IBKR aber weiterhin aktiv sein.")]
|
||||
public int OrderTimeoutSeconds { get; set; } = 60;
|
||||
|
||||
public override string ToString() =>
|
||||
$"{Host}:{Port} (Client {ClientId}){(UseTwsApi ? "" : " – TWS-Broker aus")}";
|
||||
}
|
||||
|
||||
// ─── IBKR Web API (Client Portal Gateway) ────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user