Toter Code: * ApiConfiguration.ConfigureApi (29 Z.) hatte keinen Aufrufer mehr. PredictalyticsHost baut die WebApplication seit Phase 2 selbst auf (Kestrel, CORS, Swagger, Static Files); ConfigureApi war der zurueckgebliebene Zwilling aus der Zeit davor. * IAnalyticsService.GetTraitsAsync samt Implementierung. Die Methode gab konstant eine leere Liste zurueck; ihr eigener Kommentar hielt fest, dass sie ungenutzt ist. Der Endpunkt /api/traders/traits liest direkt aus dem DbContext und bleibt unveraendert. Ungenutzte Paketreferenzen: * Swashbuckle.AspNetCore aus Predictalytics.Api - wurde nur von ConfigureApi gebraucht; Swagger baut Hosting auf, das die Referenz selbst haelt. * Microsoft.EntityFrameworkCore.Design aus Predictalytics.Worker - die Design-Time-Factory liegt in Infrastructure. * Serilog.Sinks.File/.Console und Serilog.Formatting.Compact aus Predictalytics.Infrastructure - dort wird kein Logger konfiguriert, nur Serilog.Core/Events/Context verwendet. Die Sinks haengen am Hosting. Altlast-Dateien: * Spike/ - Projektdatei ohne eine einzige Quelldatei, net8.0, nicht in der Solution. * query.csx - Ad-hoc-Abfrageskript von Juli mit fest eingetragenen DB-Zugangsdaten. * NewDesign.zip (388 KB) und temp_new_design/ - Rohmaterial des Design-Entwurfs vom 15.07. Das Ergebnis liegt fertig in wwwroot/landing.html und wwwroot/docs.html. Veraltete Verweise auf den entfernten WinForms-Host: * CLAUDE.md nannte fuer die Release-Version eine csproj, die es nicht mehr gibt - sie steht seit der Zentralisierung in Directory.Build.props. * docs/BETRIEB-Deploymentcenter.md: Anbindung und BuildInfo sitzen in Predictalytics.Hosting. * docs/API.md: Die Aussage "ohne Authentifizierung" galt vor Phase 4. Jetzt mit Header X-Predictalytics-Key und den heutigen Methodennamen. * Kommentare in Directory.Build.props, DevEndpoints.cs, PredictalyticsHost.cs. Build ohne neue Warnungen (die 8 bestehenden CS86xx sind unveraendert), 126 Tests gruen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
160 lines
7.8 KiB
Markdown
160 lines
7.8 KiB
Markdown
# Predictalytics REST API — Referenz
|
||
|
||
> Stand: 2026-08-23 · Interne API, nur lokal betreiben.
|
||
> **Lesende** Endpunkte sind ungeschützt, **steuernde** verlangen seit Phase 4 den
|
||
> Header `X-Predictalytics-Key`, sobald in den Einstellungen ein Token hinterlegt ist
|
||
> (siehe `ApiTokenFilter`; `GET /api/capabilities` meldet der WebUI den Ist-Zustand).
|
||
> Interaktive Doku: **`/swagger`** auf dem laufenden Server. Endpunkte werden
|
||
> ausschliesslich in `ApiConfiguration.MapPredictalyticsReadEndpoints()` bzw.
|
||
> `MapPredictalyticsControlEndpoints()` registriert — nur dort neue ergänzen.
|
||
|
||
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 die Schaltfläche **Recalculate All Traders**
|
||
> in der Avalonia-Shell.
|
||
|
||
---
|
||
|
||
## 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).
|