# 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).
