Docs: Konzepte/Plaene in docs/ mit Typ-Unterordnern buendeln
Root aufgeraeumt: alle Konzept-/Plan-/Fach-Dokumente nach docs/ verschoben, organisiert nach Typ (wie fuer ein separates Docs-Repo vorgeschlagen, aber bewusst in diesem Repo, damit Plan->umsetzende-Commits nachvollziehbar bleiben): - docs/konzepte/ (KONZEPT-*) - docs/umsetzungsplaene/ (UMSETZUNGSPLAN-*) - docs/ideen/ (fruehe Ideen, Platzhalter) - docs/pruefplaene/ (PRUEFPLAN-*) - docs/steuer/ (Steuer-/Buchhaltungs-Doks, z.B. US-CPA-Fragebogen) - docs/README.md (Index/Konventionen) Getrackte Plaene als Rename verschoben (History erhalten); zuvor untracked Konzept-/ Plan-Dateien jetzt versioniert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
1c3a364df2
commit
c5f0b1d188
@@ -0,0 +1,29 @@
|
||||
# Doku (Predictalytics / PolyTraderSharp)
|
||||
|
||||
Zentrale Ablage für Konzepte, Umsetzungspläne, Ideen und Fach-/Business-Dokumente — nach Typ in
|
||||
Unterordnern organisiert. Code-gekoppelte Umsetzungspläne bleiben bewusst in **diesem** Repo (statt in
|
||||
einem separaten Docs-Repo), damit „Plan → umsetzende Commits" nachvollziehbar bleibt.
|
||||
|
||||
## Struktur
|
||||
|
||||
- **`konzepte/`** — Konzepte für neue Module/Features (das „Warum" und „Was", vor der Umsetzung).
|
||||
- `KONZEPT-Modul-Accounting.md` — Buchhaltungs-/Steuer-Reporting-Modul (unabhängiger Polymarket-Abruf, BWA, CSV/PDF, US-Steuer Florida LLC).
|
||||
- `KONZEPT-Modul-DataDriven.md`
|
||||
- **`umsetzungsplaene/`** — konkrete, slice-weise Implementationspläne (das „Wie"), oft mit `file:line`-Bezügen und Fortschritt.
|
||||
- `UMSETZUNGSPLAN-Modularisierung.md` — Umbau Copytrader → Core + Module.
|
||||
- `UMSETZUNGSPLAN-CopyTrading-Verbesserungen.md` — Rentabilitäts-/Fable-Plan Copytrading.
|
||||
- `UMSETZUNGSPLAN-Fable-Review-Fixes.md` — Fable-Code-Review-Fixes (Slices 0–6 + Tests).
|
||||
- `UMSETZUNGSPLAN-Modul-ResolutionFarming.md` — Strategiemodul ResolutionFarming.
|
||||
- `UMSETZUNGSPLAN-Modul-MarketMaking.md` — Strategiemodul MarketMaking (Phase-1-blockiert).
|
||||
- `UMSETZUNGSPLAN-Modul-BundleArbitrage.md` — Strategiemodul BundleArbitrage (Phase-1-blockiert).
|
||||
- `UMSETZUNGSPLAN-AutoRedeem.md`, `UMSETZUNGSPLAN-AI-Aufloesequalitaet.md`, `UMSETZUNGSPLAN-StrategieDrift.md`
|
||||
- **`ideen/`** — frühe Ideen/Explorationen, bevor sie zu einem Konzept oder Umsetzungsplan reifen.
|
||||
- **`pruefplaene/`** — Prüf-/Validierungspläne.
|
||||
- `PREDICTALYTICS-PRUEFPLAN-Master-Auswahl.md` — Master-Trader-Auswahl (separates Predictalytics-Projekt).
|
||||
- **`steuer/`** — Steuer-/Buchhaltungs-Fachdokumente & Vorlagen (auch zum Weitergeben an Berater).
|
||||
- `Accounting-US-Tax-Questionnaire.md` — Fragebogen (EN) für die US-Steuerberaterin (Florida LLC).
|
||||
|
||||
## Konventionen
|
||||
- Neue Konzepte: `KONZEPT-*.md` → `konzepte/`. Neue Umsetzungspläne: `UMSETZUNGSPLAN-*.md` → `umsetzungsplaene/`.
|
||||
- Übergreifende/an Externe weitergebbare Dokumente können später in ein eigenes `Predictalytics-Docs`-Repo
|
||||
ausgelagert werden (Ordner rausziehen genügt) — für jetzt bewusst hier gebündelt.
|
||||
@@ -0,0 +1 @@
|
||||
Platzhalter – hier kommen frühe Ideen/Explorationen rein, bevor sie zu einem Konzept oder Umsetzungsplan werden.
|
||||
@@ -0,0 +1,255 @@
|
||||
# Konzept: Modul „Accounting" (Steuer-/Buchhaltungs-Reporting aller Live-Accounts)
|
||||
|
||||
> Stand: 2026-07-14
|
||||
> Ziel: Vollständige, **unabhängig von unserer Trading-DB** erhobene, buchhalterisch korrekte
|
||||
> Erfassung ALLER Transaktionen aller Live-Polymarket-Accounts. Periodische (meist monatliche),
|
||||
> vor einer Steuerbehörde nachvollziehbare Abrechnungen — je einzelnem Account ODER über alle
|
||||
> Accounts, für frei wählbare Zeiträume. BWA-artige Kennzahlen-Übersicht in der UI. Export als
|
||||
> CSV und PDF.
|
||||
> Reihenfolge: unabhängig, jederzeit baubar (kein Live-Trading nötig — rein lesende API-Abrufe).
|
||||
> **Kein Handel; reines Ingest-/Reporting-Modul.**
|
||||
>
|
||||
> **Entscheidungen Richard (2026-07-14):**
|
||||
> - Währung: **USDC nativ + USD + EUR** (jede Transaktion in allen drei ausgewiesen).
|
||||
> - Abrechnung: neutrale prüfbare Aufstellung **UND** konkrete **US-Steuerberechnung** — Zielland
|
||||
> **USA, Florida LLC** (Florida ohne State Income Tax → nur Federal). Als dokumentierte, vom CPA
|
||||
> prüfbare Rechenschicht, **nicht als Steuerberatung** (Disclaimer, §4a).
|
||||
> - Umfang v1: **inkl. On-Chain-Ein-/Auszahlungen** von Anfang an (vollständige Kapitalsicht).
|
||||
|
||||
---
|
||||
|
||||
## 0. Leitprinzipien
|
||||
|
||||
1. **Unabhängige Quelle = Polymarket, NICHT unsere DB.** Das Modul erhebt die Buchungsgrundlage
|
||||
ausschließlich über eigene, regelmäßige Abrufe direkt bei Polymarket und speichert sie roh +
|
||||
normalisiert in eigenen Tabellen. Unsere eigenen Trade-Logs (Copytrading/ResolutionFarming/Core)
|
||||
werden **nur** für den optionalen Abgleich (§7) herangezogen, **nie** als Buchungsgrundlage.
|
||||
2. **Nachvollziehbarkeit / Audit.** Jeder Buchungssatz führt auf einen konkreten, prüfbaren Nachweis
|
||||
zurück (Transaktions-Hash, Activity-/Trade-ID, Abruf-Zeitpunkt, Rohdaten-Snapshot). Der Roh-Ingest
|
||||
ist **unveränderlich (append-only)**; Abrechnungen sind daraus **reproduzierbar** ableitbar.
|
||||
3. **Zwei Ebenen: neutraler Ledger + prüfbare US-Steuerschicht.** Unten liegt eine vollständige,
|
||||
länderneutrale Transaktions-/Ledger-Aufstellung + Kennzahlen (belastbare Basis). Darauf setzt eine
|
||||
**konfigurierbare, dokumentierte US-Steuer-Rechenschicht** (Florida LLC, §4a) — mit klaren, im
|
||||
Export ausgewiesenen Annahmen, **die der US-CPA prüft/bestätigt**. Das Tool rechnet; es berät nicht
|
||||
(Disclaimer, §4a). Der neutrale Ledger bleibt auch bei anderer steuerlicher Einordnung gültig.
|
||||
4. **Lesend / idempotent.** Keine Orders, keine On-Chain-Writes. Überlappende Wiederholungs-Abrufe
|
||||
dürfen **nichts doppelt buchen** (stabile Idempotenz-Schlüssel, Upsert statt Insert).
|
||||
|
||||
---
|
||||
|
||||
## 1. Architektur-Einbettung
|
||||
|
||||
Neues Projekt `src/PolyTrader.Modules.Accounting/` als `IPolyTraderModule`
|
||||
(`Name = "Accounting"`, `DbPrefix = "acc_"`), Registrierung in `Program.cs`. Referenziert nur den
|
||||
Core. Eigener `AccountingDbContext` (acc_-Tabellen), eigene UI (ein Fenster mit Tabs), eigene
|
||||
Settings-Sektion.
|
||||
|
||||
- Nutzt den bestehenden `PolymarketApiService` (Data-API `/activity`, `/positions`,
|
||||
`GetUsdcBalanceAsync(wallet)`) und für On-Chain-Ein-/Auszahlungen die vorhandene Alchemy-Anbindung.
|
||||
- Betrifft ALLE Live-Accounts (aus `TradingState.Accounts` bzw. `IAccountRepository`; `!IsDemo`,
|
||||
mit gesetzter `WalletAddress`).
|
||||
- **Hinweis Ist-Stand:** `PolymarketApiService.GetTraderActivityAsync` filtert heute hart auf
|
||||
`type=TRADE`. Fürs Accounting brauchen wir ALLE Activity-Typen → entweder den Filter parametrisieren
|
||||
oder eine eigene, accounting-spezifische Abruf-Methode (schlanker, ohne Copytrading-Annahmen).
|
||||
|
||||
---
|
||||
|
||||
## 2. Datenbeschaffung (der Kern: der unabhängige Abruf)
|
||||
|
||||
### 2.1 Ledger-Quellen bei Polymarket
|
||||
- **Data-API `/activity?user=<wallet>`** = primäres Kontobuch. Enthält (Feldnamen/Typen bei Umsetzung
|
||||
zwingend aus https://docs.polymarket.com verifizieren) u. a.:
|
||||
- `TRADE` (BUY/SELL-Fills): Preis, Size, USDC, Fee, Token/Market, txHash, Timestamp, Side.
|
||||
- `REDEEM` (Resolution-Auszahlung: Gewinner-Shares → USDC).
|
||||
- `SPLIT` / `MERGE` / `CONVERSION` (CTF-/NegRisk-Operationen; meist geldneutral, aber bestandsrelevant).
|
||||
- `REWARD` (Liquidity Rewards) / Maker-Rebates — Einnahmen.
|
||||
- **On-Chain USDC-Ein-/Auszahlungen** (Deposits/Withdrawals ins/aus dem Wallet): sind **nicht** Teil
|
||||
der Trading-Activity. Quelle: Polygon/Alchemy (ERC-20-Transfer-Logs USDC ↔ Wallet).
|
||||
- **Adresse ist vorhanden:** Polymarket nutzt **Gnosis-Safe-Proxy-Wallets** — genau die Adresse, die
|
||||
wir bereits als `AccountState.WalletAddress` für Balance- und Activity-Abrufe verwenden. Sie ist
|
||||
also die Watch-Adresse für USDC-Transfers (keine zusätzliche Beschaffung nötig).
|
||||
- **Die eigentliche Arbeit ist die Klassifikation:** Die USDC-Transfers des Safes enthalten SOWOHL
|
||||
trading-interne Bewegungen (Safe ↔ Polymarket-Contracts: CTF/Exchange/NegRisk — bereits in `/activity`
|
||||
als Trades/Redeems erfasst) ALS AUCH echte Ein-/Auszahlungen (Safe ↔ EXTERNE Adressen). Nur letztere
|
||||
sind Deposits/Withdrawals. Klassifikation über eine **Whitelist der Polymarket-System-Contracts**
|
||||
(die CTF-Adresse `0x4D97…6045` liegt bereits im Code — Exchange/NegRisk-Adapter/USDC ergänzen, aus
|
||||
docs verifizieren). Alternativ als Kreuzprobe: ΔSafe-Balance − Σ(interne Activity) = externe Netto-Ein-/Auszahlung.
|
||||
- ⚠️ Gnosis-Safe-Nuance: Transfers laufen ggf. als Safe-`execTransaction`; die ERC-20-Transfer-Logs
|
||||
(from/to = Safe) bleiben aber die maßgebliche, prüfbare Quelle.
|
||||
- **Balance-Anker**: `GetUsdcBalanceAsync(wallet)` je Abruf als Kontrollpunkt (End-Saldo Soll-Ist).
|
||||
|
||||
### 2.2 Vollständigkeit & Idempotenz
|
||||
- **Backfill + Inkrementell**: Erstlauf lädt die volle Historie je Account (paginiert, `offset`/`limit`;
|
||||
Rate-Limits beachten — Activity 1000/10 s, Positions 150/10 s, bereits im ApiService limitiert).
|
||||
Danach nur neue Ereignisse ab dem letzten bekannten Zeitpunkt, mit Sicherheits-**Lookback-Überlappung**
|
||||
gegen API-Lag.
|
||||
- **Idempotenz-Schlüssel** je Buchungssatz: stabile Kombination `txHash + logIndex/assetId + type`
|
||||
→ überlappende Abrufe buchen nicht doppelt (Unique-Constraint + Upsert).
|
||||
- **Lückenerkennung**: Timestamp-Kontinuität + Seiten-Vollständigkeit prüfen; fehlende Bereiche gezielt
|
||||
nachladen und markieren.
|
||||
- **Rohdaten-Snapshot**: die JSON-Rohantwort je Abruf-Batch speichern (Nachweis + Reproduzierbarkeit),
|
||||
zusätzlich zu den normalisierten Sätzen.
|
||||
|
||||
### 2.3 Abruf-Steuerung
|
||||
- `AccountingIngestJob : BackgroundService` (JobManager-registriert, manuell triggerbar), Intervall
|
||||
konfigurierbar (z. B. stündlich inkrementell, täglich Voll-Reconcile). Nutzt die bestehenden
|
||||
Rate-Limiter des `PolymarketApiService`.
|
||||
|
||||
---
|
||||
|
||||
## 3. Persistenz (acc_-Tabellen, append-only Ledger)
|
||||
|
||||
| Tabelle | Inhalt |
|
||||
|---|---|
|
||||
| `acc_ledger` | Normalisierte, **unveränderliche** Buchungssätze: AccountId, EventType (TRADE_BUY/TRADE_SELL/REDEEM/REWARD/FEE/SPLIT/MERGE/DEPOSIT/WITHDRAWAL), Timestamp, TokenId/Market, Outcome, Size, PriceUsdc, GrossUsdc, FeeUsdc, NetUsdc, TxHash, LogIndex, Source, IngestBatchId, **IdempotencyKey (unique)** |
|
||||
| `acc_ingest_runs` | Abruf-Protokoll: AccountId, Von/Bis, Start/Ende, #Sätze, Ok/Fehler, Balance-Anker (Soll-Ist) |
|
||||
| `acc_raw` | Rohdaten-Snapshots (JSON) je Batch (Nachweis) |
|
||||
| `acc_fx_rates` | (falls Fiat, §10.1) amtliche Tages-FX-Kurse (z. B. USD→EUR) je Datum |
|
||||
| `acc_statements` (optional) | Erzeugte Periodenabrechnungen (Metadaten + Daten-Hash) für Versionierung/Reproduzierbarkeit |
|
||||
|
||||
Autoincrement-PKs (Lehre aus dem CopyTrading-`TradeId`-Problem), Unique-Index auf `IdempotencyKey`,
|
||||
Indizes auf `(AccountId, Timestamp)`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Buchhaltungs-Logik (pure, testbar) — `AccountingEngine`
|
||||
|
||||
Wie bei den anderen Modulen liegt die geldkritische Logik pur und unit-getestet in `Logic/`:
|
||||
- **Klassifikation** roher Activity → Buchungssatz-Typ + Vorzeichen (Einnahme/Ausgabe). Rein/testbar.
|
||||
- **Periodenabrechnung** (Zeitraum × Account bzw. alle): aggregiert die Ledger-Sätze zu:
|
||||
Anfangssaldo, Einlagen, Entnahmen, Handelsvolumen, realisierte Gewinne/Verluste, Fees, Rewards,
|
||||
Netto-Ergebnis, Endsaldo — mit **Soll-Ist gegen den Balance-Anker** (Abweichung = Vollständigkeits-Signal).
|
||||
- **Realisierung / Kostenbasis**: Gewinn/Verlust wird bei SELL/REDEEM realisiert; Kostenbasis je
|
||||
Position per **FIFO** (US-Norm für Krypto/Property; Specific-ID als Option, §10.5) — Lot-Matching der
|
||||
BUYs zu jeder Veräußerung, inkl. Haltefristen (short/long term). Pure/testbar. Offene Positionen zum
|
||||
Periodenende optional als **Mark-to-Market** ausweisen, aber getrennt vom realisierten Ergebnis.
|
||||
- **Währung/FX**: jede Transaktion in **USDC (nativ), USD und EUR**. Umrechnung je Transaktionsdatum:
|
||||
USDC→USD (Stablecoin, Annahme 1:1 als USD-Äquivalent — im Export dokumentiert; realer USDC/USD-Kurs
|
||||
optional) und USD→EUR über amtliche Tageskurse (EZB), versioniert in `acc_fx_rates`.
|
||||
|
||||
---
|
||||
|
||||
## 4a. US-Steuer-Rechenschicht (Florida LLC) — konfigurierbar, CPA-prüfbar
|
||||
|
||||
> ⚠️ **Kein Steuerrat.** Diese Schicht rechnet Zahlen nach **dokumentierten, konfigurierbaren
|
||||
> Annahmen** aus und weist diese im Export offen aus. Die steuerliche Einordnung von
|
||||
> Prediction-Market-/Event-Contract-Erträgen in den USA ist **nicht eindeutig geklärt**. Der Output
|
||||
> ist zur **Prüfung/Bestätigung durch einen US-CPA/Steuerberater** gedacht, nicht als endgültige
|
||||
> Steuererklärung. Jede Annahme ist im PDF/CSV dokumentiert und in den Settings umstellbar.
|
||||
|
||||
**Rahmen (Defaults, alle in Settings umstellbar):**
|
||||
- **Entität:** Florida LLC. Florida erhebt **keine State Income Tax** → nur **Federal**. LLC-Typ
|
||||
(single-member = disregarded → Schedule C/D im 1040; vs. multi-member = Partnership 1065 + K-1)
|
||||
bestimmt nur die Ziel-Formulare, **nicht** die Gewinnermittlung (§10.7).
|
||||
- **Einordnung (Default-Annahme):** jede Position = **Property-Disposition** → realisierter Gewinn/
|
||||
Verlust je Veräußerung (SELL/REDEEM) im **Form-8949/Schedule-D-Stil**: Proceeds (USD), Cost Basis
|
||||
(USD), Holding Period (short/long), Gain/Loss. Alternative Einordnungen (ordinary income, gambling,
|
||||
§1256) als umstellbare Annahme vorgesehen — Auswahl trifft der CPA (§10.4).
|
||||
- **USDC:** als **USD-Äquivalent (1:1)** behandelt; USDC-Käufe/-Verkäufe gelten nicht separat als
|
||||
steuerbares Krypto-Event (dokumentierte Vereinfachung; abschaltbar).
|
||||
- **Kostenbasis:** **FIFO** (Default) oder Specific-ID; Lot-genau, mit Haltefristen.
|
||||
- **Wash-Sale:** Default-Annahme „nicht anwendbar" auf Event-Contracts/Krypto (Stand 2026) — als
|
||||
Schalter, da Rechtslage im Fluss.
|
||||
|
||||
**Output der Steuerschicht:**
|
||||
- **Form-8949-artige Veräußerungsliste** je Account/Zeitraum (Description, Acquired, Sold, Proceeds,
|
||||
Cost Basis, Gain/Loss, Short/Long) — CSV + PDF.
|
||||
- **Schedule-D-artige Zusammenfassung** (kurz-/langfristig, Summen) je Account und aggregiert über die LLC.
|
||||
- Vollständige **Methodik-/Annahmen-Seite** im Export (Reproduzierbarkeit + Prüfbarkeit).
|
||||
|
||||
Die Rechenlogik (FIFO-Lot-Matching, Haltefrist, Gain/Loss, FX-Umrechnung je Datum) liegt **pur und
|
||||
unit-getestet** in `Logic/` (z. B. `UsTaxEngine`), getrennt vom neutralen Ledger.
|
||||
|
||||
---
|
||||
|
||||
## 5. UI (WinForms, ein Fenster mit Tabs — Muster wie ResolutionFarming)
|
||||
|
||||
- **Übersicht / BWA**: Kennzahlen-Kacheln für den gewählten Zeitraum + Account(s): Netto-Ergebnis,
|
||||
Handelsvolumen, Fees, Rewards, Einlagen/Entnahmen, Endsaldo, realisiert vs. offen; Monats-/Perioden-Vergleich.
|
||||
- **Ledger**: filterbare Transaktionsliste inkl. Nachweisspalten (txHash etc.).
|
||||
- **Steuer (US)**: Form-8949-artige Veräußerungsliste + Schedule-D-Zusammenfassung je Account/alle,
|
||||
mit ausgewiesenen Annahmen (FIFO, Einordnung, USDC=USD). Werte in USD (und EUR).
|
||||
- **Abrechnungen / Export**: Zeitraum-Picker (Monats-Presets + frei), Account-Auswahl (einzeln / alle),
|
||||
Währungswahl (USDC/USD/EUR), Buttons „CSV" und „PDF".
|
||||
- **Abruf / Status**: Ingest-Läufe, Vollständigkeits-/Lücken-Status, Balance-Soll-Ist, manueller Trigger.
|
||||
|
||||
---
|
||||
|
||||
## 6. Export (CSV + PDF)
|
||||
|
||||
- **CSV**: vollständiger Ledger + Aggregat je Abrechnung (maschinen-/prüfbar).
|
||||
- **PDF**: formatierte Abrechnung — Kopf (Account, Wallet, Zeitraum, Erstellungsdatum), Aggregat-Tabelle,
|
||||
Transaktionsliste, Methodik-/Nachweis-Hinweis. Library **PDFsharp/MigraDoc (MIT)** — echte,
|
||||
bedingungslose MIT-Lizenz ohne Umsatzschwelle; MigraDoc eignet sich für tabellarische
|
||||
Abrechnungen/Berichte. (QuestPDF bewusst NICHT: dessen „Community"-Lizenz ist kostenlos nur unter
|
||||
1 Mio USD Jahresumsatz — für eine handelnde LLC ein Lizenzrisiko. Siehe §10.1.)
|
||||
- **Reproduzierbarkeit**: jeder Export trägt Zeitraum, Datenstand (letzter Ingest), Zeilenzahl und einen
|
||||
Daten-Hash → gleiche Eingabe ⇒ identische Abrechnung (wichtig für die Prüfbarkeit).
|
||||
|
||||
---
|
||||
|
||||
## 7. Abgleich mit eigener Trade-DB (niedrige Priorität)
|
||||
|
||||
Gegenüberstellung Polymarket-Ledger ↔ unsere Modul-/Core-Trade-Logs je Account/Zeitraum: fehlende/
|
||||
zusätzliche Trades, Preis-/Size-/Fee-Abweichungen, PnL-Differenzen. Rein analytisch — findet
|
||||
Sync-/Buchungsfehler unserer Trading-Seite. Bericht in der UI + Export.
|
||||
|
||||
---
|
||||
|
||||
## 8. Phasen & Akzeptanzkriterien
|
||||
|
||||
- **A-1 Ingest (read-only), inkl. Ein-/Auszahlungen:** Modul + acc_-Persistenz + Activity-Ingest
|
||||
(ALLE Typen) + On-Chain-USDC-Deposits/Withdrawals + Backfill/Inkrement + Idempotenz + Ingest-Status-UI.
|
||||
**Akzeptanz:** volle Historie eines Live-Accounts vollständig & doppelfrei; Balance-Anker Soll-Ist ≈ 0
|
||||
(inkl. Ein-/Auszahlungen).
|
||||
- **A-2 Abrechnung + Übersicht + FX:** `AccountingEngine` + BWA-UI + Periodenabrechnung je Account/alle,
|
||||
Werte in USDC/USD/EUR (Tageskurse in `acc_fx_rates`). **Akzeptanz:** Monatsabrechnung stimmt gegen
|
||||
Balance-Anker; Kennzahlen plausibel; FX nachvollziehbar.
|
||||
- **A-3 US-Steuerschicht:** `UsTaxEngine` (FIFO-Lot-Matching, Haltefristen, Gain/Loss) + Form-8949-/
|
||||
Schedule-D-Ansicht + Annahmen-Dokumentation. **Akzeptanz:** Summe realisierter Gain/Loss stimmt gegen
|
||||
die neutrale Abrechnung; Annahmen ausgewiesen.
|
||||
- **A-4 Export:** CSV + PDF (Abrechnung, Ledger, Form-8949/Schedule-D) mit Zeitraum-/Account-/Währungswahl.
|
||||
**Akzeptanz:** vollständig, reproduzierbar, prüfbar.
|
||||
- **A-5 Reconciliation (niedrig):** Abgleich mit eigener DB.
|
||||
|
||||
Die geldkritische Logik (Klassifikation, Aggregation, Realisierung, FX) ist von Anfang an pur +
|
||||
unit-getestet; Ingest/Export werden über Interfaces (Activity-Quelle, PDF-Writer) testbar gehalten —
|
||||
wie bei ResolutionFarming die Live-Anbindung hinter Interfaces liegt.
|
||||
|
||||
---
|
||||
|
||||
## 9. Risiken & Gegenmaßnahmen
|
||||
|
||||
| Risiko | Gegenmaßnahme |
|
||||
|---|---|
|
||||
| Unvollständige API-Historie / Pagination-Lücken | Balance-Anker-Soll-Ist als Vollständigkeits-Wächter; Lückenerkennung + Nachlad; Rohdaten-Snapshots |
|
||||
| API-Feld-/Endpoint-Änderungen | Rohdaten speichern; Normalisierung entkoppelt; Feldnamen bei Umsetzung aus docs verifizieren |
|
||||
| Doppelbuchung bei überlappenden Abrufen | strikte Idempotenz-Schlüssel + Upsert |
|
||||
| Steuerliche Fehlinterpretation | bewusst neutrale, vollständige Aufstellung statt Steuerberechnung; Methodik im Export dokumentiert |
|
||||
| FX-Korrektheit | amtliche Tageskurse (z. B. EZB) versioniert in `acc_fx_rates` |
|
||||
| Falsche Wallet-Adresse (Proxy vs. Signer) für Deposits | Adress-/Transfer-Semantik je Account verifizieren |
|
||||
|
||||
---
|
||||
|
||||
## 10. Entscheidungen & offene Punkte
|
||||
|
||||
**Entschieden (2026-07-14):**
|
||||
- ✅ **Währung:** USDC nativ + USD + EUR (Tageskurse EZB, USDC≈USD dokumentiert).
|
||||
- ✅ **Abrechnung:** neutraler Ledger **+** US-Steuerschicht (Florida LLC), als CPA-prüfbare Rechenschicht.
|
||||
- ✅ **Umfang v1:** inkl. On-Chain-Ein-/Auszahlungen.
|
||||
- ✅ **Kostenbasis:** FIFO (US-Norm), Specific-ID als Option.
|
||||
|
||||
**Noch offen / vom CPA zu bestätigen:**
|
||||
1. ✅ **PDF-Library: PDFsharp/MigraDoc (MIT)** — nach Rückfrage bewusst statt QuestPDF: QuestPDFs
|
||||
„Community MIT"-Lizenz ist nur unter 1 Mio USD Jahresumsatz kostenlos (darüber Professional/
|
||||
Enterprise kostenpflichtig) → für eine handelnde LLC ein Lizenzrisiko. PDFsharp/MigraDoc ist echte
|
||||
MIT ohne Schwelle.
|
||||
2. **Steuerliche Einordnung (Default-Annahme):** Property-Disposition (Form 8949/Schedule D, Default) vs.
|
||||
ordinary income vs. gambling vs. §1256 — vom US-CPA bestätigen lassen; im Tool umstellbar.
|
||||
3. **LLC-Typ:** single-member (disregarded) vs. multi-member (Partnership 1065/K-1) — bestimmt nur die
|
||||
Ziel-Formulare/Darstellung, nicht die Gewinnermittlung.
|
||||
4. **USDC=USD-Annahme & Wash-Sale-Schalter:** Defaults gesetzt (1:1; Wash-Sale n/a) — vom CPA bestätigen.
|
||||
5. ✅ **Proxy-Wallets: geklärt.** Der Gnosis-Safe (= vorhandene `WalletAddress`) ist die Watch-Adresse;
|
||||
zu bauen ist die **Transfer-Klassifikation** intern (Polymarket-Contracts) vs. extern (Deposit/Withdrawal)
|
||||
über eine System-Contract-Whitelist (CTF-Adresse bereits im Code; Exchange/NegRisk/USDC ergänzen).
|
||||
6. **FX-Quelle & USDC/USD:** EZB-Tageskurse für USD→EUR; USDC→USD als 1:1 (Default) oder realer Kurs?
|
||||
@@ -0,0 +1,129 @@
|
||||
# Konzept: Eigenes datengetriebenes Trading-Modul („DataDriven")
|
||||
|
||||
> Stand: 2026-07-11
|
||||
> Status: KONZEPT (noch kein Umsetzungsplan). Ziel: ein Strategiemodul, das eigene
|
||||
> Handelsentscheidungen aus externen Datenquellen ableitet — je Marktkategorie eine
|
||||
> eigene Datenquelle + ein eigenes Fair-Value-Modell. Die Datenanbindung wird so
|
||||
> gebaut, dass das ResolutionFarming sie mitnutzen kann (State-aware-Filter, C-S2).
|
||||
|
||||
---
|
||||
|
||||
## 1. Grundidee
|
||||
|
||||
Alle bisherigen Module leiten Signale von ANDEREN ab (Master-Trades, Marktpreise).
|
||||
DataDriven dreht das um: **Wir berechnen aus Rohdaten eine eigene faire
|
||||
Wahrscheinlichkeit** und handeln nur, wenn der Marktpreis deutlich davon abweicht:
|
||||
|
||||
```
|
||||
FairValue(Markt) aus Datenquelle → Vergleich mit Marktpreis (Bid/Ask)
|
||||
→ |FairValue − Preis| > MinEdge (nach Fees) → Order (Maker bevorzugt) → Halten bis Resolution/Ziel
|
||||
```
|
||||
|
||||
Der Edge kommt nicht aus Geschwindigkeit, sondern daraus, die **Daten besser/
|
||||
konsequenter auszuwerten als der Durchschnitts-Teilnehmer** der jeweiligen Kategorie.
|
||||
Deshalb ist die Kategorien-Wahl die wichtigste Entscheidung dieses Moduls.
|
||||
|
||||
## 2. Architektur (fügt sich in die bestehende Modul-Landschaft)
|
||||
|
||||
```
|
||||
PolyTrader.Modules.DataDriven (IPolyTraderModule, DbPrefix dd_)
|
||||
│
|
||||
├── Core-Beitrag (geteilt, auch für ResolutionFarming nutzbar):
|
||||
│ IMarketStateProvider // je Kategorie: liefert konservative
|
||||
│ { // Wahrscheinlichkeits-Schätzung + Zustand
|
||||
│ bool Supports(MarketData m);
|
||||
│ Task<MarketStateEstimate?> EstimateAsync(MarketData m, CancellationToken ct);
|
||||
│ }
|
||||
│ record MarketStateEstimate(decimal ProbLowerBound, decimal ProbUpperBound,
|
||||
│ string StateSummary, DateTime AsOf, string Source);
|
||||
│
|
||||
├── Provider (je Kategorie ein Adapter, einzeln aktivierbar):
|
||||
│ WeatherStateProvider // Open-Meteo/NOAA-Modelläufe
|
||||
│ SportsScoreStateProvider // Live-Scores (z. B. API-Football)
|
||||
│ CryptoStrikeStateProvider // Binance-Spot + realisierte Volatilität
|
||||
│ MacroStateProvider // Nowcasts/Konsensdaten (CPI, Zinsen)
|
||||
│
|
||||
├── Services:
|
||||
│ DdScannerService // Märkte je aktiver Kategorie laden, FairValue
|
||||
│ // berechnen, Kandidaten mit Edge persistieren
|
||||
│ DdExecutionService // Sizing/Limits (Muster: FarmingRiskEngine/
|
||||
│ // Planner wiederverwenden!), Maker-first
|
||||
│ DdPositionMonitorService // Re-Evaluation offener Positionen: dreht der
|
||||
│ // FairValue, wird der Exit geprüft (Leiter-Muster)
|
||||
│
|
||||
└── Persistenz: dd_settings / dd_candidates / dd_positions / dd_closed_trades
|
||||
(Kopie des bewährten rf_-Schemas; Autoincrement-IDs, Kalibrierungs-Historie)
|
||||
```
|
||||
|
||||
**Wichtige Wiederverwendung:** Risk-Engine, Execution-Planner, Fill-Modell,
|
||||
Resolution-Monitor und UI-Aufbau des ResolutionFarming sind fast 1:1 übertragbar —
|
||||
DataDriven ist strukturell „ResolutionFarming mit eigener Signalquelle statt
|
||||
Preisband-Scan". Der Unterschied: DataDriven darf auch UNTER 0.90 kaufen (überall,
|
||||
wo FairValue ≫ Preis) und optional vor der Resolution verkaufen, wenn der Edge
|
||||
realisiert ist (Preis hat FairValue erreicht → Kapitalumschlag).
|
||||
|
||||
**ResolutionFarming-Synergie (C-S2):** Sobald ein `IMarketStateProvider` für eine
|
||||
Kategorie existiert, nutzt ihn auch der RF-Scanner: Ein Preis-Dip wird nicht mehr
|
||||
pauschal gemieden (Momentum-Filter), sondern gegen `ProbLowerBound` geprüft —
|
||||
Richards 5:1-in-Minute-80-Beispiel wird damit zur Kaufgelegenheit statt zum Reject.
|
||||
|
||||
## 3. Kategorien-Bewertung: Wo lohnt sich ein eigenes Modell?
|
||||
|
||||
Bewertung nach: Datenlage (frei/billig verfügbar?), Modell-Komplexität,
|
||||
Bot-Konkurrenz (Stand 2026), Fee-Satz, Kapitalbindung.
|
||||
|
||||
| Kategorie | Datenquelle (Kosten) | Modell | Bot-Konkurrenz | Fee | Bindung | Urteil |
|
||||
|---|---|---|---|---|---|---|
|
||||
| **Wetter (Tages-Märkte: Temperatur/Niederschlag je Stadt)** | Open-Meteo/NOAA/ECMWF-Läufe (kostenlos) | Modell-Konsens vs. Marktpreis; Update-Lag nutzen | **moderat, wachsend** — Edges von ~10 Pp (2023) auf ~3 Pp (2026) komprimiert, aber vorhanden; dünne Bücher, wenig Retail | 1,25 % | Stunden–Tage | ✅ **Bester Einstieg** |
|
||||
| **Wetter (Saison: Hurrikane, Rekorde)** | wie oben + NHC | aufwendiger | gering (Kapital-Lockup schreckt ab) | 1,25 % | Wochen–Monate | ⚠️ später (Bindung) |
|
||||
| **Sport pre-game (kleinere Ligen)** | API-Football o. ä. (~20–30 $/Mon.) | Elo-/Quotenvergleich vs. Buchmacher-Konsens | groß in Top-Ligen, **moderat in Nebenligen** | 0,75 % | Stunden–Tage | ✅ zweiter Kandidat |
|
||||
| **Sport live (State-Provider)** | wie oben, Live-Scores | Score+Restzeit → P(Sieg), konservative Untergrenze | hoch (Latenz-Bots) — aber wir brauchen nur EINEN Fill unter FairValue, nicht den schnellsten | 0,75 % | Minuten–Stunden | ✅ als RF-Filter; als eigene Strategie nur eng begrenzt |
|
||||
| **Krypto-Strikes (Wochen/Monat: „BTC über X am Y")** | Binance-WSS (kostenlos) | Distanz zum Strike + realisierte Vol → P | hoch bei 15-min/Stunde, **moderat bei Wochen-Strikes** | 1,8 % ⚠️ | Tage–Wochen | ⚠️ Fee frisst viel; nur bei großem Modell-Edge |
|
||||
| **Makro (CPI, Zinsentscheide)** | Cleveland-Fed-Nowcast, Konsens-Schätzungen (frei) | Nowcast vs. Marktpreis | moderat, aber informierte Gegenseite | 1,5 % | Tage–Wochen | ⚠️ Nische, wenige Märkte |
|
||||
| **Politik-Longtail (Nicht-Headline)** | Polls/Aggregatoren | Poll-Modell | gering im Long Tail | 1,0 % | Wochen+ | ⚠️ Bindung + Resolution-Risiko |
|
||||
| **Kultur/Awards/Mentions** | Box-Office-Daten teils frei; sonst dünn | schwach | **gering** | 1,25–1,56 % | variabel | ❌ Resolution-Risiko (AI-Rater Pflicht), Datenlage schlecht |
|
||||
| Krypto 15-min/1h Up-Down | Binance | Latenz | **extrem** (Sub-100-ms-Bots) | 1,8 % | Minuten | ❌ nicht unser Spiel |
|
||||
|
||||
**Antwort auf „nicht geflutete Kategorien":** Am wenigsten Bot-dominiert sind 2026
|
||||
(a) **Wetter** — dünne Bücher, Nischenwissen (Stations-Regeln, Modell-Läufe), Retail
|
||||
meidet die Kategorie; (b) **Long-Tail-/Nebenliga-Sport pre-game**; (c) **Makro-
|
||||
Nischen** und (d) Long-Tail-Politik. Geflutet sind: Krypto-Kurzfrist, Top-Sport
|
||||
in-play, Headline-Elections, Arbitrage/NegRisk-Rebalancing. Faustregel: Bots meiden
|
||||
Kapitalbindung und Nischenwissen — genau dort liegt unser Fenster.
|
||||
|
||||
## 4. Empfohlener Aufbau-Pfad
|
||||
|
||||
1. **Phase DD-0:** `IMarketStateProvider`-Contract in Core + Modul-Skelett
|
||||
(rf_-Schema kopieren). Kein Provider aktiv.
|
||||
2. **Phase DD-1 (Wetter, read-only):** WeatherStateProvider (Open-Meteo, tägliche
|
||||
Temperatur-Märkte 2–3 US-Städte). Scanner läuft wochenlang read-only:
|
||||
FairValue vs. Marktpreis loggen → **misst den real verbliebenen Edge, bevor
|
||||
irgendetwas gehandelt wird** (dasselbe Kalibrierungs-Gate-Prinzip wie RF).
|
||||
3. **Phase DD-2:** Demo-Execution (Planner/Fill-Modell aus RF), 4 Wochen.
|
||||
4. **Phase DD-3:** SportsScoreStateProvider — zuerst NUR als RF-Filter (C-S2:
|
||||
Dip-Freigabe bei klarer Führung), erst danach als eigene DD-Strategie.
|
||||
5. **Phase DD-4:** Live klein (eigener Account, wie bei RF), dann weitere Provider
|
||||
nach gemessenem Edge.
|
||||
|
||||
## 5. Risiken dieses Moduls (ehrlich)
|
||||
|
||||
1. **Modell-Risiko ersetzt Master-Risiko:** Ein Bug/Bias im Fair-Value-Modell
|
||||
produziert systematisch falsche Trades. Gegenmittel: read-only-Messphase je
|
||||
Provider (DD-1-Prinzip), konservative Untergrenzen statt Punktschätzern.
|
||||
2. **Edge-Kompression:** Der Wetter-Edge ist dokumentiert am Schrumpfen (10→3 Pp).
|
||||
Read-only-Messung VOR jedem Livegang, und die Bereitschaft, eine Kategorie
|
||||
wieder abzuschalten, wenn die Messung < MinEdge zeigt.
|
||||
3. **Regel-Fallen:** Wetter-Märkte lösen nach exakten Stations-Regeln auf — der
|
||||
AI-Auflösequalitäts-Rater (separater Plan) und das genaue Lesen der Regeln
|
||||
je Markt-Serie sind Pflicht (welche Station, welche Rundung, welcher Zeitraum).
|
||||
4. **Aufwand:** Jede Kategorie ist ein eigenes kleines Forschungsprojekt. Deshalb:
|
||||
strikt eine Kategorie nach der anderen, jede mit eigenem Go/No-Go-Gate.
|
||||
|
||||
## 6. Quellen (Kategorien-/Konkurrenz-Einschätzung)
|
||||
|
||||
- Polymarket Weather/Climate-Kategorieübersichten (Volumen/Marktzahl):
|
||||
https://polymarket.com/predictions/weather, https://polymarket.com/predictions/climate
|
||||
- Weather-Bot-Funktionsweise & Edge-Kompression 2023→2026:
|
||||
https://laikalabs.ai/prediction-markets/polymarket-weather-trading-bot
|
||||
- Markt-Mikrostruktur/Tiefe Wetter-Märkte: https://polymart.app/blog/polymarket-weather-markets,
|
||||
https://polymarkets.co.il/en/guide/weather-guide/
|
||||
@@ -0,0 +1,127 @@
|
||||
# Predictalytics: Prüf- und Ergänzungsplan für die Master-Trader-Auswahl
|
||||
|
||||
> Stand: 2026-07-11
|
||||
> Zweck: Dieses Dokument geht an den Predictalytics-Agenten. Es beschreibt, welche
|
||||
> Auswahl-Kriterien und Validierungsschritte die Master-Trader-Selektion für das
|
||||
> PolyTrader-Copytrading erfüllen soll — zum Abgleich mit den bereits vorhandenen
|
||||
> Berechnungen und als Ergänzungsliste. Predictalytics ist ein eigenständiges Projekt;
|
||||
> dieses Dokument setzt KEINE Kenntnis des PolyTrader-Codes voraus.
|
||||
|
||||
---
|
||||
|
||||
## 1. Kontext: Wofür die Auswahl gebraucht wird
|
||||
|
||||
PolyTrader kopiert Trades ausgewählter Polymarket-Wallets („Master") auf eigene
|
||||
Accounts. Zielprofil laut Strategie-Entscheidung: **Buy-and-Hold-Master** — Trader,
|
||||
die Positionen kaufen und in der Regel bis zur Marktauflösung halten, mit
|
||||
überdurchschnittlichem Erfolg. Bei diesem Typ ist die Kopier-Latenz fast irrelevant;
|
||||
die Auswahlqualität entscheidet über ~90 % des Ergebnisses.
|
||||
|
||||
Wichtig für alle Metriken: Der Kopierende zahlt gegenüber dem Master einen
|
||||
**Kopier-Aufschlag** (Spread + bis zu 2 % Limit-Aufschlag + 0,75–1,8 % Taker-Fee je
|
||||
nach Kategorie; bei Maker-Einstieg weniger, dafür Fill-Risiko). Ein Master ist erst
|
||||
dann kopierenswert, wenn sein Edge diesen Aufschlag DEUTLICH übersteigt.
|
||||
|
||||
## 2. Kern-Metriken je Wallet (prüfen ob vorhanden, sonst ergänzen)
|
||||
|
||||
Alle Metriken über ein definiertes Fenster (Vorschlag: 90 Tage) und nur über
|
||||
**aufgelöste/geschlossene** Trades:
|
||||
|
||||
| # | Metrik | Definition | Warum |
|
||||
|---|---|---|---|
|
||||
| M1 | Edge pro Trade | Ø realisierter PnL in % des Einsatzes je Trade | Muss > Kopier-Aufschlag (~3–4 Pp) liegen; „profitabel" allein reicht nicht |
|
||||
| M2 | Profit-Faktor | Bruttogewinn / Bruttoverlust | Robuster als Winrate (Favoriten-Käufer haben 95 % Winrate und können negativ sein) |
|
||||
| M3 | Holder-Quote | Anteil Positionen, die per Resolution enden (nie aktiv verkauft) | Zielprofil-Filter: Zielwert nahe 100 % |
|
||||
| M4 | Stop-Loss-Verhalten | Anteil SELLs, die NACH einem Preisrückgang ≥ X % erfolgen | Trennt „Stur-Halter" von „Stop-Loss-Nutzern" — Letztere sind fürs Kopieren ungeeignet (Exit-Latenz-Nachteil) |
|
||||
| M5 | Trade-Frequenz & Stichprobe | Trades/Woche; Gesamtzahl im Fenster | Mindeststichprobe für alles Weitere (siehe 3.1) |
|
||||
| M6 | Ø-Haltedauer | Median Stunden Kauf→Auflösung | Kapitalbindung des Kopierenden; plus Konsistenz-Indikator |
|
||||
| M7 | Preisband-Profil | Verteilung der Einstiegspreise (z. B. je 10-¢-Band) | Charakterisiert die Strategie (Favoriten-Halter vs. Longshot-Spieler) |
|
||||
| M8 | Kategorien-Mix | Einsatz-Anteil je Marktkategorie | Für Korrelations-/Portfolio-Betrachtung (siehe 5) und Fee-Rechnung |
|
||||
| M9 | Einsatz-Disziplin | Verteilung der Positionsgrößen relativ zur Wallet | Erkennt Martingale-/Tilt-Muster (stark wachsende Einsätze nach Verlusten = rotes Tuch) |
|
||||
|
||||
## 3. Validierungs-Methodik (die drei klassischen Fallen)
|
||||
|
||||
### 3.1 Survivorship-/Glücks-Bias
|
||||
|
||||
Unter zehntausenden Wallets sehen einige rein zufällig brillant aus. Gegenmaßnahmen:
|
||||
|
||||
1. **Mindeststichprobe:** keine Bewertung unter ~100 aufgelösten Trades im Fenster.
|
||||
2. **Out-of-Sample-Pflicht:** Auswahl auf Zeitfenster A (z. B. Tag −180 bis −60),
|
||||
Bestätigung auf Fenster B (Tag −60 bis heute). Nur Master, die in BEIDEN Fenstern
|
||||
die Schwellen erfüllen, kommen auf die Kopier-Liste. Master, die nur in A glänzen,
|
||||
werden verworfen — egal wie gut A aussieht.
|
||||
3. **Plausibilitäts-Check des Edges:** Bei Favoriten-Haltern lässt sich der Edge als
|
||||
„realisierte Winrate je Einstiegs-Preisband vs. Preisband" ausdrücken (kauft er
|
||||
95-¢-Shares, die zu 98 % gewinnen → +3 Pp Edge). Diese Darstellung bitte je Master
|
||||
ausgeben — sie macht Glück von System unterscheidbar und ist direkt mit der
|
||||
ResolutionFarming-Kalibrierung in PolyTrader vergleichbar.
|
||||
|
||||
### 3.2 Kopierbarkeit
|
||||
|
||||
Ein profitabler Master kann unkopierbar sein. Je Master prüfen:
|
||||
|
||||
1. **Markt-Liquidität:** Median-Liquidität/Volumen der gehandelten Märkte. Handelt er
|
||||
in Kleinstmärkten, bewegt schon der Kopier-Kauf den Preis. Vorschlag: Median-Buch-
|
||||
Tiefe oder 24h-Volumen der gehandelten Märkte als Kriterium, Schwelle empirisch.
|
||||
2. **Edge-Verbleib nach Kopier-Aufschlag:** M1 minus 3–4 Pp muss > 0 bleiben
|
||||
(Kategorie-Fee einrechnen: Sports 0,75 %, Politik 1,0 %, Krypto 1,8 %).
|
||||
3. **Einstiegs-Fenster:** Wie schnell bewegt sich der Preis nach dem Master-Kauf?
|
||||
(Median-Preisänderung 1 min / 10 min / 1 h nach seinen Fills, aus der Preis-
|
||||
Historie). Läuft der Preis sofort weg, ist der Edge zeitkritisch → schlecht
|
||||
kopierbar; bleibt er stabil, passt auch ein ruhender Maker-Einstieg.
|
||||
|
||||
### 3.3 Korrelation / Portfolio-Ebene
|
||||
|
||||
Nicht nur Einzel-Scores ranken — die Kopier-Liste ist ein Portfolio:
|
||||
|
||||
1. **Master-Korrelation:** Überlappung der gehandelten Märkte/Kategorien zwischen
|
||||
Kandidaten (z. B. Jaccard auf ConditionIds, Kategorie-Mix-Ähnlichkeit). Drei gute
|
||||
Wetter-Bots sind EIN Klumpenrisiko, nicht drei Ertragsquellen.
|
||||
2. **Empfehlung als Portfolio:** Ausgabe nicht nur als Rangliste, sondern als
|
||||
diversifizierter Vorschlag (z. B. max. 2 Master je Kategorie-Schwerpunkt).
|
||||
|
||||
## 4. Verhaltens-Fingerprint als Basisdaten (Übergabe an PolyTrader)
|
||||
|
||||
PolyTrader soll Strategie-Drift der Master zur Laufzeit erkennen (separater Plan
|
||||
dort). Dafür braucht es je ausgewähltem Master eine **Baseline**, die Predictalytics
|
||||
ohnehin berechnet — bitte mit exportieren: Trade-Frequenz/Woche, Kategorien-Mix,
|
||||
Einstiegs-Preisband-Verteilung, Median-Haltedauer, Positionsgrößen-Verteilung
|
||||
(jeweils Fenster B). Format: JSON je Wallet.
|
||||
|
||||
## 5. Übergabe-Format an PolyTrader (Vorschlag)
|
||||
|
||||
Je empfohlenem Master ein Datensatz:
|
||||
|
||||
```json
|
||||
{
|
||||
"wallet": "0x…",
|
||||
"displayName": "…",
|
||||
"classification": "HOLDER", // HOLDER | STOPLOSS | MIXED — nur HOLDER wird kopiert
|
||||
"windowA": { "trades": 214, "edgePerTradePct": 6.1, "profitFactor": 2.4, "holderRatio": 0.98 },
|
||||
"windowB": { "trades": 180, "edgePerTradePct": 5.4, "profitFactor": 2.1, "holderRatio": 0.99 },
|
||||
"copyability": { "medianMarketVolumeUsd": 120000, "postFillDrift10minPct": 0.4, "netEdgeAfterCopyCostsPct": 2.1 },
|
||||
"categoryMix": { "Sports": 0.7, "Politics": 0.3 },
|
||||
"fingerprintBaseline": { "tradesPerWeek": 38, "medianHoldHours": 22, "priceBands": { "0.90-0.95": 0.6, "0.95-0.99": 0.3 }, "sizeP90Usd": 450 },
|
||||
"riskFlags": ["…"] // z. B. Martingale-Verdacht, Kategorie-Klumpen
|
||||
}
|
||||
```
|
||||
|
||||
## 6. Akzeptanzkriterien des Prüflaufs
|
||||
|
||||
1. Jede Kern-Metrik (M1–M9) ist je Kandidat berechnet oder als „nicht berechenbar"
|
||||
mit Grund markiert.
|
||||
2. Kein Master auf der Empfehlungsliste ohne bestandene Out-of-Sample-Bestätigung
|
||||
und Mindeststichprobe.
|
||||
3. Klassifikation HOLDER/STOPLOSS/MIXED je Kandidat mit den zugrunde liegenden
|
||||
Zahlen (M3/M4) nachvollziehbar.
|
||||
4. Die Empfehlungsliste enthält die Korrelations-/Portfolio-Betrachtung (5.).
|
||||
5. Export im Übergabe-Format (5.) für den PolyTrader-Import.
|
||||
|
||||
## 7. Offene Fragen an Predictalytics (bitte im Ergebnis beantworten)
|
||||
|
||||
1. Welche der Metriken/Validierungen existieren bereits, welche wurden ergänzt?
|
||||
2. Wie viele Wallets überleben die volle Filterkette (Funnel-Zahlen je Stufe)?
|
||||
Wenn < 3: Welche Schwelle ist der Engpass, und wie sähe eine begründete
|
||||
Lockerung aus (statt stillschweigend zu lockern)?
|
||||
3. Wie aktuell sind die Daten (Lag der Datenquelle), und wie oft kann die
|
||||
Auswahl neu gerechnet werden (Ziel: mindestens wöchentlich)?
|
||||
@@ -0,0 +1,122 @@
|
||||
# US Tax Treatment Questionnaire — Polymarket Trading Operations (Florida LLC)
|
||||
|
||||
*Prepared for our US CPA / tax advisor. Purpose: determine the correct federal tax treatment and the
|
||||
exact report formats so our in-house accounting tool computes and exports precisely what you need.*
|
||||
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
We operate automated trading strategies on **Polymarket** — a blockchain-based prediction-market /
|
||||
event-contract platform — through a **Florida LLC**. Positions settle in **USDC** (a USD-pegged
|
||||
stablecoin) on the Polygon network via Polymarket's smart contracts and **Gnosis-Safe proxy wallets**.
|
||||
|
||||
We are building an in-house accounting tool that:
|
||||
|
||||
- Independently pulls **every transaction of every trading account directly from Polymarket** (not from
|
||||
our own trading database) and stores an **immutable, audit-traceable ledger** — each entry backed by a
|
||||
blockchain transaction hash / platform activity ID and a stored raw-data snapshot.
|
||||
- Reconciles each account against its **on-chain USDC balance** as a completeness check.
|
||||
- Produces **per-account and consolidated period statements** (monthly and custom date ranges) and will
|
||||
produce **US federal tax computations** (Form 8949 / Schedule D-style) under assumptions **you specify**.
|
||||
|
||||
**Transaction/event types we capture per account:** buys, sells, redemptions (winning-position payouts at
|
||||
market resolution), losing positions expiring worthless, trading fees, maker rewards / rebates, on-chain
|
||||
USDC deposits and withdrawals.
|
||||
|
||||
Where a treatment is uncertain, we will implement **your chosen approach as a documented, configurable
|
||||
assumption** that is disclosed on every export. Please answer as many items as are relevant.
|
||||
|
||||
---
|
||||
|
||||
## A. Entity, filing & registration
|
||||
1. Federal classification of the LLC: **single-member (disregarded entity)** or **multi-member
|
||||
(partnership, Form 1065 + Schedules K-1)**? Any election to be taxed as **S-corp / C-corp**
|
||||
(Form 2553 / 8832)?
|
||||
2. Which federal forms/schedules will this activity flow into (e.g., Schedule C, Schedule D + Form 8949,
|
||||
Form 1065/K-1, Form 4797)?
|
||||
3. Florida has no personal state income tax — is there anything at the entity level we must reflect, or
|
||||
is this **federal only**? Any Florida annual-report items affecting our accounting?
|
||||
4. EIN and tax year (we assume calendar year)?
|
||||
|
||||
## B. Character & classification of Polymarket P&L
|
||||
5. How should gains/losses from Polymarket **event contracts** be characterized: **capital gains/losses**
|
||||
(Form 8949 / Schedule D), **ordinary income**, **gambling winnings/losses**, **§1256 contracts**
|
||||
(60/40, mark-to-market), or **other**?
|
||||
6. Do you regard these instruments as **securities, commodities, swaps, wagering transactions, or
|
||||
property**? Does the characterization differ by market type (e.g., sports vs. politics vs. crypto-price)?
|
||||
7. If capital: our holding periods are effectively always **under one year** — do you want everything
|
||||
reported as **short-term**, or should we still compute per-lot holding periods (acquisition → disposition)?
|
||||
8. If gambling treatment applies: how should we present winnings vs. losses (losses limited to winnings;
|
||||
per-wager vs. session netting)?
|
||||
|
||||
## C. Trader Tax Status & §475(f) mark-to-market
|
||||
9. Given the volume and automation, could the LLC qualify for **Trader Tax Status (TTS)**? Do you
|
||||
recommend a **§475(f) mark-to-market election** (ordinary gain/loss, no wash-sale, no capital-loss
|
||||
limitation, year-end MTM)?
|
||||
10. If §475(f) MTM applies, what **price source and timing** would you accept to mark **open positions**
|
||||
at period/year end (last trade, mid-price, resolution probability)?
|
||||
11. **Self-employment tax:** does this activity create SE-tax exposure, or is it exempt (trading gains
|
||||
generally not SE income)?
|
||||
|
||||
## D. Cost basis & lot accounting
|
||||
12. Cost-basis method: **FIFO** (our default), **specific identification**, or other? Any documentation
|
||||
requirements for specific-ID?
|
||||
13. Should trading **fees** be **capitalized into basis / netted against proceeds**, or deducted
|
||||
**separately** as expenses?
|
||||
14. **Redemption** (winning shares pay out at resolution): treat as a disposition at **$1.00/share**
|
||||
proceeds against lot basis? **Losing shares** expiring worthless: treat as a disposition at **$0**
|
||||
(realized loss) on the resolution date?
|
||||
15. Partial fills within one transaction: acceptable to **aggregate same-tx fills into one lot**?
|
||||
|
||||
## E. USDC / stablecoin treatment
|
||||
16. May we treat **USDC as a USD cash-equivalent (1:1)**, so acquiring/spending USDC is **not** itself a
|
||||
separate taxable crypto disposition? Or must USDC be tracked as **property** with its own basis?
|
||||
17. If USDC must be tracked as property, what **USD valuation source/timing** per transaction do you require?
|
||||
|
||||
## F. Wash-sale & related rules
|
||||
18. Do **wash-sale rules (§1091)** apply to these instruments (they are not traditional "stock or
|
||||
securities," and crypto is currently generally exempt)? If potentially applicable, should the tool
|
||||
**flag/adjust** wash sales?
|
||||
19. Are **straddle (§1092)** or **constructive-sale** rules relevant to any hedged/paired positions?
|
||||
|
||||
## G. Income items & deductions
|
||||
20. **Maker rewards / liquidity rebates** received in USDC: **ordinary income at fair value on receipt**?
|
||||
Where reported? Does receipt create a **new USDC lot** at that value?
|
||||
21. Deductible business **expenses** (platform/trading fees, Polygon gas/POL, infrastructure, software,
|
||||
this tooling): where and how (Schedule C vs. netted)?
|
||||
22. Will Polymarket issue any **1099** (likely not, as a non-US operator)? If so, how should we reconcile to it?
|
||||
|
||||
## H. Foreign account / information reporting
|
||||
23. Is a Polymarket account (funds in a Polygon **Gnosis-Safe proxy** on a non-US platform) a **"foreign
|
||||
financial account"** triggering **FBAR (FinCEN Form 114)** above the $10,000 aggregate threshold?
|
||||
24. Does **FATCA / Form 8938** reporting apply (specified foreign financial assets)?
|
||||
25. Is **Form 8886** (reportable transactions) or any other information return relevant?
|
||||
26. Any concerns arising from Polymarket's **US regulatory status** that affect characterization or reporting?
|
||||
|
||||
## I. Currency & valuation
|
||||
27. Reporting/functional currency: **USD** confirmed? We also generate **EUR** figures — needed for the US
|
||||
filing, or purely internal/EU personal use?
|
||||
28. FX source/timing: for non-USD figures, is the **ECB daily reference rate at transaction date**
|
||||
acceptable? For **USDC→USD**, is **1:1** acceptable or do you require actual spot?
|
||||
|
||||
## J. Report format & delivery (so we tailor exports to you)
|
||||
29. Preferred deliverables: **Form 8949 CSV in the exact IRS column layout**, a **general-ledger** export,
|
||||
a **Schedule D summary**, and/or a **PDF statement**? Which formats do you want?
|
||||
30. Level: **per-account** statements, a **consolidated LLC** view, or both?
|
||||
31. Cadence: **monthly** bookkeeping packages plus an **annual** tax package? Do you need **quarterly
|
||||
estimated-tax** figures?
|
||||
32. Exact **columns/fields** on the disposition report (e.g., Description of property, Date acquired, Date
|
||||
sold, Proceeds, Cost basis, Wash-sale adjustment, Gain/loss, Short/Long)?
|
||||
33. **Audit-defensibility** documentation you want attached (methodology page, source transaction hashes,
|
||||
raw-data retention, reconciliation to on-chain balances)?
|
||||
34. Rounding/precision conventions (whole USD vs. cents)?
|
||||
|
||||
## K. Anything else
|
||||
35. Any other **elections, forms, thresholds, or record-keeping standards** we should build into the tool
|
||||
now to make your work smooth and the LLC's filings defensible?
|
||||
|
||||
---
|
||||
|
||||
*We will encode your answers as the tool's default assumptions, each disclosed on every statement and
|
||||
adjustable in settings. Thank you.*
|
||||
@@ -0,0 +1,126 @@
|
||||
# Umsetzungsplan: AI-Bewertung der Auflösequalität (C-S4)
|
||||
|
||||
> Stand: 2026-07-11
|
||||
> Ziel: Ein LLM (via OpenRouter) bewertet je Markt das RESOLUTION-Risiko (subjektive
|
||||
> Auflösequellen, Regeltext-Fallen, UMA-Dispute-Muster). Die Bewertung wird beim
|
||||
> Markt-Import in der DB gespeichert und dient als Entry-Gate — zuerst im
|
||||
> ResolutionFarming, perspektivisch auch im Copytrading.
|
||||
> Einordnung: Core-Baustein (beide Module profitieren), kein eigenes Strategiemodul.
|
||||
|
||||
---
|
||||
|
||||
## 1. Abgrenzung (wichtig für die Umsetzung)
|
||||
|
||||
Das LLM prognostiziert NICHT den Markt-Ausgang. Es beantwortet ausschließlich:
|
||||
**„Wie sauber/objektiv wird dieser Markt aufgelöst werden?"** — Input ist der
|
||||
Regeltext, nicht das Weltgeschehen. Das hält die Aufgabe eng, billig und testbar.
|
||||
|
||||
## 2. Architektur
|
||||
|
||||
### 2.1 Core-Service `IMarketRiskRater` (PolyTrader.Core)
|
||||
|
||||
```csharp
|
||||
public interface IMarketRiskRater
|
||||
{
|
||||
/// Liefert die (ggf. gecachte) Bewertung; null wenn (noch) keine vorliegt.
|
||||
Task<MarketRiskRating?> GetOrRateAsync(MarketData market, CancellationToken ct);
|
||||
}
|
||||
|
||||
public class MarketRiskRating // Tabelle core_market_risk_ratings
|
||||
{
|
||||
public string ConditionId { get; set; } // PK — Regeltexte ändern sich nicht → dauerhaft cachebar
|
||||
public int Score { get; set; } // 0–100 (100 = völlig objektiv auflösbar)
|
||||
public string Flags { get; set; } // CSV: SUBJECTIVE_SOURCE, DEADLINE_AMBIGUITY,
|
||||
// MENTIONS_TYPE, DISPUTE_PATTERN, MISSING_RULES
|
||||
public string Reason { get; set; } // Einzeiler-Begründung des Modells
|
||||
public string Model { get; set; } // verwendetes Modell (Nachvollziehbarkeit)
|
||||
public DateTime RatedAt { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 `OpenRouterClient` (Core, dünn)
|
||||
|
||||
- HTTP-Client gegen https://openrouter.ai/api/v1/chat/completions, API-Key aus
|
||||
appsettings (`OpenRouter:ApiKey`, gitignoriert wie andere Secrets).
|
||||
- **Modellwahl:** günstiges Modell reicht (Haiku-Klasse, z. B.
|
||||
`anthropic/claude-haiku-4.5` via OpenRouter; Modell-ID als Setting, nicht
|
||||
hartkodieren). Kosten je Markt: Bruchteile eines Cents; mit Cache je ConditionId
|
||||
einmalig pro Markt.
|
||||
- **Structured Output:** Antwort als JSON erzwingen (Schema im Prompt + JSON-Mode);
|
||||
bei Parse-Fehler 1 Retry, danach „kein Rating" (fail-closed, siehe 3.3).
|
||||
- Timeout kurz (~15 s), Fehler loggen, NIE den aufrufenden Scanner blockieren.
|
||||
|
||||
### 2.3 Prompt (Kern, bei Umsetzung feinjustieren)
|
||||
|
||||
Input je Markt: `Question`, `Description`/Resolution-Kriterien (Gamma-API liefert
|
||||
den Regeltext am Markt-Objekt — Feld bei Umsetzung verifizieren), Kategorie, EndDate.
|
||||
|
||||
Bewertungsauftrag an das Modell (sinngemäß):
|
||||
1. Gibt es eine EINDEUTIGE, öffentlich prüfbare Auflösequelle (offizielles
|
||||
Endergebnis, behördliche Zahl, On-Chain-Fakt)?
|
||||
2. Sind Randfälle geregelt (Verschiebung, Abbruch, Unentschieden, Definitionsfragen
|
||||
wie „offiziell angekündigt")?
|
||||
3. Ähnelt der Markt bekannten Streit-Mustern (Mentions-/„sagt X"-Märkte, vage
|
||||
Deadlines, Definitions-Ambiguität, mehrdeutige Quellen)?
|
||||
Output: `{ "score": 0-100, "flags": [...], "reason": "…" }`.
|
||||
|
||||
## 3. Integration
|
||||
|
||||
### 3.1 Wann wird bewertet?
|
||||
|
||||
Beim Markt-Import bzw. beim ersten Kontakt: Der **RF-Scanner** ruft
|
||||
`GetOrRateAsync` für jeden Kandidaten auf, der alle billigen Filter passiert hat
|
||||
(NACH Preisband/Kategorie/Fenster, VOR dem Accept — kein LLM-Call für offensichtliche
|
||||
Rejects). Cache macht Wiederholungs-Scans kostenlos.
|
||||
|
||||
### 3.2 Entry-Gate im ResolutionFarming
|
||||
|
||||
Neue `RfSettings`:
|
||||
- `MinResolutionScore` (Default 70): Kandidaten mit Score darunter → Reject mit
|
||||
Grund `"AI-Resolution-Score {score} < {min}: {reason}"` (landet wie alle Rejects
|
||||
in rf_candidates → die Kalibrierung kann später prüfen, ob das Gate Geld spart!).
|
||||
- `RequireRating` (Default true): fail-closed-Schalter (siehe 3.3).
|
||||
|
||||
### 3.3 Fail-Closed-Regeln (Sicherheitskern)
|
||||
|
||||
1. Kein Rating verfügbar (API down, Parse-Fehler, kein Regeltext) → Kandidat gilt
|
||||
als riskant und wird abgelehnt — AUSSER die Kategorie steht auf einer
|
||||
Objektiv-Whitelist (Default: Sports-Endergebnisse), dann Durchlass mit Log.
|
||||
2. Das Rating **ersetzt die harte Blacklist nicht**: bekannte Giftmuster
|
||||
(Mentions-Märkte etc.) bleiben in `BlacklistCsv` hart geblockt. Das LLM ist die
|
||||
zweite Verteidigungslinie für den Long Tail, nicht die erste.
|
||||
3. **Post-Mortem-Pflicht:** Jeder real erlebte Dispute → Muster in Blacklist/Prompt
|
||||
aufnehmen. Dafür Flag-Feld in rf_closed_trades (`ResolutionDisputed`) vorsehen.
|
||||
|
||||
### 3.4 Copytrading (zweiter Schritt, optional)
|
||||
|
||||
Gleicher Service: Vor einem BUY den Score prüfen; unter Schwelle → Trade
|
||||
verwerfen mit TradeReasoning-Log. Als Per-Account-Setting (`MinResolutionScore`,
|
||||
0 = aus), Default zunächst AUS, um das Copy-Verhalten nicht zu verändern, bis der
|
||||
Rater validiert ist.
|
||||
|
||||
## 4. Validierung VOR dem Scharfschalten (Pflicht-Phase)
|
||||
|
||||
1. **Retrospektiv-Test:** ~15–20 öffentlich bekannte, umstrittene UMA-Resolutions
|
||||
(Recherche-Aufgabe: bekannte Dispute-Fälle) + ~30 unstrittig aufgelöste
|
||||
Vergleichsmärkte durch den Rater schicken. Messen: erwischt er die Streitfälle
|
||||
(niedriger Score), ohne die sauberen zu blockieren?
|
||||
2. **Akzeptanz:** ≥ 80 % der Streitfälle unter der Schwelle, ≤ 10 % der sauberen
|
||||
fälschlich blockiert. Sonst Prompt/Schwelle iterieren.
|
||||
3. Ergebnisse als Testdaten einfrieren (Golden-File-Test, läuft ohne API gegen
|
||||
gespeicherte Antworten — kein LLM-Call in der CI).
|
||||
|
||||
## 5. Phasen
|
||||
|
||||
| Phase | Inhalt | Akzeptanz |
|
||||
|---|---|---|
|
||||
| AR-1 | OpenRouterClient + IMarketRiskRater + Tabelle/Migration + Unit-Tests (Parsing, Fail-Closed) | Build grün; Rater liefert für einen Beispiel-Regeltext strukturiertes Rating |
|
||||
| AR-2 | Retrospektiv-Validierung (4.) | Akzeptanzquoten erreicht, dokumentiert |
|
||||
| AR-3 | RF-Integration (3.1/3.2/3.3) + UI-Spalte (Score in Kandidaten-Tab) | Rejects mit AI-Grund sichtbar; Kalibrierung kann Gate-Wirkung auswerten |
|
||||
| AR-4 | Copytrading-Integration (3.4), Default aus | Setting vorhanden, dokumentiert |
|
||||
|
||||
## 6. Leitplanken
|
||||
|
||||
- API-Key nie committen; Kosten-Deckel (max. Ratings/Tag als Setting, Default 500).
|
||||
- Der Rater beeinflusst NIE Exits, nur Entries (keine Panik-Verkäufe durch LLM).
|
||||
- Score/Reason immer mitloggen — Entscheidungen müssen im Log nachvollziehbar sein.
|
||||
@@ -0,0 +1,117 @@
|
||||
# Umsetzungsplan: On-Chain-Auto-Redeem (modulweise schaltbar)
|
||||
|
||||
> Stand: 2026-07-11
|
||||
> Ziel: Gewonnene Positionen automatisch on-chain einlösen (Shares → USDC), als
|
||||
> **Core-Baustein** mit **Aktivierung je Modul**. Richards Anforderung: In Testphasen
|
||||
> neuer Module soll Auto-Redeem gezielt AUS bleiben können, um die Performance der
|
||||
> Entwicklung manuell nachvollziehen zu können — ohne dass andere, etablierte Module
|
||||
> ihren Automatismus verlieren.
|
||||
> ⚠️ Höchste clob.md-Kritikalität: On-Chain-Signing mit echten Private Keys.
|
||||
> Jede Phase: Backup/Commit vorher, Testmarkt/Kleinstbetrag zuerst.
|
||||
|
||||
---
|
||||
|
||||
## 1. Architektur: Queue statt Direktaufruf
|
||||
|
||||
Module redeemen nie selbst. Sie melden einlösbare Positionen in eine zentrale
|
||||
Queue; ein Core-Worker arbeitet sie ab — nur für Module, deren Auto-Redeem aktiv ist.
|
||||
|
||||
```
|
||||
Modul (RF-Monitor, CT-Sync, später DD) PolyTrader.Core
|
||||
│ erkennt „Position gewonnen & aufgelöst" │
|
||||
├── IRedeemQueue.Enqueue(RedeemRequest) ─────────────▶│ Tabelle core_redeem_queue
|
||||
│ (immer! unabhängig vom Schalter) │
|
||||
│ ▼
|
||||
│ OnChainRedeemWorker (BackgroundService)
|
||||
│ • nur Requests von Modulen mit AutoRedeemEnabled
|
||||
│ • Rest bleibt als "Manual" sichtbar (UI-Liste)
|
||||
▼ • CTF redeemPositions / NegRiskAdapter
|
||||
UI je Modul: Pending-Redeems-Ansicht • Verifikation über USDC-Balance-Delta
|
||||
```
|
||||
|
||||
**Warum immer enqueuen:** Auch bei deaktiviertem Auto-Redeem entsteht so eine
|
||||
vollständige, je Modul gefilterte „zum Redeem bereit"-Liste (Dashboard/UI) — genau
|
||||
die Übersicht, die Richard in Testphasen für die manuelle Betreuung will. Der
|
||||
Schalter entscheidet nur, ob der Worker sie abarbeitet.
|
||||
|
||||
### 1.1 Datenmodell (`core_redeem_queue`)
|
||||
|
||||
| Feld | Inhalt |
|
||||
|---|---|
|
||||
| Id (auto) | PK |
|
||||
| ModuleName | "ResolutionFarming" / "CopyTrading" / … |
|
||||
| AccountId, TokenId, ConditionId | Ziel der Einlösung (ConditionId zwingend — für den Contract-Call) |
|
||||
| IsNegRisk | Adapter-Wahl |
|
||||
| SizeShares, ExpectedUsd | erwartete Auszahlung (Shares × 1.00) |
|
||||
| Status | Pending / Processing / Done / Failed / Manual |
|
||||
| Attempts, LastError, EnqueuedAt, CompletedAt, TxHash | Betrieb/Nachvollziehbarkeit |
|
||||
|
||||
### 1.2 Schalter
|
||||
|
||||
- **Je Modul:** `core_module_settings` (oder appsettings-Sektion) —
|
||||
`AutoRedeem:ResolutionFarming = false`, `AutoRedeem:CopyTrading = false`
|
||||
(Default IMMER aus; bewusstes Einschalten je Modul).
|
||||
- **Global-Not-Aus:** `AutoRedeemGlobalEnabled` (analog GlobalTradingPaused,
|
||||
Quickbar-Toggle) — schlägt alle Modul-Schalter.
|
||||
- UI: Schalter je Modul in dessen Settings-Tab + Anzeige im Core-Dashboard,
|
||||
welche Module aktiv sind.
|
||||
|
||||
## 2. Der On-Chain-Teil (`OnChainCtfService`, Core)
|
||||
|
||||
1. **Bibliothek:** Nethereum (bereits als Abhängigkeit im Projekt für EIP-712-Signing
|
||||
vorhanden) — Contract-Calls über die bestehende Alchemy-RPC-Anbindung (Polygon).
|
||||
2. **Aufrufe:** Standard-Markt: ConditionalTokens `redeemPositions(collateral,
|
||||
parentCollectionId=0x0, conditionId, indexSets)`; NegRisk-Markt: über den
|
||||
NegRisk-Adapter. **Contract-Adressen + ABI + indexSets-Ermittlung bei Umsetzung
|
||||
zwingend aus https://docs.polymarket.com (Developer/CTF) verifizieren — nicht aus
|
||||
dem Gedächtnis kodieren.** Die USDC-/CTF-Adressen als Konstanten mit Quellenangabe.
|
||||
3. **Gas:** Wallet braucht POL. Vor jedem Call Balance-Check; unter Schwelle
|
||||
(Setting, z. B. 0.5 POL) → Request auf `Manual` + Threema-Warnung „POL nachfüllen".
|
||||
Gas-Preis: Standard-Estimation, Cap als Setting.
|
||||
4. **Verifikation = Wahrheit:** Ein Redeem gilt erst als `Done`, wenn (a) die Tx
|
||||
bestätigt ist UND (b) das USDC-Balance-Delta ≈ ExpectedUsd (Toleranz) gemessen
|
||||
wurde. Sonst `Failed` mit Fehlertext.
|
||||
5. **Retry:** max. 3 Versuche mit Backoff (1/10/60 min), danach `Manual` + Threema.
|
||||
Idempotenz beachten: vor jedem Versuch prüfen, ob die Position on-chain überhaupt
|
||||
noch einlösbar ist (bereits redeemte Shares → als Done werten, nicht als Fehler).
|
||||
|
||||
## 3. Modul-Integration
|
||||
|
||||
### 3.1 ResolutionFarming (erster Nutzer)
|
||||
`FarmingResolutionMonitorService` setzt heute `RedeemStatus = "Pending"` am
|
||||
RfClosedTrade. Ergänzung: beim Schließen eines Gewinners → `IRedeemQueue.Enqueue`.
|
||||
Worker-Callback (oder Status-Poll) aktualisiert `RedeemStatus` (Pending → Redeemed/
|
||||
Manual/Failed) → sichtbar im Historie-Tab. **Wichtig für Richards Testphasen-
|
||||
Anforderung:** Der realisierte PnL ist bereits bei Resolution gebucht; der Redeem
|
||||
ändert nur die Kapitalverfügbarkeit. Die Performance-Auswertung bleibt also mit und
|
||||
ohne Auto-Redeem identisch — nur die Bankroll-Rotation unterscheidet sich.
|
||||
|
||||
### 3.2 CopyTrading (zweiter Nutzer)
|
||||
Im `TraderMonitorService` existiert die Stelle bereits: der auskommentierte
|
||||
Python-Redeem-Block im Resolution-Fallback („bereit für manuellen Redeem")
|
||||
— dort `Enqueue` statt Kommentar. Gleicher PnL-Hinweis wie oben.
|
||||
|
||||
### 3.3 Künftige Module
|
||||
Contract: Ein Modul, das Positionen bis Resolution hält, ruft bei „gewonnen &
|
||||
aufgelöst" genau einmal `Enqueue` und liest optional den Status zurück. Mehr nicht.
|
||||
|
||||
## 4. Phasen & Akzeptanzkriterien
|
||||
|
||||
| Phase | Inhalt | Akzeptanz |
|
||||
|---|---|---|
|
||||
| RD-1 | Queue-Tabelle + IRedeemQueue + Modul-Schalter + UI-Pending-Liste (noch KEIN On-Chain-Code) | Module enqueuen; Liste zeigt je Modul „bereit zum Redeem"; Schalter sichtbar; 100 % ohne Live-API testbar |
|
||||
| RD-2 | `OnChainCtfService` gegen Polygon: zuerst READ-only (Balance, Einlösbarkeits-Check) | Balance-/Zustandsabfragen stimmen gegen Polygonscan |
|
||||
| RD-3 | Erster echter Redeem: EIN Testmarkt, Kleinstbetrag, manuell getriggert (Button an der Pending-Liste) | Tx bestätigt, USDC-Delta verifiziert, Status Done |
|
||||
| RD-4 | Worker-Automatik scharf für RF (Schalter an), CT folgt nach Beobachtung | 1 Woche fehlerfreier Betrieb, Failed-Quote < 5 %, POL-Warnung getestet |
|
||||
|
||||
## 5. Leitplanken
|
||||
|
||||
1. `.agents/rules/clob.md` gilt verschärft: Private-Key-Nutzung außerhalb des
|
||||
erprobten Order-Signing-Pfads. Jede Phase einzeln committen; RD-3 nie
|
||||
überspringen.
|
||||
2. Der Worker fasst NUR Queue-Einträge an — er scannt nie selbst Positionen
|
||||
(klare Verantwortung: Module erkennen, Core löst ein).
|
||||
3. Alle Beträge/TxHashes loggen; Threema-Tageszusammenfassung „X Redeems, Y USDC
|
||||
freigesetzt, Z manuell offen".
|
||||
4. Manuelle Redeems (über die Website) müssen erkannt werden: Einlösbarkeits-Check
|
||||
in 2.5 markiert extern eingelöste Einträge als Done statt Failed.
|
||||
@@ -0,0 +1,314 @@
|
||||
# Umsetzungsplan: Copytrading-Modul — Rentabilitäts-Verbesserungen
|
||||
|
||||
> Stand: 2026-07-06
|
||||
> Ziel: Bekannte Verlustquellen im Copytrading-Modul beseitigen und die
|
||||
> Rentabilität durch datengetriebene Trader-Auswahl, echte Fill-Daten und
|
||||
> besseres SELL-Handling steigern.
|
||||
> Reihenfolge: **Dieser Plan zuerst.** Phase 1 (Marktdaten-Fundament) ist
|
||||
> Voraussetzung für die Strategiemodule MarketMaking und BundleArbitrage.
|
||||
|
||||
---
|
||||
|
||||
## 0. Kontext & Hintergrund (für die Umsetzung ohne Vorwissen)
|
||||
|
||||
Das Copytrading-Modul (`src/PolyTrader.Modules.CopyTrading/`) kopiert Trades von
|
||||
Master-Tradern auf Polymarket. Signalkette:
|
||||
|
||||
1. `AlchemyWebsocketService` erkennt On-Chain-Events der Master-Wallets (WSS).
|
||||
2. `TraderMonitorService.TriggerFastBlockchainPoll()` parst die Transaktion direkt
|
||||
(Fast Track, ~3–4 s hinter dem Master) oder fällt auf Data-API-Polling zurück.
|
||||
3. Signale (`CopySignal`) laufen über einen Channel in die `CopyTradingEngine`.
|
||||
4. Die Engine prüft Risiko-Limits (`CopyTradingAccountSettings`: PerMarketLimit,
|
||||
PerMasterLimit, Zeitfenster-Limits, MaxBuyPrice) und platziert CLOB-Orders
|
||||
über `PolymarketClobClient` (Core).
|
||||
|
||||
**Historischer Kontext (wichtig!):** Eine Verlustanalyse im April 2026
|
||||
(`agentspace/prompts/AnalyzingOvernightTradingLosses.md`) hat als Hauptursache
|
||||
für Overnight-Verluste identifiziert, dass der Bot SELLs der Master mit
|
||||
Market-Orders ins leergeräumte Orderbuch kopiert und so zur „Exit-Liquidity"
|
||||
wird (Beispiel: Entry 0.51, Master-Exit 0.99, unser Exit 0.49). Der damalige
|
||||
Fix (GTD-Limit-Sells) ist **im aktuellen Modul-Code nicht mehr vorhanden** —
|
||||
vermutlich bei der Modularisierung verloren gegangen.
|
||||
|
||||
**Seit März 2026 erhebt Polymarket Taker-Fees** (Sports ~0,75 %, Politik/Finanzen
|
||||
~1,0 %, Krypto ~1,8 %, am 50-¢-Preis am höchsten, Richtung 1 ¢/99 ¢ abnehmend;
|
||||
Maker zahlen nichts und erhalten Rebates). Der Bot ist heute fast immer Taker.
|
||||
Quelle: https://docs.polymarket.com/trading/fees — **bei Umsetzung aktuellen
|
||||
Stand verifizieren.**
|
||||
|
||||
### Leitplanken (gelten für alle Phasen)
|
||||
|
||||
1. `.agents/rules/clob.md` beachten: Änderungen an der CLOB-Integration sind
|
||||
hochkritisch. Vor jeder Änderung Backup/Commit der alten Version, jede
|
||||
Änderung mehrfach prüfen.
|
||||
2. Jede Phase lässt die App baubar und lauffähig zurück (Debug-Build grün).
|
||||
3. Entscheidungslogik als testbare, pure Funktionen extrahieren und in
|
||||
`PolyTrader.Tests` (xUnit, existiert bereits) abdecken.
|
||||
4. Kein Livegang einer Phase ohne mehrtägige Beobachtung auf dem Server.
|
||||
|
||||
---
|
||||
|
||||
## Phase 0 — Sofortmaßnahmen: Blutung stoppen
|
||||
|
||||
### 0.1 🔴 SELL-Exit-Liquidity-Regression beheben (höchste Priorität)
|
||||
|
||||
**Befund:** In `CopyTradingEngine.cs` (Live-SELL-Pfad, aktuell ~Zeile 694–735)
|
||||
werden SELLs als `"MARKET"` mit Fallback-Limit `0.01m` gesendet:
|
||||
|
||||
```csharp
|
||||
decimal sellLimit = 0.01m; // Market Order Fallback Limit
|
||||
...
|
||||
var result = await _clob.PlaceOrderAsync(account, signal.TokenId, signal.Side,
|
||||
expectedUsdc, sellLimit, "MARKET", _state.DebugOrderPayloadLog, isNegRisk);
|
||||
```
|
||||
|
||||
Das ist exakt das Verhalten, das die April-Verluste verursacht hat.
|
||||
|
||||
**Ziel-Design: Eskalationsleiter statt Market-Order**
|
||||
|
||||
1. Referenzpreis = `signal.Price` (Exit-Preis des Masters).
|
||||
2. Erste Order: GTD-Limit.
|
||||
- HF-Trader (`trader.Category == "HF"`): `signal.Price - 0.005m`.
|
||||
- Sonst: `signal.Price * (1 - settings.MaxPriceDifference / 100m)`.
|
||||
3. Neuer Setting-Wert `SellFloorPct` in `CopyTradingAccountSettings`
|
||||
(Default z. B. 15 %): absolute Untergrenze = `signal.Price * (1 - SellFloorPct/100)`.
|
||||
4. Hintergrund-Loop (Erweiterung von `CleanupStaleOpenOrdersAsync` in
|
||||
`TraderMonitorService` oder eigener Loop): Order nach T Sekunden ohne Fill
|
||||
(HF: ~20 s, sonst: ~120 s) canceln und eine Stufe tiefer neu platzieren
|
||||
(Schrittweite z. B. 2 ¢ oder 3 % relativ), bis zum Floor.
|
||||
5. Floor erreicht und kein Fill → Position halten, **Threema-Benachrichtigung**
|
||||
senden (`ThreemaService` im Core existiert) und Position als „ExitPending"
|
||||
markieren.
|
||||
6. Position darf **nicht mehr optimistisch** aus `account.OpenPositions`
|
||||
entfernt werden. Stattdessen Flag `ExitPending` (neues Property auf
|
||||
`Position` oder Tracking-Dictionary im `CopyTradingState`), damit Limits
|
||||
weiterhin korrekt rechnen und kein Doppel-SELL entsteht. Entfernen erst,
|
||||
wenn der Fill über Sync/User-Channel (Phase 1) bestätigt ist.
|
||||
|
||||
**Preis-/Stufenlogik als pure statische Funktion** implementieren (z. B.
|
||||
`SellLadder.NextPrice(referencePrice, step, floor, attempt)`) und mit
|
||||
Unit-Tests abdecken.
|
||||
|
||||
**Akzeptanzkriterien:**
|
||||
- Kein Code-Pfad sendet mehr `"MARKET"`-SELLs mit 0.01-Limit.
|
||||
- Unit-Tests für Ladder-Preise (HF/normal, Floor-Clamping, 0.01/0.99-Grenzen).
|
||||
- Log zeigt pro SELL: Referenzpreis, gewähltes Limit, Stufe.
|
||||
|
||||
### 0.2 Fee-Modell einführen
|
||||
|
||||
1. Fee-Rate je Markt beschaffen: Die CLOB-/Gamma-API liefert Fee-Informationen
|
||||
am Markt-Objekt (Feldname bei Umsetzung anhand
|
||||
https://docs.polymarket.com/trading/fees verifizieren, z. B. `fee_rate_bps`).
|
||||
Fallback: statische Kategorie-Tabelle (Sports 0.75 %, Politics/Finance 1.0 %,
|
||||
Crypto 1.8 %, Geopolitics 0 %).
|
||||
2. `MarketData` (Core) um `TakerFeeBps` erweitern (EF-Migration Core),
|
||||
Befüllung über `MarketSyncService` bzw. beim Markt-Fetch.
|
||||
3. Risk-Check in `CopyTradingEngine`: erwartete Fee vom verfügbaren Edge
|
||||
abziehen; Mikro-Trades, deren Fee den erwartbaren Gewinn frisst, verwerfen
|
||||
(Logging mit Begründung wie bei den bestehenden Checks).
|
||||
4. PnL-Berechnung (Demo **und** Live-Anzeige) um Fees korrigieren.
|
||||
|
||||
**Akzeptanz:** Fee erscheint im TradeReasoning-Log jedes BUY; Demo-PnL weist
|
||||
Fees aus.
|
||||
|
||||
### 0.3 `ProfitTarget` implementieren oder entfernen
|
||||
|
||||
`CopyTradingAccountSettings.ProfitTarget` (Default 50.0) existiert in Settings,
|
||||
DB und UI, wird aber **nirgends ausgewertet** (toter Knopf).
|
||||
|
||||
**Empfehlung: implementieren** als optionaler Take-Profit:
|
||||
- Semantik: `0` = deaktiviert; sonst Prozent-Gewinnschwelle.
|
||||
- Prüfung im 30-s-Live-Sync (`PollLiveAccountsAsync`): wenn
|
||||
`CurrentPrice >= EntryPrice * (1 + ProfitTarget/100)` → Verkauf über die
|
||||
Eskalationsleiter aus 0.1 (Startlimit = CurrentPrice), ExitReason
|
||||
`"Profit Target"`.
|
||||
- Zusammenspiel mit `PreRedeemLimit` beachten (beide können feuern —
|
||||
PreRedeem hat Vorrang, da näher an 1.00).
|
||||
|
||||
### 0.4 Kleinere Konsistenz-Fixes
|
||||
|
||||
1. **20-Sekunden-Spam-Blockade** (`PendingOrderTimestamps`-Check am Anfang des
|
||||
SELL-Pfads): blockiert aktuell auch legitime SELLs, wenn der Master < 20 s
|
||||
nach dem Kauf aussteigt. Fix: Blockade nur für gleichgerichtete Orders
|
||||
(BUY nach BUY), SELL nach BUY zulassen.
|
||||
2. **`_state.GlobalPnl`**: wird in `PollLiveAccountsAsync`-Close-Pfaden addiert,
|
||||
in `PollClosedAccountsAsync` nicht → Anzeige driftet. Vereinheitlichen.
|
||||
3. **Demo-`ClosedTrade` ohne `TokenId`**: Im Demo-SELL-Pfad wird `TokenId` nicht
|
||||
gesetzt (Preload von `_processedClosures` filtert auf `TokenId`). Setzen.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1 — Marktdaten-Fundament (Core-Infrastruktur)
|
||||
|
||||
> Diese Phase gehört in **PolyTrader.Core** (`src/PolyTrader.Core/Streaming/`),
|
||||
> nicht ins Modul — MarketMaking- und BundleArbitrage-Modul (separate Pläne)
|
||||
> setzen sie voraus.
|
||||
|
||||
### 1.1 CLOB User-Channel (echte Fills in Echtzeit)
|
||||
|
||||
Polymarket bietet einen authentifizierten WSS-User-Channel, der Order-Events
|
||||
(Platzierung, Teil-/Voll-Fill, Cancel) der eigenen Accounts pusht.
|
||||
Endpoint/Protokoll bei Umsetzung verifizieren:
|
||||
https://docs.polymarket.com (CLOB WSS, `user` channel; Auth via API-Key/
|
||||
Secret/Passphrase — liegen je Account in `AccountState`).
|
||||
|
||||
Neuer Core-Service `ClobUserChannelService : BackgroundService`:
|
||||
- Verbindet pro Live-Account, Auto-Reconnect mit Backoff (Muster von
|
||||
`AlchemyWssClient` übernehmen).
|
||||
- Publiziert Fill-Events intern (Event oder Channel), z. B.
|
||||
`record OrderFillEvent(int AccountId, string TokenId, string OrderId, string Side, decimal Price, decimal Size, DateTime Ts)`.
|
||||
|
||||
Konsumenten im Copytrading-Modul:
|
||||
- `Position.EntryPrice`/`Size` mit **echten Fill-Daten** aktualisieren
|
||||
(heute: Limit-Preis als EntryPrice, Korrektur erst im 30-s-REST-Sync).
|
||||
- SELL-Eskalationsleiter (Phase 0.1): Fill-Bestätigung beendet die Leiter.
|
||||
- Neue Tabelle `ct_fill_log` (EF-Migration im Modul): SignalPrice, OrderPrice,
|
||||
FillPrice, Latenz (Signal→Fill in ms), TraderId, AccountId, TokenId, Side.
|
||||
→ Grundlage für Slippage-Statistik in Phase 3.
|
||||
|
||||
### 1.2 CLOB Market-Channel (Orderbücher live)
|
||||
|
||||
Neuer Core-Service `ClobMarketDataService`:
|
||||
- Abonniert den öffentlichen `market`-Channel für eine dynamische Token-Liste
|
||||
(Subscribe/Unsubscribe zur Laufzeit).
|
||||
- Hält `OrderBookCache` (Best-Bid/Ask, Tiefe der obersten N Level, Timestamp).
|
||||
- Interface für Konsumenten: `IOrderBookProvider.TryGetBook(tokenId, maxAgeMs)`.
|
||||
- REST-Fallback `GET /book` über `PolymarketClobClient`, wenn kein Stream aktiv.
|
||||
|
||||
**Hinweis:** Im Modul existiert bereits ein `PolymarketWssClient` (Auto-Redeem).
|
||||
Nicht verschieben/umbauen (Regression-Risiko), sondern den neuen Core-Service
|
||||
parallel aufbauen; spätere Konsolidierung als separater Schritt.
|
||||
|
||||
### 1.3 Pre-Trade-Orderbuch-Check in der Engine
|
||||
|
||||
Vor jedem Live-BUY in `CopyTradingEngine.ProcessAccountOrderAsync`:
|
||||
1. Buch holen (`IOrderBookProvider`, Fallback REST, Timeout ~150 ms —
|
||||
bei Timeout Verhalten wie heute, nicht blockieren).
|
||||
2. Checks (neue Settings in `CopyTradingAccountSettings`):
|
||||
- `MaxSpreadPct` (Default z. B. 5 %): Spread größer → Skip mit Log.
|
||||
- Tiefen-Check: liegt an unserem Limit-Preis genug Ask-Size für
|
||||
`exactShares`? Wenn nein → Skip („Sniping-Verdacht: Liquidität bereits
|
||||
konsumiert") statt teuer ins dünne Buch zu laufen.
|
||||
|
||||
**Akzeptanz Phase 1:** Fill-Log füllt sich mit echten Fills; TradeReasoning
|
||||
zeigt Spread/Tiefe-Entscheidungen; kein messbarer Latenz-Nachteil im Hot-Path
|
||||
(> 200 ms Zusatz wäre Regression).
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 — SELL-Verfeinerung: Proportionalität
|
||||
|
||||
Heute (Proportionalitätsfilter in `CopyTradingEngine`, SELL-Pre-Flight):
|
||||
verkauft der Master < 30 % seines Bestands → ignorieren; ≥ 30 % → **wir
|
||||
verkaufen alles**. Information über gestaffelte Exits geht verloren.
|
||||
|
||||
**Ziel:** Verkaufsquote spiegeln.
|
||||
1. Beim Öffnen einer Position den Master-Bestand zum Einstiegszeitpunkt
|
||||
festhalten (`MasterSharesAtEntry`, im `CopyTradingState.MasterTraderPositions`
|
||||
bzw. auf der Position persistieren).
|
||||
2. Bei SELL-Signal: `sellRatio = signal.Size / masterSharesVorVerkauf` (wie
|
||||
heute berechnet). Statt Voll-Exit: `sharesToSell = ourShares * sellRatio`.
|
||||
3. Untergrenzen beachten: bleibt danach < Polymarket-Minimum (5–6 Shares) übrig
|
||||
→ Voll-Exit statt Rest-Dust.
|
||||
4. Kleiner Teilverkauf (< 10 %) weiterhin ignorieren (Rauschen von Day-Tradern),
|
||||
Schwelle konfigurierbar (`MinSellRatioPct`).
|
||||
5. Verkauf läuft immer über die Eskalationsleiter aus Phase 0.1.
|
||||
|
||||
Akzeptanz: Unit-Tests für die Ratio-Logik inkl. Dust-Grenzen; Logs zeigen
|
||||
„Teilverkauf x % gespiegelt".
|
||||
|
||||
---
|
||||
|
||||
## Phase 3 — Trader-Intelligence (Auswahl automatisieren)
|
||||
|
||||
> Beim Copytrading entscheidet die Master-Auswahl über den Großteil des
|
||||
> Ergebnisses. Diese Phase macht sie messbar und selbstkorrigierend.
|
||||
|
||||
### 3.1 Copy-PnL-Score („Kopierbarkeit")
|
||||
|
||||
Der `MasterTraderAnalyticsJob` misst heute den PnL des **Masters**. Relevanter
|
||||
ist, was **wir** mit ihm verdient haben — inkl. unserer Slippage und Fees.
|
||||
|
||||
1. Neue Kennzahlen je Master aus `ct_`-Closed-Trades (`ICopyTradeLogRepository`,
|
||||
Filter `SourceTraderId`, letzte 30 Tage):
|
||||
- `CopyPnl30d`, `CopyProfitFactor` (Bruttogewinn/Bruttoverlust),
|
||||
`CopyAvgPnlPerTrade`, `CopyTradeCount30d`.
|
||||
- `AvgSlippagePct` aus `ct_fill_log` (Phase 1.1): Ø(FillPrice−SignalPrice)/SignalPrice.
|
||||
2. Felder auf `TrackedTrader` ergänzen (+ EF-Migration `mod_copytrading_trackers`),
|
||||
Berechnung im `MasterTraderAnalyticsJob`, Anzeige in `MastersTradersView`.
|
||||
3. **Achtung Metrik-Falle:** Winrate allein ist irreführend (Favoriten-Käufer
|
||||
haben 95 % Winrate und können trotzdem negativ sein). Profit-Faktor und
|
||||
Ø-PnL/Trade als primäre Sortierung in der UI.
|
||||
|
||||
### 3.2 Sniper-/Verhaltens-Metriken in den Analytics-Job
|
||||
|
||||
Portierung der Logik aus `analyze_snipers.py` (liegt im Projektroot) nach C#
|
||||
in den `MasterTraderAnalyticsJob`:
|
||||
1. Data-API-Activity je Master über volle 3 Tage paginieren (das Skript zeigt
|
||||
das Pagination-Muster; API-Limit je Request beachten).
|
||||
2. Kennzahlen: `MedianHoldMinutes`, `SellWithin5MinPct` (Anteil SELLs < 5 min
|
||||
nach zugehörigem BUY), `SellCount3d`.
|
||||
3. Schwellen (konfigurierbar): `SellWithin5MinPct > 50 %` → Master als Sniper
|
||||
flaggen: Warn-Status in UI + Threema-Hinweis. Optional Auto-Pause (siehe 3.3).
|
||||
|
||||
### 3.3 Automatischer Kill-Switch je Master
|
||||
|
||||
Neue Modul-Settings (global, z. B. in `CopyTradingState` + Persistenz):
|
||||
`AutoPauseEnabled`, `AutoPauseMinTrades` (z. B. 10), `AutoPauseDrawdownUsd`
|
||||
oder `-Pct`.
|
||||
|
||||
Regel im Analytics-Job (läuft 2×/Tag — zusätzlich stündlicher Light-Check
|
||||
sinnvoll): Copy-PnL der letzten N Trades unter Schwelle → `IsActive = false`,
|
||||
`Reasoning` mit Begründung + Zeitstempel befüllen, Threema-Notification.
|
||||
Reaktivierung bewusst nur manuell.
|
||||
|
||||
**Akzeptanz Phase 3:** UI zeigt Copy-Score-Spalten; ein simulierter
|
||||
Verlust-Master wird automatisch pausiert (Test mit Demo-Daten).
|
||||
|
||||
---
|
||||
|
||||
## Phase 4 — Maker-Mode & Demo-Realismus
|
||||
|
||||
### 4.1 Maker-Einstieg für langsame Master
|
||||
|
||||
Für Master mit Haltedauern von Stunden/Tagen (SwissTony/RN1-Typ) ist der
|
||||
3-Sekunden-Taker-Fill unnötig teuer (Fees + Spread). Neues Verhalten
|
||||
(Flag je Trader, z. B. `Category == "HOLDER"` oder eigenes Bool `MakerEntry`):
|
||||
1. BUY als GTC-Limit **auf** Best-Bid (oder Mid − 1 Tick) statt über dem Ask.
|
||||
2. Kein Fill nach T Minuten (konfigurierbar, z. B. 10) und Signal-Markt noch
|
||||
im Preisband → auf Taker-Verhalten eskalieren oder verwerfen (Setting).
|
||||
3. Fees: Maker zahlt 0 und sammelt ggf. Rebates — im Fee-Modell (0.2) abbilden.
|
||||
|
||||
### 4.2 Demo-Modus realistisch machen
|
||||
|
||||
Demo füllt heute zum Signalpreis ohne Slippage/Fees → Demo-Ergebnisse sind
|
||||
systematisch geschönt und als Validierung neuer Master unbrauchbar.
|
||||
|
||||
Fill-Modell im Demo-Pfad der Engine:
|
||||
`FillPreis = Signalpreis + halber Spread (aus IOrderBookProvider, Fallback
|
||||
+1 ¢) `, Fee der Marktkategorie abziehen, beides im `ClosedTrade` ausweisen.
|
||||
|
||||
**Akzeptanz:** Demo- und Live-PnL desselben Masters weichen über 2 Wochen um
|
||||
< 20 % relativ ab (grobe Plausibilität statt heutiger Systematik-Lücke).
|
||||
|
||||
---
|
||||
|
||||
## Offene Entscheidungen (vor Umsetzung mit Richard klären)
|
||||
|
||||
1. `SellFloorPct`-Default und Stufen-Timing der Eskalationsleiter (0.1).
|
||||
2. `ProfitTarget`: implementieren (Empfehlung) oder Feld entfernen?
|
||||
3. Auto-Pause: nur benachrichtigen oder hart deaktivieren? (Empfehlung: hart,
|
||||
nachts passiert sonst genau das Falsche.)
|
||||
4. Maker-Mode: als Trader-Flag oder automatisch aus `MedianHoldMinutes`
|
||||
ableiten? (Empfehlung: automatisch ab z. B. Median > 60 min, manuell
|
||||
überschreibbar.)
|
||||
|
||||
## Reihenfolge & Abhängigkeiten
|
||||
|
||||
```
|
||||
Phase 0 (sofort, unabhängig)
|
||||
└── Phase 1 (Core-Infra; parallel zu 0 möglich, Livegang nach 0)
|
||||
├── Phase 2 (braucht 0.1-Leiter)
|
||||
├── Phase 3 (braucht 1.1-Fill-Log für Slippage; Rest unabhängig)
|
||||
└── Phase 4 (braucht 1.2-Orderbuch)
|
||||
```
|
||||
@@ -0,0 +1,163 @@
|
||||
# Umsetzungsplan: Fable-Code-Review-Fixes (Copytrading)
|
||||
|
||||
> Basis: Fable-5-Review nach Umsetzung des Rentabilitätsplans (Stand 2026-07-08).
|
||||
> Ausgangslage: 207 Tests grün, Build/Smoke grün. Die Logic/-Klassen sind laut Review
|
||||
> sauber; die Lücken liegen im **Zusammenspiel** von SELL-Leiter, Engine und den
|
||||
> Hintergrund-Services (TraderMonitorService).
|
||||
|
||||
## Fortschritt
|
||||
- ✅ **Slice 0** – IClobClient-Seam + FakeClobClient (verhaltensneutral).
|
||||
- ✅ **Slice 1** – K1/H2/H1: atomarer Claim, Cleanup+Engine schonen Leitern, Floor-Robustheit. 8 Tests.
|
||||
- ✅ **Slice 2** – K2: Startup-Reconciliation (GetOpenOrders ohne assetId = alle). 3 Tests.
|
||||
- ✅ **Slice 3** – K3 (System-SELL vom Ownership-Check ausgenommen + Resolved-Cache) + M5 (Demo-Score-Anzeige, stündl. Auto-Pause). 5 Tests.
|
||||
- ✅ **Slice 4** – H4 (RoundToTick + Dust-Abbruch), M1 (GlobalPnl im Guard), M2 (TokenId), M3-min (serverseitiges Max + lauter Fehlschlag), M4 (Parser 9999), M6 (Fees in Orders), Doku. 10 Tests.
|
||||
- ✅ **Slice 5** – H3: BUY-Skip während ExitPending (Entscheidung A).
|
||||
- ✅ **Slice 6** – SnapshotService entfernt, Demo-Balance/PnL-Reconciliation, Settings-Validierung (IsLadderConfigInverted + Load-Warnung). 3 Tests.
|
||||
|
||||
**Stand: 244 Tests grün, Build/Smoke grün.**
|
||||
|
||||
### Nachgelagerte Testabdeckung (nach dem K3-Fund)
|
||||
- **Engine-Integrationstests** (`CopyTradingEngineTests`, gemockter CLOB): H3 BUY-Skip, Doppel-SELL-Guard, K3 System-Close, Fremd-Trader-Reject, H2 Cleanup-schont-Leiter (+Kontrast). Engine `_clob`→`IClobClient`, `ProcessAccountOrderAsync` internal.
|
||||
- **⚠️ K3-Korrektur:** Der Slice-3-Fix sass am falschen Ort (downstream ~Z.643). Der echte Ownership-Check ist der frühe `inPortfolio`-Lookup (~Z.437, `p.SourceTraderId == signal.TraderId`), der System-Signale schon vorher mit early return abwies. Jetzt am richtigen Ort via `IsAuthorizedSell` – **vom Engine-Test aufgedeckt**.
|
||||
- **K1a-Test** (`TraderMonitorServiceTests`): Cleanup cancelt Leiter-Order nicht (aktive Leiter) bzw. cancelt sie ohne Leiter. `_clob`→`IClobClient`, `CleanupStaleOpenOrdersAsync` internal.
|
||||
|
||||
**Alle 3 kritischen + 4 hohen Bugs sind jetzt durch Tests abgesichert** (K1a/K1b/K2/K3/H1/H2/H3/H4).
|
||||
|
||||
### Bewusst aufgeschobene Follow-ups (Live-Verifikation/Risiko)
|
||||
- **M3 Autoincrement-Migration**: `TradeId` auf DB-Autoincrement umstellen – Schema-Änderung an der Trade-Persistenz, erst im Zielland live verifizieren. (M3-Minimum ist umgesetzt.)
|
||||
- **PersistenceService-Dedup-Zeitfenster**: `Exists(AccountId,TokenId)` blockt legit Re-Entries; robuster Fix (z.B. OpenedAt-basiert) braucht Live-Daten – Duplikat-Schutz nicht unverifiziert brechen.
|
||||
- **Perf**: `UpsertLive`-Dirty-Check (Schreib-Amplifikation) und Leiter-Parallelität – laut Fable bei aktueller Größe unkritisch.
|
||||
- **M6/K2**: fee-signierte Orders bzw. `/data/orders` ohne asset_id sind API-gated → im Zielland verifizieren.
|
||||
|
||||
## Arbeitsgrundsätze (für jeden Slice)
|
||||
|
||||
1. **`.agents/rules/clob.md`:** vor jedem CLOB-nahen Slice ein Commit als Rollback-Punkt;
|
||||
Preis-/Zustandslogik pur in `SellLogic`/`CopyTradingRisk` + neue Tests; Service-Interaktionen
|
||||
(Cleanup überspringt Leiter etc.) mit kleinem **Integrationstest über gemockten CLOB-Client**.
|
||||
2. Nach jedem Slice: `dotnet build` + `dotnet test` (alle grün) + `--smoke-ui` grün, dann commit+push.
|
||||
3. Ein Slice = eine kohärente Einheit = ein Commit. Reihenfolge unten folgt Fables Empfehlung.
|
||||
|
||||
---
|
||||
|
||||
## Slice 0 (Prereq): Testbarkeit — `IClobClient`-Interface
|
||||
**Warum zuerst:** K1/H2/K2 brauchen Integrationstests mit gemocktem CLOB. `PolymarketClobClient`
|
||||
ist heute eine konkrete Klasse ohne Interface → nicht mockbar.
|
||||
|
||||
- Interface `IClobClient` (Core) mit den von Leiter/Reconciliation genutzten Methoden:
|
||||
`PlaceOrderAsync`, `CancelOrderAsync`, `GetOpenOrdersAsync`, `CancelConflictingOrdersAsync`.
|
||||
- `PolymarketClobClient : IClobClient`. DI zusätzlich `IClobClient → PolymarketClobClient`.
|
||||
- `SellLadderService`/Reconciliation gegen `IClobClient` typisieren (Engine kann vorerst konkret bleiben).
|
||||
- **Verhaltensneutral, keine Logikänderung.** Ermöglicht `FakeClobClient` im Testprojekt.
|
||||
- Tests: keine neuen fachlichen; Build grün genügt.
|
||||
|
||||
---
|
||||
|
||||
## Slice 1: „Wer darf Leiter-Orders anfassen" (H1 + K1 + H2) 🔴🟠
|
||||
Kernthema: Leiter-Order darf nur von der Leiter angefasst/gecancelt werden.
|
||||
|
||||
- **H1 — Atomarer Claim:** In `SellLadderService.StartLadderAsync` als ERSTES
|
||||
`if (!_copyState.ExitLadders.TryAdd(key, placeholder)) return false;` → macht ALLE Aufrufer
|
||||
(Engine-SELL + ProfitTarget) idempotent. Bei Fehlschlag der Order den Key wieder entfernen.
|
||||
- **K1 — Cleanup überspringt Leitern:** In `TraderMonitorService.CleanupStaleOpenOrdersAsync`
|
||||
Keys mit `_copyState.ExitLadders.ContainsKey(key)` überspringen (`continue`).
|
||||
- **K1 — Floor-Robustheit:** In `SellLadderService.ProcessLadderAsync` am Floor NICHT dauerhaft
|
||||
früh zurückkehren, sondern periodisch via `GetOpenOrdersAsync` prüfen, ob die Floor-Order noch
|
||||
ruht; wenn nicht → am Floor neu platzieren (+ `PendingOrderTimestamps` refreshen).
|
||||
- **H2 — Engine-Cancel schont Leiter:** Den Pre-Signal-`CancelConflictingOrdersAsync`-Aufruf der
|
||||
Engine überspringen, wenn `_copyState.ExitLadders.ContainsKey(key)` (oder hinter den
|
||||
ExitPending-Check verschieben).
|
||||
- Tests: Integrationstest (FakeClob) — Cleanup cancelt KEINE Leiter-Order; zwei parallele
|
||||
StartLadder-Aufrufe → nur eine Leiter; Floor-Order weg → Leiter platziert neu. Pure: ggf.
|
||||
Floor-Recheck-Entscheidung.
|
||||
|
||||
---
|
||||
|
||||
## Slice 2: Neustart-Reconciliation (K2) 🔴
|
||||
Ruhende GTC-Leiter-/Maker-Orders überleben Neustarts, der Verwaltungszustand nicht.
|
||||
|
||||
- Beim Modul-Start je **Live-Account** alle offenen CLOB-Orders via `GetOpenOrdersAsync` abrufen und
|
||||
pauschal canceln (deterministisch; die Engine entscheidet danach sauber neu). Kein Leiter-Rebuild.
|
||||
- Ort: eigener Startup-Schritt im Modul (z. B. in `TraderMonitorService`-Warmup oder als kurzer
|
||||
`IHostedService`), NACH der State-Hydration, VOR dem ersten Signal-Processing.
|
||||
- Umfangreiches Logging (welche Orders gecancelt).
|
||||
- Tests: Integrationstest (FakeClob) — für jeden offenen Order-Eintrag wird Cancel gerufen.
|
||||
|
||||
---
|
||||
|
||||
## Slice 3: Demo-Resolution + Demo-Score (K3 + M5) 🔴🟡
|
||||
Sonst ist die Demo-Validierungsphase (auf der die Zielland-Strategie beruht) wertlos.
|
||||
|
||||
- **K3 — System-Signale (TraderId==0) vom Ownership-Check ausnehmen:** In der Engine SELL-Pre-Flight
|
||||
(`p.SourceTraderId == signal.TraderId`) den Fall `signal.TraderId == 0` zulassen (System-Close bei
|
||||
Marktauflösung). Zusätzlich „bereits als resolved erkannt"-Cache, damit ein Markt nur einmal
|
||||
verarbeitet wird (verhindert 30-s-Loop-Spam + API-Last).
|
||||
- **M5 — Demo-Score & schnellerer Auto-Pause:** Copy-Score getrennt für Demo (Anzeige/Validierung)
|
||||
und Live (Pausieren) berechnen; der Kill-Switch filtert weiterhin `!IsDemo`, aber die Demo-Kennzahlen
|
||||
füllen die Spalten. Zusätzlich stündlicher Light-Check nur für die Pause-Regel (statt nur alle 12 h).
|
||||
- Tests: Ownership-Ausnahme (Engine), Resolved-Cache (pure). Demo/Live-Score-Trennung ist Job-Logik.
|
||||
|
||||
---
|
||||
|
||||
## Slice 4: Kleine, klar umrissene Fixes (H4 + M1 + M2 + M3 + M4 + M6 + Doku) 🟠🟡🟢
|
||||
Jeweils klein und abgegrenzt — in einem oder zwei Commits.
|
||||
|
||||
- **H4 — Dust-Reject-Schleife:** (a) Leiter-Preis vor der USDC-Berechnung auf Tick runden
|
||||
(`Math.Round(next, 3)`, zentral in `SellLogic`); (b) Abbruch in `ProcessLadderAsync`:
|
||||
`pos.Size < CopyTradingRisk.MinShares` → Leiter beenden, `ExitPending=false`, Dust loggen.
|
||||
Pure Tests für Rundung + Abbruch.
|
||||
- **M1 — GlobalPnl-Doppelzählung:** In `TraderMonitorService` (~Z.910 und ~Z.961) das
|
||||
`GlobalPnl += realizedPnl` INNERHALB des `_processedClosures`-Guards buchen (wie in
|
||||
`PollClosedAccountsAsync` bereits korrekt).
|
||||
- **M2 — TokenId in Live-Close-Records:** In beiden Live-Close-Records (~Z.922-940 und ~Z.972-990)
|
||||
`TokenId = removedPos.TokenId` setzen (der 0.4-Fix erwischte nur den Demo-Pfad).
|
||||
- **M3 — TradeId robust:** `ClosedTrade.TradeId` auf DB-Autoincrement (`ValueGeneratedOnAdd`)
|
||||
umstellen + Code-Vergabe (`GetNextTradeId`) entfernen + Migration. Eliminiert die stille
|
||||
PK-Kollisions-Fehlerklasse und den teuren Full-Table-`Max()`-Startup in `Program.cs`.
|
||||
(Alternative/Minimum: serverseitiges `Max()` + lauter Fehlschlag statt `catch {}`.)
|
||||
- **M4 — Parser-Default:** `MongoExportParser` ProfitTarget-Fallback `50m → 9999m` (sonst schaltet
|
||||
ein erneuter `--migrate-json`-Lauf Take-Profit unbeabsichtigt scharf). Pure Test.
|
||||
- **M6 — Fee in signierte Orders:** An den Callsites (Engine-BUY, Leiter, PreRedeem)
|
||||
`actualFeeBps` aus `FeeModel`/`MarketData.TakerFeeBps` an `PlaceOrderAsync` durchreichen.
|
||||
Verifikation im Zielland, aber die Verdrahtung jetzt.
|
||||
- **Doku — Stale [Description]:** `SellFloorPct` ist verdrahtet (nicht „Phase 0.1 offen");
|
||||
`ProfitTarget`-Text nicht mehr „folgt in Phase 0.3". Texte aktualisieren (Richard verlässt sich drauf).
|
||||
|
||||
---
|
||||
|
||||
## Slice 5: H3 — BUY während ExitPending 🟠
|
||||
Re-buyt der Master, während unsere Leiter verkauft, kauft die Engine normal zu → die Leiter verkauft
|
||||
danach `pos.Size` inkl. neuer Shares zum alten Floor.
|
||||
|
||||
**ENTSCHEIDUNG (Richard, 2026-07-08): Variante A — BUYs skippen, solange `ExitPending`.**
|
||||
Während des Ausstiegs keine Zukäufe; die Leiter verkauft die Position sauber zu Ende.
|
||||
|
||||
- Umsetzung: In der Engine BUY-Pre-Flight früh prüfen —
|
||||
`if (account.OpenPositions.TryGetValue(signal.TokenId, out var p) && p.ExitPending) { log + return; }`.
|
||||
(Spiegelt die bestehende Double-Sell-Guard-Logik, nur für den BUY-Pfad.)
|
||||
- Umfangreiches Logging (verworfener BUY während aktivem Exit inkl. TokenId/TraderId).
|
||||
- Tests: Engine-BUY-Pfad überspringt, solange `ExitPending`; nach Leiter-Ende (ExitPending=false)
|
||||
wird ein neuer BUY wieder normal ausgeführt.
|
||||
|
||||
---
|
||||
|
||||
## Slice 6: Rest nach Gelegenheit (🟢 Perf/Doku)
|
||||
- **PersistenceService-Dedup:** `Exists(AccountId, TokenId)` blockt legitime Re-Entries (HF-Alltag) →
|
||||
Dedup-Schlüssel um Zeitfenster ergänzen. (Copy-Score untererfasst sonst.)
|
||||
- **Demo-Balance vs. PnL:** Balance sollte `exitUsd − ExitFee` gutschreiben (und der BUY die Entry-Fee
|
||||
abziehen), damit Σ(Balance-Änderungen) = Σ(PnL). Aktuell driftet es um die Fees.
|
||||
- **Settings-Validierung:** `MaxPriceDifference% > SellFloorPct` → Leiter startet unter dem Floor
|
||||
(sofortige „Floor erreicht"-Notification). UI-Warnung/Validierung.
|
||||
- **Perf — Schreib-Amplifikation:** `PollLiveAccountsAsync` `UpsertLive` je Position alle 30 s →
|
||||
Dirty-Check (nur bei Änderung) oder Batch.
|
||||
- **Perf — Leitern seriell:** `ProcessLadderAsync` pro Tick seriell → begrenzte Parallelität + Timeout.
|
||||
- **Totcode:** `services/SnapshotService.cs` entfernen (nirgends registriert) oder bewusst reaktivieren.
|
||||
|
||||
---
|
||||
|
||||
## Empfohlene Reihenfolge (Fable)
|
||||
`Slice 0` (Test-Infra) → `Slice 1` (K1+H2+H1) → `Slice 2` (K2) → `Slice 3` (K3+M5) →
|
||||
`Slice 4` (H4/M1/M2/M3/M4/M6/Doku) → `Slice 5` (H3, nach Entscheidung) → `Slice 6` (Rest).
|
||||
|
||||
**Als korrekt bestätigt (nicht anfassen):** Logic/-Klassen sauber/verhaltenstreu; ExitPending
|
||||
EF-ignoriert; TotalFees gemappt; closed_trades-Indizes vorhanden; SellLadderService als
|
||||
Singleton+Hosted (eine Instanz); Copy-Score-Find serverseitig; SELL-Spam-Blockade seitensensitiv.
|
||||
@@ -0,0 +1,187 @@
|
||||
# Umsetzungsplan: Modul „BundleArbitrage" (Intra-Market- & NegRisk-Arbitrage)
|
||||
|
||||
> Stand: 2026-07-06
|
||||
> Ziel: Neues Strategiemodul, das Preissummen-Anomalien innerhalb von
|
||||
> Polymarket erkennt und handelt: YES + NO < $1.00 (binäre Märkte) und
|
||||
> Summen-Verletzungen in NegRisk-Multi-Outcome-Märkten.
|
||||
> Reihenfolge: Nach/parallel zu MarketMaking — nutzt dieselbe Orderbuch-
|
||||
> Infrastruktur. **Harte Voraussetzung:** Phase 1 (Marktdaten-Fundament) aus
|
||||
> `UMSETZUNGSPLAN-CopyTrading-Verbesserungen.md`.
|
||||
> **Wichtig:** Dieses Modul startet bewusst als reines Mess-Modul
|
||||
> (Detection-only). Ob Execution gebaut wird, entscheidet die Messphase.
|
||||
|
||||
---
|
||||
|
||||
## 0. Strategie-Hintergrund & ehrliche Einordnung
|
||||
|
||||
**Mechanik:**
|
||||
- **Binär:** Kostet YES + NO zusammen < $1.00 (beide zum Ask kaufbar),
|
||||
ist der Kauf beider Seiten ein garantierter Gewinn: Das Paar zahlt bei
|
||||
Resolution sicher $1.00 aus — oder kann on-chain sofort zu $1.00 USDC
|
||||
zusammengelegt werden (CTF `mergePositions`).
|
||||
- **NegRisk (Multi-Outcome, genau ein Gewinner):** Summe aller YES-Asks < $1.00
|
||||
→ alle YES kaufen (eines zahlt aus). Komplementär: Überteuerte Summen über
|
||||
die NO-Seite bzw. NegRisk-Konvertierungen handeln.
|
||||
|
||||
**Ehrliche Einordnung (Stand 2026):** Auf den großen Märkten ist das ein
|
||||
HFT-Spiel — Fenster von Sekunden, dominiert von spezialisierten Bots; die
|
||||
Taker-Fees seit März 2026 haben viele kleine Anomalien zusätzlich unprofitabel
|
||||
gemacht. **Die Chance liegt im Long Tail** (kleine/neue Märkte, auf die die
|
||||
großen Bots nicht schauen) und als **Beifang** der ohnehin laufenden
|
||||
Orderbuch-Streams des MarketMaking-Moduls. Deshalb: erst messen, dann bauen.
|
||||
|
||||
**Fee-Beachtung:** Als Taker fallen je Leg Fees an (kategorieabhängig,
|
||||
0–1,8 %). Ein Bundle mit 2 ¢ Brutto-Marge kann nach Fees negativ sein.
|
||||
Die Profitrechnung muss Fees je Leg von Anfang an enthalten. Maker-seitige
|
||||
Ausführung (ein Leg ruht als Limit) ist fee-frei, aber nicht atomar.
|
||||
|
||||
---
|
||||
|
||||
## 1. Architektur-Einbettung
|
||||
|
||||
Neues Projekt `src/PolyTrader.Modules.BundleArbitrage/` als `IPolyTraderModule`
|
||||
(`Name = "BundleArbitrage"`, `DbPrefix = "ba_"`), Registrierung in `Program.cs`.
|
||||
|
||||
**Eigener Polymarket-Account** (gleiche Begründung wie in den anderen
|
||||
Modul-Plänen; kann sich in v1 den Account mit MarketMaking teilen, sofern
|
||||
die Inventar-Buchführung getrennt bleibt — Empfehlung: eigener Account,
|
||||
sobald Execution live geht).
|
||||
|
||||
### Persistenz
|
||||
|
||||
| Tabelle | Inhalt |
|
||||
|---|---|
|
||||
| `ba_opportunities` | Jede erkannte Anomalie: Zeitpunkt, Markt/Event, Legs mit Preisen & ausführbarer Size, Brutto-/Netto-Marge (nach Fees), Lebensdauer (wann verschwunden) |
|
||||
| `ba_executions` | Ausgeführte Bundles: Legs, Fills, Slippage, Ergebnis |
|
||||
| `ba_settings` | Schwellen, Size-Limits, Modus (Detect/Execute) |
|
||||
|
||||
Die Lebensdauer-Messung („wie lange war die Anomalie ausführbar?") ist der
|
||||
wichtigste Datenpunkt der Messphase — sie entscheidet, ob unsere
|
||||
Ausführungslatenz überhaupt konkurrenzfähig ist.
|
||||
|
||||
---
|
||||
|
||||
## 2. Komponenten
|
||||
|
||||
### 2.1 `ArbScannerService : BackgroundService` — Detection
|
||||
|
||||
Zwei Datenpfade:
|
||||
1. **Hot Set (WSS):** Für die vom `ClobMarketDataService` (Core) ohnehin
|
||||
gestreamten Bücher (MarketMaking-Märkte + Top-Volumen-Märkte) wird bei
|
||||
jedem Book-Update die Summenprüfung getriggert (< 1 ms, pure Funktion).
|
||||
2. **Long-Tail-Sweep (REST):** Zyklischer Scan über aktive Märkte
|
||||
(Gamma-API-Liste, dann CLOB `GET /book` bzw. Batch-Preis-Endpoints —
|
||||
verfügbare Batch-Endpoints bei Umsetzung in der Doku prüfen).
|
||||
Rate-Limits respektieren (Batching + Delays wie im
|
||||
`TraderMonitorService`-Muster); Sweep-Frequenz Setting (z. B. alle 60 s
|
||||
für 500 Märkte, priorisiert nach Volumen/Neuheit).
|
||||
|
||||
**Prüf-Logik (pure, getestete Klasse `BundleMath`):**
|
||||
- Binär: `bestAskYes + bestAskNo + FeeYes + FeeNo < 1.00 − MinMarginPct`.
|
||||
Ausführbare Size = min(AskSize beider Seiten), ggf. über mehrere Book-Level
|
||||
kumuliert (Level-2-Sweep-Rechnung).
|
||||
- NegRisk: `Σ bestAskYes_i + Σ Fees < 1.00 − MinMarginPct` über alle Outcomes
|
||||
eines NegRisk-Events (Event-Gruppierung über Gamma-API; `NegRisk`-Flag
|
||||
existiert bereits in `MarketData`).
|
||||
- Jede erkannte Anomalie → `ba_opportunities`; bei Verschwinden (nächstes
|
||||
Update unterschreitet Schwelle) Lebensdauer nachtragen.
|
||||
|
||||
### 2.2 Mess-Auswertung (Phase BA-1, entscheidungsrelevant)
|
||||
|
||||
Report (UI-Tab + wöchentlicher Threema-Report):
|
||||
- Anomalien/Tag nach Marge-Bucket (0,5–1 %, 1–2 %, > 2 % netto).
|
||||
- Verteilung ausführbare Size und Lebensdauer.
|
||||
- Erwarteter Monatsertrag bei angenommener Erfolgsquote X % =
|
||||
Σ(Netto-Marge × min(Size, unser Limit)) über gefangene Fenster.
|
||||
|
||||
**Go/No-Go-Kriterium für Execution:** erwarteter Ertrag > Entwicklungs- und
|
||||
Kapitalkosten; realistisch fangbare Fenster (Lebensdauer > unsere Latenz,
|
||||
konservativ ≥ 2–3 s).
|
||||
|
||||
### 2.3 `ArbExecutionService` — nur nach Go-Entscheidung
|
||||
|
||||
1. **Beide Legs gleichzeitig** als IOC-artige Orders senden (CLOB-Ordertypen
|
||||
FOK/FAK bei Umsetzung in der Doku verifizieren; `PolymarketClobClient`
|
||||
ggf. erweitern). Preis = erkannter Ask + kleiner Puffer, Size = min-Leg.
|
||||
2. **Single-Leg-Risiko** (ein Leg füllt, das andere nicht) ist das
|
||||
Kernproblem — Behandlungsreihenfolge:
|
||||
a) Sofortiger Retry des offenen Legs (bis Preis `1.00 − Fees − MinMargin/2`).
|
||||
b) Kein Fill → offenes Leg als GTC-Maker-Order zum Break-even-Preis stellen.
|
||||
c) Timeout (Setting, z. B. 10 min) → Leg über Eskalationsleiter abbauen
|
||||
(Muster aus Copytrading-Plan Phase 0.1) und Verlust in `ba_executions`
|
||||
verbuchen. `MaxSingleLegLossUsd`-Tageslimit als Kill-Switch.
|
||||
3. Size-Limits: `MaxUsdPerBundle` (Start 10–25), `MaxOpenBundles`,
|
||||
Tagesbudget.
|
||||
4. `.agents/rules/clob.md` beachten — jede CLOB-Client-Erweiterung mit
|
||||
Backup/Commit und Mehrfach-Review.
|
||||
|
||||
### 2.4 Kapital-Recycling: CTF `mergePositions` (Phase BA-4)
|
||||
|
||||
Ohne Merge bindet jedes Bundle Kapital bis zur Resolution (bei kurzlaufenden
|
||||
Märkten oft akzeptabel — Priorisierung im Scanner auf EndDate < 7 Tage
|
||||
umgeht das Problem anfangs).
|
||||
|
||||
On-Chain-Merge: YES + NO gleicher Size → $1.00 USDC sofort, via
|
||||
ConditionalTokens `mergePositions(...)`; NegRisk-Sets über den
|
||||
NegRisk-Adapter. Implementierung teilt sich Infrastruktur mit dem
|
||||
Auto-Redeem des ResolutionFarming-Moduls (Phase RF-4) — **gemeinsamen
|
||||
Core-Baustein `OnChainCtfService` bauen**, nicht zweimal implementieren.
|
||||
Contract-Adressen/ABI aus https://docs.polymarket.com (Developer/CTF)
|
||||
verifizieren; Gas (POL) -Handling und Balance-Warnung wie im RF-Plan.
|
||||
|
||||
### 2.5 UI
|
||||
|
||||
- Tab „Live-Anomalien": aktuelle Opportunities mit Netto-Marge/Size.
|
||||
- Tab „Messung": Statistik-Report aus 2.2.
|
||||
- Tab „Executions": Bundles, Single-Leg-Vorfälle, PnL.
|
||||
- Tab „Settings": Schwellen, Modus-Schalter Detect/Execute (Default: Detect).
|
||||
|
||||
---
|
||||
|
||||
## 3. Phasen & Akzeptanzkriterien
|
||||
|
||||
### Phase BA-1: Detection-only (2–4 Wochen Messung)
|
||||
- Scanner (Hot Set + Long-Tail-Sweep), `BundleMath` mit Unit-Tests
|
||||
(inkl. Fee-Rechnung, Level-2-Kumulation, NegRisk-Summen),
|
||||
`ba_opportunities`-Logging, Mess-Report.
|
||||
- Akzeptanz: App baut & läuft; Report nach 2 Wochen vollständig;
|
||||
dokumentierte Go/No-Go-Empfehlung.
|
||||
|
||||
### Phase BA-2: Execution klein (nur bei Go)
|
||||
- IOC-Doppel-Leg, Single-Leg-Behandlung, Size-Limits, Kill-Switch.
|
||||
- Zunächst nur binäre Märkte (NegRisk-Execution ist komplexer → BA-3).
|
||||
- Akzeptanz: ≥ 20 Bundles ausgeführt; Single-Leg-Quote < 20 %;
|
||||
Netto-PnL nach Fees > 0.
|
||||
|
||||
### Phase BA-3: NegRisk-Execution
|
||||
- Multi-Leg-Bundles (N Outcomes), strengere Size-/Slippage-Grenzen
|
||||
(mehr Legs = mehr Single-Leg-Risiko).
|
||||
|
||||
### Phase BA-4: `OnChainCtfService` (Merge) — Kapital-Recycling
|
||||
- Gemeinsam mit ResolutionFarming RF-4 (Redeem) als ein Core-Baustein.
|
||||
- Testmarkt/Kleinstbetrag zuerst; Akzeptanz: Bundle → USDC ohne manuellen
|
||||
Eingriff, USDC-Delta verifiziert.
|
||||
|
||||
---
|
||||
|
||||
## 4. Risiken & Gegenmaßnahmen
|
||||
|
||||
| Risiko | Gegenmaßnahme |
|
||||
|---|---|
|
||||
| Anomalien existieren, sind aber in < 1 s weg | Messphase BA-1 entscheidet VOR Entwicklungsaufwand für Execution |
|
||||
| Single-Leg-Exposure | IOC-Orders, Retry-Kaskade, Tages-Verlustlimit, kleine Bundles |
|
||||
| Fees fressen Marge | Netto-Rechnung inkl. Fees je Leg von Anfang an; `MinMarginPct` konservativ (Start ≥ 1 %) |
|
||||
| Rate-Limits durch Long-Tail-Sweep | Batching, Priorisierung, Sweep-Frequenz drosseln; API-Fehlerquote überwachen |
|
||||
| Stale-Book-Falsch-Signale | Max-Age-Check auf Book-Daten (`TryGetBook(maxAgeMs)`); Anomalie erst nach 2 aufeinanderfolgenden Bestätigungen |
|
||||
| On-Chain-Merge-Fehler | Separater Baustein, Testmarkt, clob.md-Regeln, Balance-Verifikation |
|
||||
|
||||
## 5. Offene Entscheidungen
|
||||
|
||||
1. `MinMarginPct` (netto, nach Fees) für Detection-Logging (Empfehlung 0,5 %)
|
||||
vs. Execution (Empfehlung ≥ 1 %).
|
||||
2. Long-Tail-Sweep-Umfang (alle aktiven Märkte vs. Top-N + Neue) — abhängig
|
||||
von beobachteten Rate-Limits.
|
||||
3. Account-Frage: mit MarketMaking teilen oder eigener (Empfehlung: eigener,
|
||||
sobald BA-2 startet).
|
||||
4. Priorität von BA-4 (Merge): Bei Fokus auf kurzlaufende Märkte zunächst
|
||||
verzichtbar — Kapitalbindung von Tagen ist bei kleinen Größen tragbar.
|
||||
@@ -0,0 +1,200 @@
|
||||
# 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.)
|
||||
@@ -0,0 +1,212 @@
|
||||
# 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?
|
||||
@@ -0,0 +1,361 @@
|
||||
# Umsetzungsplan: Modularisierung PolyTraderSharp
|
||||
|
||||
> Stand: 2026-07-01
|
||||
> Ziel: Umbau des monolithischen WinForms-Copytraders in ein modulares System
|
||||
> mit einem schlanken **Core** und unabhängigen **Modulen**. Erstes Modul: **Copytrading**.
|
||||
|
||||
---
|
||||
|
||||
## 1. Leitprinzipien
|
||||
|
||||
1. **Core kennt keine Module.** Der Core stellt nur Basis-Infrastruktur bereit
|
||||
(Host, DB/Persistenz, Settings, Jobs, Logging, API-Clients, Benachrichtigungen,
|
||||
Modul-Contract). Er hat **keine** Referenz auf irgendein Modul.
|
||||
2. **Module hängen nicht voneinander ab.** Jedes Modul referenziert nur den Core.
|
||||
Ein Modul kennt kein anderes Modul. Dies wird durch getrennte Projekte
|
||||
**zur Compile-Zeit erzwungen**.
|
||||
3. **Jede Phase lässt die App lauffähig und baubar zurück.** Kein „Big Bang".
|
||||
Nach jeder Phase: Debug-Build grün, App startet, Copytrading funktioniert.
|
||||
4. **WinForms bleibt.** Die GUI-Anforderung ist fix. Module tragen ihre eigenen
|
||||
UI-Tabs zur Shell bei.
|
||||
5. **Sicherheit vor Geschwindigkeit beim Refactoring.** CLOB-Integration ist
|
||||
hochkritisch (siehe `.agents/rules/clob.md`) – bei Berührung besonders sorgfältig,
|
||||
jede Änderung mehrfach prüfen. Rollback jederzeit über Git möglich.
|
||||
|
||||
---
|
||||
|
||||
## 2. Zielarchitektur
|
||||
|
||||
### 2.1 Solution-Struktur (Multi-Projekt)
|
||||
|
||||
```
|
||||
PolyTraderSharp.sln
|
||||
│
|
||||
├── PolyTrader.Core (Class Library, net8.0-windows)
|
||||
│ • Generic Host / Bootstrap-Infrastruktur
|
||||
│ • Persistenz: Repository-Interfaces + Implementierung (EF Core)
|
||||
│ • Settings (appsettings.json + IOptions) + Core-Settings-Sektion
|
||||
│ • JobManager, Logging (TerminalLogger / ILogger-Sink)
|
||||
│ • Polymarket-Infrastruktur: PolymarketApiService, PolymarketClobClient,
|
||||
│ PolymarketWssClient, AlchemyWebsocketService
|
||||
│ • Querschnitt: MullvadVpnService, ThreemaService
|
||||
│ • Eigene Trading-Accounts (AccountState) — die Konten, mit denen WIR traden
|
||||
│ • Generischer Trade-Log (modulübergreifend auswertbar)
|
||||
│ • Gesamt-Dashboard (Overview über alle Module)
|
||||
│ • Core-State (generisch): MarketCache, globale Betriebsschalter
|
||||
│ • IPolyTraderModule-Contract + Modul-Registry
|
||||
│
|
||||
├── PolyTrader.Modules.CopyTrading (Class Library, net8.0-windows)
|
||||
│ • TraderMonitorService (Signalquelle)
|
||||
│ • CopyTradingEngine (Ausführung)
|
||||
│ • MasterTraderAnalyticsJob, TraderAnalyticsJob
|
||||
│ • Models: TrackedTrader (kopierte Master-Trader), CopySignal,
|
||||
│ CopyTradeRecord, TraderAnalyticsResult, MasterTraderHistoryRecord
|
||||
│ • Copytrading-State: Traders (Master), MasterTraderPositions,
|
||||
│ PendingOrderTimestamps, TraderAnalyticsCache
|
||||
│ • Channels: CopySignal, ClosedTrade
|
||||
│ • Eigener Copytrading-Trade-Log (Detail-Auswertung kopierter Trades,
|
||||
│ zusätzlich zum generischen Core-Log)
|
||||
│ • Eigene UI-Tabs (Master/Slave-Verwaltung, Modul-Analyse, Closed Trades)
|
||||
│ • Eigene Modul-Settings-Sektion
|
||||
│ • CopyTradingModule : IPolyTraderModule
|
||||
│
|
||||
├── PolyTrader.App (WinForms .exe, net8.0-windows)
|
||||
│ • Program.cs: Host-Bootstrap, lädt Core + registrierte Module
|
||||
│ • Shell-Form (frm_main reduziert auf Rahmen: Terminal, Jobs, Settings-Tab)
|
||||
│ • Referenziert Core + alle aktiven Module
|
||||
│
|
||||
└── PolyTrader.Tests (xUnit, optional — spätere Phase)
|
||||
• Risk-/Entscheidungslogik des Copytrading-Moduls
|
||||
```
|
||||
|
||||
### 2.2 Modul-Contract (Entwurf)
|
||||
|
||||
```csharp
|
||||
public interface IPolyTraderModule
|
||||
{
|
||||
string Name { get; } // "CopyTrading"
|
||||
string DbPrefix { get; } // Namespace für DB-Objekte, z.B. "ct_"
|
||||
|
||||
void RegisterServices(IServiceCollection services, IConfiguration config);
|
||||
void RegisterUi(IModuleUiHost uiHost); // Modul hängt seine Tabs ein
|
||||
Task StartAsync(CancellationToken ct); // läuft NACH Core-Hydration
|
||||
Task StopAsync(CancellationToken ct);
|
||||
}
|
||||
```
|
||||
|
||||
- **Discovery:** Die App registriert Module explizit in `Program.cs`
|
||||
(`services.AddPolyTraderModule<CopyTradingModule>()`). Kein Runtime-Assembly-Scanning
|
||||
(bewusst einfach gehalten; kann später zum Plugin-System ausgebaut werden).
|
||||
- **Feature-/Lizenz-Gating:** `IPolyTraderModule` ist die natürliche Schnittstelle,
|
||||
um Module später per Lizenz zu aktivieren/deaktivieren (vgl. `lizenssystem.md`).
|
||||
|
||||
### 2.3 State-Aufteilung
|
||||
|
||||
`TradingState` wird zerlegt:
|
||||
|
||||
| Feld | Ziel |
|
||||
|------|------|
|
||||
| `MarketCache` | **Core** (generischer Markt-Cache) |
|
||||
| `GlobalTradingPaused`, `LiveTradingMode`, `DemoTradingMode` | **Core** (globale Betriebsschalter) |
|
||||
| `Accounts` (unsere eigenen Trading-Accounts, `AccountState`) | **Core** — die Konten, mit denen WIR traden; modulübergreifend nutzbar |
|
||||
| `Traders` (kopierte Master-Trader, `TrackedTrader`) | **CopyTrading-Modul** |
|
||||
| `MasterTraderPositions`, `PendingOrderTimestamps`, `TraderAnalyticsCache`, `TotalCopyTrades`, `GlobalPnl` | **CopyTrading-Modul** |
|
||||
|
||||
> Entschieden (2026-07-01): Eigene Trading-Accounts liegen im **Core** (auch künftige
|
||||
> Module handeln über dieselben Konten). Die **kopierten** Master-Trader (`TrackedTrader`)
|
||||
> sind ein Copytrading-Konzept und liegen im **Modul**.
|
||||
|
||||
### 2.4 Trade-Logging (zweistufig)
|
||||
|
||||
Zwei unabhängige, parallel geführte Logs:
|
||||
|
||||
1. **Generischer Core-Trade-Log** (`TradeRecord` + `ITradeLogRepository`):
|
||||
modulneutrale Felder (ModulName, AccountId, Markt, Side, Entry/Exit, PnL, Zeiten,
|
||||
ExitReason). Ermöglicht die **modulübergreifende** Gesamtauswertung. Jedes Modul,
|
||||
das Trades ausführt, schreibt hier einen Eintrag.
|
||||
2. **Copytrading-spezifischer Log** (`CopyTradeRecord`, im Modul): erweitert die
|
||||
generischen Felder um Copytrading-Details (`SourceTraderId`, `SourceTraderName`,
|
||||
Master-Adresse, Signal-Herkunft) für die **detaillierte** Copytrading-Analyse.
|
||||
|
||||
Beim Schließen eines kopierten Trades schreibt das Modul **beides**: einen generischen
|
||||
Eintrag in den Core-Log und einen Detaileintrag in seinen eigenen Log.
|
||||
|
||||
### 2.5 Dashboard & Analyse
|
||||
|
||||
- **Core-Gesamt-Dashboard:** Overview über alle Module (aggregierte PnL, Kontostände,
|
||||
offene Positionen, grobe Kennzahlen je Modul) — gespeist aus dem generischen Core-Log.
|
||||
- **Modul-Analyse:** Jedes Modul liefert seine eigene Detailansicht (Copytrading:
|
||||
Trader-Winrates, kopierte Trades, Master-Performance) — gespeist aus dem Modul-Log.
|
||||
|
||||
### 2.6 Settings
|
||||
|
||||
- **Core-Settings-Sektion:** globale/Infrastruktur-Einstellungen (DB, VPN, Threema,
|
||||
Betriebsschalter).
|
||||
- **Modul-Settings-Sektion:** jedes Modul trägt seine eigene Sektion zum Settings-Tab bei
|
||||
(analog zu den UI-Tabs), registriert über den `IPolyTraderModule`-Contract.
|
||||
- **API-Keys sind Modul-Settings:** Alchemy-/Polymarket-WSS-Keys wandern von der globalen
|
||||
`ServerSettings` in die jeweilige Modul-Settings-Sektion (siehe 2.7).
|
||||
|
||||
### 2.7 Streaming / WebSocket-Architektur *(Entscheidung 2026-07-01)*
|
||||
|
||||
**Prinzip:** Der **Core stellt die WSS-Verbindungs-Klasse als wiederverwendbare Fähigkeit**
|
||||
bereit — **keinen** geteilten Singleton-Stream. Jedes **Modul erzeugt seine eigene Instanz**
|
||||
mit **eigenem API-Key und eigenem Filter**.
|
||||
|
||||
**Begründung:** Blockchain-/WSS-Streams werden modulspezifisch **gefiltert** (sonst viel zu
|
||||
umfangreich). Ein einzelner, Core-gesteuerter Stream, auf den mehrere Module gleichzeitig
|
||||
zugreifen, wäre für jedes einzelne Modul mit nutzlosen Informationen geflutet.
|
||||
|
||||
**Aufteilung des heutigen `AlchemyWebsocketService`:**
|
||||
- **Core** (`PolyTrader.Core.Streaming`): Verbindungs-Mechanik — `ClientWebSocket`, `eth_subscribe`,
|
||||
Empfangs-Loop, Decode, Reconnect/429-Backoff, Health. Parametrisiert über eine
|
||||
`BlockchainWssSubscription` (Contract, Topics, Adress-Filter) + RPC-URL/Key. Als **Factory**
|
||||
(`IBlockchainWssClientFactory.Create()`), damit jedes Modul eine eigene Instanz bekommt.
|
||||
- **Modul** (`CopyTrading`): `CopyTradingBlockchainListener : BackgroundService`, der eine
|
||||
Core-WSS-Instanz mit dem Copytrading-Filter (Wallets der getrackten Master-Trader) + dem
|
||||
Modul-eigenen Alchemy-Key betreibt, den gefilterten Substream konsumiert und selbst reagiert
|
||||
(TraderMonitor-Poll, Re-Subscribe bei Trader-Listen-Änderung).
|
||||
|
||||
Analog für den Polymarket-User/Market-WSS (`PolymarketWssClient` → Core-Verbindungsklasse +
|
||||
Modul-Listener). `IsAlchemyHealthy` (heute im Core-State) wird zum Health-Signal der jeweiligen
|
||||
Modul-Instanz.
|
||||
|
||||
---
|
||||
|
||||
## 3. Persistenz-Strategie
|
||||
|
||||
- **Zielrichtung: Wechsel auf MySQL** via **EF Core + Pomelo.EntityFrameworkCore.MySql**,
|
||||
gekapselt hinter Repository-Interfaces im Core.
|
||||
- **Begründung:** DB liegt off-hot-path (Live-Pfad ist RAM-only) → kein Performance-Nachteil.
|
||||
Gewinn: saubere relationale Tabellen statt Collection-per-Account + Shim, ACID,
|
||||
EF-Migrations, Standard-Backups.
|
||||
- **Risikoarm durch Reihenfolge:** Zuerst Repository-Abstraktion einziehen (Phase 3),
|
||||
MySQL-Umstieg als eigene späte Phase (Phase 6). Die Modularisierung ist davon
|
||||
entkoppelt und nicht blockiert.
|
||||
- **Aufräumen:** LiteDB-Paket, `data.db` und `MongoDbLiteDBShim` entfallen nach der Migration.
|
||||
- **ORM: Entity Framework Core** (entschieden) — Migrations + wenig Boilerplate.
|
||||
|
||||
---
|
||||
|
||||
## 4. Phasenplan
|
||||
|
||||
> Jede Phase endet mit grünem Debug-Build + lauffähiger App + Git-Commit.
|
||||
|
||||
### Phase 0 — Fundament: Versionskontrolle & Aufräumen *(ABGESCHLOSSEN 2026-07-01)*
|
||||
- [x] `git init` (Branch `main`), `.gitignore` (bin/, obj/, .vs/, *.user, *.db, server_settings.xml, agentspace/antigravity/, .claude/settings.local.json).
|
||||
- [x] Alle 11 `.bak*`-Dateien entfernt (per `-f` im Baseline-Commit `475d396` archiviert, danach entfernt → rekonstruierbar).
|
||||
- [x] Tote Stubs entfernt: `services/database.cs`, `services/settings.cs`, `polymarket/*.cs`.
|
||||
- [x] Threema-Lib unter `libs/` vendored (nested `.git` entfernt).
|
||||
- [x] Baseline-Commit `475d396` + Cleanup-Commit `f76ad73`; Debug-Build 0 Fehler verifiziert.
|
||||
|
||||
### Phase 1 — Multi-Projekt-Gerüst anlegen *(ABGESCHLOSSEN 2026-07-01, Commit `4f130ff`)*
|
||||
- [x] Drei Projekte: `PolyTrader.App` (umbenanntes WinForms-Projekt, Root),
|
||||
`src/PolyTrader.Core`, `src/PolyTrader.Modules.CopyTrading` (net8.0-windows).
|
||||
- [x] Referenzen: App → Core + CopyTrading; CopyTrading → Core; Core → nichts.
|
||||
- [x] App-csproj: `src\**` vom Globbing ausgeschlossen (keine Glob-Kollision);
|
||||
RootNamespace auf `PolyTraderSharp` gepinnt (schützt .resx/Namespaces).
|
||||
- [x] Threema-Lib-Referenz bleibt im App-Projekt (wandert in Phase 4 zu Bedarf in Core).
|
||||
- [x] **Ergebnis:** Solution-Build 0 Fehler, Code liegt weiterhin im App-Projekt.
|
||||
- [ ] *Offen für spätere Phasen:* NuGet-Pakete beim Code-Umzug auf Core/Modul verteilen.
|
||||
|
||||
### Phase 2 — Konfiguration externalisieren *(ABGESCHLOSSEN 2026-07-01, Commit `e312fbb`)*
|
||||
- [x] `appsettings.json` eingeführt (Mongo-Connection + DB-Name), Copy-to-Output.
|
||||
- [x] `DatabaseOptions` im Core, via `IOptions<T>` gebunden; hart codierte Strings
|
||||
aus `Program.cs` entfernt.
|
||||
- [x] Startup-Cleanup-Hack aus `Main()` entfernt und gekapselt nach Host-Build über
|
||||
die konfigurierte DB neu verankert.
|
||||
- [ ] *Offen (bewusst später):* Alchemy-Key / Mullvad-Account / Threema bleiben vorerst
|
||||
im GUI-editierbaren `server_settings.xml` (kein Konflikt mit Settings-Tab).
|
||||
|
||||
### Phase 3 — Persistenz-Abstraktion (DB noch Mongo) *(IN ARBEIT)*
|
||||
- [x] **3a** (`8b3264f`): Core-Modelle `AccountState`/`Position`/`MarketData` in den Core
|
||||
verschoben (Namespace `PolyTraderSharp.Models` beibehalten), MongoDB.Driver-Paket im Core.
|
||||
- [x] **3b** (`ed5d6e3`): Repository-Interfaces + Mongo-Implementierungen im Core
|
||||
(`IAccountRepository`, `IMarketRepository`, `IPositionRepository`), `AddCorePersistence()`.
|
||||
- [x] **3c** (`7197f9b`): Unkritische Call-Sites migriert (MarketSyncService, PolymarketWssClient).
|
||||
- [x] **3d — Hot-Path** (`a0e367e`, `0c6fc6a`): TraderMonitorService + CopyTradingEngine
|
||||
auf `IPositionRepository`/`IMarketRepository`/`IAccountRepository` umgestellt.
|
||||
`_db` aus CopyTradingEngine komplett entfernt; Verhalten unverändert.
|
||||
- [ ] **frm_main-UI:** Account/Market/Demo-Position-Zugriffe → wird zusammen mit der
|
||||
UI-Zerlegung in Phase 5 migriert (vermeidet Wegwerf-Arbeit).
|
||||
- [ ] *Offen für Phase 5:* generisches `ITradeLogRepository` (Core) + `ICopyTradeLogRepository`
|
||||
+ `ITraderRepository` (Modul), sobald `ClosedTrade`/`TrackedTrader` ins Modul wandern.
|
||||
- [ ] **Ergebnis (Ziel):** Kein direkter DB-Zugriff mehr außerhalb der Repository-Schicht.
|
||||
|
||||
### Phase 4 — Core herauslösen *(IN ARBEIT)*
|
||||
- [x] **4.1** (`9039af8`): TerminalLogger, JobManager, JobStatusRow → Core;
|
||||
toten Stub `logging.cs` gelöscht.
|
||||
- [x] **4.2** (`eebe992`): PolymarketClobClient → Core (+ Nethereum.Web3), reines Verschieben.
|
||||
- [x] **4.3** (`8c126cd`): ServerSettings → Core.
|
||||
- [x] **4.4** (`a1ce3fc`): `IPolyTraderModule`-Contract im Core (UI-Teil auf Phase 5 vertagt).
|
||||
- [x] **4.5** (`c88eac5`): Startup-Reihenfolge-Fix — `StartupHydrationService` (IHostedService,
|
||||
als erster registriert) hydriert Accounts/Trader vor den Trading-Services;
|
||||
`frm_main.LoadDatabaseAndState` entfernt.
|
||||
- [x] **4.6a** (`9c068b4`): CopySignal + PolymarketApiService → Core.
|
||||
- [x] **4.7** (`0ffc041`): MullvadVpnService + ThreemaService (+ Threema-Lib-Ref) → Core;
|
||||
toter Stub `mullvad.cs` gelöscht.
|
||||
- [ ] **BLOCKIERT durch TradingState-Split (→ Phase 5):** MarketSyncService,
|
||||
AlchemyWebsocketService, PolymarketWssClient, SnapshotService nutzen `TradingState`
|
||||
(MarketCache/Accounts/globale Flags). Sie können erst nach dem Split in den Core.
|
||||
- [x] **Ergebnis:** Core baut eigenständig und enthält jetzt: Modelle (Account/Position/
|
||||
Market/CopySignal/JobStatusRow/ServerSettings), Repository-Schicht, Config, Logging,
|
||||
JobManager, CLOB-Client, API-Service, Mullvad, Threema, IPolyTraderModule.
|
||||
|
||||
**Stand nach Phase 4:** Der Core ist substanziell und eigenständig. Was noch in der App liegt:
|
||||
Modul-Services (TraderMonitor, CopyTradingEngine, Analytics-Jobs), die TradingState-abhängige
|
||||
Infra (MarketSync, Alchemy, WSS, Snapshot), PersistenceService, StartupHydrationService,
|
||||
der Shim, `TradingState`, `frm_main` und die Modul-Modelle (TrackedTrader, TraderAnalyticsResult,
|
||||
MasterTraderHistoryRecord, ClosedTrade, DashboardRow). Der **TradingState-Split** ist der
|
||||
Dreh- und Angelpunkt für Phase 5.
|
||||
|
||||
> **Entscheidung (2026-07-01):** `CopySignal` wird ein **Core**-Typ (generisches Markt-Trade-
|
||||
> Signal). Das entkoppelt die Polymarket-Infrastruktur sauber in den Core. Der Channel/Workflow
|
||||
> bleibt Copytrading. Umbenennung zu `TradeSignal` optional/später.
|
||||
|
||||
### Phase 5 — CopyTrading-Modul herauslösen *(IN ARBEIT)*
|
||||
- [x] **5.1** (`55050a1`): Modul-Modelle (TrackedTrader, TraderAnalyticsResult,
|
||||
MasterTraderHistoryRecord) ins Modul verschoben.
|
||||
- [x] **5.2** (`f8d395b`): **TradingState-Split** — Core `TradingState` (globale Schalter,
|
||||
Accounts, MarketCache, GlobalPnl) vs. `CopyTradingState` im Modul (Traders,
|
||||
MasterTraderPositions, TraderAnalyticsCache, TotalCopyTrades, PendingOrderTimestamps,
|
||||
SixSharesMinimum); 10 Konsumenten umgestellt. Modulgrenze auf State-Ebene gezogen.
|
||||
- [x] **5.3a** (`f5e7eaf`): MarketSyncService → Core (nur Core-State).
|
||||
- [x] **5.3-WSS 1/2** (`3be75c0`): Core-WSS-Verbindungsklasse extrahiert
|
||||
(`IBlockchainWssClient` + Factory + Modelle in `PolyTrader.Core.Streaming`);
|
||||
`AlchemyWebsocketService` nutzt sie via Factory. Verhaltensneutral.
|
||||
- [x] **ClosedTrade-Migration** (`88fc982`): `ClosedTrade` → Modul, `ICopyTradeLogRepository`
|
||||
(+ Mongo-Impl) im Modul; `closed_trades`-Zugriffe der Services (TraderMonitor,
|
||||
Persistence, WSS, TraderAnalytics) auf das Repo umgestellt. TraderMonitor nutzt kein
|
||||
`_db` mehr. frm_main/Program.cs bleiben auf `_db`.
|
||||
- [ ] **5.3b (jetzt unblockiert):** Modul-Services physisch ins Modul-Projekt verschieben:
|
||||
TraderMonitorService, CopyTradingEngine, TraderAnalyticsJob, MasterTraderAnalyticsJob.
|
||||
(Vorher: reststehende `PolyTraderSharp.Extensions`-Usings in CopyTradingEngine entfernen.)
|
||||
- [ ] **5.3-WSS 2/2:** `CopyTradingBlockchainListener` → Modul (eigener Key + Filter);
|
||||
API-Keys → Modul-Settings. Analog `PolymarketWssClient`.
|
||||
- **UI-Trennung (Launcher-Modell, entschieden 2026-07-01):** Hauptfenster = schlanke
|
||||
Startleiste; jede Ansicht öffnet als eigenständiges Fenster. Module liefern designbare
|
||||
`UserControl`s via `IPolyTraderModule.RegisterUi` / `IModuleUiHost`. `frm_main` bleibt
|
||||
übergangsweise als „Legacy-UI" per Button erreichbar, bis alle Views extrahiert sind.
|
||||
- [x] UI-Contract im Core (`IModuleUiHost`, `ModuleView`, `RegisterUi`) — `26dd68a`.
|
||||
- [x] Proof-of-Pattern: `LauncherForm` + `ViewHostForm` + `ShellUiHost` + erste View
|
||||
`TerminalView` (designbar); App startet Launcher — `3503bbb`.
|
||||
- [ ] Restliche Views view-für-view extrahieren:
|
||||
**App/Core:** Jobs, Server Settings, Dashboard (Overview), License, Accounts (Slave),
|
||||
Offene Positionen. **Modul:** Master-Traders, Top/Flop-Analytics, Geschlossene Trades.
|
||||
- [ ] `frm_main` (Legacy) entfernen, sobald alle Views raus sind.
|
||||
- [ ] `CopyTradingModule : IPolyTraderModule` implementieren (Services + UI-Tabs +
|
||||
Settings-Sektion + Modul-Log + Start/Stop).
|
||||
- [ ] Dualen Trade-Log verdrahten: beim Schließen kopierter Trades in Core-Log **und**
|
||||
Copytrading-Log schreiben.
|
||||
- [ ] Latenten Collection-Namensbug beheben (`traders` vs. `trackers`).
|
||||
- [ ] **Ergebnis:** Copytrading ist ein eigenständiges, entfernbares Modul.
|
||||
|
||||
### Phase 6 — MySQL-Migration
|
||||
- [ ] EF Core + Pomelo einrichten; relationales Schema modellieren
|
||||
(u.a. `positions` mit `account_id` statt Collection-per-Account;
|
||||
`trader_accounts` Join-Tabelle für `AssignedAccountIds`).
|
||||
- [ ] Zweite Repository-Implementierung (MySQL) hinter den bestehenden Interfaces.
|
||||
- [ ] Einmaliges Migrationsskript Mongo → MySQL (agentspace/scripts).
|
||||
- [ ] Umschalten per Konfiguration; Mongo/LiteDB/Shim + `data.db` entfernen.
|
||||
|
||||
### Phase 7 — Nacharbeiten *(optional, später zu priorisieren)*
|
||||
- [ ] Test-Projekt: Risk-/Entscheidungslogik als reine Funktionen extrahieren & testen.
|
||||
- [ ] God-Methoden splitten (`PollLiveAccountsAsync`, `ProcessAccountOrderAsync`);
|
||||
duplizierte Closed-Trade-Erzeugung zentralisieren.
|
||||
- [ ] Leere `catch {}` durch gezieltes Logging ersetzen.
|
||||
- [ ] Secrets-Verschlüsselung (DPAPI) für PrivateKey/ApiSecret/ApiPassphrase.
|
||||
- [ ] TerminalLogger auf `Microsoft.Extensions.Logging` + UI-Sink umstellen.
|
||||
|
||||
---
|
||||
|
||||
## 5. Datei-→-Ziel-Zuordnung (Referenz)
|
||||
|
||||
| Aktuell | Ziel |
|
||||
|---------|------|
|
||||
| `Program.cs` | PolyTrader.App |
|
||||
| `frm_main.*` | PolyTrader.App (Shell) + Copytrading-Tabs → Modul |
|
||||
| `frm_analytics.*` | PolyTrader.Modules.CopyTrading |
|
||||
| `TradingState.cs` | aufgeteilt: Core + Modul |
|
||||
| `services/PolymarketApiService.cs` | Core |
|
||||
| `services/PolymarketClobClient.cs` | Core |
|
||||
| `services/PolymarketWssClient.cs` | Core |
|
||||
| `services/AlchemyWebsocketService.cs` | Core |
|
||||
| `services/MullvadVpnService.cs`, `mullvad.cs` | Core |
|
||||
| `services/ThreemaService.cs` | Core |
|
||||
| `services/JobManager.cs`, `TerminalLogger.cs`, `logging.cs` | Core |
|
||||
| `services/PersistenceService.cs` | Core (generischer Trade-Log-Writer); Copytrading-Detail-Writer → Modul |
|
||||
| `services/MarketSyncService.cs`, `SnapshotService.cs` | Core |
|
||||
| `Extensions/MongoDbLiteDBShim.cs` | Core (temporär), entfällt in Phase 6 |
|
||||
| `services/CopyTradingEngine.cs` | Modul |
|
||||
| `services/TraderMonitorService.cs` | Modul |
|
||||
| `services/MasterTraderAnalyticsJob.cs`, `TraderAnalyticsJob.cs` | Modul |
|
||||
| `Models/AccountState.cs`, `Position.cs`, `MarketData.cs`, `ServerSettings.cs`, `JobStatusRow.cs`, `DashboardRow.cs` | Core |
|
||||
| `Models/ClosedTrade.cs` | aufgeteilt: generischer `TradeRecord` → Core, `CopyTradeRecord` (mit SourceTrader-Feldern) → Modul |
|
||||
| `Models/TrackedTrader.cs`, `CopySignal.cs`, `TraderAnalyticsResult.cs`, `MasterTraderHistoryRecord.cs` | Modul |
|
||||
| `services/database.cs`, `settings.cs`, `polymarket/*.cs` | löschen (Phase 0) |
|
||||
| `*.bak*` | löschen (Phase 0) |
|
||||
|
||||
---
|
||||
|
||||
## 6. Getroffene Entscheidungen (2026-07-01)
|
||||
|
||||
1. **Eigene Trading-Accounts → Core**, **kopierte Master-Trader → Copytrading-Modul.**
|
||||
2. **Zweistufiges Trade-Logging:** generischer Core-Log (modulübergreifend) **und**
|
||||
zusätzlicher Copytrading-Detail-Log im Modul (siehe 2.4).
|
||||
3. **ORM: Entity Framework Core.**
|
||||
4. **Dashboard:** Core liefert Gesamt-Overview über alle Module; Module liefern
|
||||
eigene Detail-Analysen (siehe 2.5).
|
||||
5. **Settings:** getrennte Core- und Modul-Settings-Sektionen (siehe 2.6).
|
||||
|
||||
---
|
||||
|
||||
## 7. Risiken & Gegenmaßnahmen
|
||||
|
||||
- **CLOB-Regression:** Höchstes Risiko. Gegenmaßnahme: CLOB-Client möglichst unverändert
|
||||
in den Core verschieben (nur Namespace/Referenzen), keine Logikänderung in der
|
||||
Umstrukturierungsphase.
|
||||
- **Startup-Race weiterhin aktiv, bis Phase 4:** Bis der Startup-Fix greift, bleibt das
|
||||
bestehende Verhalten – kein neues Risiko, aber früh angehen.
|
||||
- **Datenmigration (Phase 6):** Server läuft produktiv. Migration mit Read-Only-Export +
|
||||
Verifikation vor Umschaltung; Rollback-Pfad (Mongo bleibt bis Verifikation bestehen).
|
||||
@@ -0,0 +1,98 @@
|
||||
# Umsetzungsplan: Strategie-Drift-Erkennung für Master-Trader (B-S2)
|
||||
|
||||
> Stand: 2026-07-11
|
||||
> Ziel: Verhaltens-Änderungen eines Masters erkennen, BEVOR sie sich im Copy-PnL
|
||||
> niederschlagen. Die bestehende Auto-Pause (Copy-PnL-basiert) ist ein nachlaufender
|
||||
> Indikator — bei 95-¢-Tradern sieht man den Schaden erst nach mehreren Verlusten.
|
||||
> Verhalten läuft dem PnL voraus: Ein Wetter-Bot, der plötzlich Politik-Longshots
|
||||
> kauft, hat die Strategie gewechselt, lange bevor die Verluste messbar sind.
|
||||
> Modul: PolyTrader.Modules.CopyTrading (baut auf vorhandenem MasterTraderAnalyticsJob auf).
|
||||
|
||||
---
|
||||
|
||||
## 1. Der Verhaltens-Fingerprint
|
||||
|
||||
Je Master werden zwei Fenster verglichen: **Referenz** (30 Tage bzw. die von
|
||||
Predictalytics gelieferte Baseline) vs. **aktuell** (7 Tage). Datenquelle: die
|
||||
Activity-/History-Daten, die der `MasterTraderAnalyticsJob` bereits lädt
|
||||
(`mod_copytrading_mt_history` + Data-API-Activity; für Preisband/Größe die
|
||||
Activity-Items — Felder existieren in den bereits geparsten JSONs).
|
||||
|
||||
Fingerprint-Metriken (pure Klasse `Logic/TraderFingerprint.cs`, voll unit-getestet):
|
||||
|
||||
| Metrik | Definition | Drift-Beispiel |
|
||||
|---|---|---|
|
||||
| `TradesPerWeek` | Trade-Frequenz | Bot-Betreiber wechselt von 40 auf 400/Woche |
|
||||
| `CategoryMix` | Einsatz-Anteil je Kategorie (Vektor) | Wetter-Bot kauft plötzlich Politik |
|
||||
| `PriceBandMix` | Einsatz-Anteil je Einstiegs-Preisband (10-¢-Bänder) | Favoriten-Halter kauft Longshots |
|
||||
| `MedianHoldHours` | Median Haltedauer (Kauf→Close/Resolution) | Halter wird Day-Trader |
|
||||
| `SellRatio` | Anteil aktiv verkaufter Positionen | „Stur-Halter" beginnt zu verkaufen |
|
||||
| `SizeP90Rel` | 90. Perzentil Positionsgröße relativ zur Referenz | Martingale-/Tilt-Muster |
|
||||
|
||||
### Drift-Score
|
||||
|
||||
Pro Metrik eine normierte Abweichung (für Anteils-Vektoren: L1-Distanz / 2 → 0..1;
|
||||
für Skalare: `|akt − ref| / max(ref, ε)` gekappt auf 1). Gesamt:
|
||||
|
||||
```
|
||||
DriftScore = gewichtete Summe (Default-Gewichte: CategoryMix 0.3, PriceBandMix 0.25,
|
||||
SellRatio 0.2, TradesPerWeek 0.1, MedianHoldHours 0.1, SizeP90Rel 0.05)
|
||||
```
|
||||
|
||||
Schwellen (global in `CopyTradingState`, per PropertyGrid änderbar, mit
|
||||
[Description]): `DriftWarnScore` (Default 0.25) und `DriftPauseScore` (Default 0.5).
|
||||
**Mindeststichprobe:** unter 10 Trades im 7-Tage-Fenster keine Bewertung (Rauschen).
|
||||
|
||||
## 2. Aktionen bei Drift
|
||||
|
||||
| Stufe | Bedingung | Aktion |
|
||||
|---|---|---|
|
||||
| Beobachten | Score < Warn | nichts; Score in UI-Spalte sichtbar |
|
||||
| **Warnen** | Warn ≤ Score < Pause | Threema-Meldung mit den 2 größten Abweichungen („Kategorie-Mix: Wetter 90→40 %, Politik 0→45 %"); Master in UI gelb |
|
||||
| **Neu-Trades pausieren** | Score ≥ Pause UND `AutoPauseEnabled` | NEUE BUYs dieses Masters aussetzen (`DriftPaused`-Flag auf TrackedTrader, Engine-Check im BUY-Pfad analog ExitPending); offene Positionen + SELL-Handling laufen normal weiter; Threema; Reaktivierung manuell |
|
||||
|
||||
Bewusst: Drift pausiert nur **Neu-Käufe** — es verkauft nichts. Bestehende
|
||||
Positionen sind Sache der normalen Exit-Mechanik (Halter: Resolution).
|
||||
|
||||
## 3. Umsetzung
|
||||
|
||||
### Slice D-1: Pure Logik + Persistenz
|
||||
- `Logic/TraderFingerprint.cs`: `Compute(IEnumerable<TradeObservation>)` →
|
||||
Fingerprint; `Drift(reference, current)` → Score + Top-Abweichungen. Unit-Tests
|
||||
(Vektor-Distanzen, Mindeststichprobe, Rand: leere Referenz).
|
||||
- `TrackedTrader`: Felder `FingerprintBaselineJson` (Referenz, von Predictalytics
|
||||
importierbar ODER selbst aus 30 Tagen berechnet), `DriftScore`, `DriftPaused`,
|
||||
`DriftDetail` (Kurztext) + Migration.
|
||||
- `MasterTraderHistoryRecord` erweitern um die dafür nötigen Felder (EntryPrice-Band,
|
||||
Kategorie, Size, Haltedauer), sofern noch nicht vorhanden — beim History-Download
|
||||
mit befüllen (Daten sind in den API-Antworten enthalten).
|
||||
|
||||
### Slice D-2: Job-Integration
|
||||
- Im `MasterTraderAnalyticsJob` nach dem History-Download: Fingerprint aktuell (7 T)
|
||||
vs. Referenz (30 T bzw. BaselineJson) → Score, Aktionen gemäß Tabelle.
|
||||
- **Frequenz:** Der Job läuft 12-stündlich — für Drift zu träge. Leichten
|
||||
Stunden-Tick ergänzen (nur Fingerprint-Neuberechnung aus bereits geladenen
|
||||
History-Daten, KEINE zusätzlichen API-Calls; die 12-h-Läufe aktualisieren die
|
||||
Rohdaten).
|
||||
- Referenz-Handhabung: Baseline wird NICHT automatisch nachgezogen, solange eine
|
||||
Warnung/Pause aktiv ist (sonst „lernt" die Referenz die Drift). Nach manueller
|
||||
Entwarnung: Baseline auf aktuelles 30-T-Fenster zurücksetzen (Button in UI).
|
||||
|
||||
### Slice D-3: Engine + UI
|
||||
- Engine-BUY-Pfad: `DriftPaused`-Check (analog `IsActive`), TradeReasoning-Log.
|
||||
- `MastersTradersView`: Spalten DriftScore (mit Ampelfarbe) + DriftDetail;
|
||||
Kontextmenü „Drift entwarnen + Baseline zurücksetzen".
|
||||
|
||||
## 4. Akzeptanzkriterien
|
||||
1. Unit-Tests: konstruierte Drift-Szenarien (Kategorie-Wechsel, Frequenz-Explosion,
|
||||
Longshot-Umstieg) erzeugen erwartete Scores; stabile Master bleiben < Warn.
|
||||
2. Simulierter Kategorie-Wechsel in Testdaten führt zu `DriftPaused` + Engine
|
||||
verweigert Neu-BUY mit nachvollziehbarem Log.
|
||||
3. Kein zusätzlicher Data-API-Traffic durch den Stunden-Tick (nur DB/RAM).
|
||||
4. Threema-Meldungen enthalten die konkreten Top-Abweichungen, nicht nur den Score.
|
||||
|
||||
## 5. Abgrenzung
|
||||
- Ersetzt NICHT die PnL-Auto-Pause (Phase 3.3, bleibt) — Drift ist das Frühwarnsystem,
|
||||
PnL-Pause das Sicherheitsnetz.
|
||||
- Sniper-Metriken (Plan Phase 3.2, Median-Haltezeit via Activity-Pagination) sind ein
|
||||
Spezialfall dieses Fingerprints — bei Umsetzung zusammenlegen statt doppelt bauen.
|
||||
Reference in New Issue
Block a user