Files
Predictalytics/docs/archiv/PLAN-DatenIngest-Skalierung.md
T
RichardandClaude Opus 5 6975720dc6 Eine Roadmap statt neun Plandokumente; alte Plaene ins Archiv
Die offenen Punkte lagen ueber neun Dokumente verstreut, teils widersprechend,
teils mit Punkten, die laengst umgesetzt waren. ROADMAP.md fuehrt sie zusammen:
sechs Stufen, jeder Punkt gegen den Code geprueft.

Markierung ueber eine Legende, damit Konzepte nicht mit Aufgaben verwechselt
werden: dringend, eingeplant, Backlog, Konzept (durchdacht, aber bewusst nicht
eingeplant), liegt beim Nutzer, verworfen.

Stufen: 0 Sofort (OpenRouter-Key) - 1 Aufraeumen abschliessen (Merge nach main,
Nullable-Warnungen, Startup-Backfill) - 2 Portierung abschliessen (Linux-Erstlauf
und Verifikation, dann Deployment/CI) - 3 Analytik schaerfen (Strategie-
Klassifikation, Backtest-Harness, Track-Record im Score, Ranking) - 4 Daten-
haushalt (SQL des Nutzers) - 5 Ingest skalieren - 6 Monetarisierung vorbereiten.

Ein Anhang haelt fest, was geprueft und bewusst NICHT auf die Roadmap kam, damit
es nicht versehentlich wieder als Aufgabe auftaucht (Azuro/Limitless, die
Marketing-Seiten, Kaltarchiv, EF Core 10).

Archiv: FIXPLAN-DONE, FIXPLAN-G-Speicher, FIXPLAN-TODO, FIXPLAN-UI-Ranglisten,
UMSETZUNGSPLAN sowie ANALYSE-Linux-Portierung, PLAN-Linux-Portierung,
PLAN-Architektur-WebUI-Backend und PLAN-DatenIngest-Skalierung liegen jetzt
unter docs/archiv/ mit einer README, die jedes Dokument einordnet. Sie bleiben
als Begruendungs- und Detailquelle - die Roadmap nennt jeden Punkt knapp, die
Herleitung steht dort.

Dabei aufgefallen: die beiden nie gepflegten Plaene (Architektur, DatenIngest)
zeigten 40 offene Punkte, von denen die Haelfte umgesetzt war - Read/Control-
Split, /api/capabilities, CORS-Whitelist, Egress-Kanaele mit Cooldown und
Per-Kanal-Limiter, Ingest-Tiering. Nachgeprueft, abgehakt und mit Statusblock
eingeordnet, sonst waere das Archiv selbst eine Fehlerquelle.

Was dabei nur teilweise umgesetzt war, ist als Roadmap 5.3 aufgenommen
(Health-Statistik je Kanal, multi-homed pruefen, DB-Guard, Plausibilitaets-
pruefung), ebenso der nie durchgefuehrte Audit auf versteckte Writes in
Read-Endpunkten (6.1). Header-Rotation ist als verworfen markiert statt offen
zu bleiben: Verschleierung gegenueber Polymarket riskiert genau den Zugang, auf
dem das Projekt aufsetzt.

STATUS.md beschreibt jetzt nur noch den Ist-Stand und verweist fuer die offenen
Punkte auf die Roadmap, damit nichts doppelt gepflegt wird. CLAUDE.md nennt
beide Einstiege.

Build gruen, 126 Tests gruen, keine toten Links.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 18:46:00 +02:00

9.2 KiB
Raw Blame History

Plan: Daten-Ingest skalieren (Rate-Limits, Egress-Kanäle, Blockchain)

Archiviert am 2026-08-23 — offene Punkte siehe ROADMAP.md, Stufe 5. Dieses Dokument wird nicht mehr gepflegt.

Erledigt und hier nachträglich abgehakt:

  • 1c Ingest-TieringIngestMode mit SnapshotOnly/Aggregated, siehe FIXPLAN-TODO.md Teil D.
  • 1d RedundanzIMemoryCache im PolymarketApiClient.
  • 2a/2b Egress-KanäleInfrastructure/Services/EgressPoolService.cs und EgressPoolHandler.cs: Round-Robin über die aktiven Kanäle, Umschalten rein per Konfiguration, Cooldown nach drei Fehlschlägen in Folge (:152), sodass ein 429 nur den betroffenen Kanal trifft. Der Limiter-Schlüssel enthält den Kanal (RateLimiterService.cs:36). Tests: EgressPoolTests.cs.

Teilweise: Health-Statistik je Kanal (Erfolgsquote, 429-Rate, Latenz) fehlt — es gibt nur Fehlerzähler und Cooldown. Tote Kanäle werden also pausiert, aber nicht ausgewertet.

