- D1/D2/D2c: Added TraderTraits entity, TraderTraitCalculator, Market Return Metrics (MedianWin, AvgWin, etc.), and trait filters
- D3: Implemented HF-Trader Tiering via IngestMode (Full, Aggregated, SnapshotOnly) and updated TradeHistoryWorker to respect tiers
- E1-E5: Added MasterStatus to Trader, TraderWindowMetrics for rolling analytics, Fingerprint metrics (PriceBandProfile, P50/P90), Copyability aggregates (Volume, Drift, Edge)
- E6: Implemented GET /api/traders/{id}/profile and GET /api/traders/correlation
- Replaced FIXPLAN-2026-07-09.md with FIXPLAN-TODO.md and FIXPLAN-DONE.md
- Cleaned up API docs and plan to use generic terms (removed hardcoded PolyTrader references)
- Added respective EF Core Migrations
158 lines
7.7 KiB
Markdown
158 lines
7.7 KiB
Markdown
# Predictalytics REST API — Referenz
|
||
|
||
> Stand: 2026-07-11 · Interne API ohne Authentifizierung (nur lokal betreiben!).
|
||
> Interaktive Doku: **`/swagger`** auf dem laufenden Server (Standalone-API und
|
||
> WinForms-Embedded-Server registrieren identische Endpoints über
|
||
> `ApiConfiguration.MapPredictalyticsEndpoints()` — dort ist die einzige Stelle,
|
||
> an der neue Endpoints registriert werden dürfen).
|
||
|
||
Konventionen: JSON mit camelCase-Feldnamen · Zeiten in UTC (ISO 8601) ·
|
||
Prozente auf 0–100-Skala · Beträge in USD · `WinRate` ist marktbasiert
|
||
(gewonnene abgeschlossene Märkte / abgeschlossene Märkte, nicht pro Trade).
|
||
|
||
---
|
||
|
||
## Traders
|
||
|
||
### `GET /api/traders`
|
||
Trader-Liste, sortiert nach CombinedScore, dann TotalPnl.
|
||
|
||
| Parameter | Typ | Default | Beschreibung |
|
||
|---|---|---|---|
|
||
| `skip` / `take` | int | 0 / 50 | Paging |
|
||
| `platform` | string | All | `Polymarket`, `Limitless`, … |
|
||
| `highlyCopyable` | bool | false | nur `CopytradingScore ≥ 60` |
|
||
|
||
Antwort: Array von **TraderDto** — `id`, `platform`, `platformUserId` (Wallet),
|
||
`displayName`, `tier`, `strategy`, `combinedScore`, `copytradingScore` (kombinierter
|
||
Estimator-Score), `copytradingQualityScore` (LCB-Edge), `copytradingCopyabilityScore`
|
||
(Alpha-Decay/Sizing), `winRate`, `totalPnl`, `totalTrades`, `trades30d`, `pnL30d`,
|
||
`winRate30d`, `estimatedBankroll`, `isOnWatchlist`, `isSuspectedBot`, `lastPolledAt`.
|
||
|
||
*Geplant (FIXPLAN D2):* `trait`-Parameter (mehrfach = UND) und `traits`-Feld im DTO.
|
||
|
||
### `GET /api/traders/{id}`
|
||
**TraderDetailDto** — alles aus TraderDto plus: `notes`, `manualPriorityOverride`,
|
||
Zeitfenster `pnL7d`/`winRate7d`/`pnL24h`/`winRate24h`, `currentBalance`
|
||
(kumulierter Cashflow seit Tracking-Beginn), Teil-Scores `activityScore`/
|
||
`qualityScore`/`volumeScore`/`timingScore`, `rank`, `createdAt`,
|
||
`aiStrategySummary`, `recentTrades` (letzte 50, **TradeDto**),
|
||
`categoryPerformances` (je Kategorie: `category`, `totalVolume`, `totalPnL`,
|
||
`totalTrades` = abgeschlossene Märkte, `winningTrades`, `winRate` 0–1).
|
||
|
||
**TradeDto:** `id`, `traderId`, `traderName`, `platform`, `dbMarketId`, `marketId`
|
||
(ConditionId), `marketQuestion`, `outcome`, `side` (`Buy`/`Sell`/`Redeem`/`Split`/
|
||
`Merge`/…), `price`, `size`, `amount`, `executedAt`.
|
||
|
||
### `GET /api/traders/{id}/deep-dive`
|
||
On-the-fly-Analyse über die letzten 500 Trades (lädt bei Bedarf Preis-Historie nach —
|
||
langsamster Endpoint). Felder: `classifiedStrategy`, `isSuspectedBot`,
|
||
`avgHoldDurationHours`, `avgPositionSizeUsd`, `marketsTraded`, `hedgingFrequency`,
|
||
`timingAccuracy`, `entryQuality`, `exitQuality` (je 0–100, 50 = neutral),
|
||
`botIndicators` (string[]), `summary`, `recentTrades` (100).
|
||
|
||
### `GET /api/traders/{id}/positions`
|
||
Offene und realisierte Positionen. Je **TraderPositionDto**: `marketId`,
|
||
`marketName`, `category`, `outcomeToken`, `sharesHeld`, `avgCost`, `realizedPnl`,
|
||
`unrealizedPnl`, `currentPrice`, `lastTradeExecutedAt`.
|
||
|
||
### `GET /api/traders/{id}/profile`
|
||
**TraderProfileDto**: Erweitertes Profil für die Master-Trader-Analyse. Enthält:
|
||
`masterStatus` (`None`, `Candidate`, `Master`), `medianHoldDurationHours`, `p50PositionSize`,
|
||
`p90PositionSize`, `tradesPerWeek`, `medianMarketVolumeUsd`, `medianPostFillDriftPct`,
|
||
`netEdgeAfterFeesPct`, `priceBandProfileJson`, `windowMetrics` (Array von 60-/120-Tage Metriken).
|
||
|
||
### `GET /api/traders/correlation?traderIdA=…&traderIdB=…`
|
||
Vergleicht zwei Trader. **TraderCorrelationDto**: `commonMarketsCount`,
|
||
`sameDirectionMarketsCount`, `intersectionRatioA`, `intersectionRatioB`,
|
||
`agreementRatio` (wie oft in gemeinsamen Märkten die gleiche Richtung gehandelt wurde).
|
||
|
||
### `POST /api/traders?platform=Polymarket&wallet=0x…`
|
||
Trader manuell anlegen (Import + Discovery-Flag). Antwort: Trader-Id.
|
||
|
||
### `POST /api/traders/{id}/priority?score=…`
|
||
Manuellen Prioritäts-Override setzen (ohne `score`: löschen).
|
||
|
||
### `POST /api/traders/{id}/watchlist` · `DELETE /api/traders/{id}/watchlist`
|
||
Watchlist-Zugehörigkeit setzen/entfernen. Watchlist-Trader sind von Retention/
|
||
Cleanup ausgenommen und werden bevorzugt synchronisiert/enriched.
|
||
|
||
### `POST /api/traders/{id}/ai-analysis?manual=true|false`
|
||
LLM-Strategie-Analyse anstoßen (synchron; `manual=true` nutzt das teurere Modell).
|
||
Antwort: `{ summary }`. Persistiert `aiStrategySummary`, `strategy`, `isSuspectedBot`.
|
||
|
||
---
|
||
|
||
## Markets
|
||
|
||
### `GET /api/markets`
|
||
Aktive Märkte. Parameter: `skip`/`take`, `platform`, `category`
|
||
(z. B. `Sports`, `Politics`, `Crypto`), `query` (Textsuche in Frage/ConditionId).
|
||
Je **MarketDto**: `id`, `platform`, `question`, `volume`, `liquidity`, `endDate`,
|
||
`isResolved`.
|
||
|
||
### `GET /api/markets/{id}`
|
||
**MarketDetailDto**: zusätzlich `platformMarketId` (ConditionId), `description`,
|
||
`category`, `subcategory`, `resolutionOutcome`, `imageUrl`, `botActivityScore`/
|
||
`uniqueTradersCount`/`averageTradeSize` (⚠ derzeit immer 0 — MarketAnalytics wird
|
||
noch nicht berechnet), `outcomes` (`name`, `price`), `recentTrades` (50).
|
||
|
||
---
|
||
|
||
## Watchlist
|
||
|
||
### `GET /api/watchlist`
|
||
Alle Einträge: `traderId`, `displayName`, `platformUserId`, `platform`, `totalPnl`,
|
||
`winRate`, `copytradingScore`, `label`, `notes`, `createdAt`.
|
||
|
||
---
|
||
|
||
## Jobs (asynchrone Hintergrund-Aufträge)
|
||
|
||
Jobs werden von den Workern abgearbeitet (Worker müssen laufen!). Status:
|
||
`Pending` → `InProgress` → `Completed`/`Failed`.
|
||
|
||
| Endpoint | Wirkung |
|
||
|---|---|
|
||
| `GET /api/jobs?skip&take` | Liste, neueste zuerst: `id`, `jobType`, `status`, `traderId`, `traderName`, `createdAt`, `startedAt`, `completedAt`, `errorMessage` |
|
||
| `POST /api/jobs/sync/{traderId}` | Trade-Historie synchronisieren (HistorySync) |
|
||
| `POST /api/jobs/analyze/{traderId}` | PnL-Engine + Copytrading-Estimator (TraderAnalysis) |
|
||
| `POST /api/jobs/deep-resync/{traderId}` | Komplette Historie paginiert neu importieren; löscht vorher COMPACT-Aggregate und alle Positionen des Traders |
|
||
| `POST /api/jobs/deep-resync-pruned` | DeepResync-Jobs für alle Trader mit gepruneten Positionen/COMPACT-Trades enqueuen |
|
||
| `POST /api/jobs/analyze-backlog?take=50` | TraderAnalysis-Jobs für unanalysierte Trader enqueuen (nie analysiert zuerst, dann nach TotalTrades) |
|
||
|
||
---
|
||
|
||
## Dashboard, Suche, Alerts, Sonstiges
|
||
|
||
| Endpoint | Beschreibung |
|
||
|---|---|
|
||
| `GET /api/dashboard` | Kennzahlen-Übersicht: `totalTraders`, `activeTraders24h`, `totalTrades`, `volume24h`, `unreadAlerts`, `watchlistCount`, `topTraders` (Top 5 nach PnL7d), `largestTrades` (24h), `recentAlerts`, `platformBreakdown` |
|
||
| `GET /api/search?q=…` | Sucht Trader (DisplayName **und** Wallet-Adresse) und Märkte; Antwort `{ traders, markets }` |
|
||
| `GET /api/alerts?count&unreadOnly` | Alert-Liste |
|
||
| `PUT /api/alerts/{id}/read` | Alert als gelesen markieren |
|
||
| `GET /api/health` | `{ status, timestamp }` |
|
||
|
||
## Dev (Diagnose)
|
||
|
||
| Endpoint | Beschreibung |
|
||
|---|---|
|
||
| `GET /api/dev/verify-positions/{traderId}` | Vergleicht unsere `TraderPositions` mit Polymarkets `/positions`-API; Antwort: `mismatches[]`, `match`, `dbPositionsCount`, `apiPositionsCount` |
|
||
|
||
> Ein früherer `POST /api/dev/repair-db` wurde entfernt (fehlerhaftes SQL,
|
||
> destruktiv). Reparatur läuft über den WinForms-Menüpunkt **Development →
|
||
> Recalculate All Traders**.
|
||
|
||
---
|
||
|
||
## Geplante Erweiterungen (FIXPLAN Teil D/E — für API-Konsumenten relevant)
|
||
|
||
- `GET /api/traits` + `trait`-Filter auf `/api/traders`; `traits`-Liste in den Trader-DTOs (D2).
|
||
- Markt-Rendite-Metriken im Detail-DTO: `medianWinReturnPct`, `avgWinReturnPct`,
|
||
`medianLossReturnPct`, `avgLossReturnPct`, `profitFactor` (D2c).
|
||
- `GET /api/traders/{id}/profile` — vollständiges Analyse-Profil eines Traders in
|
||
einem Aufruf (Kennzahlen + Zeitfenster + Traits + Fingerprint-Verteilungen +
|
||
Kopierbarkeits-Aggregate), gedacht für externe Konsumenten (Teil E).
|
||
- Out-of-Sample-Fenster (A/B), Preisband-Profil, Stop-Loss-Klassifikation,
|
||
Portfolio-/Korrelations-Sicht (Teil E).
|