Files
IBKRTrader/docs/ARCHITECTURE.md
T
RichardandClaude Opus 5 b96a20788c R10: Lesender Bestandsabgleich (IBrokerPortfolioReader) + Datenlage-Konzepte
Eigener Seam neben IBrokerClient: Wer handelt, braucht ihn nicht; wer die
eigene Buchfuehrung gegen den Broker abstimmt, braucht nur ihn. Zuteilung
und Verfall aendern Positionen ohne Order von uns - ohne Abgleich laeuft
das Managementbuch zwangslaeufig auseinander.

- IBrokerPortfolioReader mit GetPositionsAsync/GetExecutionsAsync;
  implementiert von IbkrBrokerClient und NullBrokerClient (DI registriert
  beide Rollen auf derselben Instanz).
- IbkrConnection: reqAccountUpdates statt reqPositions (nur dieser Weg
  liefert Marktwert und unrealisierten G/V), reqExecutions inkl. Zuordnung
  der verspaetet eintreffenden commissionReport-Callbacks ueber die ExecId.
- BrokerPosition/BrokerExecution als Broker-Wahrheit neben Position;
  IbkrMapping: ParseSide, ParseExecutionTime, FormatExecutionFilterTime
  (UTC wegen TWS-Warnung 2174) - mit Unit-Tests.
- Verifiziert gegen Paper-Konto DUR371528: 2 Positionen, 2 Ausfuehrungen
  inkl. Kommissionen.

Doku: Kapital- und Buchmodell (drei Wahrheiten, Kapitalzuteilung),
KONZEPT-Datenlage-und-Strategien (gemessen, was die API auf diesem Konto
liefert). Options-Wheel: Greeks bei verzoegerten Daten funktionieren
(Feld 83); Earnings-Termine sind ueber die TWS API nicht erreichbar
(Fehler 10358) - Behelf ueber IV-Filter statt Fremddatenquelle.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 10:51:51 +02:00

