--- trigger: always_on --- Projektname: IBKRTrader Ziel: Modulares, hochperformantes C# Trading-Framework (.NET 10) für automatische Aktien-Strategien mit Interactive Brokers API. Vorbild-Konzept: Polytrader (Core + unabhängige Module + Launcher, der die Fenster der einzelnen Module öffnet). Strikte Architektur-Regeln (immer einhalten): Harter Core + beliebig viele unabhängige Module Module dürfen Core oder andere Module niemals beeinflussen DB-Tabellen-Namensschema: {ModulKürzel}_Tabellenname → Core = core_xxx → CongressTrading = ct_xxx Vollständig modulare Worker-Engine: Jeder Worker ist komplett unabhängig, hat eigenen Zeitplan, ist einzeln aktivierbar/deaktivierbar/manuell startbar Keine gegenseitigen Blockierungen – alles thread-sicher und performant Technik (fest): C# .NET 10, **Avalonia** für die Oberfläche – plattformneutral (Windows und Linux). KEIN WinForms und kein System.Drawing: beides bindet an Windows. Alle Projekte sind `net10.0` ohne Plattform-Suffix; ein `net10.0-windows` irgendwo ist ein Fehler. Avalonia bleibt auf der 11er-Linie (11.3.19 / DataGrid 11.3.13), bis LiveCharts2 Avalonia 12 unterstützt – sonst brechen die Diagramme der kommenden Module. MySQL – Zugangsdaten NUR in settings.json (gitignored), NIE im Repo/Code/Doku hinterlegen IBKR TWS/Gateway API (Paper: Port 4002, Live: Port 4001 – Umschaltung über TradingSettings.Mode) Interne REST-API + lokaler Webserver (für späteres Web-UI) Settings: settings.json (Vorlage: settings.example.json) Logging: LoggingService meldet Einträge über das Ereignis `EntryWritten` (die Oberfläche hängt sich ein und färbt selbst) + Dateien unter Logs/[Modul]/[Level]-dd-MM-yy.txt sowie Logs/[Datum].jsonl Zeit: Zeitstempel IMMER in UTC persistieren. Für Anzeige, Tagesgrenzen und Zeitpläne `AppTimeZone` verwenden, NIE `DateTime.Now` oder `DateTimeKind.Local` – wir betreiben Instanzen in EU und US, die Ortszeit darf nicht am Rechner hängen. Kultur: Jede Zahl-/Datumsformatierung und jedes Parsen braucht einen ausdrücklichen IFormatProvider (i. d. R. InvariantCulture). Ohne ihn hängt das Ergebnis an der Kultur des Hosts. Tests: eigenes Projekt IBKRTrader.Tests (xUnit + NSubstitute + FluentAssertions), NUR Unit-Tests, alles Externe (DB/IBKR/Scraper) gemockt. DoD jeder Phase: `dotnet test` grün + Build sauber. UI-Grundmodell (Launcher-Prinzip nach Polytrader): LauncherWindow = Basis-Fenster mit einer Schaltfläche je registrierter Ansicht und dem gemeinsamen Fenster-Menü. Die Inhalte (Dashboard, Workers, Logs, Settings, Modul-Fenster) sind eigenständige Fenster, keine Tabs; je Ansicht höchstens eines, erneutes Öffnen fokussiert. Layout deklarativ in .axaml, nicht zur Laufzeit im Code. Kompilierte Bindings sind aktiv, jeder Datenkontext braucht ein x:DataType – dadurch fallen Bindungsfehler beim Kompilieren auf. Module tragen KEINEN UI-Code: sonst müssten sie Avalonia referenzieren und wären nicht mehr kopflos lauffähig. Ihr RegisterUi bleibt leer, die Fenster registriert die Shell zentral in src/IBKRTrader.App/Shell/ModuleViews.cs. Workers-Ansicht, Spalten: Aktiv | Typ | Modul | Worker | Letzter Lauf | Nächster Lauf | Intervall | Info Type = "Worker" oder "Service" (Service = permanent laufend) Betriebsformen (beide aus derselben Host-Zusammenstellung, src/IBKRTrader.Hosting): src/IBKRTrader.App – mit Oberfläche; `--smoke-ui` prüft die Fenster-Konstruktion ohne Anzeigegerät src/IBKRTrader.Daemon – kopflos für Linux/systemd; `--check` fährt die Startprüfungen ohne Dienste Core-Worker (müssen zuerst): Backup (alle 30 min) Webserver (Service) WebAPI (Service) Erstes Modul: CongressTrading → Scrapt https://www.capitoltrades.com/trades?pageSize=96 → Tabellen: ct_congressMember + ct_trade → Zuerst alle Trades der letzten 3 Jahre, danach Worker alle 30 min neue Trades Entwicklungs-Regeln: Immer extrem saubere, modulare, wartbare Architektur Build-Ordner muss absolut clean sein (nur notwendige Dateien) Arbeite streng schrittweise: zuerst Core fertig, dann Module Jede neue Funktion zuerst als Worker/Service im Core oder im jeweiligen Modul anlegen Diese Rule hat immer höchste Priorität. Bei jedem Prompt und jedem Neustart gelten diese Vorgaben.