API audit: expose 7d/24h windows, remove broken repair-db, add API docs

- TraderDetailDto now exposes PnL7d/WinRate7d/PnL24h/WinRate24h and
  CurrentBalance — the engine has computed these all along but the API
  never delivered them.
- Removed POST /api/dev/repair-db: its raw SQL referenced non-existent
  columns/tables (Trades.Type/Payout, Traders.LastPositionsUpdatedAt,
  table "Jobs") and would have deleted ALL TraderPositions including
  pruned-history conserves. The supported repair path is the WinForms
  "Recalculate All Traders" action.
- Swagger tags for Jobs and Dev groups; full endpoint reference in
  docs/API.md (kept generic — external consumers like PolyTrader adapt
  to our API, not vice versa).
- FIXPLAN Teil E: master-selection gap analysis as generic extensions
  (profile endpoint, out-of-sample window metrics, price-band profile
  with per-band win rate, stop-loss ratio, copyability aggregates with
  category fees, correlation endpoint, martingale trait).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-07-12 18:34:02 +02:00
co-authored by Claude Fable 5
parent 28e112f128
commit a1fcb4ace5
6 changed files with 264 additions and 28 deletions
+102
View File
@@ -506,3 +506,105 @@ gegen 300+/min) — das Trade-Replay-PnL ist für diese Klasse bereits falsch un
4. Tägliches DB-Wachstum sichtbar reduziert (DB-Size-Anzeige im WinForms-Statusbar beobachten).
Reihenfolge: **D1 → D2/D2b/D2c → D3** (D2c ist klein und gehört in denselben Engine-Durchlauf wie die Winrate; bei D3 zuerst Tier C, dann Tier B).
---
## Teil E — Master-Auswahl-Metriken & generischer Profil-Endpoint (ergänzt 2026-07-11)
> Hintergrund: Ein externer Konsument (PolyTrader-Copytrading) braucht eine belastbare
> Master-Trader-Auswahl (Prüfplan liegt in `PREDICTALYTICS-PRUEFPLAN-Master-Auswahl.md` im
> PolyTraderSharp-Repo). **Bewusste Architektur-Entscheidung: Die API bleibt generisch.**
> Kein PolyTrader-spezifisches Format, kein „HOLDER/STOPLOSS"-Vokabular in der API —
> wir exponieren neutrale Metriken, der Konsument mappt selbst.
> Abgleich: M2/M8 existieren (D2c/CategoryPerformances), M3/M9 teilweise als Traits (D2),
> M1/M5/M6 teilweise; **komplett neu sind M4, M7, Out-of-Sample-Fenster, Kopierbarkeits-
> Aggregate und die Korrelations-Sicht** — das ist Teil E.
### E1. Generischer Profil-Endpoint `GET /api/traders/{id}/profile`
Ein Aufruf liefert das vollständige Analyse-Profil (statt 4+ Einzel-Calls):
Stammdaten + alle Analytics-Felder + Traits (D2) + Rendite-Metriken (D2c) +
Fenster-Blöcke (E2) + Fingerprint-Verteilungen (E3) + Kopierbarkeits-Aggregate (E5).
Nur persistierte Werte ausliefern (kein On-the-fly-Rechnen wie im Deep-Dive) —
der Endpoint muss schnell und pollbar sein. In `docs/API.md` dokumentieren.
### E2. Fenster-Metriken als Struktur + Out-of-Sample-Vergleich
**Problem:** Die 24h/7d/30d-Felder sind Einzelspalten; der Prüfplan braucht zwei frei
definierte Vergleichsfenster (z. B. Tag 180…−60 vs. 60…heute), um Glücks-Wallets
auszusortieren (nur wer in BEIDEN Fenstern liefert, ist ein Kandidat).
**Fix:**
- Neue Tabelle `TraderWindowMetrics`: TraderId, WindowStart, WindowEnd, ClosedMarkets,
WinRate, AvgReturnPct (M1: Ø realisierte Rendite je Markt), MedianWinReturnPct,
MedianLossReturnPct, ProfitFactor, ComputedAt. Unique (TraderId, WindowStart, WindowEnd).
- Berechnung im Analytics-Lauf für zwei konfigurierbare Fenster
(`AnalysisWindows`-Sektion in appsettings, Default: 180…−60 und 60…0 Tage).
Wiederverwendet die D2c-Logik mit Zeitfilter auf den Markt-Abschlusszeitpunkt.
- Im Profil (E1) als `windows[]`-Array. **Achtung Retention:** Fenster A reicht weiter
zurück als 90 Tage — Berechnung muss mit fehlender Historie ehrlich umgehen
(`closedMarkets` klein → Konsument sieht die dünne Stichprobe). Nach der
Retention-Verlängerung auf 180 Tage (D3) wird Fenster A tragfähig.
### E3. Fingerprint-Verteilungen (persistiert, im Profil)
Im Analytics-Lauf berechnen und als JSON-Spalte(n) auf `TraderAnalytics` oder eigene
Tabelle persistieren:
- **Preisband-Profil (M7):** Einsatz-Anteil je 10-¢-Einstiegspreisband über Buys,
**plus realisierte Winrate je Band** (macht Glück von System unterscheidbar:
„kauft 9095-¢-Shares, gewinnt 97 %" = +Edge sichtbar pro Band).
- **Haltedauer:** Median (nicht nur Ø) Stunden Kauf→Exit/Auflösung (M6).
- **Positionsgrößen:** P50/P90-Amount (M9-Basis).
- Trade-Frequenz je Woche (aus Trades30d ableitbar, im Profil ausgeben).
### E4. Exit-Verhalten klassifizieren (M4) — generisch als Trait + Kennzahl
- Kennzahl `stop_loss_ratio`: Anteil der Sells, die nach einem Preisrückgang von
≥ 10 % unter den Einstands-AvgCost erfolgen (Sell-Preis ≤ 0,9 × AvgCost),
bezogen auf alle geschlossenen Positionen. Braucht KEINE Preis-Historie —
Sell-Preis vs. AvgCost der Position reicht als v1-Näherung.
- Traits: `sells_at_loss` (Ratio > 0,15) ergänzt das vorhandene `holds_to_resolution`.
Ein Konsument bildet daraus selbst HOLDER (`holds_to_resolution` ∧ ¬`sells_at_loss`),
STOPLOSS, MIXED.
### E5. Kopierbarkeits-Aggregate (im Profil)
- `medianMarketVolumeUsd`: Median des `Market.Volume` (bzw. Volume24h) der vom Trader
gehandelten Märkte — handelt er in Kleinstmärkten, bewegt der Kopierer den Preis.
- `medianPostFillDriftPct`: Median-Preisänderung nach seinen Buys (aus vorhandenem
`TradeContext.PriceAfter1m`/`FollowerFillPrice60s`, nur enriched Trades; Anzahl
der Datenpunkte mit ausgeben).
- `netEdgeAfterFeesPct`: `AvgReturnPct` (E2, Fenster B) minus kategorie-gewichteter
Taker-Fee (aus `Market.FeeRateBps` — wird bereits erfasst!) minus konfigurierbarem
Spread-Aufschlag (`CopyCostSettings:SpreadPct`, Default 2,0). Generisch als
„Netto-Edge nach Kopierkosten" benannt.
### E6. Korrelations-/Portfolio-Sicht
- Neuer Endpoint `GET /api/traders/correlation?ids=1,2,3` (oder `?top=20`):
paarweise Jaccard-Ähnlichkeit über die gehandelten ConditionIds (Fenster B) +
Kategorie-Mix-Cosinus. Antwort: Matrix + je Paar die Overlap-Zahl.
- Kein „Portfolio-Empfehlungs"-Endpoint in v1 — die Auswahl-Logik (max. 2 je
Kategorie etc.) gehört zum Konsumenten. Wir liefern die Korrelationsdaten.
### E7. Martingale-Erkennung (M9) als Trait
`martingale_pattern`: mittleres Verhältnis Einsatz(nach verlorenem Markt) /
Einsatz(nach gewonnenem Markt) über die Sequenz der abgeschlossenen Märkte;
Trait ab Verhältnis ≥ 1,5 bei ≥ 20 Märkten. (Einsatz = investiertes Kapital je
Markt aus D2c.)
### E8. Abnahme Teil E
1. Bestehende Tests grün (Assertions unverändert) + neue Tests: Fenster-Metriken
(bekannte Markt-Menge, zwei Fenster → korrekte Werte je Fenster), Preisband-
Winrate (Band-Zuordnung + Ränder 0,895/0,90), `stop_loss_ratio`
(Positiv-/Negativfall), Jaccard-Berechnung, Martingale (steigende Einsätze nach
Losses → Trait; konstante → kein Trait).
2. `GET /api/traders/{id}/profile` liefert für einen analysierten Trader alle Blöcke
gefüllt; Antwortzeit < 200 ms (nur persistierte Daten).
3. `docs/API.md` um Profile-/Correlation-Endpoint ergänzt.
4. Kein PolyTrader-spezifisches Vokabular in API/DTOs.
Reihenfolge: E1+E3 zuerst (Profil mit vorhandenen + Fingerprint-Daten), dann E2
(Fenster), E4/E5/E7 (Kennzahlen), E6 zuletzt. Teil E setzt D1/D2/D2c voraus.