# 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]`). --- ### Als Naechstes 1. **[X] #388 — WorkerBase: Intervall ueber 24,85 Tage toetet den Worker still und reisst beim Herunterfahren den Prozess mit** 2. **[X] #390 — Fehlgeschlagener DB-Dump gilt als erfolgreicher Backup-Lauf** 3. **[X] #389 — BackupWorker sichert eine andere Datenbank als die, mit der die Anwendung arbeitet** 4. **[X] #391 — --check meldet "Pruefdurchlauf OK", ohne die Datenbank je zu erreichen** ### X — Kritische Bugs | | Vorhaben | Stand | Ziel | |---|---|---|---| | #388 | WorkerBase: Intervall ueber 24,85 Tage toetet den Worker still und reisst beim Herunterfahren den Prozess mit | 📋 Offen | — | | #390 | Fehlgeschlagener DB-Dump gilt als erfolgreicher Backup-Lauf | 📋 Offen | — | | #389 | BackupWorker sichert eine andere Datenbank als die, mit der die Anwendung arbeitet | 📋 Offen | — | | #391 | --check meldet "Pruefdurchlauf OK", ohne die Datenbank je zu erreichen | 📋 Offen | — | | #394 | CapitolTrades-Scraper behandelt 429 nicht - beide CT-Worker fallen bei jedem Lauf aus | 📋 Offen | — | | #396 | Die Shell reagiert unter Linux nicht auf SIGTERM - kein geordnetes Herunterfahren ausserhalb des Fensters | 📋 Offen | — | ### 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 | 📋 Offen | — | ### H — Handelspfad (TWS-Broker-Adapter) | | Vorhaben | Stand | Ziel | |---|---|---|---| | #293 | PlaceOrderAsync gegen das Paper-Konto verifizieren | 📋 Offen | — | | #294 | Asynchrone Order- und Fill-Verfolgung | 📋 Offen | — | | #295 | IBKR-Zugangsdaten mit EncryptedStringConverter ablegen | 📋 Offen | — | | #296 | IBC/IBController einrichten (Auto-Login, taeglicher Gateway-Neustart) | 📋 Offen | — | ### O — Options-Fundament im Core | | Vorhaben | Stand | Ziel | |---|---|---|---| | #298 | InstrumentKind/OptionSpec, IbkrMapping.Option, Positionen mit Multiplikator | 📋 Offen | — | | #299 | Optionskette und Greeks im Core (reqSecDefOptParams, tickOptionComputation) | 📋 Offen | — | | #300 | Positionsabgleich bei Zuteilung/Verfall und RiskService um sell-to-open erweitern | 📋 Offen | — | | #301 | IV-Rank als Core-Baustein | 📋 Offen | — | ### K — Kapital- und Buchmodell | | Vorhaben | Stand | Ziel | |---|---|---|---| | #302 | Buecher und Eigentumsregeln | 📋 Offen | — | | #303 | Ein Pool, Obergrenzen | 📋 Offen | — | | #304 | Margin-Sperre in vier Schichten | 📋 Offen | — | | #305 | Reservierungen ueber den Order-Lebenszyklus inkl. Crash-Recovery | 📋 Offen | — | | #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 | 📋 Offen | — | | #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 | — | | #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 | 📋 Offen | — | | #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 | — | | #333 | Web-UI ueber die interne REST-API | 🧊 Zurueckgestellt — Ausloeser: Fernzugriff auf eine laufende Instanz noetig wird | — | | #337 | InvariantGlobalization=true fuer ein schlankes Linux-Image | ❌ Verworfen | — | --- ## 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. ### [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. ### [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.** ### [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`.