# Umsetzungsplan: Modul „ResolutionFarming" (Favoriten nahe Auflösung)

> Stand: 2026-07-06
> Ziel: Neues Strategiemodul, das systematisch unterbewertete Favoriten
> (~90–98 ¢) in bald auflösenden Märkten kauft, bis zur Resolution hält und
> automatisch redeemt.
> Reihenfolge: **Erstes neues Strategiemodul** (geringster Infrastrukturbedarf,
> validiert die Modul-Architektur über Copytrading hinaus).
> Voraussetzung: Phase 0 + 0.2 (Fee-Modell) aus
> `UMSETZUNGSPLAN-CopyTrading-Verbesserungen.md`. Phase 1 (Orderbuch) ist
> hilfreich, aber nicht zwingend für den Start.

---

## 0. Strategie-Hintergrund (Warum das funktioniert)

Auswertungen der Polymarket-Handelsdaten zeigen ein **Favorite-Longshot-
Reversal**: Outcomes mit hoher Wahrscheinlichkeit sind systematisch
*unterbewertet* (Retail überschätzt Longshots und drückt damit den Favoriten-
Preis). Ein 95-¢-Favorit gewinnt im Schnitt öfter als in 95 % der Fälle.
2–5 % Marge in 24–48 h ergibt hohe annualisierte Renditen — **sofern das
Tail-Risiko diszipliniert gemanagt wird**: Ein verlorener 95-¢-Trade
vernichtet ~19 gewonnene. Das Risikomodell IST die Strategie.

Interner Kontext: Die profitabelsten kopierten Master (Typ „SwissTony"/„RN1")
machen genau das — hunderte BUYs, nie SELLs, Auflösung abwarten. Dieses Modul
internalisiert die Strategie und eliminiert die Copy-Latenz und die
Fremdbestimmung der Marktauswahl.

**Fees (seit März 2026):** Taker-Fees je Kategorie (Sports ~0,75 %, Politik
~1,0 %, Krypto ~1,8 %, Geopolitik 0 %) — bei 2–5 % Brutto-Marge ist die
Kategorie-Wahl entscheidend. Maker-Einstieg (Limit ins Buch) zahlt 0 Fees.

---

## 1. Architektur-Einbettung

Neues Projekt `src/PolyTrader.Modules.ResolutionFarming/` (Class Library,
net8.0-windows), Registrierung als `IPolyTraderModule` analog
`CopyTradingModule` (`Name = "ResolutionFarming"`, `DbPrefix = "rf_"`),
Einbindung in `Program.cs` der App.

### ⚠️ Grundsatzentscheidung: Eigener Polymarket-Account je Strategiemodul

**Dringende Empfehlung:** Das Modul handelt über einen **eigenen Account**
(Multi-Account-Support existiert im Core / `AccountState`).

Begründung: Der `TraderMonitorService` des Copytrading-Moduls synct **alle**
Wallet-Positionen eines Accounts in `account.OpenPositions`, würde
ResolutionFarming-Positionen „adoptieren" (Master-Zuordnungs-Fallbacks),
in seine Limits (PerMarket/PerMaster/Zeitfenster) einrechnen und ggf.
Auto-Redeem-/Cleanup-Logik darauf anwenden. Saubere Trennung über getrennte
Wallets vermeidet diese gesamte Konfliktklasse zur Laufzeit **und**
buchhalterisch (PnL je Strategie sauber messbar).

In der UI/Settings des Moduls: Zuordnung `AccountId ↔ Modul` mit Warnung,
wenn derselbe Account auch im Copytrading aktiv ist.

### Persistenz (EF Core / Pomelo / MySQL, eigener DbContext analog `CopyTradingDbContext`)

| Tabelle | Inhalt |
|---|---|
| `rf_settings` | Modul-Settings je Account (Preisband, Budgets, Limits) |
| `rf_candidates` | Scanner-Ergebnisse (Markt, Preis, Score, Filtergründe) — auch abgelehnte, für spätere Kalibrierung |
| `rf_positions` | Offene Farming-Positionen (TokenId, Entry, Size, EndDate, ClusterKey, Status) |
| `rf_closed_trades` | Abgeschlossene Trades inkl. Fees, Redeem-Infos |

Zusätzlich schreibt das Modul in den generischen Core-Trade-Log
(modulübergreifendes Dashboard).

---

## 2. Komponenten

### 2.1 `MarketScannerJob : BackgroundService`

Alle 10–15 Minuten (JobManager-Registrierung wie `MasterTraderAnalyticsJob`,
manuell triggerbar):

