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>
This commit is contained in:
@@ -1,7 +1,12 @@
|
||||
# Predictalytics
|
||||
|
||||
**Stand des Projekts, offene Punkte und Altlasten-Entscheidungen:
|
||||
[`STATUS.md`](STATUS.md)** — dort zuerst nachsehen.
|
||||
**Zuerst hier nachsehen:**
|
||||
* [`STATUS.md`](STATUS.md) — wo das Projekt steht, was fertig ist.
|
||||
* [`ROADMAP.md`](ROADMAP.md) — was ansteht, in welcher Reihenfolge, und welche Konzepte
|
||||
bewusst zurückgestellt sind.
|
||||
|
||||
Die früheren Plandokumente liegen unter [`docs/archiv/`](docs/archiv/) und werden nicht
|
||||
mehr gepflegt.
|
||||
|
||||
Betriebsdokumentation zur Anbindung an das Deployment Center (Lizenz, Watchdog,
|
||||
Updates, Fehler-Stream): [`docs/BETRIEB-Deploymentcenter.md`](docs/BETRIEB-Deploymentcenter.md).
|
||||
|
||||
+310
@@ -0,0 +1,310 @@
|
||||
# Predictalytics — Roadmap
|
||||
|
||||
> Angelegt am **2026-08-23**. Führt zusammen, was vorher über neun Plandokumente verstreut
|
||||
> lag. Jeder Punkt hier ist gegen den Code geprüft — was schon umgesetzt war, steht nicht
|
||||
> mehr drin.
|
||||
>
|
||||
> **Ist-Stand des Projekts:** [`STATUS.md`](STATUS.md).
|
||||
> **Die alten Dokumente** liegen vollständig unter [`docs/archiv/`](docs/archiv/) und
|
||||
> werden nicht mehr gepflegt. Sie bleiben als Begründungs- und Detailquelle: wo ein Punkt
|
||||
> unten knapp bleibt, steht die ausführliche Herleitung dort. Die Verweise sind jeweils
|
||||
> angegeben.
|
||||
|
||||
## Legende
|
||||
|
||||
| | Bedeutung |
|
||||
|---|---|
|
||||
| 🔴 | Dringend — sollte vor allem anderen passieren |
|
||||
| 🟢 | Eingeplant — wird als Nächstes abgearbeitet |
|
||||
| 🟡 | Backlog — gewollt, aber noch nicht terminiert |
|
||||
| 💡 | **Konzept — bewusst nicht eingeplant.** Idee ist durchdacht und aufgehoben, die Umsetzung ist nicht beschlossen |
|
||||
| 👤 | Liegt beim Nutzer, nicht am Code (SQL, Kontoverwaltung, Entscheidungen) |
|
||||
| ❌ | Bewusst verworfen — nicht wieder aufgreifen ohne neuen Anlass |
|
||||
|
||||
Innerhalb der Stufen ist die Reihenfolge gedacht, aber nicht bindend. Zwischen den Stufen
|
||||
schon: jede baut auf der vorigen auf.
|
||||
|
||||
---
|
||||
|
||||
## Stufe 0 — Sofort
|
||||
|
||||
### 0.1 🔴 👤 OpenRouter-API-Key zurückziehen und neu ausstellen
|
||||
|
||||
`src/Predictalytics.Api/appsettings.json` enthält einen **echten** Schlüssel im Klartext,
|
||||
versioniert seit Commit `7045002` und damit auf dem Gitea-Server.
|
||||
|
||||
1. Schlüssel bei OpenRouter widerrufen, neuen ausstellen.
|
||||
2. Neuen Schlüssel **nicht** in die Datei schreiben, sondern als Umgebungsvariable
|
||||
`OpenRouter__ApiKey` setzen. `WebApplication.CreateBuilder` liest Umgebungsvariablen mit
|
||||
Vorrang vor `appsettings.json` — dafür ist keine Codeänderung nötig.
|
||||
3. Erst danach den Platzhalter in `appsettings.json` leeren.
|
||||
|
||||
Den Wert nur aus der Datei zu löschen genügt nicht: der Git-Verlauf behält ihn. Deshalb
|
||||
führt an Schritt 1 kein Weg vorbei.
|
||||
|
||||
> Herkunft: [`archiv/UMSETZUNGSPLAN.md`](docs/archiv/UMSETZUNGSPLAN.md) B2 — dort noch als „kein akuter Risikofall" eingestuft, was
|
||||
> sich als falsch herausgestellt hat.
|
||||
|
||||
---
|
||||
|
||||
## Stufe 1 — Aufräumen abschließen
|
||||
|
||||
### 1.1 🟢 `feature/linux-net10` nach `main` bringen
|
||||
|
||||
`main` steht neun Commits zurück und kennt weder die Avalonia-Shell noch die
|
||||
Deploymentcenter-Anbindung. Alle Feature-Zweige sind in `feature/linux-net10` aufgegangen.
|
||||
|
||||
Danach löschbar (lokal und auf origin):
|
||||
|
||||
```
|
||||
copy-portfolio edge-freshness fingerprint-drift-foundation insider-follow-feed
|
||||
integration smart-money-comovement smart-money-graph ui-ranglisten-showcases
|
||||
ops-watchdog-license fix-event-description-truncation
|
||||
```
|
||||
|
||||
### 1.2 🟡 Acht Nullable-Warnungen beheben
|
||||
|
||||
`TradeRepository.cs:94-102` (6×), `PolymarketProvider.cs:357`,
|
||||
`TraderAnalyticsWorker.cs:152`. Bestehen seit Längerem und sind kein Aufräumen, sondern
|
||||
Logikarbeit — jede will einzeln angesehen werden, ob `null` dort auftreten kann.
|
||||
|
||||
### 1.3 🟡 Startup-Backfill entschärfen
|
||||
|
||||
`PredictalyticsHost.cs:116` lädt bei **jedem Start** alle Märkte samt Event in den
|
||||
Speicher, um Kategorien neu abzuleiten. Bei wachsendem Bestand belastet das die Startzeit
|
||||
spürbar. Entweder auf Märkte mit `Category = Other` einschränken, oder einmalig laufen
|
||||
lassen und über ein Flag abschalten.
|
||||
|
||||
---
|
||||
|
||||
## Stufe 2 — Portierung abschließen
|
||||
|
||||
Der Code ist plattformneutral gebaut, aber **auf keinem Linux-System je ausgeführt worden**.
|
||||
Bis das nachgeholt ist, ist „läuft unter Linux" eine Annahme.
|
||||
|
||||
> Details zu allen Punkten: [`docs/archiv/PLAN-Linux-Portierung.md`](docs/archiv/PLAN-Linux-Portierung.md),
|
||||
> Abschnitte 7 und 8.
|
||||
|
||||
### 2.1 🟢 Erstlauf und Verifikation unter Linux
|
||||
|
||||
Die Reihenfolge ist bewusst so: erst beweisen, dass es läuft, dann Deployment bauen.
|
||||
|
||||
- [ ] Shell auf einem Linux-Desktop starten — alle Schaltflächen, Menüs, Persistenz der Einstellungen
|
||||
- [ ] Derselbe Build mit `--headless` auf einem Server ohne X11: Start, Lizenz aus der Konfiguration, sauberer Stopp per SIGTERM
|
||||
- [ ] Worker-Dauerlauf ≥ 24 h gegen die **Dev-DB**, Logvergleich mit einem Windows-Lauf
|
||||
- [ ] Lauf unter `LANG=de_DE.UTF-8` — Volumina, Preise, PnL gegen die Windows-Referenz prüfen (Kultur-Fallen)
|
||||
- [ ] Web-UI vollständig durchklicken — case-sensitive Assets sind unter Linux ein echtes Risiko
|
||||
- [ ] Lizenz: Erstaktivierung, Neustart aus dem Cache, Offline-Gnadenfrist, Revalidierung
|
||||
- [ ] Watchdog-Heartbeats erscheinen am Deployment Center
|
||||
- [ ] EF-Migrationen von Null gegen die Dev-DB
|
||||
- [ ] Egress-Kanäle, falls genutzt (`SourceIp` verhält sich unter Linux anders)
|
||||
|
||||
### 2.2 🟢 Deployment und CI
|
||||
|
||||
- [ ] `dotnet publish -r linux-x64` und `-r win-x64`; bei self-contained das Trimming-Verhalten von Avalonia beachten
|
||||
- [ ] Linux-Systemabhängigkeiten dokumentieren: `libx11-6`, `libice6`, `libsm6`, `libfontconfig1`, `libharfbuzz0b`, Monospace-Schriften
|
||||
- [ ] systemd-Unit bzw. Dockerfile für den Headless-Betrieb — es existiert bereits `J:\Softwareprojekte\dockerCompose`, vermutlich anknüpfbar
|
||||
- [ ] Reverse Proxy (nginx/Caddy) mit TLS vor Kestrel
|
||||
- [ ] Secrets unter Linux: EnvironmentFile mit `0600` statt Klartext in `settings.json`
|
||||
- [ ] CI: Build + Test auf Linux **und** Windows
|
||||
- [ ] `docs/BETRIEB-Deploymentcenter.md` um den Linux-Betrieb ergänzen
|
||||
|
||||
---
|
||||
|
||||
## Stufe 3 — Analytik schärfen
|
||||
|
||||
### 3.1 🟢 Strategie-Klassifikation reparieren (ehemals A4)
|
||||
|
||||
Der größte fachliche Rückstand. `StrategyType` entsteht aus genau zwei Signalen —
|
||||
`avgSize > 10000` ergibt `Whale`, `hedgingRate > 30` ergibt `Hedger`, sonst `Bot` oder
|
||||
`Unknown`. Deshalb landet der **Großteil der Trader strukturell auf `Unknown`**, was den
|
||||
Wert der Einstufung gegen null gehen lässt.
|
||||
|
||||
Erschwerend: die Logik steht **doppelt** da und die beiden Schreiber überschreiben einander
|
||||
— `AnalyticsService.cs:418` und `ScoringService.cs:89`.
|
||||
|
||||
- [ ] Zuerst die Doppelung auflösen: **ein** Ort, der `StrategyType` bestimmt
|
||||
- [ ] Vorhandene, bereits berechnete Signale einspeisen statt neue zu erheben:
|
||||
`StrategyMetricsCalculator` (Kategorie-Konzentration, Conviction-Edge),
|
||||
`TraderTraitCalculator` (Traits), `FingerprintSnapshotService` (Kategorie-Mix über Zeit)
|
||||
- [ ] Ergänzend, falls nötig: Verteilung der Haltedauern, Anteil später vs. früher Einstiege
|
||||
im Marktleben, Varianz der Ordergrößen
|
||||
- [ ] Prüfen, ob ein Einzel-Enum reicht oder ob Mehrfachsignale danebengehören
|
||||
(Enum als Primär-Tag, Zusatzsignale als eigene Felder)
|
||||
- [ ] Abnahme: der Anteil `Unknown` ist deutlich gesunken
|
||||
|
||||
> Herkunft: [`docs/archiv/UMSETZUNGSPLAN.md`](docs/archiv/UMSETZUNGSPLAN.md) A4.
|
||||
|
||||
### 3.2 🟡 `CopytradingBacktestHarness` anschließen oder verwerfen
|
||||
|
||||
123 Zeilen fertig implementierter Latenz-Sweep (0/10/30/60 s) samt `BacktestResult`, per DI
|
||||
registriert — und **von niemandem aufgerufen**. Der Sweep würde beziffern, wie viel Alpha
|
||||
ein Nachahmer bei welcher Verzögerung verliert; das passt genau zum Zweck des Projekts.
|
||||
|
||||
Entscheidung nötig: an einen Endpunkt und die Trader-Detailseite hängen, oder ersatzlos
|
||||
löschen. Der jetzige Zustand — gepflegt, aber wirkungslos — ist die schlechteste Variante.
|
||||
|
||||
### 3.3 🟡 Track-Record-Länge in den Copyability-Score
|
||||
|
||||
Der Score besteht heute aus Alpha-Verfall (70 %) und Sizing-Konsistenz (30 %). Die
|
||||
ursprünglich geplante vierte Komponente — Länge und Konsistenz des Track Records — fehlt.
|
||||
Ein Trader mit drei glücklichen Märkten bekommt denselben Score wie einer mit dreihundert.
|
||||
|
||||
> Herkunft: [`archiv/UMSETZUNGSPLAN.md`](docs/archiv/UMSETZUNGSPLAN.md) A5, letzter Unterpunkt.
|
||||
|
||||
### 3.4 🟡 Edge-Freshness und Strategie-Drift ins Ranking
|
||||
|
||||
Beide Kennzahlen existieren, erscheinen aber nur auf der Detailseite und in Alarmen. In der
|
||||
Rangliste — dort, wo ausgewählt wird — spielen sie keine Rolle. Ein Master mit abgestandener
|
||||
Edge steht weiterhin oben.
|
||||
|
||||
### 3.5 🟡 Co-Movement-Graph vorberechnen
|
||||
|
||||
`GET /api/co-movement/graph` rechnet bei jedem Aufruf. Für die Netzwerkansicht ist das
|
||||
träge und belastet die DB unnötig. In den `ScoringAndAlertsWorker` verlagern und das
|
||||
Ergebnis ablegen.
|
||||
|
||||
### 3.6 🟡 Restpunkte aus der Kategorie-Erkennung
|
||||
|
||||
- [ ] Gezielt fehlende Event-Tags nachladen für Märkte, die getrackte Trader gehandelt haben
|
||||
([`archiv/FIXPLAN-TODO.md`](docs/archiv/FIXPLAN-TODO.md) F5) — der tägliche Sync geschlossener Märkte deckt den Fall
|
||||
inzwischen weitgehend ab, die Lücke ist klein
|
||||
- [ ] Zwei fehlende Tests (F6): Event-Tag-Vererbung und Offline-Backfill
|
||||
|
||||
### 3.7 🟡 Sortierpfeile in der Trader-Tabelle
|
||||
|
||||
Die Tabellenköpfe zeigen statisch `↕`, auch in der aktiven Sortierspalte. Reine Politik,
|
||||
war schon im UI-Plan als „Optional" markiert.
|
||||
|
||||
---
|
||||
|
||||
## Stufe 4 — Datenhaushalt
|
||||
|
||||
Alles hier läuft über SQL, das **der Nutzer selbst** gegen die Datenbank fährt. Wir liefern
|
||||
die Anweisungen, führen sie aber nicht aus.
|
||||
|
||||
> Details: [`docs/archiv/FIXPLAN-G-Speicher.md`](docs/archiv/FIXPLAN-G-Speicher.md) (Anhang)
|
||||
> und [`docs/archiv/UMSETZUNGSPLAN.md`](docs/archiv/UMSETZUNGSPLAN.md) C3.
|
||||
|
||||
### 4.1 👤 🟡 Einmalige DB-Optimierungen
|
||||
|
||||
- [ ] Spaltentypen verkleinern: `TransactionHash`, `MarketId`, `AssetId` sind Hex-/Dezimalstrings in überbreiten Feldern
|
||||
- [ ] InnoDB-Kompression (`ROW_FORMAT=COMPRESSED`) für `Trades` — schneller Zugewinn, geringes Risiko
|
||||
- [ ] Partitionierung von `Trades` nach Monat (`ExecutedAt`) prüfen — erlaubt späteres Verwerfen ganzer Partitionen
|
||||
|
||||
### 4.2 👤 💡 Materialitätsschwelle für Mikro-Trades
|
||||
|
||||
Trades unterhalb eines Betrags (Vorschlag: $0,50) unabhängig vom Retention-Fenster
|
||||
verwerfen. Durchdacht, aber nicht beschlossen — die Schwelle verändert die PnL-Rechnung
|
||||
leicht, und der Gewinn ist ungewiss, bis 4.1 gemessen ist.
|
||||
|
||||
### 4.3 👤 💡 Frischer Datenbank-Neustart
|
||||
|
||||
Die alte Überlegung, die Produktivdatenbank leer neu aufzusetzen und über die Worker neu zu
|
||||
befüllen (Rohdaten sind über `/activity` jederzeit nachladbar). **Nicht beschlossen.** Falls
|
||||
er kommt, gehört er ans Ende von Stufe 3, nicht davor — sonst laufen Analytik-Änderungen und
|
||||
Datenumzug gleichzeitig.
|
||||
|
||||
Vorgelagerter Bestätigungs-Check: stichprobenartig prüfen, wie weit `/activity` für ein
|
||||
lange aktives Wallet tatsächlich zurückreicht.
|
||||
|
||||
### 4.4 💡 65 Migrationsdateien zusammenfassen
|
||||
|
||||
32 Migrationen ergeben 65 Dateien und rund 37.000 Zeilen. Eine neue Baseline wäre
|
||||
übersichtlicher, kostet aber die Schemahistorie und ist gegen eine laufende Produktivdatenbank
|
||||
heikel. Nur sinnvoll im Zuge von 4.3.
|
||||
|
||||
---
|
||||
|
||||
## Stufe 5 — Ingest skalieren
|
||||
|
||||
Erst angehen, wenn Rate-Limits tatsächlich drücken. Die wirksamsten Maßnahmen sind bereits
|
||||
umgesetzt (Ingest-Tiering, Egress-Kanäle, Kurzzeit-Cache).
|
||||
|
||||
> Details: [`docs/archiv/PLAN-DatenIngest-Skalierung.md`](docs/archiv/PLAN-DatenIngest-Skalierung.md).
|
||||
|
||||
### 5.1 💡 Historische Massendaten aus der Blockchain statt über REST
|
||||
|
||||
Der größte ungenutzte Hebel. Polymarket-Trades sind On-Chain-Events auf Polygon; für
|
||||
Backfill und Deep-Resync — die teuersten REST-Verbraucher — ist `/activity` die falsche
|
||||
Quelle. Ein GraphQL-Aufruf gegen einen Subgraph (The Graph / Goldsky) liefert tausende Fills
|
||||
eines Wallets auf einmal.
|
||||
|
||||
Skizze: `IHistoricalTradeSource` neben den REST-Provider stellen, Deep-Resync zieht darüber.
|
||||
**Nicht eingeplant**, weil erst zu evaluieren ist, ob ein brauchbarer Subgraph existiert und
|
||||
wie vollständig er ist.
|
||||
|
||||
### 5.2 🟡 Markt-Stammdaten aggressiv cachen
|
||||
|
||||
Metadaten (Frage, Kategorie, Outcomes, `ConditionId`↔`TokenId`) ändern sich nie — einmal
|
||||
ziehen, lang halten; nur Volumen, Liquidität und Auflösung periodisch aktualisieren.
|
||||
Teilweise erledigt: geschlossene Märkte werden nur noch einmal täglich synchronisiert.
|
||||
|
||||
### 5.3 🟡 Egress-Kanäle: Betriebsreste
|
||||
|
||||
Die Mechanik steht (Round-Robin, Cooldown nach drei Fehlschlägen, Limiter je Kanal). Was
|
||||
im Ingest-Plan noch danebensteht:
|
||||
|
||||
- [ ] Health-Statistik je Kanal — Erfolgsquote, 429-Rate, Latenz. Heute gibt es nur einen
|
||||
Fehlerzähler: tote Kanäle werden pausiert, aber nicht ausgewertet
|
||||
- [ ] Bei eigenen IPs prüfen, ob es echte getrennte Egress-IPs sind (multi-homed) und nicht
|
||||
NAT hinter derselben öffentlichen Adresse — sonst bringt die Aufteilung nichts
|
||||
- [ ] Regressionsschutz: die MySQL-Verbindung darf **nie** über den Egress-Pool oder einen
|
||||
Proxy laufen
|
||||
- [ ] Grob unplausible Provider-Antworten abfangen (z. B. Preis außerhalb 0–1)
|
||||
|
||||
### 5.4 ❌ Header- und User-Agent-Rotation
|
||||
|
||||
Im Ingest-Plan bewusst als „standardmäßig AUS" eingeordnet. Rotation zur Verschleierung
|
||||
gegenüber Polymarket ist gegen deren Interesse gerichtet und riskiert die Sperrung genau des
|
||||
Zugangs, auf dem das Projekt aufsetzt. Der ehrliche Weg ist, die Nachfrage zu senken (5.1,
|
||||
5.2) und legitime Kanäle zu erhöhen (bereits umgesetzt).
|
||||
|
||||
---
|
||||
|
||||
## Stufe 6 — Monetarisierung vorbereiten
|
||||
|
||||
Nur relevant, falls aus dem internen Werkzeug ein Produkt werden soll. **Bislang eine Idee,
|
||||
keine Entscheidung.** Die Vorarbeit (Read/Control-Trennung, `/api/capabilities`,
|
||||
CORS-Whitelist) ist im Zuge der Portierung ohnehin schon passiert.
|
||||
|
||||
> Details: [`docs/archiv/PLAN-Architektur-WebUI-Backend.md`](docs/archiv/PLAN-Architektur-WebUI-Backend.md).
|
||||
|
||||
### 6.1 💡 Datenbank für eine öffentliche Schicht vorbereiten
|
||||
|
||||
- **Read-Endpunkte auf versteckte Writes und Provider-Aufrufe prüfen.** Der Read/Control-Split
|
||||
steht, aber ob jeder einzelne Read-Endpunkt frei von Schreibzugriffen ist, wurde nie
|
||||
systematisch geprüft — besonders der Deep-Dive-Pfad. Vor einem öffentlichen Host
|
||||
nachzuholen, sonst wird die read-only Verbindung im Betrieb Fehler werfen
|
||||
- Read-only DB-Benutzer auf der Analyse-DB (nur `SELECT`) — 👤 der Nutzer führt die Grants aus
|
||||
- Schema-Kopplung dokumentieren: liest eine öffentliche Schicht direkt mit, wird das
|
||||
DB-Schema zur **Vertragsfläche**. Views als Puffer erwägen, damit interne Umbauten die
|
||||
öffentliche Sicht nicht brechen.
|
||||
|
||||
Billig und jederzeit vorziehbar, auch wenn 6.2 nie kommt.
|
||||
|
||||
### 6.2 💡 Öffentlicher Host
|
||||
|
||||
Eigenes Projekt `Predictalytics.PublicApi`: registriert nur die Read-Endpunkte, dazu
|
||||
Konten/Authentifizierung in einer **getrennten** User-DB, Rate-Limits und Kontingente pro
|
||||
Konto, Mandantensicht (Kunde sieht seine Watchlist, nicht das ganze Universum), liefert
|
||||
dasselbe SPA aus.
|
||||
|
||||
**Nicht-Ziele, die dabei gelten** — ❌ kein Zugriff der öffentlichen Schicht auf Core-Prozess,
|
||||
lokale API oder Steuerendpunkte; ❌ kein Schreibzugriff auf die Analyse-DB; ❌ keine
|
||||
Kunden-Authentifizierung nachträglich in die lokale Vollschicht bauen; ❌ Read-Endpunkte
|
||||
machen keine Provider-Aufrufe und keine Writes.
|
||||
|
||||
---
|
||||
|
||||
## Anhang — bewusst nicht auf der Roadmap
|
||||
|
||||
Geprüft und mit Absicht ausgelassen. Nicht versehentlich wieder aufnehmen:
|
||||
|
||||
| Was | Warum |
|
||||
|---|---|
|
||||
| `AzuroProvider` löschen | Platzhalter mit `IsImplemented => false`, wird sauber übersprungen. Kostet nichts, markiert den Ausbaupfad. |
|
||||
| `Providers/Limitless/` löschen | Voll implementierter zweiter Marktplatz, `IsImplemented => true`. Wird nur nicht bespielt — Löschen wäre Funktionsverlust. |
|
||||
| `wwwroot/landing.html`, `docs.html` | Marketing-Seiten mit Preis-Abschnitt, vom Dashboard nicht verlinkt. Gehören zu Stufe 6. |
|
||||
| Kaltarchiv außerhalb der DB | Verworfen: Rohdaten sind über die Polymarket-API jederzeit nachladbar, ein Archiv wäre reine Zusatzlast. |
|
||||
| EF Core auf 10 heben | Blockiert: Pomelo hat keinen EF-10-Provider und pinnt Relational hart auf `[9.0.0, 9.0.999]`. Vor einem Versuch prüfen, ob Pomelo nachgezogen hat. |
|
||||
@@ -4,8 +4,9 @@
|
||||
> gegen den Code geprüft, nicht aus den Plandokumenten übernommen — die waren zu diesem
|
||||
> Zeitpunkt durchweg veraltet.
|
||||
>
|
||||
> Dieses Dokument ist die Einstiegsseite. Die Detailpläne bleiben bestehen und tragen
|
||||
> jetzt jeweils oben einen eigenen Statusblock.
|
||||
> Dieses Dokument beschreibt den **Ist-Stand**. Was ansteht, steht in
|
||||
> [`ROADMAP.md`](ROADMAP.md); die abgelösten Plandokumente liegen unter
|
||||
> [`docs/archiv/`](docs/archiv/).
|
||||
|
||||
---
|
||||
|
||||
@@ -46,27 +47,28 @@ dem Predictalytics-Checkout liegen, sonst bricht der Build mit einer erklärende
|
||||
|
||||
## 2. Was fertig ist
|
||||
|
||||
Alles Folgende ist im Code belegt — die Belegstellen stehen in den jeweiligen Plandokumenten.
|
||||
Alles Folgende ist im Code belegt; die Belegstellen stehen in den archivierten Plandokumenten
|
||||
unter [`docs/archiv/`](docs/archiv/).
|
||||
|
||||
* **Kernanalytik** (`UMSETZUNGSPLAN.md`, Phase 1): positionsbasierte PnL-Engine nach
|
||||
* **Kernanalytik** ([`archiv/UMSETZUNGSPLAN.md`](docs/archiv/UMSETZUNGSPLAN.md), Phase 1): positionsbasierte PnL-Engine nach
|
||||
Average-Cost mit sauberer Behandlung jeder `TradeSide`, marktbasierte Win-Rate,
|
||||
Deep-Dive-Kennzahlen aus echter Preishistorie, Copytrading-Score aus gemessenem
|
||||
Alpha-Verfall gegen das Markt-Tape.
|
||||
* **Robustheit** (Phase 2): EF-Migrationen statt handgeschriebener `ALTER TABLE`,
|
||||
entkoppelte Scoring-Pipeline, Log-Retention, Testprojekt. Alle fünf Bugs aus dem
|
||||
Review-Pass vom 2026-07-01 sind behoben.
|
||||
* **Speicher-Haushalt** (`FIXPLAN-G-Speicher.md`): budgetabhängiges Retention-Fenster,
|
||||
* **Speicher-Haushalt** ([`archiv/FIXPLAN-G-Speicher.md`](docs/archiv/FIXPLAN-G-Speicher.md)): budgetabhängiges Retention-Fenster,
|
||||
Burst-Kompaktierung, Per-Kategorie-Edge.
|
||||
* **Kategorie-Erkennung** (`FIXPLAN-TODO.md`, Teil F): kanonische Tag-Tabelle,
|
||||
* **Kategorie-Erkennung** ([`archiv/FIXPLAN-TODO.md`](docs/archiv/FIXPLAN-TODO.md), Teil F): kanonische Tag-Tabelle,
|
||||
Rausch-Filter, Tag-Nachladen für On-Demand-Märkte, Offline-Backfill beim Start.
|
||||
* **HF-Trader-Tiering** (Teil D): `IngestMode` mit Hysterese, wöchentliche Biopsie,
|
||||
Aggregations-Buckets.
|
||||
* **Web-UI** (`FIXPLAN-UI-Ranglisten.md`): Showcase-Sektionen, serverseitige Sortierung
|
||||
* **Web-UI** ([`archiv/FIXPLAN-UI-Ranglisten.md`](docs/archiv/FIXPLAN-UI-Ranglisten.md)): Showcase-Sektionen, serverseitige Sortierung
|
||||
und Filterung.
|
||||
* **Copytrading-Analytik**: Co-Movement samt Clusterung, Strategie-Drift, Edge-Freshness,
|
||||
Copy-Portfolio, Insider-Feed — alle fünf Vorschläge der Roadmap sind umgesetzt und
|
||||
in diesem Zweig enthalten.
|
||||
* **Portierung** (`docs/PLAN-Linux-Portierung.md`, Phasen 0–4): .NET 10, extrahierter
|
||||
* **Portierung** ([`archiv/PLAN-Linux-Portierung.md`](docs/archiv/PLAN-Linux-Portierung.md), Phasen 0–4): .NET 10, extrahierter
|
||||
Hosting-Kern, Avalonia-Shell, abgesicherte Steuerendpunkte, plattformfeste Kultur- und
|
||||
Log-Pfade. Der WinForms-Host ist entfernt.
|
||||
* **Betriebsanbindung**: Lizenz, Watchdog, UpdateService, Fehler-Stream und Bugtracker
|
||||
@@ -76,47 +78,17 @@ Alles Folgende ist im Code belegt — die Belegstellen stehen in den jeweiligen
|
||||
|
||||
## 3. Was offen ist
|
||||
|
||||
Nach Dringlichkeit:
|
||||
Die offenen Punkte stehen vollständig und nach Reihenfolge sortiert in
|
||||
**[`ROADMAP.md`](ROADMAP.md)** — hier nur die drei, die den Blick aufs Ganze bestimmen:
|
||||
|
||||
### 3.1 ⚠️ OpenRouter-API-Key liegt im Klartext im Repository
|
||||
|
||||
`src/Predictalytics.Api/appsettings.json` enthält einen **echten** OpenRouter-Schlüssel,
|
||||
versioniert seit Commit `7045002` und damit auf dem Gitea-Server.
|
||||
|
||||
**Zu tun:** Den Schlüssel bei OpenRouter zurückziehen und neu ausstellen. Ihn nur aus der
|
||||
Datei zu entfernen genügt nicht — der Git-Verlauf behält ihn. Anschließend über die
|
||||
Umgebungsvariable `OpenRouter__ApiKey` setzen; eine Codeänderung braucht es dafür nicht,
|
||||
`WebApplication.CreateBuilder` liest Umgebungsvariablen bereits mit Vorrang.
|
||||
|
||||
Der Schlüssel wurde bewusst **nicht** eigenmächtig entfernt: ohne Rotation bringt das
|
||||
keinen Sicherheitsgewinn, würde aber die KI-Strategieanalyse stillschweigend abschalten.
|
||||
|
||||
### 3.2 Die Portierung ist unter Linux nie gelaufen
|
||||
|
||||
Phase 5 (Deployment, systemd/Container, Reverse Proxy, CI) und Phase 6 (Verifikation) des
|
||||
Portierungsplans sind unangetastet. Der Code ist plattformneutral gebaut, aber **auf keinem
|
||||
Linux-System je ausgeführt worden**. Die Ende-zu-Ende-Prüfung vom 2026-08-08 lief unter
|
||||
Windows. Solange das aussteht, ist „läuft unter Linux" eine Annahme, kein Befund.
|
||||
|
||||
### 3.3 A4 — Strategie-Klassifikation
|
||||
|
||||
Der einzige größere unerledigte Block aus Phase 1. `StrategyType` entsteht weiterhin aus
|
||||
zwei Signalen — `avgSize > 10000` ergibt `Whale`, `hedgingRate > 30` ergibt `Hedger`, sonst
|
||||
`Bot`/`Unknown` — weshalb der Großteil der Trader strukturell auf `Unknown` landet. Die
|
||||
Bausteine für eine bessere Einstufung liegen fertig herum (`StrategyMetricsCalculator`,
|
||||
`TraderTraitCalculator`, `FingerprintSnapshotService`), sie speisen die Klassifikation nur
|
||||
nicht.
|
||||
|
||||
Die Logik steht außerdem **doppelt** da: `AnalyticsService.cs:418` und
|
||||
`ScoringService.cs:89`. Beim Anfassen zusammenführen.
|
||||
|
||||
### 3.4 Kleinere Reste
|
||||
|
||||
* `FIXPLAN-UI-Ranglisten.md`: Pfeilrichtung ▲/▼ in der aktiven Sortierspalte (war als
|
||||
„Optional" markiert).
|
||||
* `FIXPLAN-TODO.md` F5/F6: gezielter Nachlade-Schritt für fehlende Event-Tags, zwei Tests.
|
||||
* `UMSETZUNGSPLAN.md` C3 und D1/D2: DB-Arbeiten auf SQL-Ebene und die Entscheidung über
|
||||
einen Datenbank-Neustart — beides liegt beim Nutzer.
|
||||
1. **Ein echter OpenRouter-API-Key liegt im Klartext im Repository**
|
||||
(`src/Predictalytics.Api/appsettings.json`, versioniert seit `7045002`). Er muss beim
|
||||
Anbieter zurückgezogen und neu ausgestellt werden — ihn nur zu löschen hilft nicht, die
|
||||
Git-Historie behält ihn. Roadmap 0.1.
|
||||
2. **Die Portierung ist auf keinem Linux-System je gelaufen.** Der Code ist plattformneutral
|
||||
gebaut, die Ende-zu-Ende-Prüfung vom 2026-08-08 lief aber unter Windows. Roadmap Stufe 2.
|
||||
3. **Die Strategie-Klassifikation ist faktisch wirkungslos** — zwei Signale, der Großteil
|
||||
der Trader landet auf `Unknown`, und die Logik steht doppelt da. Roadmap 3.1.
|
||||
|
||||
---
|
||||
|
||||
@@ -142,16 +114,17 @@ Avalonia-Shell noch die Deploymentcenter-Anbindung.
|
||||
## 5. Bewusst stehengelassen
|
||||
|
||||
Beim Aufräumen geprüft und **nicht** entfernt, weil Löschen hier Funktionsverlust wäre und
|
||||
nicht Entrümpelung:
|
||||
nicht Entrümpelung. Dieselbe Liste steht im Anhang der [`ROADMAP.md`](ROADMAP.md), damit sie
|
||||
nicht versehentlich als Aufgabe wieder auftaucht:
|
||||
|
||||
| Was | Warum es bleibt |
|
||||
|---|---|
|
||||
| `Providers/Azuro/AzuroProvider.cs` | Platzhalter mit `IsImplemented => false`. Die Worker überspringen ihn sauber; er kostet nichts und markiert den Ausbaupfad. |
|
||||
| `Providers/Limitless/` (3 Dateien) | **Voll implementierter** zweiter Marktplatz mit `IsImplemented => true`. Wird produktiv nur nicht bespielt. |
|
||||
| `Services/CopytradingBacktestHarness.cs` (123 Z.) | Fertig implementierter Latenz-Sweep, per DI registriert, aber **von niemandem aufgerufen**. Entweder anschließen oder bewusst verwerfen — beides eine fachliche Entscheidung. |
|
||||
| `Services/CopytradingBacktestHarness.cs` (123 Z.) | Fertig implementierter Latenz-Sweep, per DI registriert, aber **von niemandem aufgerufen**. Entscheidung steht aus, siehe Roadmap 3.2. |
|
||||
| `wwwroot/landing.html`, `wwwroot/docs.html` | Marketing-Seiten mit Preis-Abschnitt, vom Dashboard aus nicht verlinkt. Passen zur später angedachten Monetarisierung. |
|
||||
| 8 Nullable-Warnungen | `TradeRepository.cs:94-102`, `PolymarketProvider.cs:357`, `TraderAnalyticsWorker.cs:152`. Bestehen seit Längerem; sie zu beheben ist Logikarbeit, kein Aufräumen. |
|
||||
| 65 Migrationsdateien | Die Schemahistorie. Zusammenfassen ginge, ist aber riskant und sollte eine bewusste Entscheidung sein. |
|
||||
| 65 Migrationsdateien | Die Schemahistorie. Zusammenfassen ginge, ist aber riskant — siehe Roadmap 4.4. |
|
||||
|
||||
Ein Nebenbefund ohne Handlungszwang: der Kategorie-Backfill beim Start
|
||||
(`PredictalyticsHost.cs:116`) lädt **alle** Märkte samt Event in den Speicher. Bei
|
||||
|
||||
+30
-8
@@ -1,5 +1,27 @@
|
||||
# Plan: Drei-Schichten-Architektur (Core / Lokal / Public)
|
||||
|
||||
> **Archiviert am 2026-08-23** — offene Punkte siehe [`ROADMAP.md`](../../ROADMAP.md),
|
||||
> Stufe 6. Dieses Dokument wird nicht mehr gepflegt.
|
||||
>
|
||||
> **Phase 0 bis 2 sind erledigt**, überwiegend als Nebenprodukt der Linux-Portierung, und
|
||||
> hier nachträglich abgehakt:
|
||||
> * Read/Control-Split (`ApiConfiguration.MapPredictalyticsReadEndpoints()` bzw.
|
||||
> `MapPredictalyticsControlEndpoints()`), `/api/dev/*` und die Job-Trigger liegen auf der
|
||||
> Control-Seite.
|
||||
> * `GET /api/capabilities` existiert und meldet den tatsächlichen Zustand; die WebUI
|
||||
> koppelt ihre Admin-Aktionen daran (`app.js:880,1132`).
|
||||
> * `API_BASE` ist im SPA konfigurierbar (`app.js:2`), Trait-Chips sind da.
|
||||
> * CORS läuft über eine Origin-Whitelist, die Bind-Adresse ist explizit
|
||||
> (`PredictalyticsHost.cs:177,198-201`) — kein `0.0.0.0`.
|
||||
>
|
||||
> **Nicht abgehakt** ist der Deep-Dive-Audit auf versteckte Writes in Read-Endpunkten
|
||||
> (Phase 0, dritter Punkt): die Trennung steht, ob jeder Read-Endpunkt einzeln daraufhin
|
||||
> geprüft wurde, lässt sich im Nachhinein nicht belegen. Vor einem öffentlichen Host
|
||||
> nachholen.
|
||||
>
|
||||
> **Phase 3 und 4 sind offen** und bilden Roadmap-Stufe 6 — dort als Konzept markiert,
|
||||
> weil über eine Monetarisierung nicht entschieden ist.
|
||||
|
||||
> Stand: 2026-07-12 · Status: **Architektur bestätigt** (Nutzer-Entscheidung), Implementierung
|
||||
> schrittweise. Kein Code in diesem Schritt.
|
||||
> Kontext: Neues WebUI-Design (mit Claude Design vorbereitet) wird nach der Schicht-Trennung
|
||||
@@ -88,24 +110,24 @@ und von beiden Hosts wiederverwendet — kein Duplizieren:
|
||||
## 3. Implementierungsplan (schrittweise)
|
||||
|
||||
### Phase 0 — Endpunkte klassifizieren & Read/Control trennen (Fundament, klein)
|
||||
- [ ] Jeden Endpunkt in `docs/API.md` als **Read** (public-tauglich) oder **Control** (nur lokal)
|
||||
- [x] Jeden Endpunkt in `docs/API.md` als **Read** (public-tauglich) oder **Control** (nur lokal)
|
||||
markieren. Kandidaten Control: alle `POST/PUT/DELETE`, `/api/dev/*`, Job-Trigger.
|
||||
- [ ] Auf **versteckte Writes/Provider-Calls** in Read-Endpunkten prüfen (Deep-Dive!) und
|
||||
bereinigen oder als Control einstufen.
|
||||
- [ ] `MapPredictalyticsEndpoints()` in `MapReadEndpoints()` + `MapControlEndpoints()` splitten
|
||||
- [x] `MapPredictalyticsEndpoints()` in `MapReadEndpoints()` + `MapControlEndpoints()` splitten
|
||||
(rein struktureller Refactor, Verhalten unverändert; bestehende Tests bleiben grün).
|
||||
- [ ] `GET /api/capabilities` einführen.
|
||||
- [x] `GET /api/capabilities` einführen.
|
||||
|
||||
### Phase 1 — WebUI als sauberes, gemeinsames SPA (parallel zum neuen Design)
|
||||
- [ ] Neues Design als **ein statisches Artefakt** bauen, reiner API-Client, `API_BASE`
|
||||
- [x] Neues Design als **ein statisches Artefakt** bauen, reiner API-Client, `API_BASE`
|
||||
konfigurierbar (heute `''` = gleiche Origin bleibt lokal gültig).
|
||||
- [ ] Admin-Aktionen an `capabilities.canControl` koppeln.
|
||||
- [ ] Trait-Chips/-Filter im Design vorsehen — **erscheinen erst, wenn Backend-D2 steht**
|
||||
- [x] Admin-Aktionen an `capabilities.canControl` koppeln.
|
||||
- [x] Trait-Chips/-Filter im Design vorsehen — **erscheinen erst, wenn Backend-D2 steht**
|
||||
(kein UI-Bug, das Backend liefert Traits noch nicht).
|
||||
|
||||
### Phase 2 — Lokale Grenze härten (klein, jetzt schon sinnvoll)
|
||||
- [ ] CORS von `AllowAnyOrigin` auf konfigurierte Origin-Whitelist umstellen.
|
||||
- [ ] Bind-Adresse explizit (localhost/LAN), nie `0.0.0.0` ohne Firewall; Konfig-Kommentar
|
||||
- [x] CORS von `AllowAnyOrigin` auf konfigurierte Origin-Whitelist umstellen.
|
||||
- [x] Bind-Adresse explizit (localhost/LAN), nie `0.0.0.0` ohne Firewall; Konfig-Kommentar
|
||||
„NIEMALS ins Internet — das ist die interne Schicht".
|
||||
|
||||
### Phase 3 — DB für Public vorbereiten (mittel, kann früh passieren)
|
||||
@@ -1,5 +1,26 @@
|
||||
# Plan: Daten-Ingest skalieren (Rate-Limits, Egress-Kanäle, Blockchain)
|
||||
|
||||
> **Archiviert am 2026-08-23** — offene Punkte siehe [`ROADMAP.md`](../../ROADMAP.md),
|
||||
> Stufe 5. Dieses Dokument wird nicht mehr gepflegt.
|
||||
>
|
||||
> **Erledigt und hier nachträglich abgehakt:**
|
||||
> * **1c Ingest-Tiering** — `IngestMode` mit `SnapshotOnly`/`Aggregated`, siehe
|
||||
> [`FIXPLAN-TODO.md`](FIXPLAN-TODO.md) Teil D.
|
||||
> * **1d Redundanz** — `IMemoryCache` im `PolymarketApiClient`.
|
||||
> * **2a/2b Egress-Kanäle** — `Infrastructure/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.
|
||||
@@ -32,11 +53,11 @@ REST-Verbraucher) ist `/activity` die falsche Quelle.
|
||||
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` +
|
||||
- [x] 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
|
||||
- [x] Worker-übergreifender Kurzzeit-Cache „gerade geholt", damit nicht mehrere Worker denselben
|
||||
Markt/Trader kurz hintereinander abrufen.
|
||||
|
||||
---
|
||||
@@ -59,18 +80,18 @@ Ein Kanal ist genau eine Ausgangsroute, per Config als einer von zwei Typen defi
|
||||
]
|
||||
}
|
||||
```
|
||||
- [ ] Pro Kanal **ein** `SocketsHttpHandler`:
|
||||
- [x] Pro Kanal **ein** `SocketsHttpHandler`:
|
||||
- `SourceIp` → `ConnectCallback`, Socket vor Connect an die lokale IP binden
|
||||
(`socket.Bind(new IPEndPoint(ip, 0))`).
|
||||
- `Proxy` → `handler.Proxy = new WebProxy(url); handler.UseProxy = true;`.
|
||||
- [ ] `IEgressPool` verteilt Requests round-robin/least-loaded über die aktiven Kanäle.
|
||||
- [x] `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.
|
||||
- [x] 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
|
||||
- [x] 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.
|
||||
- [x] 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.
|
||||
@@ -123,10 +144,10 @@ Auf Wunsch integriert, bewusst opt-in:
|
||||
(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
|
||||
- [x] Per-Kanal-Limiter: unabhängige Budgets (kein globales Blocken); 429 sperrt nur einen Kanal.
|
||||
- [x] 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.
|
||||
- [x] 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
|
||||
@@ -0,0 +1,25 @@
|
||||
# Archiv — abgelöste Plandokumente
|
||||
|
||||
Diese Dokumente wurden am **2026-08-23** hierher verschoben. Sie werden **nicht mehr
|
||||
gepflegt**. Was von ihnen noch offen war, steht gebündelt in [`ROADMAP.md`](../../ROADMAP.md);
|
||||
der Ist-Stand des Projekts in [`STATUS.md`](../../STATUS.md).
|
||||
|
||||
**Wozu sie trotzdem da sind:** Die Roadmap nennt jeden offenen Punkt knapp. Die Herleitung —
|
||||
warum etwas so entschieden wurde, welche Messungen dahinterstehen, welche Alternativen
|
||||
verworfen wurden — steht hier. Wer einen Roadmap-Punkt umsetzt, findet hier den Kontext.
|
||||
|
||||
**Vorsicht bei der Lektüre:** Der Text unterhalb des jeweiligen Statusblocks beschreibt den
|
||||
Stand seiner Entstehungszeit. Test-Baselines, Dateipfade und „so ist es heute"-Aussagen sind
|
||||
teils überholt. Immer gegen den Code prüfen, nie direkt übernehmen.
|
||||
|
||||
| Dokument | Stand | Was drinsteht |
|
||||
|---|---|---|
|
||||
| [`UMSETZUNGSPLAN.md`](UMSETZUNGSPLAN.md) | 2026-07-01, abgehakt 2026-08-23 | Phase 1 (Kernanalytik: PnL-Engine, Win-Rate, Deep-Dive, Copytrading-Score) und Phase 2 (Migrationen, Scoring-Entkopplung, Bugliste, Tests) sowie das Speicherplatz-Konzept. Bis auf A4 und B2 umgesetzt. |
|
||||
| [`FIXPLAN-DONE.md`](FIXPLAN-DONE.md) | 2026-07-09 | Vorgängerfassung des Fix-Plans, vollständig abgearbeitet. Reine Historie. |
|
||||
| [`FIXPLAN-TODO.md`](FIXPLAN-TODO.md) | 2026-07-09/11/13 | Teil D (Merkmals-Tags, HF-Trader-Tiering mit `IngestMode`) und Teil F (Kategorie-Erkennung: kanonische Tags, Rausch-Filter, Backfill). Umgesetzt bis auf F5 und zwei Tests. |
|
||||
| [`FIXPLAN-G-Speicher.md`](FIXPLAN-G-Speicher.md) | 2026-07-17 | Speicher-Governor, Retention für aggregierte Trader, `UsdcSize`/`OutcomeIndex`, Per-Kategorie-Edge. Vollständig umgesetzt; der Anhang mit den einmaligen SQL-Optimierungen ist offen. |
|
||||
| [`FIXPLAN-UI-Ranglisten.md`](FIXPLAN-UI-Ranglisten.md) | 2026-08-03 | Web-UI: Showcase-Sektionen, serverseitige Sortierung und Filterung. Vollständig umgesetzt bis auf die Sortierpfeile. |
|
||||
| [`PLAN-Linux-Portierung.md`](PLAN-Linux-Portierung.md) | 2026-08-06 bis -08 | Der Portierungsplan mit allen Entscheidungen und Abnahmevermerken. **Die ausführlichste Quelle für Roadmap-Stufe 2** — Abschnitt 7 (Deployment) und 8 (Verifikationsmatrix) sind dort detaillierter als in der Roadmap. |
|
||||
| [`ANALYSE-Linux-Portierung.md`](ANALYSE-Linux-Portierung.md) | 2026-08-06 | Die Bestandsaufnahme, die dem Portierungsplan vorausging: was am WinForms-Host hing, welche Pakete windows-spezifisch waren. Historisch. |
|
||||
| [`PLAN-Architektur-WebUI-Backend.md`](PLAN-Architektur-WebUI-Backend.md) | 2026-07 | Drei-Schichten-Konzept Core/Lokal/Public als Vorbereitung einer Monetarisierung. Phase 0–2 sind im Zuge der Portierung erledigt; Phase 3–4 sind Roadmap-Stufe 6. |
|
||||
| [`PLAN-DatenIngest-Skalierung.md`](PLAN-DatenIngest-Skalierung.md) | 2026-07 | Rate-Limits, Egress-Kanäle, Blockchain als Bulk-Quelle. Egress-Kanäle und Ingest-Tiering sind umgesetzt; der Rest ist Roadmap-Stufe 5. |
|
||||
@@ -138,7 +138,7 @@ Beim Review ist aufgefallen, dass `TraderAnalyticsWorker.CalculatePnL` **jeden T
|
||||
- [x] Eigenes Intervall für volle Neuberechnung/Ranking (z.B. alle 15 Min) getrennt vom reinen Trade-Polling (60s)
|
||||
|
||||
### B6. Weitere gefundene Bugs/Performance-Probleme (Review-Pass 2026-07-01)
|
||||
- [x] **`MarketSyncWorker` re-synct alle 30 Minuten ALLE Märkte, inkl. `includeClosed=true`, von Offset 0** ([MarketSyncWorker.cs](src/Predictalytics.Worker/Services/MarketSyncWorker.cs)) — holt damit bei jedem Zyklus jeden jemals geschlossenen Polymarket-Markt erneut komplett durch. Wächst unbegrenzt mit der Zeit, echtes Risiko für Rate-Limiting/Sperrung. Sollte auf: aktive Märkte häufig, geschlossene Märkte selten/inkrementell (z.B. nur kürzlich geschlossene, nicht der komplette Bestand) umgestellt werden
|
||||
- [x] **`MarketSyncWorker` re-synct alle 30 Minuten ALLE Märkte, inkl. `includeClosed=true`, von Offset 0** ([MarketSyncWorker.cs](../../src/Predictalytics.Worker/Services/MarketSyncWorker.cs)) — holt damit bei jedem Zyklus jeden jemals geschlossenen Polymarket-Markt erneut komplett durch. Wächst unbegrenzt mit der Zeit, echtes Risiko für Rate-Limiting/Sperrung. Sollte auf: aktive Märkte häufig, geschlossene Märkte selten/inkrementell (z.B. nur kürzlich geschlossene, nicht der komplette Bestand) umgestellt werden
|
||||
- [x] **Watchlisted Trader nicht von Auto-Löschung ausgeschlossen** (`TraderRepository.GetTradersForCleanupAsync` / `TraderCleanupWorker`) — da `Trades`/`TraderScore`/`WatchlistEntries` per Cascade am Trader hängen, könnte ein manuell beobachteter Trader nach 1 Jahr Inaktivität (oder bei kurzzeitigem API-Fehler) unbemerkt komplett gelöscht werden. Watchlist-Einträge sollten von der Cleanup-Query ausgenommen werden
|
||||
- [x] **`TradeRepository.GetKnownPlatformTradeIdsAsync` lädt die komplette Trade-ID-Historie eines Traders ins RAM**, nur um eine kleine neu geholte Charge (~100-1000 Trades) zu deduplizieren — aufgerufen alle 60s (`PollingWorker`) bzw. alle 12h (`TradeHistoryWorker`) pro Trader. Wird mit wachsender Trade-Zahl immer teurer. Fix: nur `WHERE PlatformTradeId IN (<geholte Batch-IDs>)` abfragen statt der gesamten Historie
|
||||
- [x] **Race Condition in `MarketRepository.AddOrUpdateAsync`** (im Gegensatz zu `AddOrUpdateRangeAsync` ohne Locking) — `TradeHistoryWorker` verarbeitet bis zu 5 Trader parallel (`Parallel.ForEachAsync`); referenzieren zwei gleichzeitig denselben noch unbekannten Markt, prüfen beide unabhängig "existiert nicht" und einer crasht beim `Add` mit Unique-Constraint-Verletzung (wird geloggt, Trader-Sync für den Zyklus bricht ab, nächster Zyklus heilt es meist). Fix: gleiches Locking-Muster wie `AddOrUpdateRangeAsync` verwenden, oder Insert-Konflikt sauber abfangen/retry
|
||||
@@ -121,7 +121,7 @@ public static class DependencyInjection
|
||||
/// <summary>
|
||||
/// Applies pending EF Core migrations and seeds default platform rows.
|
||||
/// Requires the target database to already be "stamped" with the InitialBaseline
|
||||
/// migration in __EFMigrationsHistory (see UMSETZUNGSPLAN.md, section B1) if it was
|
||||
/// migration in __EFMigrationsHistory (see docs/archiv/UMSETZUNGSPLAN.md, B1) if it was
|
||||
/// previously created via the old EnsureCreated + manual ALTER approach.
|
||||
/// </summary>
|
||||
public static async Task EnsureDatabaseAsync(IServiceProvider services, bool dbDebug = false)
|
||||
|
||||
Reference in New Issue
Block a user