# Umsetzungsplan: Modularisierung PolyTraderSharp > Stand: 2026-07-01 > Ziel: Umbau des monolithischen WinForms-Copytraders in ein modulares System > mit einem schlanken **Core** und unabhängigen **Modulen**. Erstes Modul: **Copytrading**. --- ## 1. Leitprinzipien 1. **Core kennt keine Module.** Der Core stellt nur Basis-Infrastruktur bereit (Host, DB/Persistenz, Settings, Jobs, Logging, API-Clients, Benachrichtigungen, Modul-Contract). Er hat **keine** Referenz auf irgendein Modul. 2. **Module hängen nicht voneinander ab.** Jedes Modul referenziert nur den Core. Ein Modul kennt kein anderes Modul. Dies wird durch getrennte Projekte **zur Compile-Zeit erzwungen**. 3. **Jede Phase lässt die App lauffähig und baubar zurück.** Kein „Big Bang". Nach jeder Phase: Debug-Build grün, App startet, Copytrading funktioniert. 4. **WinForms bleibt.** Die GUI-Anforderung ist fix. Module tragen ihre eigenen UI-Tabs zur Shell bei. 5. **Sicherheit vor Geschwindigkeit beim Refactoring.** CLOB-Integration ist hochkritisch (siehe `.agents/rules/clob.md`) – bei Berührung besonders sorgfältig, jede Änderung mehrfach prüfen. Rollback jederzeit über Git möglich. --- ## 2. Zielarchitektur ### 2.1 Solution-Struktur (Multi-Projekt) ``` PolyTraderSharp.sln │ ├── PolyTrader.Core (Class Library, net8.0-windows) │ • Generic Host / Bootstrap-Infrastruktur │ • Persistenz: Repository-Interfaces + Implementierung (EF Core) │ • Settings (appsettings.json + IOptions) + Core-Settings-Sektion │ • JobManager, Logging (TerminalLogger / ILogger-Sink) │ • Polymarket-Infrastruktur: PolymarketApiService, PolymarketClobClient, │ PolymarketWssClient, AlchemyWebsocketService │ • Querschnitt: MullvadVpnService, ThreemaService │ • Eigene Trading-Accounts (AccountState) — die Konten, mit denen WIR traden │ • Generischer Trade-Log (modulübergreifend auswertbar) │ • Gesamt-Dashboard (Overview über alle Module) │ • Core-State (generisch): MarketCache, globale Betriebsschalter │ • IPolyTraderModule-Contract + Modul-Registry │ ├── PolyTrader.Modules.CopyTrading (Class Library, net8.0-windows) │ • TraderMonitorService (Signalquelle) │ • CopyTradingEngine (Ausführung) │ • MasterTraderAnalyticsJob, TraderAnalyticsJob │ • Models: TrackedTrader (kopierte Master-Trader), CopySignal, │ CopyTradeRecord, TraderAnalyticsResult, MasterTraderHistoryRecord │ • Copytrading-State: Traders (Master), MasterTraderPositions, │ PendingOrderTimestamps, TraderAnalyticsCache │ • Channels: CopySignal, ClosedTrade │ • Eigener Copytrading-Trade-Log (Detail-Auswertung kopierter Trades, │ zusätzlich zum generischen Core-Log) │ • Eigene UI-Tabs (Master/Slave-Verwaltung, Modul-Analyse, Closed Trades) │ • Eigene Modul-Settings-Sektion │ • CopyTradingModule : IPolyTraderModule │ ├── PolyTrader.App (WinForms .exe, net8.0-windows) │ • Program.cs: Host-Bootstrap, lädt Core + registrierte Module │ • Shell-Form (frm_main reduziert auf Rahmen: Terminal, Jobs, Settings-Tab) │ • Referenziert Core + alle aktiven Module │ └── PolyTrader.Tests (xUnit, optional — spätere Phase) • Risk-/Entscheidungslogik des Copytrading-Moduls ``` ### 2.2 Modul-Contract (Entwurf) ```csharp public interface IPolyTraderModule { string Name { get; } // "CopyTrading" string DbPrefix { get; } // Namespace für DB-Objekte, z.B. "ct_" void RegisterServices(IServiceCollection services, IConfiguration config); void RegisterUi(IModuleUiHost uiHost); // Modul hängt seine Tabs ein Task StartAsync(CancellationToken ct); // läuft NACH Core-Hydration Task StopAsync(CancellationToken ct); } ``` - **Discovery:** Die App registriert Module explizit in `Program.cs` (`services.AddPolyTraderModule()`). Kein Runtime-Assembly-Scanning (bewusst einfach gehalten; kann später zum Plugin-System ausgebaut werden). - **Feature-/Lizenz-Gating:** `IPolyTraderModule` ist die natürliche Schnittstelle, um Module später per Lizenz zu aktivieren/deaktivieren (vgl. `lizenssystem.md`). ### 2.3 State-Aufteilung `TradingState` wird zerlegt: | Feld | Ziel | |------|------| | `MarketCache` | **Core** (generischer Markt-Cache) | | `GlobalTradingPaused`, `LiveTradingMode`, `DemoTradingMode` | **Core** (globale Betriebsschalter) | | `Accounts` (unsere eigenen Trading-Accounts, `AccountState`) | **Core** — die Konten, mit denen WIR traden; modulübergreifend nutzbar | | `Traders` (kopierte Master-Trader, `TrackedTrader`) | **CopyTrading-Modul** | | `MasterTraderPositions`, `PendingOrderTimestamps`, `TraderAnalyticsCache`, `TotalCopyTrades`, `GlobalPnl` | **CopyTrading-Modul** | > Entschieden (2026-07-01): Eigene Trading-Accounts liegen im **Core** (auch künftige > Module handeln über dieselben Konten). Die **kopierten** Master-Trader (`TrackedTrader`) > sind ein Copytrading-Konzept und liegen im **Modul**. ### 2.4 Trade-Logging (zweistufig) Zwei unabhängige, parallel geführte Logs: 1. **Generischer Core-Trade-Log** (`TradeRecord` + `ITradeLogRepository`): modulneutrale Felder (ModulName, AccountId, Markt, Side, Entry/Exit, PnL, Zeiten, ExitReason). Ermöglicht die **modulübergreifende** Gesamtauswertung. Jedes Modul, das Trades ausführt, schreibt hier einen Eintrag. 2. **Copytrading-spezifischer Log** (`CopyTradeRecord`, im Modul): erweitert die generischen Felder um Copytrading-Details (`SourceTraderId`, `SourceTraderName`, Master-Adresse, Signal-Herkunft) für die **detaillierte** Copytrading-Analyse. Beim Schließen eines kopierten Trades schreibt das Modul **beides**: einen generischen Eintrag in den Core-Log und einen Detaileintrag in seinen eigenen Log. ### 2.5 Dashboard & Analyse - **Core-Gesamt-Dashboard:** Overview über alle Module (aggregierte PnL, Kontostände, offene Positionen, grobe Kennzahlen je Modul) — gespeist aus dem generischen Core-Log. - **Modul-Analyse:** Jedes Modul liefert seine eigene Detailansicht (Copytrading: Trader-Winrates, kopierte Trades, Master-Performance) — gespeist aus dem Modul-Log. ### 2.6 Settings - **Core-Settings-Sektion:** globale/Infrastruktur-Einstellungen (DB, VPN, Threema, Betriebsschalter). - **Modul-Settings-Sektion:** jedes Modul trägt seine eigene Sektion zum Settings-Tab bei (analog zu den UI-Tabs), registriert über den `IPolyTraderModule`-Contract. - **API-Keys sind Modul-Settings:** Alchemy-/Polymarket-WSS-Keys wandern von der globalen `ServerSettings` in die jeweilige Modul-Settings-Sektion (siehe 2.7). ### 2.7 Streaming / WebSocket-Architektur *(Entscheidung 2026-07-01)* **Prinzip:** Der **Core stellt die WSS-Verbindungs-Klasse als wiederverwendbare Fähigkeit** bereit — **keinen** geteilten Singleton-Stream. Jedes **Modul erzeugt seine eigene Instanz** mit **eigenem API-Key und eigenem Filter**. **Begründung:** Blockchain-/WSS-Streams werden modulspezifisch **gefiltert** (sonst viel zu umfangreich). Ein einzelner, Core-gesteuerter Stream, auf den mehrere Module gleichzeitig zugreifen, wäre für jedes einzelne Modul mit nutzlosen Informationen geflutet. **Aufteilung des heutigen `AlchemyWebsocketService`:** - **Core** (`PolyTrader.Core.Streaming`): Verbindungs-Mechanik — `ClientWebSocket`, `eth_subscribe`, Empfangs-Loop, Decode, Reconnect/429-Backoff, Health. Parametrisiert über eine `BlockchainWssSubscription` (Contract, Topics, Adress-Filter) + RPC-URL/Key. Als **Factory** (`IBlockchainWssClientFactory.Create()`), damit jedes Modul eine eigene Instanz bekommt. - **Modul** (`CopyTrading`): `CopyTradingBlockchainListener : BackgroundService`, der eine Core-WSS-Instanz mit dem Copytrading-Filter (Wallets der getrackten Master-Trader) + dem Modul-eigenen Alchemy-Key betreibt, den gefilterten Substream konsumiert und selbst reagiert (TraderMonitor-Poll, Re-Subscribe bei Trader-Listen-Änderung). Analog für den Polymarket-User/Market-WSS (`PolymarketWssClient` → Core-Verbindungsklasse + Modul-Listener). `IsAlchemyHealthy` (heute im Core-State) wird zum Health-Signal der jeweiligen Modul-Instanz. --- ## 3. Persistenz-Strategie - **Zielrichtung: Wechsel auf MySQL** via **EF Core + Pomelo.EntityFrameworkCore.MySql**, gekapselt hinter Repository-Interfaces im Core. - **Begründung:** DB liegt off-hot-path (Live-Pfad ist RAM-only) → kein Performance-Nachteil. Gewinn: saubere relationale Tabellen statt Collection-per-Account + Shim, ACID, EF-Migrations, Standard-Backups. - **Risikoarm durch Reihenfolge:** Zuerst Repository-Abstraktion einziehen (Phase 3), MySQL-Umstieg als eigene späte Phase (Phase 6). Die Modularisierung ist davon entkoppelt und nicht blockiert. - **Aufräumen:** LiteDB-Paket, `data.db` und `MongoDbLiteDBShim` entfallen nach der Migration. - **ORM: Entity Framework Core** (entschieden) — Migrations + wenig Boilerplate. --- ## 4. Phasenplan > Jede Phase endet mit grünem Debug-Build + lauffähiger App + Git-Commit. ### Phase 0 — Fundament: Versionskontrolle & Aufräumen *(ABGESCHLOSSEN 2026-07-01)* - [x] `git init` (Branch `main`), `.gitignore` (bin/, obj/, .vs/, *.user, *.db, server_settings.xml, agentspace/antigravity/, .claude/settings.local.json). - [x] Alle 11 `.bak*`-Dateien entfernt (per `-f` im Baseline-Commit `475d396` archiviert, danach entfernt → rekonstruierbar). - [x] Tote Stubs entfernt: `services/database.cs`, `services/settings.cs`, `polymarket/*.cs`. - [x] Threema-Lib unter `libs/` vendored (nested `.git` entfernt). - [x] Baseline-Commit `475d396` + Cleanup-Commit `f76ad73`; Debug-Build 0 Fehler verifiziert. ### Phase 1 — Multi-Projekt-Gerüst anlegen *(ABGESCHLOSSEN 2026-07-01, Commit `4f130ff`)* - [x] Drei Projekte: `PolyTrader.App` (umbenanntes WinForms-Projekt, Root), `src/PolyTrader.Core`, `src/PolyTrader.Modules.CopyTrading` (net8.0-windows). - [x] Referenzen: App → Core + CopyTrading; CopyTrading → Core; Core → nichts. - [x] App-csproj: `src\**` vom Globbing ausgeschlossen (keine Glob-Kollision); RootNamespace auf `PolyTraderSharp` gepinnt (schützt .resx/Namespaces). - [x] Threema-Lib-Referenz bleibt im App-Projekt (wandert in Phase 4 zu Bedarf in Core). - [x] **Ergebnis:** Solution-Build 0 Fehler, Code liegt weiterhin im App-Projekt. - [ ] *Offen für spätere Phasen:* NuGet-Pakete beim Code-Umzug auf Core/Modul verteilen. ### Phase 2 — Konfiguration externalisieren *(ABGESCHLOSSEN 2026-07-01, Commit `e312fbb`)* - [x] `appsettings.json` eingeführt (Mongo-Connection + DB-Name), Copy-to-Output. - [x] `DatabaseOptions` im Core, via `IOptions` gebunden; hart codierte Strings aus `Program.cs` entfernt. - [x] Startup-Cleanup-Hack aus `Main()` entfernt und gekapselt nach Host-Build über die konfigurierte DB neu verankert. - [ ] *Offen (bewusst später):* Alchemy-Key / Mullvad-Account / Threema bleiben vorerst im GUI-editierbaren `server_settings.xml` (kein Konflikt mit Settings-Tab). ### Phase 3 — Persistenz-Abstraktion (DB noch Mongo) *(IN ARBEIT)* - [x] **3a** (`8b3264f`): Core-Modelle `AccountState`/`Position`/`MarketData` in den Core verschoben (Namespace `PolyTraderSharp.Models` beibehalten), MongoDB.Driver-Paket im Core. - [x] **3b** (`ed5d6e3`): Repository-Interfaces + Mongo-Implementierungen im Core (`IAccountRepository`, `IMarketRepository`, `IPositionRepository`), `AddCorePersistence()`. - [x] **3c** (`7197f9b`): Unkritische Call-Sites migriert (MarketSyncService, PolymarketWssClient). - [x] **3d — Hot-Path** (`a0e367e`, `0c6fc6a`): TraderMonitorService + CopyTradingEngine auf `IPositionRepository`/`IMarketRepository`/`IAccountRepository` umgestellt. `_db` aus CopyTradingEngine komplett entfernt; Verhalten unverändert. - [ ] **frm_main-UI:** Account/Market/Demo-Position-Zugriffe → wird zusammen mit der UI-Zerlegung in Phase 5 migriert (vermeidet Wegwerf-Arbeit). - [ ] *Offen für Phase 5:* generisches `ITradeLogRepository` (Core) + `ICopyTradeLogRepository` + `ITraderRepository` (Modul), sobald `ClosedTrade`/`TrackedTrader` ins Modul wandern. - [ ] **Ergebnis (Ziel):** Kein direkter DB-Zugriff mehr außerhalb der Repository-Schicht. ### Phase 4 — Core herauslösen *(IN ARBEIT)* - [x] **4.1** (`9039af8`): TerminalLogger, JobManager, JobStatusRow → Core; toten Stub `logging.cs` gelöscht. - [x] **4.2** (`eebe992`): PolymarketClobClient → Core (+ Nethereum.Web3), reines Verschieben. - [x] **4.3** (`8c126cd`): ServerSettings → Core. - [x] **4.4** (`a1ce3fc`): `IPolyTraderModule`-Contract im Core (UI-Teil auf Phase 5 vertagt). - [x] **4.5** (`c88eac5`): Startup-Reihenfolge-Fix — `StartupHydrationService` (IHostedService, als erster registriert) hydriert Accounts/Trader vor den Trading-Services; `frm_main.LoadDatabaseAndState` entfernt. - [x] **4.6a** (`9c068b4`): CopySignal + PolymarketApiService → Core. - [x] **4.7** (`0ffc041`): MullvadVpnService + ThreemaService (+ Threema-Lib-Ref) → Core; toter Stub `mullvad.cs` gelöscht. - [ ] **BLOCKIERT durch TradingState-Split (→ Phase 5):** MarketSyncService, AlchemyWebsocketService, PolymarketWssClient, SnapshotService nutzen `TradingState` (MarketCache/Accounts/globale Flags). Sie können erst nach dem Split in den Core. - [x] **Ergebnis:** Core baut eigenständig und enthält jetzt: Modelle (Account/Position/ Market/CopySignal/JobStatusRow/ServerSettings), Repository-Schicht, Config, Logging, JobManager, CLOB-Client, API-Service, Mullvad, Threema, IPolyTraderModule. **Stand nach Phase 4:** Der Core ist substanziell und eigenständig. Was noch in der App liegt: Modul-Services (TraderMonitor, CopyTradingEngine, Analytics-Jobs), die TradingState-abhängige Infra (MarketSync, Alchemy, WSS, Snapshot), PersistenceService, StartupHydrationService, der Shim, `TradingState`, `frm_main` und die Modul-Modelle (TrackedTrader, TraderAnalyticsResult, MasterTraderHistoryRecord, ClosedTrade, DashboardRow). Der **TradingState-Split** ist der Dreh- und Angelpunkt für Phase 5. > **Entscheidung (2026-07-01):** `CopySignal` wird ein **Core**-Typ (generisches Markt-Trade- > Signal). Das entkoppelt die Polymarket-Infrastruktur sauber in den Core. Der Channel/Workflow > bleibt Copytrading. Umbenennung zu `TradeSignal` optional/später. ### Phase 5 — CopyTrading-Modul herauslösen *(IN ARBEIT)* - [x] **5.1** (`55050a1`): Modul-Modelle (TrackedTrader, TraderAnalyticsResult, MasterTraderHistoryRecord) ins Modul verschoben. - [x] **5.2** (`f8d395b`): **TradingState-Split** — Core `TradingState` (globale Schalter, Accounts, MarketCache, GlobalPnl) vs. `CopyTradingState` im Modul (Traders, MasterTraderPositions, TraderAnalyticsCache, TotalCopyTrades, PendingOrderTimestamps, SixSharesMinimum); 10 Konsumenten umgestellt. Modulgrenze auf State-Ebene gezogen. - [x] **5.3a** (`f5e7eaf`): MarketSyncService → Core (nur Core-State). - [ ] **5.3:** Modul-Services physisch ins Modul-Projekt verschieben: TraderMonitorService, CopyTradingEngine, beide Analytics-Jobs (blockiert durch ClosedTrade-Migration, s.u.). - [ ] **5.3-WSS (siehe 2.7):** `AlchemyWebsocketService` **aufteilen** — Verbindungs-Klasse (`IBlockchainWssClient` + Factory) → Core; `CopyTradingBlockchainListener` → Modul (eigener Key + Filter). Analog `PolymarketWssClient`. API-Keys → Modul-Settings. - [ ] **ClosedTrade-Migration (Voraussetzung für 5.3):** `ClosedTrade` → Modul, `ICopyTradeLogRepository`, `closed_trades`-Zugriffe in TraderMonitor/CopyTradingEngine/WSS umstellen (~20-25 Stellen; frm_main/Persistence-Nutzungen laufen via Modul-Referenz weiter). - [ ] Copytrading-UI-Tabs aus `frm_main` in das Modul auslagern (Master/Slave-Verwaltung, Modul-Analyse, Closed Trades). `frm_main` wird zur reinen Shell (Terminal, Jobs, Core-Gesamt-Dashboard, Settings-Rahmen). - [ ] `CopyTradingModule : IPolyTraderModule` implementieren (Services + UI-Tabs + Settings-Sektion + Modul-Log + Start/Stop). - [ ] Dualen Trade-Log verdrahten: beim Schließen kopierter Trades in Core-Log **und** Copytrading-Log schreiben. - [ ] Latenten Collection-Namensbug beheben (`traders` vs. `trackers`). - [ ] **Ergebnis:** Copytrading ist ein eigenständiges, entfernbares Modul. ### Phase 6 — MySQL-Migration - [ ] EF Core + Pomelo einrichten; relationales Schema modellieren (u.a. `positions` mit `account_id` statt Collection-per-Account; `trader_accounts` Join-Tabelle für `AssignedAccountIds`). - [ ] Zweite Repository-Implementierung (MySQL) hinter den bestehenden Interfaces. - [ ] Einmaliges Migrationsskript Mongo → MySQL (agentspace/scripts). - [ ] Umschalten per Konfiguration; Mongo/LiteDB/Shim + `data.db` entfernen. ### Phase 7 — Nacharbeiten *(optional, später zu priorisieren)* - [ ] Test-Projekt: Risk-/Entscheidungslogik als reine Funktionen extrahieren & testen. - [ ] God-Methoden splitten (`PollLiveAccountsAsync`, `ProcessAccountOrderAsync`); duplizierte Closed-Trade-Erzeugung zentralisieren. - [ ] Leere `catch {}` durch gezieltes Logging ersetzen. - [ ] Secrets-Verschlüsselung (DPAPI) für PrivateKey/ApiSecret/ApiPassphrase. - [ ] TerminalLogger auf `Microsoft.Extensions.Logging` + UI-Sink umstellen. --- ## 5. Datei-→-Ziel-Zuordnung (Referenz) | Aktuell | Ziel | |---------|------| | `Program.cs` | PolyTrader.App | | `frm_main.*` | PolyTrader.App (Shell) + Copytrading-Tabs → Modul | | `frm_analytics.*` | PolyTrader.Modules.CopyTrading | | `TradingState.cs` | aufgeteilt: Core + Modul | | `services/PolymarketApiService.cs` | Core | | `services/PolymarketClobClient.cs` | Core | | `services/PolymarketWssClient.cs` | Core | | `services/AlchemyWebsocketService.cs` | Core | | `services/MullvadVpnService.cs`, `mullvad.cs` | Core | | `services/ThreemaService.cs` | Core | | `services/JobManager.cs`, `TerminalLogger.cs`, `logging.cs` | Core | | `services/PersistenceService.cs` | Core (generischer Trade-Log-Writer); Copytrading-Detail-Writer → Modul | | `services/MarketSyncService.cs`, `SnapshotService.cs` | Core | | `Extensions/MongoDbLiteDBShim.cs` | Core (temporär), entfällt in Phase 6 | | `services/CopyTradingEngine.cs` | Modul | | `services/TraderMonitorService.cs` | Modul | | `services/MasterTraderAnalyticsJob.cs`, `TraderAnalyticsJob.cs` | Modul | | `Models/AccountState.cs`, `Position.cs`, `MarketData.cs`, `ServerSettings.cs`, `JobStatusRow.cs`, `DashboardRow.cs` | Core | | `Models/ClosedTrade.cs` | aufgeteilt: generischer `TradeRecord` → Core, `CopyTradeRecord` (mit SourceTrader-Feldern) → Modul | | `Models/TrackedTrader.cs`, `CopySignal.cs`, `TraderAnalyticsResult.cs`, `MasterTraderHistoryRecord.cs` | Modul | | `services/database.cs`, `settings.cs`, `polymarket/*.cs` | löschen (Phase 0) | | `*.bak*` | löschen (Phase 0) | --- ## 6. Getroffene Entscheidungen (2026-07-01) 1. **Eigene Trading-Accounts → Core**, **kopierte Master-Trader → Copytrading-Modul.** 2. **Zweistufiges Trade-Logging:** generischer Core-Log (modulübergreifend) **und** zusätzlicher Copytrading-Detail-Log im Modul (siehe 2.4). 3. **ORM: Entity Framework Core.** 4. **Dashboard:** Core liefert Gesamt-Overview über alle Module; Module liefern eigene Detail-Analysen (siehe 2.5). 5. **Settings:** getrennte Core- und Modul-Settings-Sektionen (siehe 2.6). --- ## 7. Risiken & Gegenmaßnahmen - **CLOB-Regression:** Höchstes Risiko. Gegenmaßnahme: CLOB-Client möglichst unverändert in den Core verschieben (nur Namespace/Referenzen), keine Logikänderung in der Umstrukturierungsphase. - **Startup-Race weiterhin aktiv, bis Phase 4:** Bis der Startup-Fix greift, bleibt das bestehende Verhalten – kein neues Risiko, aber früh angehen. - **Datenmigration (Phase 6):** Server läuft produktiv. Migration mit Read-Only-Export + Verifikation vor Umschaltung; Rollback-Pfad (Mongo bleibt bis Verifikation bestehen).