# Umsetzungsplan: Modul „MarketMaking" (Liquidity Rewards + Spread)

> Stand: 2026-07-06
> Ziel: Neues Strategiemodul, das beidseitige Limit-Orders in belohnungs-
> berechtigten Polymarket-Märkten stellt und drei Ertragsquellen kombiniert:
> tägliche Liquidity Rewards (USDC), Maker-Rebates und den Spread selbst.
> Reihenfolge: Nach ResolutionFarming. **Harte Voraussetzung:** Phase 1
> (Marktdaten-Fundament: `ClobMarketDataService`, `ClobUserChannelService`)
> aus `UMSETZUNGSPLAN-CopyTrading-Verbesserungen.md`.

---

## 0. Strategie-Hintergrund

Polymarket zahlt täglich (00:00 UTC) USDC-Rewards an Wallets, die kompetitive
Resting-Limit-Orders in berechtigten Märkten stellen. Der Reward-Pool liegt
2026 bei > $5 M/Monat (Sport-Peaks ~$8 M). Die Formel belohnt: Nähe zum
Midpoint (innerhalb eines markt-spezifischen Max-Spreads), Ordergröße
(Mindestgröße je Markt) und beidseitige Tiefe (einseitige Orders scoren
reduziert). Seit den Taker-Fees (März 2026) gibt es zusätzlich ein
**Maker-Rebate-Programm** (Anteil der Taker-Fees wird täglich an Maker
ausgeschüttet). Maker zahlen selbst keine Fees.

**Referenzen (bei Umsetzung Formel/Parameter aktuell verifizieren):**
- https://docs.polymarket.com/market-makers/liquidity-rewards
- https://docs.polymarket.com/trading/fees (Maker-Rebates)
- Reward-Parameter je Markt (Max-Spread, Min-Size, Tages-Pool) kommen aus der
  Gamma-/CLOB-API am Markt-Objekt.

**Warum dieses Modul strategisch wertvoll ist:** Es ist die einzige Strategie,
bei der wir nicht gegen schnellere Bots um denselben Trade konkurrieren —
Anwesenheit wird bezahlt. Ertrag ist stetig statt direktional.

**Hauptrisiko: Adverse Selection.** Unsere Quotes werden bevorzugt dann
gefüllt, wenn jemand mit besserer Information (News-Bot, Live-Sport-Feed)
gegen uns handelt. Gegenmaßnahmen: Marktauswahl (ruhige, langlaufende Märkte;
anfangs KEINE Live-Sport- und KEINE Krypto-Kurzfrist-Märkte), Inventar-Limits,
Volatilitäts-Pause.

---

## 1. Architektur-Einbettung

Neues Projekt `src/PolyTrader.Modules.MarketMaking/` als `IPolyTraderModule`
(`Name = "MarketMaking"`, `DbPrefix = "mm_"`), Registrierung in `Program.cs`.

**Eigener Polymarket-Account zwingend** (gleiche Begründung wie im
ResolutionFarming-Plan, hier noch kritischer: Der Copytrading-
`TraderMonitorService` würde MM-Inventar als Positionen adoptieren und der
Copytrading-`CancelConflictingOrdersAsync`-Mechanismus würde unsere
Resting-Quotes canceln!).

### Persistenz

| Tabelle | Inhalt |
|---|---|
| `mm_settings` | Globale + je-Markt-Settings (Size, Spread-Ziel, Limits) |
| `mm_markets` | Kuratierte/gescorte Märkte (Reward-Parameter, Status) |
| `mm_quotes_log` | Quote-Historie (Preis, Size, Dauer, Cancel-Grund) — für Reward-Optimierung |
| `mm_fills` | Fills mit Seite, Preis, Inventar danach |
| `mm_daily_pnl` | Tagesabrechnung: Rewards, Rebates, Spread-PnL, Inventar-PnL |

---

## 2. Komponenten

### 2.1 `MarketSelectorJob` — Marktauswahl & Scoring

Täglich + manuell triggerbar:
1. Reward-berechtigte Märkte über Gamma-/CLOB-API listen (Felder: Reward-Pool/
   Rate, `rewardsMaxSpread`, `rewardsMinSize` — Feldnamen verifizieren).