Offen: 1a (Blockchain/Subgraph als Bulk-Quelle) und 1b (Markt-Stammdaten-Cache) sind Roadmap 5.1 und 5.2. Abschnitt 3a (Header-Rotation) ist bewusst verworfen — siehe Roadmap 5.3: Verschleierung gegenüber Polymarket riskiert genau den Zugang, auf dem das Projekt aufsetzt.

Stand: 2026-07-12 · Status: Richtung bestätigt (Nutzer: beide Egress-Wege umschaltbar umsetzen, sofern Aufwand vertretbar). Kein Code in diesem Schritt. Problem: Polymarket-Rate-Limits bremsen den Datenimport teils extrem aus.

0. Ist-Zustand (verifiziert)

  • RateLimiterService = globaler Singleton-Token-Bucket, feste Delays je Endpoint-Gruppe (Gamma ≈28/s, Data ≈18/s, Clob ≈66/s).
  • PolymarketApiClient = Singleton mit 3 benannten HttpClients, ohne Proxy/IP-Konfig → ein einziger Ausgangs-IP, ein globales Budget. Das ist die echte Bremse.

Zwei Hebel: Nachfrage senken (Abschnitt 1, größter Gewinn) und Angebot erhöhen (Abschnitt 2, Egress-Kanäle). Der Nutzer möchte in Abschnitt 2 beide Egress-Arten (eigene IPs UND Proxys) umschaltbar — und das ist billig, weil beide derselbe HttpClient-Seam sind (Abschnitt 2).


1. Nachfrage senken — größter Hebel (zuerst)

1a. Historische Massendaten aus Blockchain/Subgraph statt REST

Polymarket-Trades sind On-Chain-Events auf Polygon. Für Backfill/Deep-Resync (größter REST-Verbraucher) ist /activity die falsche Quelle.

  • The-Graph-/Goldsky-Subgraph für Polymarket evaluieren: ein GraphQL-Call → tausende Fills eines Wallets, statt seitenweiser rate-limitierter REST-Abrufe.
  • Neue IHistoricalTradeSource neben dem REST-Provider; DeepResync (FIXPLAN A6) zieht Bulk hierüber. Effekt: nimmt die teuerste Last komplett von der REST-API.

1b. Markt-Stammdaten aggressiv cachen

  • Metadaten (Frage, Kategorie, Outcomes, ConditionIdTokenId) einmal ziehen, lange cachen; nur Volume/Liquidity/Auflösung periodisch aktualisieren. Geschlossene Märkte nie voll re-syncen.

1c. Ingest-Tiering (FIXPLAN D3)

  • Ultra-HF-Trader im SnapshotOnly-Modus erzeugen null Trade-Calls (PnL aus /positions + Leaderboard, wöchentliche Biopsie). Entfernt genau die Wallets, die das Budget auffressen.

1d. Redundanz vermeiden

  • Worker-übergreifender Kurzzeit-Cache „gerade geholt", damit nicht mehrere Worker denselben Markt/Trader kurz hintereinander abrufen.

2. Angebot erhöhen: umschaltbare Egress-Kanäle (eigene IPs UND Proxys — eine Mechanik)

Die Schlüssel-Einsicht: Ob eine Anfrage über eine eigene Quell-IP oder über einen Proxy rausgeht, ist im HttpClient nur eine andere Konfiguration desselben SocketsHttpHandler. Deshalb wird nicht zweimal gebaut, sondern ein Konzept: der Egress-Kanal. Umschalten = Konfiguration, nicht Code. Damit bekommt der Nutzer „beides, umschaltbar" zu geringen Kosten.

2a. Abstraktion EgressChannel

Ein Kanal ist genau eine Ausgangsroute, per Config als einer von zwei Typen definiert:

"Egress": {
  "Channels": [
    { "id": "ip-a",   "type": "SourceIp", "value": "203.0.113.10" },   // eigene IP
    { "id": "ip-b",   "type": "SourceIp", "value": "203.0.113.11" },
    { "id": "prox-1", "type": "Proxy",    "value": "http://user:pass@proxy.example:8080" }
  ]
}
  • Pro Kanal ein SocketsHttpHandler:
    • SourceIpConnectCallback, Socket vor Connect an die lokale IP binden (socket.Bind(new IPEndPoint(ip, 0))).
    • Proxyhandler.Proxy = new WebProxy(url); handler.UseProxy = true;.
  • IEgressPool verteilt Requests round-robin/least-loaded über die aktiven Kanäle. Leere/❑ Kanalliste = heutiges Verhalten (ein Default-Ausgang).
  • Umschalten „nur eigene IPs" ↔ „nur Proxys" ↔ „Mix" = Config ändern, kein Deploy-Umbau.

2b. Rate-Limiter pro Kanal (Generalisierung des globalen Limiters)

  • Limiter-Schlüssel wird {platform}-{endpointGroup}-{channelId}. Jeder Kanal hält sein eigenes Budget → N Kanäle ≈ N× Durchsatz, jeder Kanal bleibt unter dem Per-Route-Limit.
  • 429 sperrt nur den betroffenen Kanal kurz, nicht alle.