1. Gamma-API: aktive Märkte mit `endDate < now + MaxHoursToResolution`
   (Default 48 h), nicht closed. Bestehenden `PolymarketApiService` erweitern
   (Query-Parameter für endDate-Fenster; Endpoint-Details bei Umsetzung aus
   https://docs.polymarket.com verifizieren).
2. Je Markt den Favoriten bestimmen (Outcome mit höchstem Preis). Preisquelle:
   CLOB Midpoint/Book (REST `GET /book` bzw. `IOrderBookProvider`, falls
   Phase 1 des Copytrading-Plans schon umgesetzt).
3. Filterkette (jeder Reject wird mit Grund in `rf_candidates` geloggt):
   - Preisband: `MinPrice ≤ ask ≤ MaxPrice` (Default 0.90–0.98).
   - Liquidität: Ask-Tiefe am Zielpreis ≥ geplante Ordergröße × Faktor;
     zusätzlich Markt-Volumen/Liquiditätsfelder der Gamma-API als Grobfilter.
   - Kategorie-Whitelist (Default: Sports, Geopolitik, Politik; **Krypto
     ausschließen** — 1,8 % Fee frisst die Marge; keine 15-Min-/Stunden-Märkte).
   - Netto-Edge-Check: `(1 − ask) − Fee(ask, Kategorie) ≥ MinEdgePct`
     (Default z. B. 1,5 %).
   - Blacklist-Mechanismus (Slugs/Tags), z. B. für Marktarten mit
     Resolution-Streitigkeiten (UMA-Disputes).
4. Kandidaten mit Score in `rf_candidates` schreiben; Anzeige in der Modul-UI.

### 2.2 Risiko-Engine (pure, testbare Klasse `FarmingRiskEngine`)

Settings je Account (`rf_settings`):

| Setting | Default | Bedeutung |
|---|---|---|
| `MaxPerMarketUsd` | 25 | Max. Einsatz je Markt |
| `MaxPerClusterPct` | 10 % | Max. Anteil der Bankroll je **Ereignis-Cluster** |
| `MaxTotalExposurePct` | 60 % | Max. Gesamteinsatz in offenen Positionen |
| `MaxNewPositionsPerDay` | 20 | Drosselung |
| `MinEdgePct` | 1.5 % | Netto-Edge nach Fees |
| `DailyLossKillSwitchUsd` | konfig. | Tagesverlust → Modul pausiert + Threema |

**Cluster-Definition (kritisch!):** 20 Fußballspiele desselben Spieltags sind
keine 20 unabhängigen Wetten. ClusterKey ableiten aus Event-/Series-Slug der
Gamma-API (z. B. Liga+Datum, Turnier, Wahl-Event). Korrelierte Favoriten
(z. B. „Kandidat X gewinnt" + „Partei von X gewinnt") teilen einen Cluster.
Erste Version: Heuristik über Event-Slug; Verfeinerung später.

### 2.3 `FarmingExecutionService`

1. Einstieg **Maker-first**: GTC-Limit auf Best-Bid bzw. Mid − 1 Tick
   (0 Fees). Kein Fill nach T Minuten (Default 15) → Entscheidung per Setting:
   Taker-Fill (wenn Netto-Edge auch mit Fee noch ≥ MinEdge) oder verwerfen.
2. Order-Verwaltung über `PolymarketClobClient` (Core), Tracking analog
   `PendingOrderTimestamps`-Muster des Copytrading-Moduls.
3. Positionen in `rf_positions` + Core-Positions-Sync gegen die Wallet
   (Data-API `positions` — Muster aus `TraderMonitorService.PollLiveAccountsAsync`
   übernehmen, aber schlanker: kein Master-Mapping nötig).

### 2.4 `ResolutionMonitorJob` + `AutoRedeemService`

1. Monitor: prüft offene `rf_positions` gegen Resolution
   (`PolymarketApiService.CheckMarketResolutionAsync` existiert bereits).
2. **On-Chain-Auto-Redeem** (heute im gesamten Projekt nur manuell — dieser
   Baustein nützt auch dem Copytrading):
   - Gewinner-Shares einlösen via ConditionalTokens-Contract auf Polygon
     (`redeemPositions(...)`); für NegRisk-Märkte über den NegRisk-Adapter.
     **Contract-Adressen und Aufrufparameter bei Umsetzung zwingend aus der
     offiziellen Doku verifizieren** (https://docs.polymarket.com,
     Developer-Sektion CTF/NegRisk).
   - Implementierung: Nethereum-Paket ODER Raw-RPC über die vorhandene
     Alchemy-Anbindung; Signing mit dem Account-PrivateKey (liegt in
     `AccountState`).
   - Gas: Wallet braucht POL; Balance-Check + Threema-Warnung bei Unterdeckung.
   - Retry mit Backoff; Erfolg = USDC-Balance-Delta verifiziert.
   - `.agents/rules/clob.md` gilt hier besonders: On-Chain-Signing ist
     hochkritisch — zuerst mit Kleinstbetrag auf einem Testmarkt verifizieren.
3. Übergangslösung bis 2.4 fertig: PreRedeem-artiger Verkauf (GTC-Limit 0.99+)
   oder manueller Redeem — das Modul funktioniert auch ohne On-Chain-Teil,
   bindet dann nur Kapital länger.

### 2.5 UI (`RegisterUi`, ein Fenster mit Tabs analog `CopyTradingMainForm`)

- Tab „Kandidaten": aktueller Scan mit Filtergründen (auch Rejects).
- Tab „Positionen": offene Farming-Positionen, Cluster-Auslastung, Countdown.
- Tab „Historie/Statistik": Winrate je Preisband (Kalibrierung!), Netto-PnL,
  Fees, Redeem-Status.
- Tab „Settings": PropertyGrid auf `rf_settings` (Muster `AccountSettingsView`).

---

## 3. Phasen & Akzeptanzkriterien

### Phase RF-1: Modul-Skelett + Scanner (read-only)
- Projekt, Modul-Registrierung, DbContext + Migration, Scanner-Job, UI-Tab
  „Kandidaten". **Keine Order-Platzierung.**
- Akzeptanz: App baut & startet mit Modul; Scanner liefert plausible
  Kandidaten; Rejects nachvollziehbar geloggt; 1 Woche Kandidaten-Sammlung.

### Phase RF-2: Demo-Betrieb (4 Wochen)
- Execution im Demo-Modus (realistisches Fill-Modell: Ask-Preis + Fee,
  siehe Copytrading-Plan Phase 4.2). Risiko-Engine aktiv.
- Akzeptanz/Go-Kriterium für Live: Kalibrierungstabelle zeigt
  `realisierte Winrate je Preisband > Preisband-Mitte` und
  Netto-Edge nach Fees > 0 über ≥ 100 Demo-Trades.

### Phase RF-3: Live klein
- Eigener Account, kleines Budget (z. B. 200–500 USDC), `MaxPerMarketUsd` 5–10.
- Kill-Switch + Threema-Reporting (Tageszusammenfassung) aktiv.
- Akzeptanz: 2 Wochen Live ohne Ausführungsfehler; Live-Ergebnis im Rahmen
  der Demo-Erwartung.

### Phase RF-4: Auto-Redeem on-chain
- Wie 2.4; zuerst Testmarkt/Kleinstbetrag, dann aktivieren.
- Akzeptanz: Gewinner-Position wird ohne manuellen Eingriff zu USDC.

### Phase RF-5: Kalibrierung & Skalierung
- Scoring von Heuristik auf Daten umstellen: historische Winrate je
  Preisband × Kategorie aus `rf_candidates`/`rf_closed_trades` (+ optional
  öffentliche Polymarket-Historien-Datensätze) → nur Bänder/Kategorien mit
  nachgewiesenem Edge handeln. Budget stufenweise erhöhen.

---

## 4. Risiken & Gegenmaßnahmen

| Risiko | Gegenmaßnahme |
|---|---|
| Tail-Event (Favorit verliert) | Cluster-Limits, MaxPerMarket, Diversifikation über Kategorien |
| Korrelierte Cluster falsch geschnitten | Konservative Cluster-Heuristik, Review der Cluster in der UI |
| Resolution-Disputes (UMA) | Blacklist strittiger Marktarten; nur klare, objektiv auflösbare Märkte |
| Fee-Änderungen | Fee je Trade persistieren, MinEdge-Check dynamisch |
| Konflikt mit Copytrading-Sync | Eigener Account (Abschnitt 1) |
| On-Chain-Redeem-Fehler | Separate Phase, Testmarkt zuerst, Balance-Verifikation, clob.md-Regeln |

## 5. Offene Entscheidungen

1. Eigener Account: neuer Polymarket-Account nötig — wer legt ihn an, wie viel
   Startkapital?
2. Preisband-Default (0.90–0.98) und `MinEdgePct` — mit Demo-Daten validieren.
3. Nethereum vs. Raw-RPC für On-Chain-Calls (Empfehlung: Nethereum, weniger
   Fehlerfläche beim ABI-Encoding).
4. Taker-Fallback beim Einstieg erlauben oder strikt Maker-only?