2. Score je Markt: `erwarteter Reward pro gequoteter $ ÷ Risiko-Proxy`.
   - Reward-Schätzung: Tages-Pool des Markts ÷ beobachtete konkurrierende
     Maker-Liquidität innerhalb des Max-Spreads (aus Orderbuch-Snapshots).
   - Risiko-Proxy: realisierte Midpoint-Volatilität (Stddev der Mid-Bewegungen
     über 24 h aus `ClobMarketDataService`-Daten), Zeit bis Resolution
     (je näher, desto gefährlicher), Kategorie.
3. Harte Ausschlüsse (erste Ausbaustufe): Live-Sport (in-play), Krypto-
   Kurzfrist-Märkte (15 min/1 h), Märkte < 7 Tage vor EndDate, Midpoint
   außerhalb 0.10–0.90 (Extrempreise = asymmetrisches Inventarrisiko).
4. Output: Ranking in `mm_markets` + UI; Betreiber aktiviert Märkte manuell
   (Whitelist-Prinzip — der Bot wählt in v1 nicht selbst).

### 2.2 `QuotingEngine : BackgroundService` — Kern des Moduls

Je aktivem Markt eine Quote-State-Machine:

1. **Zielquote:** Bid und Ask symmetrisch um den Midpoint, Abstand
   `QuoteSpreadTicks` (Setting), immer **innerhalb** des Reward-Max-Spreads;
   Size ≥ Reward-Min-Size (Setting `QuoteSizeUsd`, initial klein).
2. **Requote-Trigger:** Midpoint-Bewegung > Schwelle (z. B. 1 Tick), eigene
   Order gefüllt, Reward-Fenster verletzt. Requote = Cancel + neue Order über
   `PolymarketClobClient`.
3. **Churn-Begrenzung:** Mindest-Ruhezeit zwischen Requotes (z. B. 3–5 s),
   Hysterese (nicht bei jedem Tick nachziehen) — API-Rate-Limits und
   Order-Spam vermeiden.
4. **Fill-Verarbeitung:** über `ClobUserChannelService` (Echtzeit). Nach Fill:
   Inventar aktualisieren, Gegenquote anpassen (siehe 2.3).
5. Alle Quotes/Cancels in `mm_quotes_log` (Grundlage für Optimierung).

Die Preis-/Requote-Logik als **pure, getestete Klasse** (`QuoteCalculator`)
implementieren — Input: Book-Snapshot, Inventar, Settings; Output: Ziel-Quotes.
Unit-Tests in `PolyTrader.Tests` (das ist die kritischste Logik des Moduls).

### 2.3 `InventoryManager` — Risikosteuerung

1. Inventar je Markt = Netto-Shares (YES-äquivalent) × Preis.
2. **Skew:** Bei wachsendem Inventar Quotes asymmetrisch verschieben
   (Kaufseite weiter weg, Verkaufsseite näher/attraktiver), Faktor
   proportional zu `Inventar / MaxInventoryUsd`.
3. **Limits (Settings je Markt + global):**
   - `MaxInventoryUsd` je Markt (Default klein, z. B. 50).
   - `MaxTotalInventoryUsd` über alle Märkte.
   - Bei Limit-Bruch: Quoting nur noch auf der abbauenden Seite
     („Reduce-Only-Modus") bis Inventar < 50 % des Limits.
4. **Exit vor Resolution:** Ab `ExitHoursBeforeEnd` (Default 48 h) Reduce-Only,
   ab 24 h aktiver Abbau (Maker-seitig, notfalls Taker mit Verlust-Deckel).
5. **Volatilitäts-Pause:** Midpoint-Sprung > X % in Y Sekunden → alle Quotes
   des Markts canceln, Cooldown Z Minuten (News-Schutz). Global-Kill-Switch
   analog `GlobalTradingPaused`.

### 2.4 `RewardTracker`

1. Tägliche Reward-/Rebate-Eingänge erkennen (USDC-Transfers auf die Wallet
   via Data-API/Alchemy) und `mm_daily_pnl` zuordnen.
2. Tagesabrechnung: `Rewards + Rebates + SpreadPnL + InventarPnL(mark-to-mid)
   − Verluste = Netto`. Threema-Tagesreport.
3. Kennzahl je Markt: **Reward-ROI pro gequoteter $** → Feedback in den
   `MarketSelectorJob` (schlechte Märkte deaktivieren).

### 2.5 UI

- Tab „Märkte": Kandidaten-Ranking, aktiv/inaktiv-Toggle, Reward-Parameter.
- Tab „Live": aktuelle Quotes, Inventar je Markt (Ampel), letzte Fills.
- Tab „Abrechnung": `mm_daily_pnl`-Historie, Reward-ROI je Markt.
- Tab „Settings": PropertyGrid.

---

## 3. Phasen & Akzeptanzkriterien

### Phase MM-1: Fundament-Verifikation + Selector (read-only)
- Voraussetzung prüfen: `ClobMarketDataService`/`ClobUserChannelService`
  laufen stabil (mehrtägiger Soak-Test, Reconnect-Verhalten).
- `MarketSelectorJob` + UI-Ranking, keine Orders.
- Akzeptanz: Ranking plausibel; Orderbuch-Daten für Top-Märkte lückenlos
  über 72 h (Basis für Volatilitäts-Proxy).

### Phase MM-2: Paper-Quoting (Messung Adverse Selection)
- QuotingEngine läuft vollständig, sendet aber **keine** Orders; simulierte
  Fills: Quote gilt als gefüllt, wenn der Marktpreis durch unser Quote-Level
  handelt (aus Market-Channel-Trades ableitbar).
- 2 Wochen laufen lassen. Messen: simulierter Spread-PnL, Inventarverläufe,
  Wie oft wären wir „überfahren" worden (Fill unmittelbar vor großer
  Gegenbewegung)?
