764 lines
46 KiB
Markdown
764 lines
46 KiB
Markdown
# IBKRTrader – Roadmap
|
||
|
||
> **Der Planungsstand steht nicht mehr in dieser Datei.** Er liegt seit dem 2026-08-30 im
|
||
> Deploymentcenter, Projekt `ibkrtrader` – dort, wo auch Fehler und Zuständigkeiten geführt werden.
|
||
> Zwei Pfleger für dasselbe Feld waren der Grund, warum die alte Fassung an drei Stellen behauptete,
|
||
> etwas sei offen, das längst erledigt war.
|
||
>
|
||
> **Die Arbeitsteilung:** Status, Reihenfolge, Zielfassung und Bearbeiter kommen aus dem
|
||
> Deploymentcenter (`dc_roadmap`, WebUI). Begründung, Auslöser und Herleitung stehen hier.
|
||
>
|
||
> Der Block zwischen den `dc:roadmap`-Markern ist eine **erzeugte Kopie** und darf älter sein als
|
||
> der echte Stand. **Dort niemals von Hand etwas ändern** – der nächste Lauf überschreibt es. Alles
|
||
> außerhalb der Marker ist von Hand und bleibt.
|
||
>
|
||
> Die Kennung ist die **Item-ID** aus dem Deploymentcenter (`#289`), nicht mehr `B1` oder `W-2`.
|
||
> Handvergebene Kennungen wurden nach einer Löschung neu vergeben und meinten dann etwas anderes;
|
||
> eine Item-ID wird nie zweimal vergeben. Der Themenbuchstabe bleibt – aber nur als Gruppe: `[B]`.
|
||
>
|
||
> **Ein neues Vorhaben entsteht immer zuerst im Deploymentcenter** (`dc_report`), dann erscheint es
|
||
> im Block, dann schreibt man die Begründung darunter. Ein Punkt, der nur in dieser Datei steht,
|
||
> ist keine eingeplante Arbeit – er taucht in keiner Arbeitsschlange auf und wird nie übernommen.
|
||
|
||
**Übernommen am 2026-08-30** – 57 Einträge, 10 Themenbereiche. Die alte Fassung mit handgepflegten
|
||
Statustabellen steht in der Git-Historie (bis Commit `9f66183`).
|
||
|
||
---
|
||
|
||
## Wo wir stehen
|
||
|
||
Gebaut und grün: Multi-Projekt-Aufbau nach PolytraderSharp, Generic Host, EF Core, Trading-Kern,
|
||
drei Module (CongressTrading, Accounting, Supervisor), Avalonia-Oberfläche auf Windows **und**
|
||
Linux, kopfloser Daemon, Deploymentcenter-Anbindung. 198 Tests, Build ohne Warnungen.
|
||
|
||
Nicht gebaut: **Es hat noch nie eine echte Order gegeben.** Der Broker-Adapter ist gegen das
|
||
Paper-Konto verifiziert – Verbindung, Konto, Kurse, Optionskette, Greeks, What-If-Order – aber
|
||
`PlaceOrderAsync` mit echter Ausführung steht aus (**#293**). Alles, was danach kommt
|
||
(Fill-Buchung, Kapitalmodell, OptionsWheel), hängt an diesem einen Nachweis.
|
||
|
||
**Was der erste Betriebstest ergeben hat (2026-08-31).** Der Stand `9f66183` wurde auf der
|
||
Linux-Test-VM gebaut und gefahren, ohne die Testkrücken des Aufbaus – also so, wie er ausgeliefert
|
||
würde. Build ohne Warnungen, 198 Tests grün, `--smoke-ui` alle neun Fenster, Launcher und
|
||
Workers-Ansicht rendern unter Xvfb. Der Dauerlauf hat dann zehn Fehler zutage gefördert, sechs
|
||
davon in `[X]`. Der Kern: **Was das System über sich selbst meldet, stimmt nicht.** Ein toter
|
||
Worker zeigt einen nächsten Lauf an, ein fehlgeschlagenes Backup meldet „OK", und `--check` bestätigt
|
||
eine Datenbank, die es nie kontaktiert hat. Das ist keine Ansammlung von Einzelfehlern, sondern ein
|
||
Muster – und es trifft ausgerechnet die Anzeigen, an denen man einen unbeaufsichtigten Betrieb
|
||
ablesen würde.
|
||
|
||
**Der Regelkreis steht seit dem 2026-08-31.** Werkbank- und Laufzeit-Token sind ausgestellt
|
||
(#315), der Heartbeat der Testinstanz läuft (`ibkrtrader-linuxtest` / `linuxtest-vm`), und die
|
||
Detektoren des Deploymentcenters arbeiten darauf. Der Fehler-Stream ist wieder **abgeschaltet**,
|
||
bis #403 behoben ist – sonst schreibt der Testaufbau in die Produktivmeldungen.
|
||
|
||
Zwei Sicherungen sind absichtlich getrennt und beide stehen auf „aus": `IBKR.UseTwsApi` schaltet
|
||
den Adapter, `TradingEnabled` den Handel.
|
||
|
||
---
|
||
|
||
## Die Reihenfolge – warum diese und keine andere
|
||
|
||
Die Rangfolge im Deploymentcenter (`roadmap_rank`) bildet fünf Stufen ab. Sie stehen hier als
|
||
Prosa, weil sie eine Begründung sind und keine Statusspalte.
|
||
|
||
**Stufe 0 – Was im Betrieb nachweislich nicht trägt.** Themenbereich `[X]`, Rang 1 bis 6. Diese
|
||
Punkte stammen nicht aus einer Planung, sondern aus einem Testlauf gegen den ausgelieferten Stand
|
||
auf der Linux-VM am 2026-08-31. Sie stehen vor Stufe 1, weil sie die Stufen darunter unprüfbar
|
||
machen: Ein Worker, der still stirbt, und ein Backup, das Erfolg meldet, ohne eines zu sein,
|
||
verfälschen jede spätere Messung. Solange sie offen sind, sagt ein grünes Dashboard nichts aus.
|
||
|
||
**Stufe 1 – Fundament schließen.** `#289`, `#290`, `#291`, `#292`, `#293`. Diese Punkte blockieren
|
||
oder gefährden alles Weitere. Zwei davon sind Sicherheitsschulden, die durch Warten nur teurer
|
||
werden: ein Passwort und ein Token, die beide bereits in einer Historie stehen.
|
||
|
||
**Stufe 2 – Den Handelspfad belastbar machen.** `#294`, `#295`, `#296`, `#297`. Ohne das ist kein
|
||
unbeaufsichtigter Betrieb zu verantworten.
|
||
|
||
**Stufe 3 – Options-Fundament im Core.** `#298` bis `#301`. Reine Core-Arbeit, nützt allen Modulen,
|
||
nicht nur dem Wheel. Der Aktienpfad bleibt unverändert – neue Felder sind optional, `Kind = Stock`
|
||
ist der Default.
|
||
|
||
**Stufe 4 – Kapital- und Buchmodell.** `#302` bis `#308`. Wird scharf, sobald ein **zweites** Modul
|
||
handelt. Heute handelt nur CongressTrading; mit dem Wheel sind es zwei, die sich ein Konto und ein
|
||
Guthaben teilen. Das vollständig ausgearbeitete Konzept liegt im
|
||
[Archiv](archiv/Kapital-und-Buchmodell.md) – es ist die Referenz, gegen die die Umsetzung geprüft
|
||
wird, und war nie umgesetzt.
|
||
|
||
**Stufe 5 – Modul OptionsWheel.** `#309` bis `#314`. Erst ab hier entsteht das Modul selbst.
|
||
Vollautomatisch von Anfang an – Sicherungen sind Schalter und Limits, keine Klick-Freigabe.
|
||
Strike-Wahl delta-basiert im Band 0,15–0,30. Nur Watchlist, kein Screening.
|
||
|
||
**Laufende Bahnen** hängen an keiner Stufe und können jederzeit dazwischen laufen: Auslieferung
|
||
(`[D]`), Accounting (`[A]`), Supervisor (`[S]`), technische Schulden (`[T]`).
|
||
|
||
---
|
||
|
||
<!-- dc:roadmap stand=2026-09-06T17:56Z items=79 projekt=ibkrtrader -->
|
||
|
||
<!-- ERZEUGT - nicht von Hand aendern. Dieser Block wird bei jedem Lauf von
|
||
`php cli/roadmap.php --write` ueberschrieben. Der Zustand wird im
|
||
Deploymentcenter gepflegt, nicht hier. Prosa gehoert AUSSERHALB der
|
||
Marker - dort bleibt sie unberuehrt. -->
|
||
|
||
### Als Naechstes
|
||
|
||
1. **[X] #396 — Die Shell reagiert unter Linux nicht auf SIGTERM - kein geordnetes Herunterfahren ausserhalb des Fensters**
|
||
2. **[X] #475 — Order-Nachweis auf der Test-VM durch die Lizenzsperre blockiert: kein Schluessel hinterlegt**
|
||
3. **[B] #289 — DB-Passwort der produktiven MariaDB rotieren**
|
||
4. **[B] #290 — Gitea-Zugangstoken aus der Remote-URL nehmen**
|
||
|
||
### X — Kritische Bugs
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #388 | WorkerBase: Intervall ueber 24,85 Tage toetet den Worker still und reisst beim Herunterfahren den Prozess mit | ✅ Erledigt | `1.0.0+b618efa` |
|
||
| #390 | Fehlgeschlagener DB-Dump gilt als erfolgreicher Backup-Lauf | ✅ Erledigt | `1.0.0+b618efa` |
|
||
| #389 | BackupWorker sichert eine andere Datenbank als die, mit der die Anwendung arbeitet | ✅ Erledigt | `1.0.0+b618efa` |
|
||
| #391 | --check meldet "Pruefdurchlauf OK", ohne die Datenbank je zu erreichen | ✅ Erledigt | `1.0.0+b618efa` |
|
||
| #394 | CapitolTrades-Scraper behandelt 429 nicht - beide CT-Worker fallen bei jedem Lauf aus | ✅ Erledigt | `1.0.0+b618efa` |
|
||
| #396 | Die Shell reagiert unter Linux nicht auf SIGTERM - kein geordnetes Herunterfahren ausserhalb des Fensters | 📋 Offen | — |
|
||
| #475 | Order-Nachweis auf der Test-VM durch die Lizenzsperre blockiert: kein Schluessel hinterlegt | 📋 Offen | — |
|
||
| #479 | Order lief auf die falsche Notierung: Waehrung ging beim Bau der OrderRequest verloren | ✅ Erledigt | `1.0.0` |
|
||
|
||
### B — Betrieb und Sicherheit
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #289 | DB-Passwort der produktiven MariaDB rotieren | 📋 Offen | — |
|
||
| #290 | Gitea-Zugangstoken aus der Remote-URL nehmen | 📋 Offen | — |
|
||
| #291 | EF-Schema auf die Datenbank anwenden | ✅ Erledigt | `1.0.0` |
|
||
|
||
### H — Handelspfad (TWS-Broker-Adapter)
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #293 | PlaceOrderAsync gegen das Paper-Konto verifizieren | ✅ Erledigt | `1.0.0` |
|
||
| #294 | Asynchrone Order- und Fill-Verfolgung | 📋 Offen | — |
|
||
| #295 | IBKR-Zugangsdaten mit EncryptedStringConverter ablegen | 📋 Offen | — |
|
||
| #296 | IBC/IBController einrichten (Auto-Login, taeglicher Gateway-Neustart) | 📋 Offen | — |
|
||
| #468 | DebugTrading-Modul: erzeugt selbstständig kleine Paper-Trades als Dauerlast | 📋 Offen | — |
|
||
|
||
### O — Options-Fundament im Core
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #298 | InstrumentKind/OptionSpec, IbkrMapping.Option, Positionen mit Multiplikator | ✅ Erledigt | `1.0.0` |
|
||
| #299 | Optionskette und Greeks im Core (reqSecDefOptParams, tickOptionComputation) | ✅ Erledigt | `1.0.0+0feeeba` |
|
||
| #300 | Positionsabgleich bei Zuteilung/Verfall und RiskService um sell-to-open erweitern | ✅ Erledigt | `1.0.0+b618efa` |
|
||
| #301 | IV-Rank als Core-Baustein | 📋 Offen | — |
|
||
|
||
### K — Kapital- und Buchmodell
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #302 | Buecher und Eigentumsregeln | ✅ Erledigt | `1.0.0+b618efa` |
|
||
| #474 | Eigentumsregeln 3 und 4: Modul kann sich als anderes Buch ausgeben, IBrokerClient ist per DI erreichbar | ✅ Erledigt | `1.0.0+b618efa` |
|
||
| #303 | Ein Pool, Obergrenzen | ✅ Erledigt | `1.0.0` |
|
||
| #480 | Kapitalmodell summiert Betraege ueber Waehrungen hinweg ohne Umrechnung | ✅ Erledigt | `1.0.0+b618efa` |
|
||
| #304 | Margin-Sperre in vier Schichten | ✅ Erledigt | `1.0.0` |
|
||
| #485 | Positionsverwaltung: Herkunft sichtbar, Zuordnung änderbar, Positionen stufenweise sperrbar | 📋 Offen | — |
|
||
| #486 | Instrumentenverwaltung: Handelsverbot je Instrument und harte Bestandsobergrenzen | 📋 Offen | — |
|
||
| #305 | Reservierungen ueber den Order-Lebenszyklus inkl. Crash-Recovery | ✅ Erledigt | `1.0.0` |
|
||
| #306 | Abgleich (Reconciliation) gegen den Broker | 📋 Offen | — |
|
||
| #307 | Benachrichtigungen ueber Outbox und Sink-Abstraktion | 📋 Offen | — |
|
||
| #308 | Startwerte festlegen und in settings.example.json dokumentieren | 📋 Offen | — |
|
||
| #331 | Self-Cross-Netting (Modul A kauft, Modul B verkauft dasselbe Symbol) | 🧊 Zurueckgestellt — Ausloeser: die Warnung im Order-Gateway tatsaechlich anschlaegt | — |
|
||
| #332 | Corporate Actions (Splits, Spin-offs) in der Buchzuordnung | 🧊 Zurueckgestellt — Ausloeser: ein Break durch eine Kapitalmassnahme real auftritt | — |
|
||
| #336 | Echte IBKR-Sub-Accounts (Advisor-/Family-Struktur) zur Trennung der Buecher | ❌ Verworfen | — |
|
||
|
||
### W — Strategiemodule
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #309 | OptionsWheel: Modul-Geruest | 📋 Offen | — |
|
||
| #310 | OptionsWheel: reine Strategie-Logik und Tests | ✅ Erledigt | `1.0.0` |
|
||
| #311 | OptionsWheel: Verdrahtung und vollautomatischer Paper-Betrieb | 📋 Offen | — |
|
||
| #312 | OptionsWheel: Earnings-Sperre ueber den IV-Behelf | 📋 Offen | — |
|
||
| #314 | OptionsWheel: Live-Freigabe | 📋 Offen | — |
|
||
| #327 | Trendfolge-/Momentum-Modul auf Tagesbasis als zweites Standbein | 🧊 Zurueckgestellt — Ausloeser: das OptionsWheel im Paper-Betrieb laeuft UND das Kapital- und Buchmodell (Stufe 4) steht | — |
|
||
| #338 | Fundamentales Screening (Value, Quality, Growth) | ❌ Verworfen | — |
|
||
| #339 | Earnings-Strategien (Straddle vor Zahlen, Post-Earnings-Drift) | ❌ Verworfen | — |
|
||
| #340 | Marktweite Anomalie-Suche / Screener-getriebene Auswahl | ❌ Verworfen | — |
|
||
| #341 | Daytrading, Scalping, Orderbuch-Strategien | ❌ Verworfen | — |
|
||
| #342 | Gap-Strategien auf Eroeffnung | ❌ Verworfen | — |
|
||
| #343 | Strike-Wahl ueber prozentualen Abstand statt delta-basiert | ❌ Verworfen | — |
|
||
|
||
### D — Auslieferung und Deploymentcenter
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #292 | CI wieder gruen bekommen (SDK als PackageReference statt Cross-Repo-Pfad) | 📋 Offen | — |
|
||
| #315 | Tokens fuer ibkrtrader vervollstaendigen | 📋 Offen | — |
|
||
| #316 | Update-Anwenden verdrahten | 📋 Offen | — |
|
||
| #476 | Test-VM erreicht die Gitea-Instanz nicht - Auslieferung per git pull nicht moeglich | 📋 Offen | — |
|
||
| #317 | Erstes echtes Release fahren | 📋 Offen | — |
|
||
| #318 | Deploymentcenter-Baustein in die Projektdatei aufnehmen | ✅ Erledigt | — |
|
||
| #319 | Lizenzfenster fuer die Shell | 📋 Offen | — |
|
||
| #334 | Desktop-Distribution der Shell ueber die Release-Pipeline | 🧊 Zurueckgestellt — Ausloeser: die Shell auf fremden Rechnern laufen soll | — |
|
||
|
||
### A — Modul Accounting
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #313 | Accounting-Anschluss fuer Optionen | 📋 Offen | — |
|
||
| #320 | Live-IBKR-Flex-Abruf und Balance-Anker | 📋 Offen | — |
|
||
| #321 | EZB-FX-Ingest (acc_fx_rates fuellen) | 📋 Offen | — |
|
||
| #322 | Steuerschicht: Jurisdiktionsprofil festlegen | 📋 Offen | — |
|
||
| #345 | Modulzuordnung als Korrektur des Steuerbuchs | ❌ Verworfen | — |
|
||
|
||
### S — Modul Supervisor
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #323 | Counterfactual-Kursaufloesung fuer Aktien | 📋 Offen | — |
|
||
| #324 | Externer Versand des Tagesberichts | 📋 Offen | — |
|
||
| #344 | Agent-zu-Agent-Orchestrierung im Supervisor | ❌ Verworfen | — |
|
||
|
||
### M — Marktdaten und externe Quellen
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #328 | Marktdaten-Abo US-Realtime (NYSE/AMEX/NASDAQ) | 🧊 Zurueckgestellt — Ausloeser: wir Screening oder Intraday-Strategien wollen | — |
|
||
| #329 | OPRA-Abo (Optionen-Realtime) | 🧊 Zurueckgestellt — Ausloeser: die Ausfuehrungsqualitaet im Paper-Betrieb messbar stoert | — |
|
||
| #330 | Refinitiv-Fundamentaldaten | 🧊 Zurueckgestellt — Ausloeser: der IV-Behelf der Earnings-Sperre sich als zu unscharf erweist | — |
|
||
| #335 | Ungepruefte Datenfragen der TWS API klaeren | 🧊 Zurueckgestellt — Ausloeser: eine Strategie eine der Fragen braucht - die Ratenbegrenzung schon bei einem naechtlichen Watchlist-Abruf | — |
|
||
|
||
### T — Technische Schulden und Entscheidungen
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #297 | Entscheiden, welcher IBKR-Zugangsweg bleibt | 📋 Offen | — |
|
||
| #325 | Log-Level ist nicht konfigurierbar | 📋 Offen | — |
|
||
| #326 | Diagramme einloesen oder die Avalonia-11-Pinnung aufgeben | 📋 Offen | — |
|
||
| #392 | Der Daemon schreibt jede SQL-Anweisung von EF Core auf stdout | 📋 Offen | — |
|
||
| #393 | Workers-Ansicht: die Spalte "Aktiv" ist wirkungslos - Worker lassen sich zur Laufzeit nicht abschalten | 📋 Offen | — |
|
||
| #395 | "Letzter Lauf" bleibt bei einem fehlgeschlagenen Worker-Lauf leer | ✅ Erledigt | `1.0.0+b618efa` |
|
||
| #403 | Die Umgebung des Fehler-Streams steht fest im Kompilat - jede Release-Fassung meldet "production" | 📋 Offen | — |
|
||
| #409 | --smoke-ui braucht unter Linux doch ein Anzeigegeraet und ist damit nicht CI-tauglich | 📋 Offen | — |
|
||
| #466 | Meldungen der TWS-API mit Umlauten kommen falsch dekodiert im Log an | 📋 Offen | — |
|
||
| #477 | Berechnete Eigenschaft ParsedMode wird in settings.json geschrieben | 📋 Offen | — |
|
||
| #490 | Web-UI als zweiter Ausgabeweg neben der Avalonia-Shell – Abschätzung und Schnitt | ✅ Erledigt | `1.0.0+f923721` |
|
||
| #333 | Web-UI ueber die interne REST-API | ✅ Erledigt | `1.0.0+f923721` |
|
||
| #337 | InvariantGlobalization=true fuer ein schlankes Linux-Image | ❌ Verworfen | — |
|
||
|
||
<!-- /dc:roadmap -->
|
||
|
||
---
|
||
|
||
## Begründungen
|
||
|
||
*Nicht jedes Vorhaben braucht eine – die meisten sind eine Zeile im Block wert und mehr nicht.
|
||
Hier steht, was eine Tabellenzelle nicht trägt.*
|
||
|
||
### [X] #388 — WorkerBase: Intervall über 24,85 Tage tötet den Worker still
|
||
|
||
`SemaphoreSlim.WaitAsync(TimeSpan)` nimmt höchstens `int.MaxValue` Millisekunden – rund 24,85 Tage.
|
||
`WorkerBase.RunLoopAsync` reicht die Restzeit ungeprüft durch. Zwei **ausgelieferte Vorgaben**
|
||
liegen darüber: `InstrumentSyncWorker` mit 43.200 Minuten und `CongressHistoryImportWorker` mit
|
||
365 Tagen.
|
||
|
||
Das Bemerkenswerte ist nicht der Fehler, sondern seine Unsichtbarkeit. Die Ausnahme fällt weder in
|
||
den `try/catch` von `RunOnceAsync` noch in das `catch (OperationCanceledException)` der
|
||
Warteschleife. Der Task faultet, der Worker ist tot, geloggt wird nichts, und die Workers-Ansicht
|
||
zeigt weiter einen „Nächsten Lauf" an – für den `CT-HistoryImport` einen im Jahr 2027.
|
||
|
||
Beim Herunterfahren kommt die gespeicherte Ausnahme zurück: `StopAsync` awaitet den Task und fängt
|
||
nur `OperationCanceledException`. Sie läuft bis in `Program.Main` durch und beendet den Prozess mit
|
||
Exitcode 134. Damit erreicht der Daemon weder `StopModulesAsync` noch die Zeile „IBKRTrader
|
||
beendet." – unter systemd ist **jedes** Stoppen ein Fehlschlag. Dreimal nachgestellt, zuletzt nach
|
||
4,5 Stunden Dauerlauf.
|
||
|
||
Die Testkrücken auf der VM (`FromDays(7)`, `IntervalMinutes 1440`) umgehen genau das und gehören
|
||
nach der Behebung wieder heraus.
|
||
|
||
### [X] #390 und #389 — Das Backup meldet Erfolg, ohne eines zu sein
|
||
|
||
Zwei getrennte Fehler, die sich gegenseitig verdecken.
|
||
|
||
**#390 ist der gefährlichere.** `RunMysqlDumpAsync` behandelt einen Exitcode ungleich 0 mit
|
||
`Logger.Warn` und kehrt normal zurück; fehlt das Dump-Werkzeug ganz, wird nur „übersprungen"
|
||
protokolliert. `ExecuteAsync` läuft durch, `core_worker_log` trägt `Success`, die Workers-Ansicht
|
||
zeigt „OK". Im Log stehen die beiden Zeilen direkt untereinander:
|
||
|
||
```
|
||
Warn : mariadb-dump Exitcode 2: ... "Unknown server host 'your-db-host'" when trying to connect
|
||
Info : Backup abgeschlossen: 2026-08-31_14-30
|
||
```
|
||
|
||
**#389 ist die Ursache dieses konkreten Fehlschlags.** Es gibt zwei Datenbank-Konfigurationen:
|
||
`Database:MySqlConnectionString` aus `appsettings*.json` – daran hängen EF und alle drei Module –
|
||
und `AppSettings.Database` aus `settings.json`, aus der sich `BackupWorker` und `DbVersion`
|
||
bedienen. Nichts erzwingt, dass beide dasselbe meinen; die Vorgabe der zweiten ist der Platzhalter
|
||
`your-db-host`. Eine Installation kann also monatelang sauber laufen und dabei kein einziges
|
||
brauchbares Backup haben. Die Grundregeln sagen „Zugangsdaten NUR in settings.json" – die
|
||
maßgebliche Verbindung liegt tatsächlich woanders.
|
||
|
||
Reihenfolge mit Absicht: **erst #390, dann #389.** Ein Worker, der über Erfolg lügt, verdeckt jedes
|
||
weitere Backup-Problem, auch die, die nach #389 noch kommen.
|
||
|
||
### [X] #391 — `--check` erreicht die Datenbank nie
|
||
|
||
Der Schalter ist als Trockenlauf „für Deployment und CI" dokumentiert und soll laut Kommentar die
|
||
„DB-Verbindungszeichenfolge" prüfen. Er prüft den *String*, nicht die *Verbindung*: `RunStartupChecks`
|
||
baut den Host, sieht sich Dateirechte an und schaut nach, ob „SslMode" im Text vorkommt. Gegen
|
||
`Server=127.0.0.1;Port=3999;Database=gibtsnicht` meldet er `=== Prüflauf OK ===` und Exitcode 0.
|
||
|
||
Zweiter Punkt derselben Sache: Die Warnungen der Startprüfungen gehen nur in die Logdatei. Ein
|
||
CI-Schritt, der Exitcode und Ausgabe auswertet – der einzige Grund, warum es diesen Schalter gibt –
|
||
sieht davon nichts.
|
||
|
||
### [X] #394 — CapitolTrades antwortet mit 429, und niemand fängt es auf
|
||
|
||
Am 2026-08-27 und am 2026-08-31 dasselbe Bild, unabhängig von der Tageszeit: beide CT-Worker
|
||
scheitern bei **jedem** Lauf. `EnsureSuccessStatusCode` wirft, es gibt keinen Backoff, kein
|
||
`Retry-After`, keine Pause zwischen den Seiten – und beide Worker starten gleichzeitig gegen
|
||
dieselbe Seite. Der ScrapeWorker versucht es alle 30 Minuten unverändert erneut.
|
||
|
||
Damit fördert das erste und bislang einzige Strategiemodul keine Daten. Ob die Sperre an der
|
||
Abrufrate hängt oder daran, dass die Gegenstelle den Vorgabe-`User-Agent` erkennt, ist **nicht
|
||
geklärt** – das gehört vor jede Änderung an der Frequenz.
|
||
|
||
### [X] #396 — Die Shell ignoriert SIGTERM
|
||
|
||
`StartWithClassicDesktopLifetime` blockiert in der Avalonia-Nachrichtenschleife; das geordnete
|
||
Herunterfahren liegt im `finally` darum und wird nur erreicht, wenn das letzte Fenster geschlossen
|
||
wird. Ein POSIX-Signal fängt niemand ab. Zweimal nachgestellt: Nach `kill -TERM` läuft der Prozess
|
||
unverändert weiter.
|
||
|
||
Auf Linux heißt das: Beim Abmelden und beim Herunterfahren wird die Shell nach Ablauf der Frist mit
|
||
SIGKILL abgeräumt. Modul-Stopp und Host-Stopp laufen nie, offene Einträge in `core_worker_log`
|
||
bleiben auf „Running" stehen. Der Daemon macht es richtig – er behandelt SIGTERM über
|
||
`WaitForShutdownAsync`; nur die Shell nicht.
|
||
|
||
### [T] #403 — Die Umgebung des Fehler-Streams steht im Kompilat
|
||
|
||
`DcErrorReporter` legt sie als Konstante fest: `#if DEBUG` heißt „development", sonst „production".
|
||
Die Wahl fällt damit beim Bauen statt beim Betreiben, und ein Testaufbau soll ja gerade das
|
||
Kompilat prüfen, das ausgeliefert wird. Am 2026-08-31 hat die Test-VM darum drei Fehler als
|
||
`production` in den Bugtracker gestellt. Die Umgebungen `staging` und `testing`,
|
||
die der Bugtracker kennt, sind aus der Anwendung heraus gar nicht erreichbar.
|
||
|
||
### [D] #292 — CI wieder gruen bekommen (SDK als PackageReference statt Cross-Repo-Pfad)
|
||
|
||
Das Deploymentcenter-SDK hängt als Cross-Repo-`ProjectReference` am Schwester-Repo;
|
||
`.gitea/workflows/build.yml` checkt nur IBKRTrader aus, also ist der CI-Lauf seit dem 2026-08-23
|
||
rot. Das war die bewusst in Kauf genommene Folge der Interimslösung.
|
||
|
||
Es kostet mehr als einen roten Haken. Am 2026-08-30 stellte sich heraus, dass die tatsächlich
|
||
kompilierte SDK-Fassung längst auf **2.6.0** stand, während überall „2.5.1" dokumentiert war –
|
||
gewandert durch ein `git pull` im Schwester-Repo, ohne eine einzige Änderung auf unserer Seite.
|
||
Ein `changelog?since=2.5.1` fragt dann nach dem falschen Ausgangspunkt. Ein `PackageReference` mit
|
||
fester Versionsnummer beendet beides auf einmal.
|
||
|
||
### [H] #294 — Asynchrone Order- und Fill-Verfolgung
|
||
|
||
`PlaceOrderAsync` ist synchron gedacht: Ausführung oder Fehlschlag innerhalb
|
||
`OrderTimeoutSeconds`. Eine Limit-Order im Buch oder eine Market-Order außerhalb der Handelszeiten
|
||
gilt damit als Fehlschlag – **ist bei IBKR aber weiter aktiv.** Das ist kein Schönheitsfehler,
|
||
sondern der Fall, in dem unser Bild vom Konto und das echte Konto auseinanderlaufen.
|
||
|
||
Diese Aufgabe stand doppelt in zwei Konzepten: als Befund der IBKR-Integration und als `W-2` im
|
||
OptionsWheel-Konzept. Es ist dieselbe Arbeit. Sie ändert den Seam, deshalb kommt sie **vor**
|
||
Stufe 4 und Stufe 5, nicht parallel dazu.
|
||
|
||
### [O] #298 — InstrumentKind/OptionSpec, IbkrMapping.Option, Positionen mit Multiplikator
|
||
|
||
Heute rechnet `Position.Notional` als `Quantity × AvgPrice`. Bei Optionen ist das um Faktor 100
|
||
falsch – womit **jedes Risikolimit wirkungslos wäre**, und zwar lautlos und in die gefährliche
|
||
Richtung. Deshalb steht dieser Punkt vor allem anderen im Options-Fundament.
|
||
|
||
### [O] #300 — Positionsabgleich bei Zuteilung/Verfall und RiskService um sell-to-open erweitern
|
||
|
||
Zuteilung und Verfall ändern Positionen **ohne** Order von uns – ein Bestand, den niemand gekauft
|
||
hat. Zugleich lehnt `EvaluateSell` heute einen Verkauf ohne Bestand grundsätzlich ab, und genau das
|
||
ist die Kernoperation des Wheels.
|
||
|
||
**Niemals nackt:** Short Call nur mit 100 freien Aktien je Kontrakt, Short Put nur mit reserviertem
|
||
Cash über Strike × 100. Die Prüfung gehört in den **Core**, damit ein Modulfehler keine ungedeckte
|
||
Option schreiben kann. Ein Modul, das sich selbst prüft, prüft sich irgendwann nicht mehr.
|
||
|
||
### [O/K] Entscheidungen bei der Umsetzung von #298, #300 und #302–#305
|
||
|
||
Die Umsetzung am 2026-09-04 hat vier Stellen aufgedeckt, an denen die Konzepte nicht eindeutig
|
||
waren oder sich widersprachen. Sie sind so entschieden worden:
|
||
|
||
**Schicht B heißt ab jetzt „kein *ungedeckter* Short".** Das Kapitalmodell formuliert §4 Schicht B
|
||
als „kein Short – Verkäufe werden auf die Buchmenge gekappt, Shorts sind implizit Margin". Für
|
||
Aktien gilt das unverändert. Für Optionen wäre es gleichbedeutend mit „kein OptionsWheel", denn
|
||
dessen Kernoperation *ist* ein verkaufter Kontrakt. Der Grund der Regel war nie der Short an sich,
|
||
sondern der **Kredit**: ein Cash-Secured Put mit reservierter Deckung über Strike × Kontraktgröße
|
||
und ein Covered Call mit gesperrten Aktien nehmen keinen Kredit auf. Die Sperre wird damit nicht
|
||
gelockert, sondern auf ihren eigentlichen Gegenstand gestellt. Ein nackter Verkauf bleibt
|
||
unmöglich, und zwar im Core.
|
||
|
||
**Die Hausreserve wird einmal abgezogen, nicht zweimal.** §4 Schicht A zieht sie vom freien
|
||
Bargeld ab, §3 zieht sie in `Verteilbar` erneut ab. Das ist dieselbe Rücklage, zweimal beschrieben.
|
||
Der doppelte Abzug hätte bei 5 % Reserve rund ein Zehntel des Kapitals stillgelegt, ohne dass es
|
||
irgendwo sichtbar gewesen wäre. `CapitalSnapshot.HouseReserve` steht nur noch zur Anzeige.
|
||
|
||
**Der Positionsschlüssel ist eine Spalte, nicht der Sechser-Verbund.** Das OptionsWheel-Konzept
|
||
sieht `(Module, Symbol, Kind, Expiry, Strike, Right)` als fachlichen Schlüssel vor. MySQL verlangt
|
||
für Primärschlüsselspalten NOT NULL; Expiry, Strike und Right sind bei Aktien aber leer, man
|
||
bräuchte also Platzhalter wie das Datum 1000-01-01. Stattdessen trägt `core_position.ContractKey`
|
||
einen druckbaren Instrumentenschlüssel – bei Aktien schlicht das Ticker-Symbol („AAPL"), bei
|
||
Optionen „AAPL|20260918|C|150". Bestandszeilen ändern sich dadurch inhaltlich nicht; die Migration
|
||
füllt die Spalte aus `Symbol`.
|
||
|
||
**Der Reservierungszustand INTENT entfällt.** §5 nennt ihn vor RESERVED. Absicht und Reservierung
|
||
entstehen aber in derselben Transaktion hinter dem globalen Order-Lock – ein Zustand, den niemand
|
||
je beobachten kann, wäre eine Zeile, die immer leer ist. Wird die Reservierung später zweistufig,
|
||
gehört er nachgezogen.
|
||
|
||
**Neu hinzugekommen: das Buch `DIAG`.** Der Order-Nachweis (#293) und später das
|
||
DebugTrading-Modul (#468) platzieren echte Orders. Ihre Positionen dürfen nicht in der Buchführung
|
||
eines Strategiemoduls landen – sie verfälschten dessen Auslastung, dessen GuV und dessen
|
||
Konzentration, und zwar dauerhaft, weil die Position echt ist.
|
||
|
||
### [O/K] Währung gehört zur Identität eines Instruments
|
||
|
||
Am 2026-09-04 stellte sich beim Order-Nachweis heraus, dass das Paper-Konto sein Bargeld in **EUR**
|
||
hält und in USD mit −3.751 im Minus steht. Ein USD-Kauf wäre damit ein USD-Kredit gewesen, und
|
||
Schicht C hat ihn zu Recht abgelehnt. Die Entscheidung fiel gegen ein Aussetzen der Sicherung und
|
||
für das, was das Problem an der Wurzel löst: **Instrumente sind währungsfähig.**
|
||
|
||
Die Währung steht dabei im Instrumentenschlüssel und nicht bloß als Attribut daneben. Derselbe
|
||
Ticker notiert an mehreren Plätzen — SAP gibt es in Frankfurt in EUR und als ADR in New York in
|
||
USD, zu deutlich verschiedenen Kursen. Zwei Notierungen als eine Position zu führen, würde Bestand
|
||
und Deckung vermischen.
|
||
|
||
**USD bleibt implizit** (`AAPL`, nicht `AAPL:USD`). Andernfalls wäre jede Bestandszeile ab sofort
|
||
ein anderes Instrument als vorher und aus einer Position würden zwei. Trennzeichen ist der
|
||
Doppelpunkt, nicht der Punkt — Ticker enthalten Punkte (BRK.B).
|
||
|
||
### [X] #479 — Die Order lief auf die falsche Notierung
|
||
|
||
Der teuerste Fund des Tages, und einer, den kein Unit-Test hätte finden können. Geprüft, bepreist
|
||
und reserviert wurde `SAP:EUR` zu 188,74 EUR. Ausgeführt wurde die SAP-ADR in New York zu 216,68
|
||
USD; das USD-Guthaben rutschte um 434 ins Minus.
|
||
|
||
Damit wurde **genau der Margin-Kredit aufgenommen, den Schicht C verhindern soll** — an der
|
||
Sicherung vorbei, weil die Sicherung ein anderes Instrument geprüft hatte als das, was gehandelt
|
||
wurde. Ohne Fehlermeldung. Die Bücher wiesen anschließend eine EUR-Position zum USD-Preis aus, die
|
||
es beim Broker nie gab.
|
||
|
||
Die Ursache war eine nicht gesetzte Eigenschaft: `ExecutionService` baute die `OrderRequest` aus
|
||
Einzelfeldern, und `Currency` fiel still auf USD zurück. Die Lehre ist allgemeiner als der Fehler:
|
||
**eine neue Dimension an der Identität eines Objekts macht jede Stelle, die dieses Objekt aus
|
||
Teilen zusammensetzt, zu einer Fehlerquelle.** Deshalb wurde nicht die Zuweisung nachgetragen,
|
||
sondern `OrderRequest.For(instrument, …)` eingeführt — im Orderpfad lässt sich ein Auftrag nicht
|
||
mehr aus losen Feldern bauen.
|
||
|
||
### [K] #480 — Das Kapitalmodell rechnet Währungen zusammen
|
||
|
||
Solange jedes Instrument USD war, war die Frage gegenstandslos. Mit der ersten EUR-Position ist sie
|
||
es nicht mehr: Pool, Konzentrationslimit und die Summe der offenen Reservierungen addieren Beträge
|
||
verschiedener Währungen unverändert.
|
||
|
||
Bei ähnlichen Kursen fällt das nicht auf — **genau deshalb ist es gefährlich.** Und die Richtung
|
||
des Fehlers ist nicht einheitlich: bei einer starken Fremdwährung wird die Auslastung
|
||
*unterschätzt*, und ein Buch darf mehr aufmachen als es soll. Das Kapitalmodell sieht die Lösung in
|
||
§7 bereits vor (Buch-Cash und Reservierungen je Währung); umgesetzt ist sie bisher nur für die
|
||
Reservierungen und für Schicht C. Für die Pool-Rechnung fehlen Umrechnungskurse — die liefert #321.
|
||
|
||
### [H] #293 — Wie der Nachweis geführt wird
|
||
|
||
`--ibkr-check` liest nur. Für #293 gibt es deshalb `--verify-order SYMBOL` am Daemon: es geht durch
|
||
die **vollständige** Kette – Buchzuordnung, Risikoprüfung, Kapitalbindung, Order, Fill, Buchung,
|
||
Abschluss der Bindung – und schreibt hinterher hin, welche Tabellen zu prüfen sind.
|
||
|
||
Drei Sicherungen, weil der Schalter als Einziger im Repository absichtlich eine echte Order
|
||
auslöst: ohne `--confirm` ist er ein Trockenlauf; er verweigert den Dienst außerhalb des
|
||
Paper-Modus **und** außerhalb eines Paper-Ports (eines allein sagt nichts – ein Paper-Modus auf
|
||
einem Live-Port bewegt echtes Geld); und den globalen Handelsschalter übergeht er nicht, sonst
|
||
wäre der keiner.
|
||
|
||
**Geführt am 2026-09-04** gegen das Paper-Konto DUR371528: Kauf von 2 × `SAP:EUR` zu 185,86 EUR,
|
||
alle fünf Tabellen stimmen. Der Nachweis hat dabei **vier Fehler gefunden**, drei davon für
|
||
Unit-Tests unerreichbar — die falsche Notierung (#479), eine Bargeldaufschlüsselung, die gar nicht
|
||
ankam, eine Kursabfrage ohne Währung, und zwei Spalten der Buchführung, die zu eng waren bzw. leer
|
||
blieben. Das ist der eigentliche Ertrag: der Lauf gegen echte Gegenstellen prüft die Fugen zwischen
|
||
den Bausteinen, und dort saßen alle vier.
|
||
|
||
### [W] #309/#310 — Was steht, und was der Handelsbetrieb noch braucht
|
||
|
||
Gerüst und reine Strategie-Logik stehen: `ow_`-Schema mit fünf Tabellen, Zustandsautomat,
|
||
`StrikeSelector`, `RollDecider`, `PremiumMath`, Regelwerk – ohne Broker und ohne Datenbank
|
||
prüfbar. **Offen aus #309 bleibt das Modulfenster**; ohne Daten hätte es fünf leere Tabs.
|
||
|
||
`OptionsWheelModule.GetActivationBlocker` nennt den Grund, warum das Modul noch nicht handelt,
|
||
statt still nichts zu tun: **#311 ist ohne #299 und #294 nicht erreichbar.** Der `StrikeSelector`
|
||
braucht das Delta aus der Optionskette, und eine limitierte Optionsorder am Mittelkurs füllt
|
||
regelmäßig erst nach Minuten – mit dem heutigen synchronen Pfad gälte sie als fehlgeschlagen,
|
||
während sie bei IBKR weiterläuft. Deshalb registriert das Modul noch keine Worker: ein Gerüst, das
|
||
handelt, ohne den Fill mitzubekommen, wäre schlimmer als keines.
|
||
|
||
### [T] #297 — Entscheiden, welcher IBKR-Zugangsweg bleibt
|
||
|
||
Es gibt zwei parallele Wege: den TWS-API-Adapter (`Trading/Ibkr/`, der handelnde Pfad) und
|
||
`IBKRGatewayService` (Client Portal REST, versorgt Instrument-Sync, Kurshistorie und den
|
||
Watchdog-Heartbeat). Zwei Broker-APIs bedeuten zwei Fehlerbilder, zwei Authentifizierungen und
|
||
zwei Betriebsvoraussetzungen – und im Störfall die Frage, welcher der beiden gerade lügt.
|
||
|
||
Entweder die Historie auf `reqHistoricalData` umziehen und den REST-Weg aufgeben – oder die
|
||
Doppelung ausdrücklich begründen. Ein Entscheidungspunkt, keine Implementierungsaufgabe.
|
||
|
||
### [D] #317 — Erstes echtes Release fahren
|
||
|
||
Die Pipeline (`scripts/release.*`, `setup.json`) steht, ist aber nie gelaufen. Zwei Fallen liegen
|
||
beim **ersten** Lauf und lassen sich danach nicht mehr billig korrigieren:
|
||
|
||
Die `preservePatterns` müssen sofort stimmen. Ein Update, das `settings.json` überschreibt, nimmt
|
||
einer laufenden Installation Datenbank, Token und Flex-Zugang gleichzeitig.
|
||
|
||
Der erste Build muss bereits den `licenseKey` mitgeben, sonst fällt die Tür hinter dem ersten
|
||
Release zu – bei Predictalytics genau so passiert.
|
||
|
||
### [A] #322 — Steuerschicht: Jurisdiktionsprofil festlegen
|
||
|
||
Die Jurisdiktion (DE-Kapitalertragsteuer / US Form 8949) ist **nicht festgelegt**. Der neutrale
|
||
Ledger und die Abrechnung gelten unabhängig davon; die Steuer-Engine ist als klar abgetrennter
|
||
Platzhalter angelegt. Das Profil wird einmalig gesetzt und danach in der DB verankert.
|
||
**Keine Steuerberatung.**
|
||
|
||
### [K] #485 — Positionsverwaltung: Herkunft, Zuordnung, Sperren
|
||
|
||
Seit dem Bestandsabgleich (#300/#306) weiß das System, welche Position zu welchem Buch gehört und
|
||
welche es beim Broker fand, ohne sie zuordnen zu können. **Sehen kann man das nirgends**, und
|
||
ändern schon gar nicht: UNASSIGNED bleibt UNASSIGNED, bis jemand in die Datenbank greift.
|
||
|
||
Die drei Fähigkeiten – sehen, zuordnen, sperren – hängen zusammen, weil sie dieselbe Zeile
|
||
betreffen. Die Sperre ist dabei die wichtigste und die einzige, die im Core sitzen muss: **Eine
|
||
Sperre, die ein Modul selbst prüfen müsste, ist keine Sperre, sondern eine Bitte.** Sie gehört
|
||
neben die Deckungsprüfung in den Risikopfad, wo ein Modulfehler sie nicht umgehen kann. Das
|
||
Fenster ist die Bedienung, nicht der Ort der Entscheidung.
|
||
|
||
Vier Stufen: frei, nur schließen, nur aufbauen, gesperrt. Die letzte verdient eine Warnung beim
|
||
Setzen – **sie verhindert auch den Ausgang.** Eine Position, die aus Risikogründen geschlossen
|
||
werden müsste, bleibt liegen, bis jemand die Sperre löst. Das ist eine zulässige Entscheidung des
|
||
Betreibers, aber sie muss beim Setzen sichtbar sein und nicht erst im Störungsfall.
|
||
|
||
Der manuelle Handel in TWS bleibt unberührt: gesperrt werden Module, nicht der Mensch.
|
||
|
||
### [K] #486 — Instrumentenverwaltung: Handelsverbot und harte Obergrenzen
|
||
|
||
Heute gibt es allein `MaxSymbolPercent` – ein prozentuales Konzentrationslimit. Das ist eine
|
||
Risikostreuung und wächst mit dem Konto. Was fehlt, sind Aussagen über ein **bestimmtes Papier**:
|
||
„dieses Instrument nie" und „von diesem höchstens 100 Stück".
|
||
|
||
Beides ist bewusst etwas anderes als der Prozentsatz und ersetzt ihn nicht; es gilt die jeweils
|
||
engere Grenze. Das Handelsverbot hängt am Instrument, nicht am Ticker allein – `SAP:EUR` und die
|
||
SAP-ADR in USD sind zwei Instrumente, und die Währung gehört seit #479 zur Identität. Ein Symbol
|
||
samt aller Notierungen zu sperren muss trotzdem möglich sein, sonst ist die Liste nicht pflegbar.
|
||
|
||
Offene Entscheidung, im Item festgehalten: Ein nachträglich gesetztes Verbot sperrt den **Kauf**,
|
||
nicht das Schließen. Ein Verbot darf keine Position einsperren, die man gerade loswerden will;
|
||
wer das ausdrücklich will, nimmt die Positionssperre aus #485.
|
||
|
||
### [T] #466 — TWS-Meldungen mit Umlauten kommen falsch dekodiert an
|
||
|
||
Am ersten Verbindungstag auf dem neuen Testserver stand im Log `verzögerte Marktdaten` – das Bild,
|
||
wenn UTF-8-Bytes als Latin-1 gelesen werden. Betroffen sind nur Texte **aus der TWS-API**; unsere
|
||
eigenen deutschen Logzeilen im selben Lauf sind sauber, Konsole und Logdatei scheiden als Ursache
|
||
damit aus.
|
||
|
||
Die Wirkung ist gering, aber nicht null: Fehlertexte der Gegenstelle sind das, was im Störungsfall
|
||
gelesen wird, und sie gehen so auch in den Fehler-Stream des Deploymentcenters – ein Text, der
|
||
schon beim Erfassen beschädigt ist, lässt sich später nicht mehr zuverlässig gruppieren.
|
||
|
||
Der schnelle Weg ist, TWS auf englische API-Meldungen zu stellen: englische Fehlertexte sind für
|
||
die Fehlersuche ohnehin die besseren, weil jede Fundstelle im Netz sie so zitiert. Das ist eine
|
||
Umgehung, keine Lösung – ob das TWS-API-Paket die Meldungen fest mit einer Kodierung liest, bleibt
|
||
zu prüfen.
|
||
|
||
### [H] #468 — DebugTrading-Modul: Dauerlast auf der Buchungskette
|
||
|
||
Alles, was den Handel absichert – Modul-Limits, Slippage-Prüfung, Kapitalpool und Reservierungen,
|
||
Abgleich gegen den Broker, Behandlung manueller Trades, Accounting-Ingest, Zeitstempel über
|
||
Zeitzonen hinweg – ist heute ausschließlich durch Unit-Tests mit gemockten Gegenstellen belegt. Im
|
||
laufenden Betrieb gab es fast keine Trades: das einzige Strategiemodul handelt selten und hing
|
||
zuletzt an der 429-Sperre. Ein Fehler in der Buchungskette fällt so erst auf, wenn eine echte
|
||
Strategie scharf geht – und das ist der teuerste Zeitpunkt, ihn zu finden.
|
||
|
||
Das Modul erzeugt deshalb absichtlich Last statt Rendite: kleine Positionen unter 1.000 USD, über
|
||
Handelsplätze und Währungen gestreut, mit gewürfelter Haltedauer von Minuten bis Tagen, die es
|
||
selbstständig wieder schließt. Die lange Spanne ist der Punkt – sie prüft, ob offene Positionen
|
||
Neustarts, Tageswechsel und den nächtlichen TWS-Neustart überstehen.
|
||
|
||
**Warum unter [H] und nicht als eigener Themenbereich:** Es ist kein Strategiemodul und darf nie
|
||
eines werden. Es ist das Prüfwerkzeug der Orderstrecke und hängt an ihr – ohne die gegen das
|
||
Paper-Konto verifizierte Order (#293) hat es nichts, worauf es aufsetzen könnte.
|
||
|
||
**Die Sicherung, die nicht verhandelbar ist:** Startverweigerung, wenn `Trading.Mode` nicht
|
||
`Paper` ist – hart im Modul, nicht als Einstellung. Ein Testmodul, das im Livebetrieb anläuft,
|
||
wäre der teuerste denkbare Fehler dieses Projekts. Dazu ein eigenes Tagesbudget, eine Obergrenze
|
||
gleichzeitig offener Testpositionen, ein Notaus und persistente Testpositionen in `dbg_position`,
|
||
damit ein Neustart keine Position vergisst.
|
||
|
||
---
|
||
|
||
## 🧊 Zurückgestellt – vorgehalten, aber nicht jetzt
|
||
|
||
*Bewusste Entscheidungen, keine Versäumnisse. Der Auslöser steht am Item im Deploymentcenter und
|
||
wird beim Zurückstellen erzwungen; hier steht, warum nicht jetzt.*
|
||
|
||
### [W] #327 — Trendfolge-/Momentum-Modul auf Tagesbasis als zweites Standbein
|
||
|
||
Die Datenlage ist komfortabel: zehn Jahre Tagesbars, dividendenbereinigt. Das Risiko liegt nicht
|
||
in den Daten, sondern in der Strategie. Aber ein zweites handelndes Modul **vor** dem Kapitalmodell
|
||
wäre fahrlässig – zwei Module an einem Konto ohne Eigentumsregeln und Reservierungen ist genau der
|
||
Zustand, den Stufe 4 verhindert.
|
||
|
||
### [M] #328 — Marktdaten-Abo US-Realtime (NYSE/AMEX/NASDAQ)
|
||
|
||
Schaltet Scanner und Realtime frei. Für Tages- und Prämienstrategien **nicht nötig** – unsere
|
||
Signale kommen aus abgeschlossenen Bars, die 15-Minuten-Verzögerung ist dabei irrelevant.
|
||
|
||
### [M] #329 — OPRA-Abo (Optionen-Realtime)
|
||
|
||
Verbessert die Ausführungsqualität beim Wheel. Für die Strike-Auswahl nachweislich nicht
|
||
erforderlich: die Greeks funktionieren mit verzögerten Daten, am 2026-08-04 gegen das
|
||
Paper-Gateway gemessen.
|
||
|
||
### [M] #330 — Refinitiv-Fundamentaldaten
|
||
|
||
Der Kandidat mit dem größten qualitativen Sprung: löst die Earnings-Sperre und öffnet fundamentale
|
||
Ansätze. Kostet aber Geld für ein System, das noch nie eine Order platziert hat. Deshalb wartet er
|
||
auf den Nachweis, dass der billige Behelf (`#312`) nicht reicht.
|
||
|
||
### [K] #331 — Self-Cross-Netting (Modul A kauft, Modul B verkauft dasselbe Symbol)
|
||
|
||
Bei unserer Handelsfrequenz unrealistisch. **Billige Vorstufe stattdessen:** ist im Order-Gateway
|
||
eine gegenläufige Order für dasselbe Symbol pending, wird protokolliert und gewarnt – der Lock ist
|
||
ohnehin da. Das liefert Daten darüber, ob das Problem je real wird, statt es zu vermuten.
|
||
|
||
### [K] #332 — Corporate Actions (Splits, Spin-offs) in der Buchzuordnung
|
||
|
||
Vorerst über den Flex-Abgleich als Break sichtbar, manuelle Zuordnung. Eine Automatik zu bauen,
|
||
bevor der erste Fall aufgetreten ist, heißt gegen eine ausgedachte Spezifikation zu entwickeln.
|
||
|
||
### [T] #333 — Web-UI über die interne REST-API
|
||
|
||
Die REST-API existiert. Ein Web-UI ist reine Zusatzarbeit ohne Betriebsnutzen, solange Shell und
|
||
Daemon reichen.
|
||
|
||
### [D] #334 — Desktop-Distribution der Shell über die Release-Pipeline
|
||
|
||
Die Vorlage nimmt genau eine `csproj` für alle Runtimes, und das Skript bleibt laut Anleitung
|
||
unverändert. Release-Kandidat ist deshalb `IBKRTrader.Daemon`.
|
||
|
||
### [M] #335 — Ungepruefte Datenfragen der TWS API klaeren
|
||
|
||
`reqNewsArticle` (Volltext), Reichweite der Nachrichtenhistorie, Markttiefe (`reqMktDepth`), leeres
|
||
`reqHistogramData`, Verlässlichkeit verzögerter Greeks außerhalb der Handelszeiten, Ratenbegrenzung
|
||
bei Historienabrufen. Keine dieser Fragen blockiert die geplanten Strategien – die Ratenbegrenzung
|
||
wird aber schon bei einem nächtlichen Watchlist-Abruf zur Frage.
|
||
|
||
---
|
||
|
||
## ❌ Verworfen – geprüft und entschieden
|
||
|
||
*Damit nichts davon in sechs Monaten erneut als gute Idee auftaucht. Ein neuer Vorschlag braucht
|
||
ein Argument, das hier noch nicht steht.*
|
||
|
||
### [K] #336 — Echte IBKR-Sub-Accounts (Advisor-/Family-Struktur) zur Trennung der Buecher
|
||
|
||
Erfordert einen Kontotypwechsel und eine feste Vorabaufteilung des Kapitals – deutlich unflexibler
|
||
als virtuelle Bücher, die denselben Zweck erfüllen.
|
||
|
||
### [T] #337 — InvariantGlobalization=true fuer ein schlankes Linux-Image
|
||
|
||
In der Portierungsanalyse noch empfohlen, **wäre ein Fehler gewesen**: ohne ICU fällt die Auflösung
|
||
von Windows-Zeitzonen-IDs aus und die feste `de-DE`-Formatierung des PDF-Exports kippt auf
|
||
invariant. Beides lautlos. Der Daemon setzt es ausdrücklich auf `false`.
|
||
|
||
### [W] #338 — Fundamentales Screening (Value, Quality, Growth)
|
||
|
||
Keine Fundamentaldaten über die TWS API.
|
||
|
||
### [W] #339 — Earnings-Strategien (Straddle vor Zahlen, Post-Earnings-Drift)
|
||
|
||
Keine Termine für Quartalszahlen erreichbar (Fehler 10358, Refinitiv-Abo nötig).
|
||
|
||
### [W] #340 — Marktweite Anomalie-Suche / Screener-getriebene Auswahl
|
||
|
||
Der Marktscanner ist ohne Realtime-Abo gesperrt. Jede Strategie arbeitet auf einer gepflegten
|
||
Watchlist.
|
||
|
||
### [W] #341 — Daytrading, Scalping, Orderbuch-Strategien
|
||
|
||
Verzögerte Kurse (~15 Min). Die Ausführung träfe den Markt zu spät.
|
||
|
||
### [W] #342 — Gap-Strategien auf Eroeffnung
|
||
|
||
Der Eröffnungskurs kommt verzögert – nur mit Realtime-Abo sinnvoll.
|
||
|
||
### [W] #343 — Strike-Wahl ueber prozentualen Abstand statt delta-basiert
|
||
|
||
Als Ersatzlösung gedacht, falls Greeks mit verzögerten Daten nicht funktionieren. Sie funktionieren
|
||
(am 2026-08-04 gemessen). Bleibt im `StrikeSelector` nur als Rückfalllinie.
|
||
|
||
### [S] #344 — Agent-zu-Agent-Orchestrierung im Supervisor
|
||
|
||
Bewusst nicht: Profile sind System-Prompt + Tool-Subset über *einer* Infrastruktur. Einfacher und
|
||
nachvollziehbarer.
|
||
|
||
### [A] #345 — Modulzuordnung als Korrektur des Steuerbuchs
|
||
|
||
Harte Regel: Das Managementbuch beeinflusst das Steuerbuch **niemals**. Die Zuordnung ist eine
|
||
optionale, nicht-autoritative Beistelltabelle – fehlt sie oder ist sie falsch, ändert sich am
|
||
Steuerergebnis exakt nichts.
|
||
|
||
---
|
||
|
||
## Fertig – der Weg bis hierher
|
||
|
||
*Kurzfassung. Die vollständigen Phasen-Checklisten stehen weiterhin in
|
||
[ARCHITECTURE.md](ARCHITECTURE.md). Diese Abschnitte wurden bei der Übernahme bewusst **nicht** zu
|
||
Items – erledigte Arbeit braucht keinen Bearbeiter.*
|
||
|
||
| Abschnitt | Inhalt | Fertig |
|
||
|---|---|---|
|
||
| **R1–R7** | Kurskorrektur auf das PolytraderSharp-Konzept: Multi-Projekt, Generic Host, EF Core, Trading-Kern, CongressTrading-Strategie, Security, Dashboard, TWS-Broker-Adapter | 2026-07 |
|
||
| **S-0–S-4** | Supervisor: Datenfundament (Entscheidungsjournal, Order-Events, `SignalId`, JSONL-Logs), Dossiers, OpenRouter-Agent mit read-only Tools, Berichte, MCP-Light | 2026-07-30 |
|
||
| **Accounting** | `acc_`-Schema, append-only Ingest, Klassifizierung, Abrechnung, FX, CSV-/PDF-Export – mit Offline-Null-Stubs | 2026-07-30 |
|
||
| **L0–L6** | Linux-Portierung: Avalonia statt WinForms, Betriebszeitzone, kopfloser Daemon, geteiltes Hosting, WinForms vollständig entfernt, Namensgebung bereinigt | 2026-08-07 |
|
||
| **DC 0–8** | Deploymentcenter: Lizenz mit Sperrbetrieb, Watchdog-Heartbeat, globale Ausnahmebehandler + Fehler-Stream, Update-Prüfung, `setup.json`, Release-Pipeline | 2026-08-23 |
|
||
| **Frühjahrsputz** | Toter Code entfernt, ungenutzte Symbole und Paketmuster raus, Dokumentenstand an die Wirklichkeit angeglichen | 2026-08-23 |
|
||
| **DC-Anbindung** | Roadmap ins Deploymentcenter übernommen, MCP-Adapter eingerichtet, Baustein A+B in `CLAUDE.md` (**#318**) | 2026-08-30 |
|
||
|
||
---
|
||
|
||
## Archiv
|
||
|
||
Die Quelldokumente sind **vollständig erhalten** und liegen unter [archiv/](archiv/). Sie werden
|
||
nicht mehr gepflegt – der Stand steht im Deploymentcenter –, aber sie tragen die Herleitung, die
|
||
Messwerte und die Begründungen, die eine Roadmap nicht fassen kann.
|
||
|
||
| Dokument | Was darin steht, das hier fehlt |
|
||
|---|---|
|
||
| [Kapital-und-Buchmodell.md](archiv/Kapital-und-Buchmodell.md) | Die vollständige Spezifikation: die drei Wahrheiten, Eigentumsregeln, Reservierungs-Lebenszyklus, Invarianten und Testkatalog. Referenz für `[K]`. |
|
||
| [KONZEPT-Modul-OptionsWheel.md](archiv/KONZEPT-Modul-OptionsWheel.md) | Zustandsautomat, Regelwerk mit Vorgabewerten, `ow_`-Datenmodell, Sicherungen. Referenz für `[W]`. |
|
||
| [KONZEPT-Datenlage-und-Strategien.md](archiv/KONZEPT-Datenlage-und-Strategien.md) | **Gegen das laufende Paper-Gateway gemessen**, nicht aus der Doku übernommen: was die TWS API liefert und welche Strategien das trägt. Grundlage der Zurückgestellt- und Verworfen-Listen. |
|
||
| [KONZEPT-Deploymentcenter-Integration.md](archiv/KONZEPT-Deploymentcenter-Integration.md) | Die bewussten Abweichungen vom DC-Leitfaden (Sperrbetrieb statt Prozessende, `exitCurrentApp: false`) samt Begründung, die Befunde P1–P6 und D1–D7. |
|
||
| [KONZEPT-Linux-Portierung.md](archiv/KONZEPT-Linux-Portierung.md) | Die Analyse vor dem Umbau: Fundstellenverzeichnis, Aufwandsschätzung und was anders kam als geschätzt. |
|
||
| [KONZEPT-Modul-Accounting.md](archiv/KONZEPT-Modul-Accounting.md) | Leitprinzipien (unabhängige Quelle, Idempotenz, append-only), Datenbeschaffung über Flex Query. |
|
||
| [KONZEPT-Modul-Supervisor.md](archiv/KONZEPT-Modul-Supervisor.md) | S-0 bis S-4 im Detail, Tool-Registry, Sicherheitsgrenzen des Agenten. |
|
||
|
||
**Weiter gepflegt** werden – sie sind Referenz, keine Planung:
|
||
[ARCHITECTURE.md](ARCHITECTURE.md) (Aufbau und Phasen-Historie),
|
||
[IBKR-Integration.md](IBKR-Integration.md) (Adapter-Design und Grenzen),
|
||
[TWS-Setup-Checkliste.md](TWS-Setup-Checkliste.md) (Einrichtung eines neuen Systems).
|
||
|
||
---
|
||
|
||
## Den Block auffrischen
|
||
|
||
Der erzeugte Block altert. Auffrischen ohne PHP auf dieser Maschine:
|
||
|
||
```bash
|
||
python scripts/roadmap_block.py
|
||
```
|
||
|
||
Das Skript holt `roadmap.php?action=render` und ersetzt den Bereich zwischen den Markern.
|
||
`DC_TOKEN` kommt aus der Umgebung oder aus `.mcp.json`.
|