149 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# IBKRTrader Architektur & Implementierungsplan
> **KORRIGIERT (2026-07-27):** Vorbild ist **PolytraderSharp** (`J:\Softwareprojekte\PolytraderSharp`),
> die C#-Neuentwicklung **nicht** die veraltete Python-Version. Die frühere Fassung dieses Plans
> basierte auf der Python-Vorlage und war konzeptionell falsch. Ziel ist eine **1:1-Neu-Fundamentierung**
> nach PolytraderSharp, im bestehenden IBKRTrader-Repo.
Ziel: modulares C#-Trading-Framework für Interactive-Brokers-Aktien, strukturell wie PolytraderSharp,
nur dass statt Polymarket über IBKR gehandelt wird.
---
## 1. Ziel-Architektur (nach PolytraderSharp)
```
IBKRTrader.App (WinExe, Root) Generic Host + Shell (Launcher) + Core-Views
│ Program.cs: Host.CreateDefaultBuilder, IConfiguration, Module laden, ShellUiHost, Application.Run
│ Ui/: LauncherForm, ShellUiHost, Views/ (Dashboard, Terminal, Settings, Jobs)
├── src/IBKRTrader.Core (classlib, net10.0-windows, UseWindowsForms)
│ ├── Modularity/ IModule (Name, DbPrefix, RegisterServices, RegisterUi, Start/Stop, ActivationBlocker)
│ │ ModuleView, IModuleUiHost, WindowMenu ← UI-Contract liegt im Core
│ ├── Configuration/ DatabaseOptions, ServerVersion-Pinning
│ ├── DependencyInjection/ AddCorePersistence(...)
│ ├── Persistence/Ef/ CoreDbContext + Entities + EF-Repositories (hinter Interfaces)
│ ├── Trading/ Broker-Seam, Risk, Execution, Portfolio, Domänentypen
│ ├── Services/ TerminalLogger, JobManager, Hosted Services (Market-Sync etc.)
│ ├── Security/ SecretProtection (Master-Key, AES-256-GCM at-rest)
│ └── Hosting/ StartupHydrationService (IHostedService, hydriert State zuerst)
├── src/IBKRTrader.Modules.CongressTrading (classlib, referenziert NUR Core)
│ ├── CongressTradingModule : IModule
│ ├── Persistence/Ef/ eigener DbContext (ct_) + Repos
│ ├── Services/ Scraper + Jobs (IHostedService)
│ └── Ui/ CongressTradingMainForm (Tabs) via RegisterUi
└── tests/IBKRTrader.Tests (xUnit, referenziert Core + Module)
```
### Leitprinzipien (aus PolytraderSharp übernommen)
- **Multi-Projekt**: Core = eigenes Assembly; jedes Modul = eigenes Projekt, referenziert **nur** Core.
Module können einander physisch nicht referenzieren.
- **Generic Host**: `Host.CreateDefaultBuilder`, `IHostedService` für alle Hintergrund-Jobs,
`IOptions`/`IConfiguration`.
- **Config**: `appsettings.json` + `appsettings.Local.json` (gitignored, hält Connection-String/Secrets).
- **Modul-Vertrag** `IModule`: `Name`, `DbPrefix`, `RegisterServices(services, config)`,
`RegisterUi(host, sp)`, `StartAsync/StopAsync`, `GetActivationBlocker(config)`.
- **UI = Shell + Views**: Core und Module registrieren `ModuleView`s beim `IModuleUiHost`.
Der Launcher öffnet je View ein Fenster (Einzelinstanz, Re-Open fokussiert). Gemeinsames
„Fenster"-Menü (`WindowMenu`) auf jedem Form. Views sind designbare Forms mit `Initialize(sp)`.
- **Persistenz**: EF Core (Pomelo/MySQL), `AddDbContextFactory`, Repositories hinter Interfaces.
- **Sicherheit**: Master-Key + AES-256-GCM-Verschlüsselung von Credentials at-rest; TLS-Warnung.
- **Headless-Test**: `--smoke-ui` konstruiert jede View + Launcher ohne Message-Loop.
- **Module an/aus** über `ServerSettings.DisabledModules`.
---
## 2. Was aus dem bisherigen Stand übernommen wird
| Bestand (Phase 03, Python-basiert) | Schicksal |
|---|---|
| Testprojekt (xUnit) | bleibt, wandert nach `tests/` |
| `RiskService`, `ExecutionService`, Domänentypen | Logik bleibt → Core/Trading (Feinschliff) |
| CongressTrading Scraper/Repo | Inhalt bleibt → eigenes Modul-Projekt (auf EF/IHostedService umgestellt) |
| `IModule`/`ModuleRegistry`/`WindowManager` | ersetzt durch PolytraderSharp-Contract (`IModule` neu, `ModuleView`, `IModuleUiHost`, `WindowMenu`) |
| Manuelles `ServiceCollection` in Program.cs | ersetzt durch Generic Host |
| `settings.json`/`SettingsService` | ersetzt durch `IConfiguration` + `appsettings.Local.json` |
| Dapper + manuelle Migrationen | ersetzt durch EF Core |
| `WorkerEngine`/`IWorker` | ersetzt durch `IHostedService` |
---
## 3. Re-Fundamentierungs-Phasen (Checkliste)
### R1 Solution-Skelett (Multi-Projekt, reiner Strukturumbau, Verhalten unverändert) ✅
- [x] `src/IBKRTrader.Core` (classlib, UseWindowsForms) `Core/` + UI-Contract (`Ui/ModuleFormBase`, `Ui/WindowManager`)
- [x] `src/IBKRTrader.Modules.CongressTrading` (classlib, referenziert nur Core)
- [x] Root-Projekt → `IBKRTrader.App` (WinExe), referenziert Core + Modul; Program/LauncherForm/UI-Shell bleiben
- [x] `tests/IBKRTrader.Tests` Referenzen auf Core + Modul; Fixture-Pfad angepasst
- [x] Neue `.slnx`; ungenutztes HtmlAgilityPack entfernt; Build + **38/38 Tests grün**; App startet
### R2 Core-Contracts + Generic Host + Shell-UI ✅
- [x] `IModule` (PolytraderSharp-Stil) + `ModuleView` + `IModuleUiHost` + `WindowMenu` in Core
- [x] `Program.cs``Host.CreateDefaultBuilder`; `IConfiguration` (appsettings.json + appsettings.Local.json, gitignored)
- [x] `ShellUiHost` + `LauncherForm` (View-Buttons + gemeinsames Fenster-Menü); Core-Views (Workers/Logs/Settings) als eigene Fenster
- [x] CongressTrading auf neuen `IModule`-Vertrag; Modul-Worker als `IWorker` registriert
- [x] `--smoke-ui` Headless-Test (alle Views + Launcher konstruieren) → grün
- [ ] **Offen (R4/R5):** Worker von `WorkerEngine`/`IWorker` auf `IHostedService` umstellen (aktuell noch WorkerEngine)
### R3 Persistenz auf EF Core
**Festgelegt:** EF-Migrationen **extern** (wie PolytraderSharp) Schema per `dotnet ef database update`,
App legt keine Tabellen zur Laufzeit an. Server: **MariaDB 11.8.6** (via `--db-version` bestätigt) →
Pin `new MariaDbServerVersion(new Version(11, 8, 6))`. Verbindung aus `appsettings.Local.json`.
- [x] `--db-version`-Diagnose (Serverversion für den EF-Pin)
- [x] **Slice 1:** `Configuration/DatabaseOptions` + `DatabaseServerVersion`-Pin (MariaDB 11.8.6); `AddCorePersistence` (`AddDbContextFactory`) + `CoreDbContext` + Entities (core_position, core_trade_history, core_budget, core_worker_log, core_settings) + Design-Time-Factory; **EF-Migration `InitialCore` erzeugt**
- [x] **Slice 2:** `PortfolioService`, `BudgetService`, `TradeHistoryService` auf EF (`IDbContextFactory<CoreDbContext>`) umgestellt; **5 EF-InMemory-Unit-Tests** (Buchführung real verifiziert). WorkerBase-Log folgt in Slice 4.
- [x] **Slice 3:** Modul auf EF (`CongressTradingDbContext` ct_ + `CongressRepository`); `WorkerBase`-Log auf EF (core_worker_log); `CoreSettingsService` (core_settings); `CoreMigrations`/`CongressMigrations` (Dapper) entfernt; EF-Migration `InitialCongressTrading`; `appsettings.Local.json` (gitignored) als Connection-Quelle; Fallback für leeren Connection-String. **+4 EF-InMemory-Tests** (CongressRepository)
- [x] **Slice 4:** IBKR-Marktdaten (`core_ibkr_*`) auf EF (3 Entities im `CoreDbContext`, Cross-Modul-Query via Raw-SQL); Migration `AddIbkr`; **Dapper + `DatabaseService` + `IBKRMigrations` vollständig entfernt** Persistenz ist jetzt **komplett EF Core**. +4 EF-InMemory-Tests.
**R3 abgeschlossen** gesamte Persistenz auf EF Core (Migrationen: `InitialCore`, `AddIbkr`, `InitialCongressTrading`), extern via `dotnet ef database update` anzuwenden.
- Hinweis: nur build-verifizierbar (Unit-Tests ohne DB); Schema-Anwendung extern via `dotnet ef database update` (env `IBKRTRADER_MYSQL`)
### R4 Worker auf `IHostedService` ✅
- [x] `WorkerBase` implementiert `IHostedService`; `IWorker` auf Metadaten+Trigger reduziert
- [x] Worker via `AddHostedService` registriert; Lebenszyklus über `AppHost.Start()`/`StopAsync()`
- [x] `WorkerEngine` auf leichte Registry reduziert (WorkerInfos für UI + `TriggerWorkerAsync`)
- [x] `LauncherForm` startet/stoppt keine Worker mehr; Build + 43/43 Tests + smoke-ui + App-Start grün
- Hinweis: Trading-Kern (Risk/Execution/Portfolio/Broker) wurde bereits in Phase 3 gebaut und in R3 auf EF gehoben
### R5 CongressTrading als vollständige Strategie ✅
- [x] `CongressTradingStrategy`: neuer Scrape-Trade → `TradeSignal` (buy/sell-Mapping) → Core-`IExecutionService`
- [x] `CongressScrapeWorker` ruft die Strategie je neuem Trade auf (per try/catch isoliert)
- [x] Modul-Fenster zeigt offene Positionen (`IPortfolioService.GetPositionsAsync("CT")`)
- [x] **8 neue Tests** (Signal-Mapping/Ausführung, gemockter ExecutionService) → 51/51 grün
- Hinweis: Handel bleibt durch Trading-Gate (`TradingEnabled=false`) + `NullBrokerClient` sicher aus, bis echter Broker + Freigabe
### R6 Sicherheit + Config-Härtung ✅
- [x] `SecretProtection` (Master-Key aus env `IBKRTRADER_MASTER_KEY`/`master.key`, AES-256-GCM at-rest, selbstheilendes `enc:v1:`-Format) + `EncryptedStringConverter` (bereit für künftige IBKR-Credentials)
- [x] `ConfigureSecretProtection` + TLS-Warnung (`SslMode`) beim Start; `master.key` gitignored
- [x] Connection-String in `appsettings.Local.json` (gitignored)
- [x] **5 SecretProtection-Tests** (Round-Trip, Idempotenz, Passthrough, Tamper/Key-Fehler) → 56/56 grün
- [ ] **Offen (Nutzer-Aktion):** geleaktes DB-Passwort rotieren (liegt in Git-Historie via `grundregeln.md`, Commit `ebeb035`); EF-Schema per `dotnet ef database update` auf die DB anwenden
### R7 Feinschliff ✅
- [x] Core-**Dashboard-View** (Gesamtüberblick: Trading-Modus, aggregierte Kennzahlen, geladene Module) + Icon
- [x] `DashboardService` (aggregiert Positionen/Exposure/Trades via EF) + **2 InMemory-Tests** → 58/58 grün
- [x] Tests durchgehend portiert; `--smoke-ui` deckt alle Views ab
- [x] **Echter `IbkrBrokerClient` über die TWS API** (2026-07-31): `src/IBKRTrader.Core/Trading/Ibkr/` `IbkrMapping` (rein, unit-getestet), `IbkrConnection` (Socket + reqId-Korrelation), `IbkrBrokerClient` (`IBrokerClient`). Aktivierung über `IBKRSettings.UseTwsApi`; `NullBrokerClient` bleibt Default. Design und Grenzen: [IBKR-Integration.md](IBKR-Integration.md), Einstellungen: [TWS-Setup-Checkliste.md](TWS-Setup-Checkliste.md).
- [x] Gegen Paper-Konto DUR371528 verifiziert: Verbindung, Konto (NetLiquidation 100.105,50 EUR), Kurse (AAPL/MSFT/NVDA, verzögert) und Fehlerpfade
- [x] Orderpfad bis zur Broker-Annahme per **What-If-Order** verifiziert (Aktie + Option, keine Ausführung); **Optionsberechtigung im Paper-Konto bestätigt**
- [x] **`IBrokerPortfolioReader`** (Bestand + Ausführungen beim Broker) eigener Seam neben `IBrokerClient`, Grundlage für den Abgleich der eigenen Buchführung; gegen DUR371528 verifiziert (2 Positionen, 2 Ausführungen inkl. Kommissionen)
- [ ] **Offen:** `PlaceOrderAsync` mit echter Ausführung verifizieren (Fill → Buchung); asynchrone Fill-Verfolgung (Orders ohne sofortige Ausführung)
- [ ] IBKR-Account-Credentials mit `EncryptedStringConverter` speichern
---
## Kurskorrektur abgeschlossen (R1R7)
IBKRTrader entspricht jetzt strukturell dem PolytraderSharp-Konzept: Multi-Projekt (Core + Modul + App + Tests),
Generic Host + `IHostedService`, `IConfiguration`, `IModule`/`ModuleView`/`ShellUiHost`, EF Core (extern migriert),
Trading-Kern (Risk/Execution/Portfolio, `NullBroker`-Default), CongressTrading-Strategie, Security (Master-Key/AES-GCM).
**Offen für später:** echte IBKR-Broker-Anbindung (Paper-Gateway), DB-Passwort-Rotation, EF-Schema anwenden.
---
## 4. Historie (bereits erledigt, teils zu ersetzen)
- Phase 03 (Python-basiert): Testfundament, IModule/ModuleRegistry, LauncherForm+WindowManager,
Trading-Kern (Risk/Execution/Portfolio, NullBroker). Logik brauchbar, Infrastruktur wird ersetzt.
- Commits bis `2ad4b55` auf Gitea.