- Akzeptanz/Go-Kriterium: simuliertes Inventar bleibt innerhalb der Limits;
  Spread-PnL ≥ 0 (Rewards kommen on top und sind der eigentliche Ertrag).
- **Hinweis:** Rewards selbst lassen sich nicht simulieren — sie erfordern
  echte Resting-Orders. Paper-Phase misst nur die Risikoseite.

### Phase MM-3: Live auf 1–2 ruhigen Märkten
- Eigener Account, kleines Kapital (z. B. 300–500 USDC), `QuoteSizeUsd`
  knapp über Reward-Min-Size, 1–2 langlaufende Politik-/Geopolitik-Märkte.
- Akzeptanz nach 2–4 Wochen: tägliche Rewards fließen nachweislich
  (`mm_daily_pnl`); Netto (Rewards + Spread − Inventarverluste) > 0;
  keine Order-Leichen (Cancel-Fehler) im CLOB.

### Phase MM-4: Skalierung + Skew-Feintuning
- Mehr Märkte (Selector-getrieben), Inventar-Skew-Parameter aus Fill-Daten
  optimieren, Size je Markt anhand Reward-ROI erhöhen.

### Phase MM-5 (optional): Reward-Optimierung
- Order-Laddering (mehrere Level innerhalb des Max-Spreads), dynamische
  Spread-Wahl abhängig von Konkurrenz-Liquidität, Teilnahme an
  Sponsor-/Sonder-Reward-Programmen (z. B. Sport-Events pre-game).

---

## 4. Risiken & Gegenmaßnahmen

| Risiko | Gegenmaßnahme |
|---|---|
| Adverse Selection durch News-/Latenz-Bots | Marktauswahl (keine Live-Events), Volatilitäts-Pause, kleine Size |
| Inventar läuft in Resolution | Exit-Regeln ab 48 h/24 h vor EndDate (2.3) |
| Order-Churn → Rate-Limits/Sperren | Requote-Hysterese, Mindest-Ruhezeit, Monitoring der API-Fehlerquote |
| Reward-Regeländerungen | Parameter täglich aus API lesen, nichts hartkodieren |
| WSS-Ausfall → blinde Quotes | Watchdog: keine Book-Updates > N s → alle Quotes canceln (Fail-Safe) |
| Konflikt mit Copytrading | Eigener Account (Abschnitt 1) |

Der Fail-Safe „bei Datenverlust alles canceln" ist Pflicht ab MM-3 und muss
getestet werden (WSS künstlich trennen).

## 5. Offene Entscheidungen

1. Startmärkte (Empfehlung: 1–2 langlaufende Politik-/Geopolitik-Märkte mit
   mittlerem Volumen — genug Reward-Pool, wenig Newsflow).
2. `QuoteSizeUsd`/Kapital für MM-3.
3. Beidseitig quoten von Anfang an (voller Reward-Score) oder zunächst
   einseitig konservativ? (Empfehlung: beidseitig, dafür kleine Size —
   einseitig scored schlechter und halbiert den Lerneffekt.)
