> ### 📩 Archiviert am 2026-08-23 > Dieses Dokument wird **nicht mehr gepflegt**. Was davon noch offen ist, steht in der > [Roadmap](../ROADMAP.md) (Stufe 4) – dort und nur dort wird der Stand nachgefĂŒhrt. > > Es bleibt erhalten, weil es die vollstaendige Spezifikation ist, gegen die die Umsetzung geprueft wird – > die drei Wahrheiten, Eigentumsregeln, Reservierungs-Lebenszyklus, Invarianten und Testkatalog. Zum Nachschlagen also weiterhin richtig, > als Aufgabenliste nicht mehr. --- # Kapital- und Buchmodell > **Status: Konzept (2026-08-03) – noch nicht implementiert.** > Dieses Dokument beschreibt, wie mehrere Strategien gleichzeitig auf *einem* IBKR-Konto mit *einem* > Guthaben arbeiten können, ohne sich gegenseitig zu stören, und wie das gegen die steuerliche > BuchfĂŒhrung abgegrenzt ist. Es dient als Referenz, gegen die die spĂ€tere Umsetzung geprĂŒft wird. ## 0. Problemstellung und Abgrenzung TWS lĂ€sst sich pro Rechner nur einmal betreiben – wir sind an **ein** Konto mit **einem** Guthaben gebunden. Trotzdem sollen mehrere Strategie-Module parallel handeln. Daraus folgen vier Anforderungen: 1. Jedes Modul bekommt eine **klar begrenzte Kapitalmenge**, die es binden darf. 2. Jede Position hat einen **eindeutigen EigentĂŒmer**. Kein Modul darf die Position eines anderen Moduls oder eine manuell angelegte Position anfassen. 3. Das Konto darf durch Modul-Handel **niemals ins Minus oder in Margin** laufen. 4. Die **steuerliche BuchfĂŒhrung** ist davon vollstĂ€ndig unabhĂ€ngig und muss zu 100 % stimmen. Nicht Gegenstand dieses Dokuments: Strategielogik, Signalerzeugung, Marktdatenversorgung. --- ## 1. Die drei Wahrheiten Es gibt drei Datenquellen mit unterschiedlicher AutoritĂ€t. Sie dĂŒrfen sich nicht vermischen. | Ebene | Quelle | Autoritativ fĂŒr | Latenz | |---|---|---|---| | **Steuerbuch** (`acc_`) | Flex Query | Geld, Steuer, GuV – alles gegenĂŒber der Steuerbehörde | T+1 | | **Depot-Ist** | TWS-API-Snapshot | Was *jetzt* real im Konto liegt | Sekunden | | **Managementbuch** (`core_`) | eigene Order-Events + Abgleich | Zuordnung von Positionen zu BĂŒchern | live | **Harte Regel:** Das Managementbuch beeinflusst das Steuerbuch **niemals** – weder korrigierend noch ergĂ€nzend. Der Accounting-Ingest liest Flex Query, klassifiziert und bucht; ob dabei eine `BookId` bekannt ist, ist ihm gleichgĂŒltig. Die Modulzuordnung ist eine *optionale, nicht-autoritative* Beistelltabelle (Flex-Trade-ID ↔ BookId). Fehlt sie oder ist sie falsch, Ă€ndert sich am Steuerergebnis exakt nichts. Umgekehrt gilt: Das Managementbuch **bezieht** Korrekturen aus dem Steuerbuch (GebĂŒhren, Dividenden, Splits), nie andersherum. --- ## 2. BĂŒcher (Books) Ein **Buch** ist ein Kapitaltopf mit zugeordneten Positionen. BĂŒcher sind: | Buch | Bedeutung | Handelt | Limits gelten | |---|---|---|---| | je Strategie (`CT`, 
) | ein Modul, ggf. ein Parametersatz | ja | ja | | `MANUAL` | von Hand in TWS/IBKR angelegt | nein (nur extern) | **nein**, zĂ€hlt aber mit | | `UNASSIGNED` | am Broker gefunden, keinem Buch zugeordnet | nein | zĂ€hlt mit | | `HOUSE` | nicht allokierte Reserve, FX, Ausgleichsposten | nein | – | **`BookId` ist ein eigenes Konzept, nicht der Modulname.** Default `BookId == Modulname`, aber die Trennung erlaubt spĂ€ter mehrere BĂŒcher desselben Moduls und macht `MANUAL`/`UNASSIGNED`/`HOUSE` sauber modellierbar. Jetzt kostenlos, spĂ€ter teuer nachzurĂŒsten. ### Eigentumsregeln (im Core erzwungen, nicht per Konvention) 1. Ein Verkaufssignal von Buch *b* kann **nur Positionen von *b*** reduzieren, gedeckelt auf `Menge(b, Symbol)`. DarĂŒber hinaus wird gekappt – **niemals** wird ein Short erzeugt. 2. `MANUAL` und `UNASSIGNED` senden keine Signale und empfangen keine. 3. Ein Modul kann seine `BookId` **nicht selbst wĂ€hlen**. Sie stammt aus der Modul-Registrierung und wird serverseitig gesetzt; `TradeSignal.SourceModule` aus dem Modul ist nicht vertrauenswĂŒrdig. 4. Module bekommen `IBrokerClient` **nicht** per DI – ausschließlich `IExecutionService`. Sonst ist die gesamte BuchfĂŒhrung umgehbar. 5. Ein Kill-Switch/Supervisor darf alles liquidieren – als explizite Core-AutoritĂ€t mit eigener Konfiguration, standardmĂ€ĂŸig unter Ausschluss von `MANUAL`. --- ## 3. Kapitalmodell: ein Pool, Obergrenzen **Es gibt keinen Kapitaltransfer zwischen BĂŒchern.** Kein Buch-Cash, keine Rebalancing-LĂ€ufe, keine Ausgleichsforderungen. Stattdessen ein gemeinsamer Cash-Pool und pro Buch eine Obergrenze: ``` Verteilbar = FreiesCash(gehaircuttet) + ÎŁ Modul-Positionswert − HouseReserve Cap(b) = konfigurierter Anteil × Verteilbar (Default: Gleichverteilung) Gebunden(b) = Marktwert der Positionen von b + offene Reservierungen von b Headroom(b) = min( Cap(b) − Gebunden(b), freies Pool-Cash ) ``` ### Eigenschaften, die bewusst so sind - **Gewinne verteilen sich von selbst.** Realisiert ein Buch einen Gewinn, wĂ€chst der gemeinsame Pool; da alle Caps aus `Verteilbar` abgeleitet werden, steigt der Headroom **aller** BĂŒcher. Diversifikation ohne einen einzigen Zwangsverkauf. - **Ein Buch darf ĂŒber seinem Cap liegen.** Steigen die Positionen im Wert, passiert nichts – außer dass nicht mehr nachgekauft werden darf. Der Zustand â€žĂŒber Cap" ist **legal**, wird angezeigt und gemeldet, aber **nie geheilt**. Es wird niemals eine Position geschlossen, nur um eine Zielquote herzustellen. - **`ÎŁ Caps ≀ 100 % − Reserve` wird beim Start validiert.** Sonst könnte ein schnelles Buch ein langsames aushungern („wer zuerst kommt"). - **Die Modul-Welt sieht nie den NAV**, sondern nur ihr eigenes Kapital plus freies Cash. Manuelle Positionen – auch kreditfinanzierte – sind eine Black Box, die nur ĂŒber das freie Cash wirkt. ### KapitalfĂŒhrung ≠ Performance-Messung Die KapitalfĂŒhrung ist ein Pool plus Caps. Die GuV **pro Buch** ist eine reine *Auswertung* ĂŒber die Trade-Historie (fĂŒr Supervisor und Reporting) und steuert nichts. Diese Entkopplung ist beabsichtigt. --- ## 4. Keine Margin – die Sperre **Modul-Handel ist strikt cash-only. Manueller Handel darf Margin nutzen.** Der Kontotyp ist Cash-Konto; brokerseitig kann trotzdem Margin verfĂŒgbar sein, deshalb ist die Software-Sperre zwingend und testpflichtig. ### Schicht A – richtige Bemessungsgrundlage `BuyingPower` und `AvailableFunds` sind auf einem Margin-Konto bereits gehebelt gerechnet und als Basis unbrauchbar. Maßgeblich ist: ``` FreiesCash = min(TotalCashValue, AvailableFunds) − HouseReserve − ÎŁ offene Reservierungen ``` `TotalCashValue` ist das echte Bargeld. Eröffnest du manuell eine Margin-Position, sinkt es, und die Modul-Kaufkraft schrumpft automatisch mit. Bei `TotalCashValue ≀ 0` ist die Modul-Kaufkraft null – ohne Sonderlogik. Module können einen manuellen Kredit strukturell nicht ausweiten. ### Schicht B – kein Short VerkĂ€ufe werden auf die Buchmenge gekappt. Shorts sind implizit Margin. ### Schicht C – WĂ€hrung Ein Kauf in WĂ€hrung X darf **nur aus Cash in WĂ€hrung X** finanziert werden. Andernfalls entsteht ein Sollsaldo in X – ein Margin-Kredit, auch wenn das Konto in Summe positiv aussieht. Buch-Cash und Reservierungen werden deshalb **pro WĂ€hrung** gefĂŒhrt (siehe Abschnitt 7). ### Schicht D – Watchdog Ein Hosted Service prĂŒft Cash und Margin-Kennzahlen laufend. Bei Unterschreitung: **globaler Kauf-Stopp + Alarm** – und **niemals automatisches Verkaufen** zur Heilung. Ein Selbstheilungs-Amoklauf ist gefĂ€hrlicher als der Zustand, den er beheben soll. --- ## 5. Reservierungen (Order-Lebenszyklus) Verhindert, dass zwei Module gleichzeitig dasselbe Geld ausgeben. Persistent in der DB, nicht im RAM. ``` INTENT → RESERVED → SUBMITTED → FILLED | PARTIAL | CANCELLED | REJECTED | EXPIRED ``` - **Reservierungshöhe:** `Menge × Referenzpreis × (1 + Puffer)` + geschĂ€tzte Kommission. Puffer klein bei Limit-Orders (das Limit *ist* die Obergrenze), grĂ¶ĂŸer bei Market (Slippage), zusĂ€tzlich FX-Puffer bei wĂ€hrungsĂŒbergreifenden VorgĂ€ngen. - **Atomar** gegen Buch-Headroom *und* Pool-Cash, in einer DB-Transaktion hinter einem **globalen Order-Lock**. Bei einer TWS-Verbindung reicht ein einfacher `SemaphoreSlim`; feingranulare Locks wĂ€ren hier nur eine zusĂ€tzliche Fehlerquelle. - **Freigabe** beim Terminalzustand; Differenz zwischen Reservierung und echtem Fill fließt zurĂŒck. - **TTL zwingend.** Erreicht eine Reservierung ohne Terminalzustand ihr Ablaufdatum oder den Handelsschluss → **Alarm, keine stille Freigabe**. Eine hĂ€ngende Order, deren Reservierung freigegeben wird, gibt das Geld zweimal aus. - **Idempotenz** ĂŒber `SignalId` bzw. eine Client-Order-ID, damit ein Reconnect keine Doppelorder erzeugt. - **Crash-Recovery:** beim Start alle nicht-terminalen Reservierungen gegen die offenen Broker-Orders abgleichen; Waisen → QuarantĂ€ne + Alarm. --- ## 6. Limits und Feedback an die Module ### Konzentrationslimit pro Einzelwert ``` SymbolExposure(s) = ÎŁ_b Marktwert(b, s) ← ĂŒber ALLE BĂŒcher, inkl. MANUAL PrĂŒfung: SymbolExposure(s) + geplanter Kauf ≀ MaxSymbolPercent × NAV ``` - **NAV als Nenner**, nicht der Positionswert – sonst wird das Limit bei viel Cash absurd eng und bei wenig Cash absurd weit. - **`MANUAL` ist von der PrĂŒfung befreit, zĂ€hlt aber voll in den ZĂ€hler.** HĂ€ltst du 50 % AAPL von Hand, sind die Module bei AAPL vollstĂ€ndig gesperrt. So gewollt. - **VerkĂ€ufe sind nie limitiert.** Ein Limit darf niemals das Schließen einer Position verhindern. ### Feedback-Kontrakt Das Gate ist **hart**. Das Modul entscheidet nur, *wie es auf die Ablehnung reagiert* – nicht, ob das Limit gilt. Ein erneut gesendetes zu großes Signal wird wieder abgelehnt. Der Core trimmt nicht selbststĂ€ndig; die Entscheidung liegt auf Strategieebene. ```csharp record LimitBreach( LimitKind Kind, // SymbolConcentration | BookCap | CashAvailable // | FxBuffer | CurrencyNotAllowed | VenueNotAllowed string Scope, // "AAPL" | "CT" | "USD" decimal Current, decimal Limit, int MaxQuantity, // was jetzt noch ginge decimal MaxNotional); ``` ErgĂ€nzend eine Vorab-Query `GetHeadroom(book, symbol)`, damit ein gut gebautes Modul gar nicht erst gegen die Wand fĂ€hrt und seine Order gleich richtig dimensioniert. **Drossel:** Ein Modul, das dasselbe Signal wiederholt gegen dieselbe Wand schickt, wird nach N Versuchen pro `SignalId` gedĂ€mpft und protokolliert. Sonst produziert eine schlecht geschriebene Strategie Logfluten und TWS-Last. --- ## 7. WĂ€hrungen und HandelsplĂ€tze **KontobasiswĂ€hrung:** konfigurierbar, bei Ersteinrichtung festgelegt, danach gesperrt (siehe Abschnitt 11 – eine Änderung nach dem ersten Trade macht alle historischen Bewertungen, Caps und GuV-Zahlen ungĂŒltig). - Produktion (US LLC): `USD` - Test/Paper (EU): `EUR` ### Contract-Auflösung ist Pflicht Eine Order mit nacktem Symbol-String ĂŒber `SMART` kann bei mehrdeutigen Tickern still an einer Börse in einer anderen WĂ€hrung landen. Deshalb: - Vor jeder Order wird der Contract ĂŒber `reqContractDetails` aufgelöst; `currency`, `exchange`, `primaryExchange` und `conId` werden geprĂŒft. - **Whitelist auf zwei Achsen:** WĂ€hrung ∈ `AllowedCurrencies` **und** Handelsplatz ∈ konfigurierter Liste. Verstoß → harte Ablehnung, unabhĂ€ngig vom Modul. - Das Ergebnis wird gecacht; **die `conId` wird in der Position gespeichert.** Sie ist IBKRs eindeutige Instrumenten-ID und deutlich sicherer als ein Ticker. ### FX-Marge als Sicherheitspuffer, nicht als Exposure-Deckel Bei ĂŒberwiegendem Handel in KontobasiswĂ€hrung wĂ€re ein FX-Exposure-Limit meist verletzt und damit nutzlos. Sinnvoll wirkt die Marge an drei anderen Stellen: 1. **Bewertungs-Haircut:** FremdwĂ€hrungs-Cash geht mit Abschlag in `Verteilbar` ein → das eigene Kapital wird nie ĂŒberschĂ€tzt. 2. **Reservierungspuffer** bei wĂ€hrungsĂŒbergreifenden KĂ€ufen, zusĂ€tzlich zum Slippage-Puffer. 3. **FX-Exposure als Kennzahl mit Alarmschwelle** – sichtbar und meldepflichtig, ohne Handelssperre. ### Kein Auto-FX im Order-Pfad Fehlt Cash in der ZielwĂ€hrung, scheitert der Modul-Kauf mit `LimitKind.CashAvailable`. Konvertiert wĂŒrde der Order-Pfad selbst, könnte ein Modul indirekt FX-Kosten und FX-Timing auslösen, und die Reservierungslogik mĂŒsste zwei WĂ€hrungen gleichzeitig sperren. FX bleibt ein expliziter Vorgang auf `HOUSE`-Ebene. --- ## 8. Abgleich (Reconciliation) Weil jederzeit manuell in TWS eingegriffen werden kann, ist der Abgleich kein Zusatz, sondern das Fundament. Zwei Stufen: **Stufe 1 – Ledger ↔ TWS (minĂŒtlich):** Handelssicherheit. Stimmen StĂŒckzahlen und Cash? | Befund | Bedeutung | Reaktion | |---|---|---| | Broker > Ledger | manuell gekauft, oder ein Fill kam nach | Überschuss → `UNASSIGNED` | | Broker < Ledger | manuell verkauft / Corporate Action | **Break:** betroffene BĂŒcher und Symbol fĂŒr neue Orders sperren, Alarm | | Cash weicht ab | GebĂŒhren, Zinsen, FX | Differenz gegen `HOUSE`, ab Schwelle Break | Bei „Broker < Ledger" wird bewusst **nicht** automatisch korrigiert. Anteiliges WegkĂŒrzen zerstört die Zurechenbarkeit – Halt-and-alert, der Mensch entscheidet. **Stufe 2 – Ledger ↔ Flex Query (tĂ€glich, nach Ingest):** QualitĂ€tssicherung. Hier kommen GebĂŒhren, Dividenden, Quellensteuer, FX-Differenzen und Splits an – Dinge, die die TWS-API gar nicht oder schlecht liefert. **GebĂŒhren gehören dem verursachenden Buch.** Sonst subventioniert `HOUSE` die vieltradenden Module und die Performance-Zahlen lĂŒgen. Beim Fill wird geschĂ€tzt, beim Flex-Abgleich exakt nachjustiert. --- ## 9. Unzugeordnete Positionen und Eskalation ZustĂ€nde: `New → Notified → Acknowledged → Assigned(Book)`, mit `DetectedAt`-Zeitstempel. - Ein Watchdog meldet alles, was **lĂ€nger als 30 Minuten** unbearbeitet liegt. - **Backoff:** nach 30 min, dann 2 h, dann tĂ€glich – sonst wird der Kanal unbrauchbar. - **Abgestufte Sperrwirkung:** Eine `UNASSIGNED`-Position **zĂ€hlt voll** in Exposure und Konzentrationslimit, bremst die Module also automatisch, **sperrt aber nicht hart**. Hart gesperrt wird nur der gefĂ€hrliche Fall aus Abschnitt 8 (Broker < Ledger). --- ## 10. Benachrichtigungen Im Code existiert derzeit **kein** Benachrichtigungssystem (die Treffer zu „Notification" im Supervisor-MCP sind JSON-RPC-Notifications, etwas anderes). Sauberer Start. ``` INotificationSink Name, SendAsync(Notification, ct) Notification Severity, Category, Title, Body, DedupKey, Data NotificationService Fan-out ĂŒber alle registrierten Sinks ``` Drei Eigenschaften mĂŒssen von Anfang an drin sein, weil sie spĂ€ter schwer nachzurĂŒsten sind: - **Outbox in der DB** (`core_notification`): erst persistieren, dann zustellen, Retry bei Fehler. Solange kein Zielkanal existiert, sammeln sich Meldungen sichtbar an und werden zugestellt, sobald ein Sink da ist. Nichts geht verloren. - **Dedup/Throttling** ĂŒber `DedupKey` (z. B. `unassigned:AAPL`). - **Severity-Routing:** Info → Log/UI, Warning → Chat, Critical → alle KanĂ€le. Ausbaureihenfolge: `LogSink` + `UiSink` sofort → `MatrixSink`, sobald der Server steht → `TelegramSink` optional als Backup. **Matrix** ist reines HTTP, keine Library nötig: `PUT /_matrix/client/v3/rooms/{roomId}/send/m.room.message/{txnId}` mit dem Access-Token eines Bot-Users. Die `txnId` ist Matrix' eingebauter Idempotenz-SchlĂŒssel und passt exakt auf die Outbox-ID. Das Token gehört in `SecretProtection`. --- ## 11. Steuerbuch: Jurisdiktionsprofil **Pro Deployment gibt es genau eine Jurisdiktion, und sie wechselt nie.** Ein Kontowechsel zwischen LĂ€ndern findet nicht statt – die Option „spĂ€ter auch in Deutschland" bedeutet ausdrĂŒcklich: anderer Server, andere Datenbank, anderes IBKR-Konto. Daraus folgt: keine Migration, keine MehrmandantenfĂ€higkeit, kein Umschalten zur Laufzeit. Das Profil ist **kein WĂ€hrungs-Flag**, sondern ein Austausch der gesamten Lot- und Klassifikationslogik: | Aspekt | US LLC (Hauptziel) | DE privat (Option) | DE GmbH (Option) | |---|---|---|---| | BerichtswĂ€hrung | USD, keine Umrechnung | EUR, Umrechnung pro Vorgang | EUR, Umrechnung pro Vorgang | | Lot-Matching | FIFO Standard, Specific ID wĂ€hlbar | FIFO zwingend | Bilanzierung | | Wash Sale (30 Tage) | **ja**, Basis-Anpassung | kein Äquivalent | kein Äquivalent | | Haltefrist | short/long term ab 1 Jahr | irrelevant | irrelevant | | Verlustverrechnung | Carryforward mit Deckel | getrennte Töpfe | wieder anders | | Quellensteuer | – | Anrechnung nach DBA | Anrechnung | | Ausgabe | 1099-B-Abgleich / K-1 | Anlage KAP | Bilanz/GuV | Die **Wash-Sale-Regel** ist die einschneidendste: sie verĂ€ndert Anschaffungskosten rĂŒckwirkend. Eine Engine, die nur FIFO kann, lĂ€sst sich dafĂŒr nicht nachrĂŒsten. Deshalb muss die Lot-Verwaltung von Anfang an lot-basiert sein und **Basis-Anpassungen als eigene Buchungsart** kennen – auch wenn das erste Profil sie noch nicht nutzt. > Die konkreten steuerlichen AusprĂ€gungen (u. a. ob die LLC als Disregarded Entity oder Partnership > behandelt wird, was das Reporting Ă€ndert) sind mit dem Steuerberater abzustimmen. Hier steht nur, > was die Software mechanisch abbilden können muss. ### Profile und Umgebungen ``` Test/Paper (EU) BaseCurrency EUR TaxProfile None Produktion (US) BaseCurrency USD TaxProfile UsLlc Option DE BaseCurrency EUR TaxProfile DePrivat | DeGmbh ``` Das Profil **`None`/`Paper`** fĂŒhrt vollstĂ€ndig Buch, rechnet aber keine Steuer und ist in UI und allen Exporten sichtbar als solches markiert. Deutsche Steuerregeln auf Paper-Trades zu rechnen wĂ€re sinnlos und produziert Zahlen, die jemand spĂ€ter fĂŒr echt halten könnte. ### Wo der Lock hingehört **Nicht in `appsettings.json`.** Eine Datei lĂ€sst sich editieren, und dann rechnet die Engine ab morgen nach anderen Regeln ĂŒber denselben Bestand – der schlimmstmögliche Fehler, weil er sich still auswirkt. Der Lock gehört **in die Datenbank, neben die Daten, die er regiert**: eine Stempelzeile im Accounting-Schema mit Jurisdiktion, BerichtswĂ€hrung, KontobasiswĂ€hrung und Einrichtungszeitpunkt. Beim Start wird die Konfiguration dagegen geprĂŒft; bei Abweichung startet das Accounting-Modul nicht, sondern meldet einen Konflikt. Gesetzt wird der Stempel bei der Ersteinrichtung, geĂ€ndert nur durch eine leere Datenbank. ### Was deshalb *nicht* gebaut wird Die EZB-Kursanbindung (Kursquelle, Stichtagsregeln, Kursarchivierung) ist fĂŒr das Hauptziel nicht nötig: USD-Konto, USD-Reporting, keine Umrechnung. Also nur die **Naht** bauen (`IFxRateSource`, im US-Profil eine No-Op), nicht die Implementierung. Wird die DE-Option je gezogen, geschieht das ohnehin auf einem anderen Server – dann wird sie dort ergĂ€nzt. Falls doch: EZB-Referenzkurse autoritativ, IBKR-Bewertungskurse nur als KontrollgrĂ¶ĂŸe; **verwendeter Kurs, Quelle, Stichtag und Abrufzeitpunkt werden mitgespeichert**, nicht nur der umgerechnete Betrag. --- ## 12. Datenmodell-Deltas | Heute | Delta | |---|---| | `core_position` (PK `Module`+`Symbol`) | `Module` → `BookId`; **`ConId`, `Currency`, `Exchange` ergĂ€nzen** | | `core_budget` (Total/Used/MaxPerTrade) | ersetzen durch `core_book`: Cap-Regel, Flags (ReadOnly, Active), MindestordergrĂ¶ĂŸe | | – | `core_reservation` (Zustandsmaschine, TTL, WĂ€hrung) | | – | `core_broker_snapshot` + `core_reconciliation_break` | | – | `core_notification` (Outbox) | | – | `core_instrument` (aufgelöste Contracts, `conId`-Cache, Whitelist-Status) | | – | `acc_jurisdiction` (Stempel, Abschnitt 11) | | ~~Buch-Cash, Transfers, Rebalance-Lauf~~ | **entfĂ€llt** – ein Pool plus Caps (Abschnitt 3) | | `RiskContext.NetLiquidation` | → `Verteilbar` und `Headroom(b)`, **nicht** NAV | | `IbkrConnection`: `NetLiquidation,AvailableFunds` | + `TotalCashValue`, `SettledCash`, Margin-Kennzahlen, **pro WĂ€hrung** | | `IBrokerClient` | + `GetPositionsAsync`, + `ResolveContractAsync` | | `ExecutionService` (Check-then-Act ohne Lock) | Order-Gateway davor: Serialisierung + Reservierung | | `ExecutionResult.Reason` (string) | + strukturiertes `LimitBreach` (Abschnitt 6) | --- ## 13. Invarianten und Testkatalog Die No-Margin-Bedingung wird als **eine ausfĂŒhrbare Invariante** formuliert, die an drei Stellen dieselbe Codebahn nimmt: ``` ∀ WĂ€hrung c: FreiesCash(c) ≄ 0 ∧ ÎŁ offene Reservierungen(c) ≀ FreiesCash(c) ∀ Buch b, Symbol s: Menge(b, s) ≄ 0 ∀ Symbol s: ÎŁ_b Menge(b, s) = BrokerMenge(s) ``` 1. als Assert am Ende **jedes** Trading-Tests (gemeinsamer Testhelfer, nicht pro Test neu geschrieben) 2. als Property-Test ĂŒber zufĂ€llige Sequenzen aus Reservierung / Fill / Teilfill / Cancel / Slippage / manuellem Eingriff 3. als LaufzeitprĂŒfung im Watchdog – **identische Implementierung**, damit Test und Produktion nicht auseinanderlaufen ### PflichtfĂ€lle | Fall | Erwartung | |---|---| | Zwei parallele Reservierungen, zusammen > freies Cash | zweite abgelehnt | | N nebenlĂ€ufige Tasks (Stresstest) | ÎŁ Reservierungen nie > freies Cash | | Fill teurer als reserviert, innerhalb Puffer | ok, Restfreigabe korrekt | | Fill jenseits des Puffers | Alarm, Cash bleibt ≄ 0 | | Manuelle Margin-Position taucht auf, Cash < Reserve | alle Modul-KĂ€ufe gesperrt | | Cash in ZielwĂ€hrung = 0, andere WĂ€hrung vorhanden | abgelehnt – **kein** stiller FremdwĂ€hrungskredit | | Verkaufssignal ĂŒber Buchmenge hinaus | gekappt, kein Short | | Reservierung erreicht TTL | Alarm, **keine** stille Freigabe | | Neustart mit offenen Reservierungen | aus DB rekonstruiert, keine Doppelausgabe | | Modul setzt fremde `BookId` im Signal | serverseitig ĂŒberschrieben | | Verkaufssignal gegen `MANUAL` | abgelehnt | | Contract löst auf fremde WĂ€hrung/Börse auf | abgelehnt vor Ordersendung | --- ## 14. Bewusst verschoben - **Self-Cross-Netting** (Modul A kauft, Modul B verkauft dasselbe Symbol gleichzeitig). Bei der erwarteten Handelsfrequenz unrealistisch und allenfalls eine Ausnahmeerscheinung. **Billige Vorstufe jetzt:** Ist im Order-Gateway eine gegenlĂ€ufige Order fĂŒr dasselbe Symbol pending, wird das protokolliert und gewarnt. Der Lock ist ohnehin da – das kostet fast nichts und liefert Daten darĂŒber, ob das Problem je real wird. - **Corporate Actions** (Splits, Spin-offs) in der Buchzuordnung – vorerst ĂŒber den Flex-Abgleich als Break sichtbar, manuelle Zuordnung. - **Echte Sub-Accounts** bei IBKR (Advisor/Family-Struktur) als brokerseitige Trennung. Erwogen und verworfen: erfordert Kontotypwechsel und feste Vorabaufteilung des Kapitals, deutlich unflexibler als virtuelle BĂŒcher. --- ## 15. Offene Punkte - **MindestordergrĂ¶ĂŸe** pro Buch: ein Wert in KontobasiswĂ€hrung, FremdwĂ€hrungsorders per Tageskurs dagegen geprĂŒft. Konkreter Wert beim Bauen festzulegen. - **Konkrete Limitwerte** (`MaxSymbolPercent`, `HouseReserve`, FX-Haircut, Slippage-Puffer, TTL) – Startwerte beim Bauen festzulegen und in `settings.example.json` dokumentieren. - **Handelsplatz-Whitelist**: konkrete Börsenliste je WĂ€hrung. - **Umsetzungsreihenfolge** – noch nicht besprochen. --- ## Zusammenfassung der getroffenen Entscheidungen | # | Entscheidung | |---|---| | 1 | Cash-Konto; Modul-Handel strikt cash-only, manueller Handel darf Margin nutzen | | 2 | Kein Kapitaltransfer zwischen BĂŒchern – ein Pool plus Obergrenzen; **niemals** aktives Schließen zum Balancieren | | 3 | Limit-Verletzung: hartes Gate, strukturiertes Feedback; die Reaktion entscheidet die Strategie | | 4 | KontobasiswĂ€hrung USD (Produktion) / EUR (Test), bei Ersteinrichtung gesetzt und danach gesperrt | | 5 | Nur USD und EUR handelbar; Contract-Auflösung mit WĂ€hrungs- und Handelsplatz-Whitelist ist Pflicht | | 6 | Steuerbuch strikt getrennt, Flex Query als einzige Quelle, Jurisdiktionsprofil einmalig und in der DB verankert | | 7 | Unzugeordnete Positionen: QuarantĂ€ne + Eskalation nach 30 Minuten mit Backoff | | 8 | Benachrichtigungen ĂŒber Outbox + Sink-Abstraktion; Matrix als Zielkanal, Telegram optional |