Added B6 to UMSETZUNGSPLAN.md: unbounded MarketSyncWorker re-sync of all closed markets, watchlisted traders not exempt from auto-cleanup deletion, full trade-history load in GetKnownPlatformTradeIdsAsync, a race condition in MarketRepository.AddOrUpdateAsync under concurrent access, and an early-break assumption in TradeHistoryWorker that isn't applied consistently. No functional code changed yet — these are earmarked for Phase 2 (B3-adjacent).
22 KiB
Predictalytics – Umsetzungsplan (Phase 1 & 2 + Storage-Optimierung)
Wie wir das nutzen: Wir arbeiten diese Liste Stück für Stück ab. Erledigte Punkte werden von
[ ]auf[x]gesetzt. Reihenfolge ist absichtlich so gewählt, dass spätere Schritte auf früheren aufbauen — nicht einfach querbeet abhaken, siehe Abschnitt "Empfohlene Reihenfolge" ganz unten für die Kurzfassung.Phase 3 (Monetarisierung: Auth, Multi-Tenant, Billing) ist bewusst nicht Teil dieses Plans.
0. Vorab-Bugfund (betrifft Phase 1 direkt)
Beim Review ist aufgefallen, dass TraderAnalyticsWorker.CalculatePnL jeden Trade, der kein Buy ist, wie ein Sell behandelt (else pnl += t.Amount). Das ist falsch für Split, Merge, Redeem, AddLiquidity, RemoveLiquidity — das sind keine gewöhnlichen Verkäufe. Dieser Fix gehört zwingend in die neue PnL-Engine (siehe A1/A6), nicht als Extra-Task.
Phase 1 – Kernanalytik korrigieren
A1. Positionsbasierte PnL-Engine
- Entscheidung dokumentieren: Average-Cost-Methode statt FIFO (einfacher, und – wichtig – kompatibel mit späterer Trade-Kompaktierung in Abschnitt C, weil Average-Cost nur Gesamtstückzahl & Gesamtkosten braucht, keine Einzel-Trade-Reihenfolge)
- Neue Domain-Struktur
TraderPosition(TraderId, MarketOutcomeId, SharesHeld, AvgCost, RealizedPnl, zuletzt aktualisiert) — inkrementell fortschreibbar statt bei jeder Berechnung die komplette Trade-Historie neu zu scannen - Buchungslogik je
TradeSidesauber definieren:Buy: Shares += Size, AvgCost neu gewichtenSell: RealizedPnl += Size × (Price − AvgCost), Shares −= SizeRedeem(Marktauflösung): RealizedPnl += verbleibende Shares × (1 oder 0 je nach Gewinn-Outcome − AvgCost), Shares = 0Split/Merge: als neutrale Positionsumwandlung behandeln (kein PnL-Effekt), nicht wieSellAddLiquidity/RemoveLiquidity: getrennt von Trading-PnL betrachten (eigene Kategorie, fließt nicht in "Trading-Skill"-Bewertung ein)
- Unrealisierten PnL für offene Positionen berechnen:
Shares × (MarketOutcome.CurrentPrice − AvgCost) - Gesamt-PnL = realisiert + unrealisiert (ersetzt
OverallPnL,PnL30d/7d/24hFelder inTraderAnalytics) - Prüfen, ob wir zusätzlich/alternativ Polymarkets eigenen
/positions-Endpoint (GetTraderPositionsAsync, liefertCurrentValue/PercentPnl) als Plausibilitäts-Check oder sogar als primäre Quelle für offene Positionen nutzen (aktuell komplett ungenutzt) CalculatePnL-Bug aus Abschnitt 0 im Zuge dessen mit erledigen
A2. Win-Rate korrekt berechnen
- Win/Loss ist pro Markt, nicht pro Trade, definiert: ein Markt zählt als "Win", wenn der realisierte PnL aus diesem Markt (nach Redeem/vollständigem Exit) positiv ist
WinRate = Anzahl gewonnener Märkte / Anzahl abgeschlossener Märkte(offene Positionen zählen nicht mit)- Placeholder
return 0;inTraderAnalyticsWorker.CalculateWinRateersetzen
A3. Deep-Dive-Kennzahlen mit echten Werten füllen
- Voraussetzung klären: Für Entry/Exit-Qualität und Timing-Accuracy brauchen wir eine Preis-Historie pro
MarketOutcome, nicht nur den aktuellen Preis (CurrentPrice). Aktuell existiert keine Historisierung.- Prüfen, ob Polymarkets CLOB-API einen Preishistorie-Endpoint (
/prices-history) hergibt, den wir zum Backfill nutzen können - Falls ja: neue Tabelle
MarketOutcomePriceSnapshot(MarketOutcomeId, Timestamp, Price) einführen, periodisch befüllt (z.B. durch bestehendenMarketSyncWorker/MarketHistoryWorkererweitern)
- Prüfen, ob Polymarkets CLOB-API einen Preishistorie-Endpoint (
AvgHoldDurationHoursecht berechnen: gewichtete Haltedauer zwischen Einstieg (Buy-Zeitpunkte, gewichtet nach Größe) und Ausstieg (Sell/Redeem) pro PositionEntryQuality: Einstiegspreis im Vergleich zur nachfolgenden Preisentwicklung (z.B. Perzentil des Einstiegspreises innerhalb eines Zeitfensters danach)ExitQuality: analog für AusstiegspreisTimingAccuracy: z.B. Anteil der Trades, die kurz vor einer für den Trader günstigen Preisbewegung platziert wurden- Hardcodierte
50-Neutralwerte inAnalyticsService.PerformDeepDiveentfernen
A4. Strategie-Klassifikation verbessern
- Zusätzliche Signale einbeziehen statt nur "Ø-Größe" und "Hedging-Rate":
- Verteilung der Haltedauern (kurz/lang, Varianz)
- Diversität der Marktkategorien
- Anteil der Trades kurz vor Marktauflösung vs. früh im Marktleben
- Nutzung gegenläufiger Positionen (Arbitrage-Muster über mehrere Outcomes/Märkte)
- Trade-Größen-Varianz (regelmäßig gleich große Orders = evtl. automatisiert)
- Überlegen, ob
StrategyTypeals reines Einzel-Enum ausreicht oder ob wir zusätzlich Mehrfach-Signale/Tags parallel speichern (z.B. "primär Hedger, aber auch Whale-Größenordnung") — Enum bleibt als Primär-Tag, Zusatzsignale als eigene Felder/Scores - Sicherstellen, dass nicht der Großteil der Trader dauerhaft bei "Unknown" landet (aktuell strukturell der Fall)
A5. Copytrading-Eignungs-Score (neu)
- Neue Metrik-Dimension definieren, unabhängig vom bestehenden
PriorityScore:- Liquiditäts-Fit: durchschnittliche Positionsgröße im Verhältnis zur Marktliquidität/zum Volumen zum Handelszeitpunkt (Slippage-Risiko für Nachahmer)
- Reaktionsfenster: wie viel Zeit bliebe einem Copytrader realistisch zum Nachziehen (Trader mit Sekunden/Millisekunden-Kadenz sind nicht kopierbar)
- Frequenz/Konzentration: sehr hochfrequente/bot-artige Trader senken den Score automatisch
- Track-Record-Länge & Konsistenz: mehr abgeschlossene Märkte mit konsistent positivem PnL = höheres Vertrauen
- Kombinierten
CopytradingScore(0–100) berechnen und persistieren (neues Feld aufTraderScoreoder eigene EntityTraderCopytradingProfile) - Im Dashboard/API sichtbar machen (getrennt von der bisherigen "Priorität", da unterschiedliche Fragestellung: gut vs. kopierbar)
A6. (siehe Abschnitt 0) TradeSide-Bugfix in PnL-Berechnung
- Erledigt sich durch A1, hier nur als Häkchen zur Nachverfolgung
- Kurzer Änderungsvermerk/Commit-Hinweis, damit klar ist, dass dieser Bug bewusst behoben wurde
Phase 2 – Robustheit & Wartbarkeit
B1. EF Core Migrationen einführen
- Aktuellen Ist-Stand des Schemas exakt erfassen (inkl. aller manuellen
ALTER TABLE-Patches ausDependencyInjection.cs) — abgeglichen, Entities/OnModelCreatingdeckten den Patch-Stand bereits vollständig ab - Erste Baseline-Migration erzeugt (
20260701102311_InitialBaseline, insrc/Predictalytics.Infrastructure/Migrations/), entspricht exakt dem aktuellen Schema EnsureCreatedAsync+ handgeschriebeneExecuteIfColumnMissing/ALTER-Helfer ausDependencyInjection.csentfernt, durchdb.Database.MigrateAsync()ersetzt (Platform-Seed bleibt alsINSERT IGNORE)- Migration end-to-end gegen eine echte, frische DEV-Datenbank getestet (
lqf7.your-database.de/bergisnu_db0, vom Nutzer bereitgestellt) —dotnet ef database updatelief fehlerfrei durch,dotnet ef migrations listbestätigt sie als angewendet AppDbContextFactory(Design-Time-Factory fürdotnet ef) liest Zielverbindung jetzt aus Env-Vars (PREDICTALYTICS_DB_SERVER/_NAME/_USER/_PASSWORD, viaMySqlConnectionStringBuilderstatt roher String-Konkatenation, da Passwörter Sonderzeichen wie;/{}enthalten können) statt fest codiert — kein Secret mehr im Repo nötig, um Migrationen gegen eine beliebige DB zu fahrenLive-Produktions-DB manuell als "bereits migriert" markieren— vorerst zurückgestellt: Da wir laut Abschnitt D ohnehin einen kompletten Neustart der Produktions-DB planen (Altdaten sind jederzeit nachladbar, siehe C0), richten wir die neue Produktions-DB am Ende genauso ein wie die DEV-DB (leer anlegen +dotnet ef database update) — der fummelige Stamp-Schritt auf die bestehende Live-DB entfällt dann komplett. Nur falls wir uns doch gegen den Neustart entscheiden, müsste dieser Schritt nachgeholt werden- Alle künftigen Schemaänderungen aus Phase 1 (z.B.
TraderPosition,MarketOutcomePriceSnapshot,TraderCopytradingProfile) als reguläre Migrationen anlegen — direkt gegen die DEV-DB entwickeln/testen, da wir dort laut Nutzer frei experimentieren dürfen
B2. Secrets-Management (Release-Vorbereitung, kein akuter Risikofall)
Software läuft aktuell nur lokal, kein Fremdzugriff — Passwort bleibt vorerst wie es ist, keine Rotation nötig. Dieser Punkt ist reine Vorbereitung, damit das Projekt bei Bedarf später auch ohne die aktuellen Secrets veröffentlicht/geteilt werden könnte, ohne den Code nochmal anfassen zu müssen. Dadurch niedrigere Priorität als vorher angenommen — kann später in der Reihenfolge stehen.
- Produktiven MySQL-Connection-String aus
appsettings.jsonin Umgebungsvariablen/User Secrets verschieben appsettings.jsonim Repo künftig nur Platzhalter/Dev-Default enthalten, damit ein Klon des Repos ohne die echten Zugangsdaten lauffähig bleibt (mit eigener lokaler DB)- Keine Passwort-Rotation nötig, solange rein lokale Nutzung
B3. Scoring-Pipeline entkoppeln
PollingWorkersoll nicht bei jedem 60-Sekunden-Zyklus alle Trader neu bewerten- Nur Trader neu bewerten, die seit letzter Berechnung neue Trades bekommen haben (Dirty-Flag oder Vergleich
LastTradesUpdatedAtvs.TraderScore.CalculatedAt) - N+1-Datenbankzugriffe in
ScoringService.RecalculateAllScoresAsyncdurch Batch-Queries ersetzen - Eigenes Intervall für volle Neuberechnung/Ranking (z.B. alle 15 Min) getrennt vom reinen Trade-Polling (60s)
B6. Weitere gefundene Bugs/Performance-Probleme (Review-Pass 2026-07-01)
MarketSyncWorkerre-synct alle 30 Minuten ALLE Märkte, inkl.includeClosed=true, von Offset 0 (MarketSyncWorker.cs) — holt damit bei jedem Zyklus jeden jemals geschlossenen Polymarket-Markt erneut komplett durch. Wächst unbegrenzt mit der Zeit, echtes Risiko für Rate-Limiting/Sperrung. Sollte auf: aktive Märkte häufig, geschlossene Märkte selten/inkrementell (z.B. nur kürzlich geschlossene, nicht der komplette Bestand) umgestellt werden- Watchlisted Trader nicht von Auto-Löschung ausgeschlossen (
TraderRepository.GetTradersForCleanupAsync/TraderCleanupWorker) — daTrades/TraderScore/WatchlistEntriesper Cascade am Trader hängen, könnte ein manuell beobachteter Trader nach 1 Jahr Inaktivität (oder bei kurzzeitigem API-Fehler) unbemerkt komplett gelöscht werden. Watchlist-Einträge sollten von der Cleanup-Query ausgenommen werden TradeRepository.GetKnownPlatformTradeIdsAsynclädt die komplette Trade-ID-Historie eines Traders ins RAM, nur um eine kleine neu geholte Charge (~100-1000 Trades) zu deduplizieren — aufgerufen alle 60s (PollingWorker) bzw. alle 12h (TradeHistoryWorker) pro Trader. Wird mit wachsender Trade-Zahl immer teurer. Fix: nurWHERE PlatformTradeId IN (<geholte Batch-IDs>)abfragen statt der gesamten Historie- Race Condition in
MarketRepository.AddOrUpdateAsync(im Gegensatz zuAddOrUpdateRangeAsyncohne Locking) —TradeHistoryWorkerverarbeitet bis zu 5 Trader parallel (Parallel.ForEachAsync); referenzieren zwei gleichzeitig denselben noch unbekannten Markt, prüfen beide unabhängig "existiert nicht" und einer crasht beimAddmit Unique-Constraint-Verletzung (wird geloggt, Trader-Sync für den Zyklus bricht ab, nächster Zyklus heilt es meist). Fix: gleiches Locking-Muster wieAddOrUpdateRangeAsyncverwenden, oder Insert-Konflikt sauber abfangen/retry TradeHistoryWorkerbricht die Trade-Verarbeitung beim ersten bekannten Trade ab (if (!isInitial) break;), verlässt sich also darauf, dass die API immer streng neueste-zuerst liefert.PollingWorkers äquivalente Schleife macht das NICHT. Sollte angeglichen werden — der Performance-Gewinn ist gering gegenüber dem Risiko einer stillen Datenlücke, falls die Annahme mal nicht stimmt
B4. Testabdeckung für die kritische Logik
- Neues Testprojekt (z.B.
Predictalytics.Application.Tests) anlegen — aktuell existiert kein einziges Testprojekt - Unit-Tests für die neue PnL-Engine (A1) — insbesondere Grenzfälle: nur offene Position, nur geschlossene Position, Split/Merge, Redeem-Verlust vs. -Gewinn
- Unit-Tests für Win-Rate (A2)
- Unit-Tests für Deep-Dive-Kennzahlen (A3) und Copytrading-Score (A5)
- Diese Tests idealerweise parallel zu A1–A5 schreiben, nicht erst am Ende nachziehen
B5. Kleine verwandte Aufräumarbeit
- Log-Rotation/Retention der Serilog-Datei-Sinks (
WinFormsHost/logs) prüfen — wächst potenziell unbegrenzt, ähnliches Prinzip wie die DB-Speicherplatzfrage unten
Datenbank-Speicherplatz-Optimierung
C0. Kritische Bewertung deiner beiden Ideen (überarbeitet nach Diskussion 2026-07-01)
Neue Rahmenbedingungen, die die Bewertung ändern:
- Alle Rohdaten sind jederzeit erneut abrufbar — über Polymarkets
/activity-Endpoint (Doku, keine sichtbare Limitierung), im Zweifel über die Blockchain selbst. Wir müssen also nichts "für immer" sichern — Löschen ist kein unwiderruflicher Datenverlust. - Analyseziel ist laut Auftrag explizit die aktuelle Strategie und aktueller Erfolg/Misserfolg, nicht die Historie von vor Jahren. Wir brauchen also gar keine unbegrenzte Detailtiefe — nur genug, um "aktuelles Verhalten" zu charakterisieren.
- Kern-Einsicht aus A1: Sobald ein Trade in
TraderPosition(SharesHeld/AvgCost/RealizedPnl) eingerechnet ist, wird die Rohzeile für die PnL-Fortführung nie wieder gebraucht — die Position ist bereits die komprimierte Zusammenfassung. Rohdaten braucht es nur noch für die Strategie-/Deep-Dive-Analyse (Haltedauer, Timing, Hedging-Muster), und die soll ohnehin nur das aktuelle Fenster betrachten.
→ Das ersetzt die alte Idee 1 (Archivierung nur inaktiver Trader + Reaktivierungs-Baseline) durch ein einfacheres, einheitliches Prinzip: siehe C1 – Rollierendes Zeitfenster.
Idee 2 (Hochfrequenz-Trader alle 10 Min. aggregieren) bleibt weiterhin sinnvoll — allerdings in überarbeiteter Form, da die ursprüngliche Beschreibung zu grob war:
- "Min/Max/Ø Buy-In" ohne Trennung nach Buy/Sell und nach Markt/Outcome zerstört genau die Information, die die PnL-Engine (A1) braucht.
- Eine feste 10-Minuten-Uhrzeit-Bucket-Grenze für alle Trades eines als "Bot" eingestuften Traders würde auch die wenigen möglicherweise bedeutsamen Trades eines Mischtyps mit-aggregieren.
- Relevant bleibt sie, weil auch innerhalb des neuen rollierenden Zeitfensters (siehe C1) ein aktiver Bot enorme Mengen an Trades erzeugen kann — das ist jetzt eine Optimierung fürs "heiße" Fenster, nicht mehr fürs Langzeitarchiv.
→ Vorschlag: Burst-Erkennung statt starrer Zeit-Buckets (nur tatsächlich dichte Trade-Sequenzen kompaktieren) und Aggregation getrennt nach Trader+Markt/Outcome+Seite mit VWAP (mengengewichteter Durchschnittspreis) statt einfachem Durchschnitt — bleibt unter der Average-Cost-Methode aus A1 nahezu verlustfrei für die PnL-Berechnung.
C1. Rollierendes Zeitfenster statt Archivierung (ersetzt die alte "Idee 1")
- Konfigurierbares Retention-Fenster einführen (Default-Vorschlag: 3–6 Monate) — gilt für alle Trader gleichermaßen, nicht nur für inaktive. Länge sollte sich daran orientieren, wie weit die Deep-Dive-/Strategie-Analyse (A3/A4) tatsächlich zurückschaut, um "aktuelle Strategie" zu charakterisieren
- Reihenfolge pro Trade zwingend einhalten: erst in
TraderPosition/Monats-Aggregat (s.u.) einrechnen und das sicher persistieren, dann erst die Rohzeile löschen — rein zeitbasiert, unabhängig davon ob die betroffene Position noch offen oder schon geschlossen ist - Kein Export/Cold-Storage nötig, da jederzeit über die Polymarket-API bzw. im Zweifel über die Blockchain nachladbar — vereinfacht C1 gegenüber der ursprünglichen Idee erheblich (keine Baseline-Felder, keine Reaktivierungs-Sonderfälle)
- Optionales, leichtgewichtiges Langzeit-Signal (nice-to-have, niedrige Priorität): ein grobes Monats-Aggregat pro Trader (Monat, realisierter PnL, Trade-Anzahl, Volumen) für einen "war er über Monate hinweg konsistent profitabel"-Trend im Copytrading-Score (A5) — ohne Trade-Detailtiefe, nur wenige Kennzahlen pro Monat
- Neuer periodischer Cleanup-Job (
TradeRetentionWorker), der Trades außerhalb des Fensters findet und löscht, nachdem die Voraussetzung (Position/Aggregat aktuell) erfüllt ist - Kurzer Stichprobentest, wie weit
/activitypro Wallet tatsächlich zurückreicht (bestätigt/verifiziert nur die schon vorliegende Doku-Aussage, geringe Priorität da schon durch Nutzer-Recherche plausibilisiert)
C2. Kompaktierung von Hochfrequenz-Tradern innerhalb des Zeitfensters (überarbeitete "Idee 2")
- Burst-Erkennung statt globalem Zeitraster: Sequenz von Trades mit Abstand kleiner als Schwellwert (z.B. 60s, konfigurierbar) zwischen aufeinanderfolgenden Trades desselben Traders, Outcomes und derselben Seite (Buy/Sell) gilt als "Burst"
- Mindestlänge für Kompaktierung festlegen (z.B. erst ab 20+ Trades im Burst lohnt sich das)
- Bestehende Bot-Heuristik (
intervals.Average() < 10inAnalyticsService) als Ausgangspunkt wiederverwenden/verallgemeinern statt eine zweite, unabhängige Definition einzuführen - Aggregat-Datensatz pro Burst: Anzahl Trades, Summe Size, Summe Amount, Min-Preis, Max-Preis, VWAP (nicht einfacher Durchschnitt)
- Design-Entscheidung: Aggregat als zusätzliche nullable Spalten auf der bestehenden
Trade-Tabelle (AggregateCount,AggregateMinPrice,AggregateMaxPrice) statt separater Tabelle — bestehender Code (PnL, Deep-Dive) muss dadurch kaum angepasst werden, ein Aggregat-Datensatz ist einfach ein "Trade" mitSize = Summe,Price = VWAP - Reihenfolge beachten: Diese Kompaktierung erst implementieren, nachdem A1 (neue PnL-Engine) steht und validiert ist — sonst kompaktieren wir Daten weg, bevor wir wissen, was die neue Engine wirklich braucht
C3. Weitere eigene Vorschläge
- Spaltentypen verkleinern:
TransactionHash,MarketId,AssetIdsind Hex-/Dezimal-Strings fester Länge (z.B.0x+ 64 Hex-Zeichen) — alsBINARY(32)stattVARCHAR(66/80)speichern spart ca. 30–50% Platz auf diesen stark indizierten Spalten und ist schneller - Tabellen-Partitionierung von
Tradesnach Monat (ExecutedAt) prüfen — erlaubt später das Archivieren/Droppen ganzer Partitionen statt teurer zeilenweiserDELETEs - Materialitätsschwelle: Mikro-Trades unterhalb eines Betrags (z.B. < $0.50) unabhängig von Bot-Klassifizierung direkt aggregiert erfassen, da sie für Copytrading/Strategieanalyse ohnehin kaum Aussagekraft haben
Kaltarchiv außerhalb der DB— nicht mehr nötig: da Rohdaten jederzeit über die API/Blockchain nachladbar sind (siehe C1), erübrigt sich ein separates Cold-Storage-Export. Nur falls sich die API-Nachladbarkeit später als doch eingeschränkt herausstellt, hier nochmal aufgreifen- InnoDB-Kompression (
ROW_FORMAT=COMPRESSED) für dieTrades-Tabelle als schneller Zwischenschritt prüfen — kein Datenverlust, kombinierbar mit allem anderen Split/Merge/AddLiquidity/RemoveLiquidity-Ereignisse (siehe A1) ggf. separat und kompakter ablegen, da sie für die Trader-Bewertung meist weniger relevant sind alsBuy/Sell
C4. Abhängigkeit zu Phase 1
- Merksatz: Erst A1 (neue PnL-Engine) fertigstellen, dann C1/C2 umsetzen. Sonst laufen wir Gefahr, Rohdaten wegzuoptimieren, die die neue Engine noch gebraucht hätte.
Entscheidung: Frischer Datenbank-Neustart nach Abschluss?
Neu bewertet (2026-07-01): Da wir laut C0/C1 ohnehin nichts an Alt-Historie "für immer" brauchen und alles bei Bedarf über die API/Blockchain nachladbar ist, ist ein sauberer Reset am Ende von Phase 1+2 risikoarm und klar empfehlenswert — nicht mehr nur eine Option mit Vorbehalt.
D1. Kurzer Bestätigungs-Check (geringe Priorität, kein Blocker mehr)
- Stichprobenartig verifizieren, dass
/activityfür ein bekanntes, lange aktives Wallet tatsächlich vollständig zurückreicht — bestätigt nur die bereits über die Doku plausibilisierte Annahme, ist kein Show-Stopper mehr für die Entscheidung
D2. Ablauf des Neustarts
- Vollständiges Backup/Dump der aktuellen Datenbank sichern (reine Vorsichtsmaßnahme, wird voraussichtlich nicht gebraucht) und einige Wochen aufbewahren
- EF-Migrationen-Baseline + alle Phase-1/2-Schemaänderungen fertigstellen (B1)
- Neue leere Datenbank anlegen, Migrationen anwenden
- Liste bereits bekannter Trader-Wallets aus dem alten Bestand als Startpunkt für die Re-Discovery übernehmen
- Re-Import über die Worker-Pipeline (mit korrigierter PnL-Logik, direkt im Rahmen des neuen Retention-Fensters aus C1) laufen lassen
- Wichtig: Dieser Schritt kommt ganz am Ende von Phase 1 + 2 — nicht vorher, damit wir nicht zweimal migrieren/importieren müssen
Empfohlene Reihenfolge (Kurzfassung, Stand 2026-07-01)
- B1 – EF-Migrationen-Baseline einführen (Fundament für alle weiteren Schemaänderungen)
- A1 + A6 – Positionsbasierte PnL-Engine inkl. TradeSide-Bugfix
- A2 – Win-Rate
- A3 – Deep-Dive-Kennzahlen (inkl. Preis-Historie-Voraussetzung klären)
- A4 – Strategie-Klassifikation verbessern
- A5 – Copytrading-Eignungs-Score
- B4 – Tests (idealerweise begleitend zu 2.–6., hier als Nachhol-Punkt falls übersprungen)
- B3 – Scoring-Pipeline entkoppeln/optimieren
- C1 + C2 + C3 – Speicherplatz-Optimierung: rollierendes Zeitfenster + Burst-Kompaktierung (bewusst erst jetzt, siehe C4)
- D – Datenbank-Neustart durchführen (ganz am Ende, jetzt als klar empfohlener Schritt statt offener Entscheidung)
(B2 – Secrets-Vorbereitung und B5 – Log-Rotation sind risikoarme Nebenpunkte ohne akute Dringlichkeit, da rein lokale Nutzung; können jederzeit zwischendurch erledigt werden, wenn Zeit ist.)