Ein Kunde mit US-Wohnsitz soll ueber Polymarket US handeln - eine eigene, CFTC-regulierte Boerse, an der die heutige CLOB-Anbindung nicht verwendbar ist. Das Konzept macht Plattform zu einem Begriff im Core, laesst Module ihre Plattformen erklaeren und haelt Strategievarianten je Plattform im Modul. Begruendungen zu #622-#629 in docs/ROADMAP.md, Bauanleitung in docs/archiv/konzepte/KONZEPT-Multi-Plattform.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
350 lines
20 KiB
Markdown
350 lines
20 KiB
Markdown
# Konzept: Mehrere Handelsplattformen (Polymarket US, später Kalshi)
|
||
|
||
**Angelegt am 16.09.2026.** Planungsstand und Reihenfolge stehen im Deploymentcenter
|
||
(Items #622–#629), nicht hier. Diese Datei ist die Bauanleitung und die Begründung.
|
||
|
||
---
|
||
|
||
## 1. Anlass und Ziel
|
||
|
||
Ein Kunde mit Wohnsitz in den USA soll PolyTrader nutzen. Er darf polymarket.com nicht verwenden
|
||
(US-IPs gesperrt), wohl aber **Polymarket US** — eine eigene, CFTC-regulierte Börse (QCX LLC als
|
||
Designated Contract Market, QC Clearing LLC als Clearingstelle) mit KYC. Der Kunde kann KYC machen.
|
||
|
||
Polymarket US ist technisch **ein anderer Handelsplatz**, nicht eine Variante desselben. Keine
|
||
Zeile der heutigen CLOB-Anbindung ist dort verwendbar (siehe Abschnitt 2). Daraus folgen drei Ziele:
|
||
|
||
1. **Ein zweiter Plattform-Adapter** für Polymarket US.
|
||
2. **Plattform als Konzept im Core**, sodass ein dritter Handelsplatz (Kalshi) ein weiterer Adapter
|
||
ist und kein weiterer Umbau.
|
||
3. **Module erklären, welche Plattformen sie bedienen können** — sichtbar in Desktop und WebUI und
|
||
wirksam im Handelspfad. Strategien dürfen sich je Plattform unterscheiden.
|
||
|
||
---
|
||
|
||
## 2. Was Polymarket US anders macht
|
||
|
||
Quelle: offizielle Doku `https://docs.polymarket.us` (Stand 16.09.2026). Vor dem Bau erneut prüfen —
|
||
die Plattform ist jung und ändert sich (Gebühren wurden am 16.09.2026 angehoben).
|
||
|
||
| | Polymarket Global (heute) | Polymarket US |
|
||
|---|---|---|
|
||
| Endpunkte | CLOB, Gamma, Data-API getrennt | `api.polymarket.us` (authentifiziert), `gateway.polymarket.us` (öffentlich) |
|
||
| Echtzeit | CLOB-WSS, Alchemy/Polygon | `wss://api.polymarket.us/v1/ws/private` (Orders, Positionen, Saldo), `/v1/ws/markets` (Buch, Trades; max. 10 Märkte je Verbindung) |
|
||
| Anmeldung | L1 EIP-712 mit Wallet-Key → L2 HMAC (apiKey/secret/passphrase) | Key-ID + Ed25519-Secret; Header `X-PM-Access-Key`, `X-PM-Timestamp` (ms, ±30 s), `X-PM-Signature` = Base64(Ed25519(`timestamp + method + path`)) |
|
||
| Konto | Wallet / Proxy-Wallet, kein KYC | KYC-Person (iOS-App), Schlüssel unter `polymarket.us/developer`, Secret wird **nur einmal** angezeigt |
|
||
| Markt-Identität | conditionId + tokenId je Ausgang | `marketSlug`; Ausgang über `intent` bzw. `outcomeSide` YES/NO |
|
||
| Order | signierte Order (EIP-712), Preis als Zahl, FOK/GTC/GTD | `POST /v1/orders`: `intent` (`BUY_LONG`, `SELL_LONG`, `BUY_SHORT`, `SELL_SHORT`), `price {value, currency}`, `quantity` oder `cashOrderQty`, TIF `DAY/GTC/GTD/IOC/FOK`, `participateDontInitiate` (Post-only), `manualOrderIndicator`, `synchronousExecution` |
|
||
| Weitere Order-Wege | — | Modify, Preview, Close-Position, Sammel-Orders, Cancel-All |
|
||
| Geld | USDC auf Polygon | USD per Karte, ACH, Wire |
|
||
| Abwicklung | On-Chain-Redeem nötig (#146) | automatisch zu 1 $ / 0 $, kein Redeem |
|
||
| Gebühr | Taker in bps je Kategorie (`FeeModel`) | `Θ · C · p · (1−p)`; Taker Θ = 0,0695 (ab 16.09.2026), Maker-Rabatt Θ = −0,0125; Banker's Rounding auf Cent |
|
||
| Limits | eigene je Endpunkt | 20 Anfragen/s je Schlüssel bzw. je IP; 429 → Backoff. „Global Rate Limit Exceeded" nach 5 s ist Latenzschutz, **kein** Limit |
|
||
| Testumgebung | — | Retail-API: keine dokumentierte Sandbox. Preprod nur für die Exchange-API (OAuth), Zugang über onboarding@polymarket.us |
|
||
| Liquidität, Marktangebot | globaler Pool, voll | eigener US-Pool, kleineres Angebot |
|
||
|
||
**Zwei Folgen, die das Design bestimmen:**
|
||
|
||
- Die **Gebührenformel** ist eine andere *Form*, nicht nur ein anderer Satz. Ein „Satz in bps" reicht
|
||
als Modell nicht. Nahe 0,95 ist die US-Gebühr winzig, bei 0,50 am höchsten.
|
||
- **Fremde Wallets sind nicht sichtbar.** Alles, was CopyTrading heute beobachtet (Polygon-Logs,
|
||
Data-API-Activity), gibt es für den US-Pool nicht.
|
||
|
||
---
|
||
|
||
## 3. Ist-Zustand im Code
|
||
|
||
PolyTrader ist modular (Core + Module), aber **Polymarket Global ist überall stillschweigend
|
||
vorausgesetzt**:
|
||
|
||
| Stelle | Bindung |
|
||
|---|---|
|
||
| [`IClobClient`](../../../src/PolyTrader.Core/Services/IClobClient.cs) | `tokenId`, `isNegRisk`, `actualFeeBps`, Decimals-Overrides — CLOB-Begriffe im Vertrag |
|
||
| [`PolymarketClobClient`](../../../src/PolyTrader.Core/Services/PolymarketClobClient.cs), [`PolymarketApiService`](../../../src/PolyTrader.Core/Services/PolymarketApiService.cs) | direkt von Modulen aufgelöst; Registrierung von `IClobClient` sogar im CopyTrading-Modul |
|
||
| [`AccountState`](../../../src/PolyTrader.Core/Models/AccountState.cs) | `WalletAddress`, `ApiPassphrase`, `PrivateKey` — Global-Zugangsdaten als feste Felder |
|
||
| [`Position`](../../../src/PolyTrader.Core/Models/Position.cs), `core_positions` | Primärschlüssel `(AccountId, IsDemo, TokenId)` |
|
||
| [`MarketData`](../../../src/PolyTrader.Core/Models/MarketData.cs), `core_markets` | `ConditionId`, `ClobTokenIds`, `NegRisk` |
|
||
| [`FeeModel`](../../../src/PolyTrader.Core/Trading/FeeModel.cs) | statisch, bps je Kategorie |
|
||
| `Streaming/AlchemyWssClient`, `BlockchainWss` | Polygon |
|
||
| CopyTrading | 10 Dateien gegen CLOB/API/Chain |
|
||
| ResolutionFarming | hat schon `IFarmingMarketSource`, `IMarketResolutionSource` — **gutes Vorbild** |
|
||
| Accounting | hat schon `IActivitySource`, `ITransferSource`, `IBalanceAnchorSource` — ebenso |
|
||
| Supervisor | nur `CounterfactualJob` liest über die API |
|
||
|
||
`TokenId` kommt in 73 Dateien vor. Ein Umbau in einem Schritt ist ausgeschlossen.
|
||
|
||
---
|
||
|
||
## 4. Leitentscheidungen
|
||
|
||
1. **Die Plattform gehört zum Konto, nicht zur Installation.** Eine Installation kann Konten
|
||
mehrerer Plattformen führen. Ob der Netzweg das zulässt (US-Standort gegen US-IP-Sperre von
|
||
polymarket.com), ist eine Betriebsfrage (#622), keine Architekturfrage.
|
||
2. **Der Global-CLOB-Code wird umhüllt, nicht umgebaut.** Signierung, Betragsrechnung und
|
||
Orderablauf von `PolymarketClobClient` bleiben Zeile für Zeile, wie sie sind. Der
|
||
Global-Adapter übersetzt nur zwischen neutralem Vertrag und bestehendem Client. Das ist die
|
||
direkte Anwendung von `.agents/rules/clob.md`.
|
||
3. **Module sprechen gegen Plattform-Verträge**, nicht gegen `Polymarket*`-Klassen. Das Muster
|
||
existiert schon in ResolutionFarming und Accounting und wird verallgemeinert.
|
||
4. **Logik fragt nach Fähigkeiten, nicht nach Namen.** `if (caps.PublicTraderActivity)` statt
|
||
`if (platform == PolymarketGlobal)`. Ein neuer Handelsplatz bringt seine Fähigkeiten mit, und
|
||
bestehende Module entscheiden richtig, ohne ihn zu kennen.
|
||
5. **Module erklären ihre Plattformen ausdrücklich.** Fähigkeiten allein reichen nicht: Dass eine
|
||
Plattform alles Nötige *hat*, heißt nicht, dass die Strategie dort *geprüft* ist. Die Erklärung
|
||
ist eine Freigabe, die Fähigkeiten sind eine Plausibilitätsprüfung.
|
||
6. **Strategievarianten leben im Modul**, als Profil je Plattform — kein „ResolutionFarmingUS"-Modul.
|
||
Die fachliche Idee bleibt eine; Gebühren, Schwellen und Marktquelle unterscheiden sich.
|
||
7. **Global bleibt die Vorgabe.** Jede neue Spalte bekommt `polymarket-global` als Standardwert.
|
||
Bestehende Installationen merken nach der Migration nichts.
|
||
|
||
---
|
||
|
||
## 5. Architektur
|
||
|
||
### 5.1 Plattform und Fähigkeiten
|
||
|
||
```csharp
|
||
namespace PolyTrader.Core.Platforms;
|
||
|
||
/// Stabile Kennung, wird in der Datenbank gespeichert – nie umbenennen.
|
||
public readonly record struct PlatformId(string Value)
|
||
{
|
||
public static readonly PlatformId PolymarketGlobal = new("polymarket-global");
|
||
public static readonly PlatformId PolymarketUs = new("polymarket-us");
|
||
public static readonly PlatformId Kalshi = new("kalshi");
|
||
}
|
||
|
||
public sealed record PlatformCapabilities(
|
||
bool PublicTraderActivity, // fremde Trades beobachtbar (CopyTrading)
|
||
bool OnChainSettlement, // Redeem nötig, Chain-Transfers als Buchungsquelle
|
||
bool PostOnlyOrders,
|
||
bool OrderModify, // Preis ändern ohne Cancel+Neu
|
||
bool MakerRebate,
|
||
bool FractionalQuantity,
|
||
bool NativeDemoEnvironment, // echte Testumgebung der Plattform
|
||
IReadOnlySet<TimeInForce> TimeInForce,
|
||
string SettlementCurrency); // "USDC", "USD"
|
||
```
|
||
|
||
### 5.2 Verträge
|
||
|
||
Neutral formuliert, je Plattform einmal implementiert. Aufgelöst über eine Registry, nie direkt.
|
||
|
||
| Vertrag | Aufgabe | Global-Adapter hüllt | US-Adapter spricht |
|
||
|---|---|---|---|
|
||
| `IMarketCatalog` | Märkte suchen, nach Enddatum/Kategorie filtern, Auflösungsstatus | Gamma-API, `MarketSyncService` | `gateway` Markets/Events/Settlement |
|
||
| `IOrderBookSource` | Buch, BBO | CLOB `/book` | `gateway` Book/BBO |
|
||
| `IOrderGateway` | Platzieren, Ändern, Canceln, offene Orders | `PolymarketClobClient` | `POST/…/v1/orders` |
|
||
| `IPortfolioSource` | Positionen, Saldo, Aktivität | Data-API, Chain | Portfolio, Account-Balances |
|
||
| `IMarketStream` / `IAccountStream` | Echtzeit | CLOB-WSS, Alchemy | `/v1/ws/markets`, `/v1/ws/private` |
|
||
| `IFeeModel` | Gebühr für (Preis, Menge, Rolle) | heutiges `FeeModel` | `Θ·C·p·(1−p)` |
|
||
| `ISettlementHandler` | Was nach Auflösung zu tun ist | Redeem (#146) | nichts, nur Abgleich |
|
||
| `ITraderActivitySource` | fremde Trades | Polygon, Data-API | **nicht vorhanden** |
|
||
|
||
> **Stand nach #623 (18.09.2026):** Gebaut sind `IMarketCatalog`, `IOrderBookSource`, `IOrderGateway`,
|
||
> `IPortfolioSource`, `IFeeModel`, gebündelt in `IPlatformAdapter` (`src/PolyTrader.Core/Platforms/`).
|
||
> Die Streams, `ISettlementHandler` und `ITraderActivitySource` entstehen **mit ihrem ersten zweiten
|
||
> Nutzer**, nicht auf Vorrat: Streams mit #625, Abwicklung mit #146 bzw. #625, Trader-Aktivität mit #628.
|
||
> Die Registry löst den ganzen Adapter auf (`registry.ForAccount(account).Orders`), nicht einzelne
|
||
> Verträge per Typ.
|
||
|
||
```csharp
|
||
public interface IPlatformRegistry
|
||
{
|
||
IReadOnlyList<PlatformId> Available { get; }
|
||
PlatformCapabilities Capabilities(PlatformId p);
|
||
T Get<T>(PlatformId p) where T : class; // wirft, wenn Plattform den Vertrag nicht hat
|
||
bool TryGet<T>(PlatformId p, out T? service) where T : class;
|
||
}
|
||
```
|
||
|
||
`IClobClient` bleibt bestehen, bis CopyTrading umgestellt ist; `IOrderGateway` für Global delegiert
|
||
darauf. Es gibt keinen Tag, an dem beides gleichzeitig umgeschrieben wird.
|
||
|
||
### 5.3 Instrument und Order
|
||
|
||
```csharp
|
||
/// Ein handelbarer Ausgang auf einer Plattform. Key ist innerhalb der Plattform eindeutig.
|
||
/// Global: Key = tokenId, MarketKey = conditionId
|
||
/// US: Key = "{marketSlug}:YES", MarketKey = marketSlug
|
||
/// Kalshi: Key = "{ticker}:YES", MarketKey = ticker
|
||
/// Gleichheit nur über (Platform, Key).
|
||
public sealed record InstrumentRef(PlatformId Platform, string Key, string MarketKey = "", string Outcome = "");
|
||
|
||
public sealed record OrderRequest(
|
||
InstrumentRef Instrument,
|
||
OrderSide Side, // Buy / Sell (US: → intent BUY_LONG usw.)
|
||
decimal LimitPrice, // immer Wahrscheinlichkeit 0..1 – Adapter rechnet um (Kalshi: Cent)
|
||
decimal? Quantity, // Kontrakte/Shares
|
||
decimal? NotionalUsd, // alternativ Betrag
|
||
TimeInForce Tif,
|
||
bool PostOnly,
|
||
string OriginModule, // für die Plattform-Sperre (5.6) und das Journal
|
||
string CorrelationId);
|
||
```
|
||
|
||
Plattformspezifisches (Global: `negRisk`, Tick-Size, Decimals; US: `manualOrderIndicator`,
|
||
`synchronousExecution`) bleibt **im Adapter**. Der US-Adapter setzt `manualOrderIndicator` fest auf
|
||
`AUTOMATIC` — ein Bot, der sich als manuell ausgibt, ist ein Compliance-Fehler, keine Einstellung.
|
||
|
||
### 5.4 Konten und Zugangsdaten
|
||
|
||
- `core_accounts.platform` (Vorgabe `polymarket-global`).
|
||
- Zugangsdaten je Plattform, verschlüsselt wie F1 (`EncryptedStringConverter`):
|
||
- Global: wie heute (Wallet, Key, Secret, Passphrase, PrivateKey).
|
||
- US: Key-ID in `ApiKey`, Ed25519-Secret in `ApiSecret`. `WalletAddress`, `PrivateKey`,
|
||
`PayoutAddress` leer.
|
||
- Kalshi: Key-ID + privater Schlüssel.
|
||
|
||
Die bestehenden Felder reichen für US und Kalshi. Eine eigene Tabelle je Plattform wäre sauberer,
|
||
kostet aber eine zweite Migration der F1-Verschlüsselung. **Entscheidung: vorhandene Felder
|
||
wiederverwenden**, die Kontenansicht zeigt je Plattform nur die passenden Felder mit passender
|
||
Beschriftung. Neu prüfen, falls eine Plattform mehr als vier Geheimnisse braucht.
|
||
- Die Passwortsperre vor Konten und Geheimnissen (#567) gilt unverändert; Geheimnisse bleiben
|
||
Desktop-only (WebUI-Parität).
|
||
|
||
### 5.5 Datenbank
|
||
|
||
| Tabelle | Änderung |
|
||
|---|---|
|
||
| `core_accounts` | `+ platform` |
|
||
| `core_positions` | **keine Änderung** (Entscheidung in #623): Eine Position gehört zu einem Konto, das Konto zu genau einer Plattform. `(AccountId, IsDemo, TokenId)` bleibt eindeutig, solange `TokenId` den plattformeindeutigen `InstrumentRef.Key` hält. Eine eigene Spalte wäre eine zweite Wahrheit, die auseinanderlaufen kann |
|
||
| `core_markets` | `+ platform`; Schlüssel `(Platform, Id)` |
|
||
| Modultabellen mit Token-Bezug (`ct_`, `rf_`, `acc_`) | `+ platform` mit Vorgabe, je Modul im jeweiligen Schritt |
|
||
|
||
`Position.TokenId` bleibt, wie es ist, und hält `InstrumentRef.Key`. Die 73 Fundstellen ziehen
|
||
schrittweise um, statt in einem Commit.
|
||
|
||
Die lesenden Methoden von `IMarketRepository` (`GetById`, `FindByTokenId`, `GetActive`) liefern seit #623
|
||
nur Global-Märkte — ihre Aufrufer arbeiten mit Gamma-IDs und Token-IDs.
|
||
|
||
**Migration `AddPlatformColumns`:** Es gibt keine automatischen Migrationen beim Start. Vor dem ersten
|
||
Start einer Fassung mit #623 muss auf dem Server `dotnet ef database update --project src/PolyTrader.Core`
|
||
laufen, sonst scheitert jede Abfrage an der fehlenden Spalte `Platform`.
|
||
|
||
### 5.6 Module erklären ihre Plattformen („Auslöser")
|
||
|
||
Erweiterung von [`IPolyTraderModule`](../../../src/PolyTrader.Core/Modularity/IPolyTraderModule.cs),
|
||
abwärtskompatibel über Default-Implementierungen:
|
||
|
||
```csharp
|
||
/// Plattformen, für die dieses Modul geprüft und freigegeben ist.
|
||
/// Vorgabe: nur Polymarket Global – ein Modul, das nichts erklärt, verhält sich wie heute.
|
||
IReadOnlySet<PlatformId> SupportedPlatforms => new HashSet<PlatformId> { PlatformId.PolymarketGlobal };
|
||
|
||
/// Grund, warum das Modul eine erklärte Plattform in dieser Installation trotzdem nicht bedienen kann
|
||
/// (fehlende Fähigkeit, fehlender Schlüssel). null = bedienbar.
|
||
string? GetPlatformBlocker(PlatformId platform, PlatformCapabilities caps) => null;
|
||
```
|
||
|
||
**Eine Stelle für die Regeln.** Wie `ModuleActivationView` seit #560 liegt die Auswertung im Core
|
||
(`ModulePlatformView`), und Desktop und WebUI zeigen dasselbe:
|
||
|
||
| Wo | Was man sieht |
|
||
|---|---|
|
||
| Modul-Tab (Desktop, WebUI) | je Modul Plattform-Kennzeichen: ✓ bedienbar, ⚠ erklärt aber blockiert (mit Grund), — nicht erklärt |
|
||
| Kontenansicht | je Konto die Module, die es bedienen |
|
||
| Dashboard-Warnung | aktives Konto, das kein aktives Modul bedient; aktives Modul ohne passendes Konto |
|
||
|
||
**Wirksam an zwei Stellen:**
|
||
|
||
1. **Zuteilung:** Ein Modul bekommt nur Konten, deren Plattform es erklärt und nicht blockiert.
|
||
Module filtern nicht selbst — sie fragen den Core nach „meinen Konten".
|
||
2. **Handelspfad:** Die Registry reicht jedem Modul ein `IOrderGateway`, das `OriginModule` prüft
|
||
und eine Order für eine nicht erklärte Plattform **ablehnt und ins Journal schreibt**. Das ist die
|
||
zweite Sicherung nach dem Muster von `TradingGate` (#570): Eine Sperre, die nur in der Oberfläche
|
||
existiert, hält keinen Programmierfehler auf.
|
||
|
||
**Erste Erklärungen:**
|
||
|
||
| Modul | Global | US | Begründung |
|
||
|---|---|---|---|
|
||
| CopyTrading | ✓ | — | braucht `PublicTraderActivity`; plattformübergreifend siehe #628 |
|
||
| ResolutionFarming | ✓ | ✓ (ab #626) | nur eigene Marktdaten nötig, US-Gebühr nahe 1 sehr klein |
|
||
| Accounting | ✓ | ✓ (ab #627) | Quellen je Plattform |
|
||
| Supervisor | ✓ | ✓ | liest Journal und Dossiers, handelt nicht; `CounterfactualJob` über `IMarketCatalog` |
|
||
|
||
### 5.7 Strategieprofile je Plattform
|
||
|
||
Ein Modul, das mehrere Plattformen erklärt, hält Einstellungen **je Plattform**
|
||
(`rf_settings.platform`). Das Profil legt fest:
|
||
|
||
- Gebührenmodell (aus der Registry, nie hart kodiert) — betrifft jeden Netto-Edge-Check.
|
||
- Schwellen (Einstiegspreis, Mindest-Edge, Mindestliquidität). Bei getrenntem, kleinerem US-Pool
|
||
sind Global-Werte **nicht** übertragbar; Startwerte stammen aus der Messphase.
|
||
- Order-Stil: auf US lohnt Post-only wegen des Maker-Rabatts; auf Global zahlt der Maker 0.
|
||
- Abwicklung: Global mit Redeem, US ohne.
|
||
|
||
Die fachliche Logik (Kandidatenbewertung, Sizing, Risikogrenzen) bleibt gemeinsam und testbar ohne
|
||
Plattform.
|
||
|
||
### 5.8 Demo-Modus
|
||
|
||
Demo bleibt eine Eigenschaft des Kontos (`IsDemo`). Demo-Fills rechnen gegen **das Buch der Plattform
|
||
des Kontos**, mit deren Gebührenmodell. Da die US-Retail-API keine Sandbox hat, ist Demo gegen das
|
||
echte US-Buch der einzige Weg zur Messphase — und damit Pflicht vor dem Livegang.
|
||
|
||
---
|
||
|
||
## 6. Umsetzungsschritte
|
||
|
||
| Item | Schritt | Voraussetzung | Ergebnis |
|
||
|---|---|---|---|
|
||
| #622 | **PL-0** Voraussetzungen US-Kunde | — | KYC, API-Schlüssel, Serverstandort, Rolle geklärt |
|
||
| #623 | **PL-1** Plattform-Fundament | — | Verträge, Registry, Global-Adapter, DB-Spalten; **Verhalten unverändert** |
|
||
| #624 | **PL-2** Plattform-Erklärung der Module | #623 | Anzeige + Zuteilung + Sperre im Gateway |
|
||
| #625 | **PL-3** Adapter Polymarket US | #623; für echte Orders #622 | erst lesend, dann Demo, dann Orders |
|
||
| #626 | **PL-4** ResolutionFarming für US | #624, #625 | Profil je Plattform, Messphase |
|
||
| #627 | **PL-5** Accounting für US | #625 | US-Quellen statt Data-API/Chain |
|
||
| #628 | **PL-6** CopyTrading plattformübergreifend | #625 + Entscheidung | nicht beschlossen |
|
||
| #629 | **PL-7** Adapter Kalshi | #623 + konkreter Bedarf | nicht beschlossen |
|
||
|
||
### Akzeptanzkriterien
|
||
|
||
**PL-1**
|
||
- Alle bestehenden Tests grün, ohne Anpassung ihrer Erwartungen.
|
||
- Diff an `PolymarketClobClient.cs` ist leer. Backup trotzdem vor Beginn (Regel).
|
||
- Migration auf einer Kopie der Server-Datenbank: Bestandspositionen haben danach
|
||
`platform = polymarket-global` und denselben `OutcomeKey` wie vorher `TokenId`.
|
||
- Neue Tests: Registry löst je Plattform auf; Global-Adapter reicht Aufrufe 1:1 an den Client durch.
|
||
|
||
**PL-2**
|
||
- Ein Modul ohne Erklärung verhält sich exakt wie heute.
|
||
- Test: Order über das Gateway mit nicht erklärter Plattform → abgelehnt, Journal-Eintrag, keine
|
||
HTTP-Anfrage.
|
||
- Desktop und WebUI zeigen für dieselbe Konfiguration dieselben Kennzeichen (ein gemeinsamer Test
|
||
gegen `ModulePlatformView`).
|
||
|
||
**PL-3**
|
||
- Signatur gegen die Beispielwerte der Doku geprüft (Einheitentest mit festem Schlüssel und Zeitstempel).
|
||
- Lesend gegen Produktion: Märkte, Buch, Positionen, Saldo des Kundenkontos.
|
||
- 429 → Backoff; „Global Rate Limit Exceeded" → **kein** Drosseln (siehe Abschnitt 2).
|
||
- Secret nie im Log, nie im WebUI, verschlüsselt at-rest.
|
||
- Erste echte Order erst nach PL-4-Messphase und mit Freigabe durch Richard.
|
||
|
||
**PL-4**
|
||
- Netto-Edge-Check nutzt das US-Gebührenmodell (Test mit p = 0,50 und p = 0,97).
|
||
- Demo-Messphase mit definiertem Zeitraum und Auswertung, bevor Live freigegeben wird.
|
||
|
||
---
|
||
|
||
## 7. Ausblick Kalshi
|
||
|
||
Kalshi ist der Prüfstein für PL-1: Lässt sich der Adapter bauen, **ohne ein Modul anzufassen**, trägt
|
||
die Abstraktion. Bekannte Unterschiede (vor dem Bau gegen die aktuelle Kalshi-Doku prüfen): eigene
|
||
Anmeldung mit signierten Anfragen und privatem Schlüssel, Märkte über Ticker, Preise in Cent, eigene
|
||
Gebührenformel, eigene Demo-Umgebung. Genau deshalb ist `LimitPrice` im Vertrag eine Wahrscheinlichkeit
|
||
0..1 und die Umrechnung Sache des Adapters.
|
||
|
||
---
|
||
|
||
## 8. Offene Fragen
|
||
|
||
| Frage | Wer | Item |
|
||
|---|---|---|
|
||
| Gibt es für die Retail-API eine Testumgebung? | Anfrage an Polymarket US | #622 |
|
||
| Wo läuft die Installation des US-Kunden, und darf sie zugleich Global-Konten führen? | Richard | #622 |
|
||
| Rechtliche Einordnung unserer Rolle bei automatisiertem Handel auf einem fremden KYC-Konto | Richard / Rechtsberatung | #622 |
|
||
| Lohnt CopyTrading mit Global-Signal und US-Ausführung trotz anderer Kurse? | Entscheidung | #628 |
|
||
| Reihenfolge gegenüber Themenbereich A (Abnahme, #621 Betriebsfreigabe) | Richard | — |
|