2c. Betrieb

  • Bei eigenen IPs prüfen: sind es echte getrennte Egress-IPs (multi-homed), nicht NAT hinter einer.
  • Health/Statistik je Kanal (Erfolg, 429-Rate, Latenz), damit tote Proxys automatisch pausiert werden.

Aufwand: moderat und einmalig — durch die gemeinsame Abstraktion kostet „beides umschaltbar" kaum mehr als „nur IPs".


3. Proxys & Header-Rotation — Einordnung (korrigiert)

Klarstellung (Korrektur einer früheren Fassung): Predictalytics betreibt kein Trading und keine Wallet — es ist reine Analysesoftware, die ausschließlich öffentliche Marktdaten liest. Das frühere „Ban gefährdet die Trading-Wallet"-Argument gehört zu PolyTrader (getrenntes Projekt) und trifft hier nicht zu. Damit ist die Proxy-Wahl eine reine Engineering-Entscheidung des Nutzers — freie Proxys eingeschlossen.

Was real bleibt (ehrliche Hinweise, keine Blocker — Entscheidung liegt beim Nutzer):

  • ToS-Grauzone: Rate-Limit-Umgehung per Routen-/Header-Rotation widerspricht vermutlich Polymarkets Nutzungsbedingungen. Realistische Konsequenz hier: einzelne IPs/Proxys werden geblockt und müssen ersetzt werden — mehr nicht (kein Kapital, keine Wallet betroffen).
  • Datenintegrität (der eigentlich relevante Punkt): Ein kaputter/bösartiger (v. a. gratis) Proxy kann Antworten verfälschen → korrupte Analyse („garbage in, garbage out"). Da die gesamte Auswertung darauf aufbaut, lohnt sich eine Plausibilitätsprüfung der Antworten (Feldtypen, Wertebereiche, z. B. Preise ∈ [0,1]) und — wo Genauigkeit zählt — das Bevorzugen kontrollierter Proxys/eigener IPs. Rein informativ, kein Zwang.
  • DB-Verbindung NIE über Proxy (ausdrücklicher Nutzer-Wille): Die MySQL-Verbindung läuft immer direkt. Der Egress-Pool gilt ausschließlich für ausgehende Polymarket-HTTP-Calls, niemals für die DB.

3a. Header-Rotation (separat aktivierbar, standardmäßig AUS)

Auf Wunsch integriert, bewusst opt-in:

  • Config Egress.HeaderRotation.EnabledDefault false. Bei false wird ein einziger, konsistenter Standard-Header-Satz gesendet (heutiges Verhalten).
  • Rotiert kohärente Header-SETS, nicht nur den User-Agent isoliert: je Eintrag ein zusammenpassendes Bündel (User-Agent + Accept + Accept-Language + Sec-CH-UA…), damit die Kombination realistisch bleibt — ein moderner UA mit widersprüchlichen Accept-Headern fällt eher auf als gar keine Rotation. Set-Pool aus Config ladbar.
  • Auswahl pro Kanal oder pro Request (konfigurierbar).
  • Greift nur für Polymarket-Read-Calls; unabhängig vom Kanaltyp (IP oder Proxy) nutzbar.

4. Reihenfolge

  1. 1b + 1d (Caching/Dedup) — sofort, klein, spürbar.
  2. 2a2c (Egress-Kanäle + Per-Kanal-Limiter) — moderat, liefert „eigene IPs UND Proxys umschaltbar".
  3. 1c (Tiering) — hängt an FIXPLAN D3.
  4. 1a (Blockchain/Subgraph-Bulk) — größter struktureller Hebel; eigener Rechercheschritt (welcher Subgraph deckt Fills sauber ab?), dann als IHistoricalTradeSource.

5. Tests / Abnahme

  • Per-Kanal-Limiter: unabhängige Budgets (kein globales Blocken); 429 sperrt nur einen Kanal.
  • Egress-Binding: Smoke gegen einen Dienst, der die Quell-IP zurückgibt → Round-Robin nutzt wirklich verschiedene IPs; Proxy-Kanal geht über den Proxy.
  • Kanal-Health: toter Proxy wird automatisch pausiert, Pool weicht aus.
  • Blockchain-Quelle: Stichproben-Abgleich Bulk-Historie ↔ REST-/activity eines Wallets, bevor sie produktiv wird.
  • Header-Rotation: bei Enabled=false wird genau ein konsistenter Standard-Satz gesendet (kein Rotieren); bei Enabled=true stammt jeder gesendete Header-Satz unverändert aus dem Pool (kohärent, keine zusammengewürfelten Felder).
  • DB-Guard: die MySQL-Verbindung nutzt nie den Egress-Pool/Proxy (Regressionsschutz).
  • Response-Plausibilität: grob unplausible Provider-Antworten (z. B. Preis außerhalb [0,1]) werden erkannt und verworfen statt in die DB zu wandern.