Produktdokumentation
Überblick
Portfolixir ist eine selbst gehostete, lokal-first Phoenix-Anwendung für die Verwaltung eines einzelnen Portfolio-Workflows. Sie ist bewusst eng gefasst:
- Manuelles Anlegen von Wertpapieren, Portfolio, Konten und Transaktionen.
- Massenimport von Portfolio-Performance-Transaktionsexporten im Format CSV/JSON v1 über einen Vorschau-und-Anwenden-Workflow.
- Bestände werden aus der Transaktionshistorie abgeleitet, mit Einstandswert und nicht realisiertem Gewinn/Verlust.
- Klassifizierungsbäume ordnen Wertpapiere; Zielgewichte je Kategorie treiben eine SOLL/IST-Allokationsaufschlüsselung mit Drift.
- Mehrwährungs-Portfolios werden über gespeicherte Wechselkurse bewertet.
- Wertpapierpreise werden als Kurshistorie gespeichert und in einem Wertpapier-Detailchart angezeigt.
- Unterstützte Funktionen sind über die UI, die JSON-API und den MCP-Begleitdienst verfügbar.
- Keine Broker-Synchronisierung, keine Bank-Synchronisierung, keine Handels-Engine, kein Zahlungs-Flow, kein Order-Flow, kein Rebalancing, keine Dokumentenerfassung und kein KI-gestütztes Verhalten.
Produktmodule
Die Codebasis ist in lokale Domänenmodule plus die Web-Schicht aufgeteilt:
Portfolixir.Catalog- Wertpapiere und Kurs-Entitäten
- Wertpapier-Metadaten und Kurssätze
Portfolixir.Portfolios- Portfolios
- Geldkonten
- Depots
- Zielgewichte und SOLL/IST-Allokation
Portfolixir.Ledger- Manuelle Kauf-/Verkauftransaktionen
- Bestandsberechnung aus unveränderlicher Historie
Portfolixir.Classifications- Eigene und integrierte Klassifizierungsbäume und Zuordnungen
Portfolixir.Fx- Wechselkurse und Mehrwährungsumrechnung
PortfolixirWeb- Routen, Seiten, LiveViews und JSON-API
mcp-server/- TypeScript-MCP-Begleitdienst, der die JSON-API kapselt
Integrationsdetails für /api/v1 und mcp-server/ sind separat unter
API und MCP dokumentiert.
Kern-Workflow
- Lege ein oder mehrere Wertpapiere mit grundlegenden Identifikationsdaten an.
- Lege ein Geldkonto und ein Depot an und verknüpfe sie (nirgendwo eine Portfolio-Entscheidung — siehe unten).
- Erfasse manuelle Kauf- und Verkauftransaktionen mit Decimal-basierten Mengen- und Preiswerten.
- Importiere optional einen Portfolio-Performance-Transaktionsexport über Imports, prüfe die Vorschau, ordne fehlende Konten zu und wende dann atomar an.
- Öffne die Bestandsansicht, um die aktuelle Position je Wertpapier zu prüfen.
- Erfasse Wertpapierkurse im Zeitverlauf und behalte die Historie für reproduzierbare Charts.
- Prüfe aktuelle Bestände und das Verhalten der Kurscharts direkt in der App.
Wertpapiere
Jedes Wertpapier ist ein erstklassiges Objekt mit stabilen Identitätsfeldern und Markt-Metadaten. Sie bilden die Basis für alle Transaktions- und Bestandsberechnungen.
Inferenz der Anlageklasse
Jedes Wertpapier hat eine Anlageklasse (asset class). Eine am Wertpapier
gespeicherte Klasse gewinnt immer: Security.effective_asset_class/1 gibt sie
unverändert zurück. Nur bei einem Wertpapier ohne gespeicherte Klasse wird
eine beim Lesen abgeleitet, aus seinem Namen und, für Krypto, seinem
Ticker. Die ISIN gehört nicht zu den Signalen: Ihr Aufbau allein sagt
nicht, um welche Art Instrument es sich handelt (#408), deshalb übergeht die
Inferenz sie bis auf die letzte Regel unten. Die Regeln laufen in dieser
Reihenfolge, und die erste, die greift, entscheidet:
- government_bond — der Name sagt, dass es eine Staatsanleihe ist: Bundesrepublik, Bundesanleihe, Bundesobligation, Bundesschatz, Staatsanleihe, Treasury Note, Treasury Bond, Treasury Bill, Government Bond, Sovereign Bond, „Republic of“, „Kingdom of“ oder „Anleihe“ am Anfang, gefolgt von einem Land (Australien, Belgien, Deutschland, Frankreich, Italien, Kanada, Niederlande, Norwegen, Österreich, Singapur, Spanien, USA, Vereinigte Staaten, United States).
- etf — der Name trägt ETF, UCITS ETF, U.ETF, UETF, ETC, ETN oder ETP als Wort.
- crypto — der ganze Name ist ein bekannter Coin (Bitcoin, Ethereum,
Ether, Solana, Cardano, Polkadot, Litecoin, Chainlink, Ripple, XRP,
Dogecoin, Avalanche, Tron), oder der Ticker ist ein bekanntes Symbol (BTC,
ETH, SOL, ADA, DOT, LTC, LINK, XRP, DOGE, AVAX, TRX), allein oder mit einer
Währung nach Bindestrich oder Punkt (
BTC-EUR). - commodity — ein physisch hinterlegtes Edelmetallprodukt (EUWAX Gold, Xetra-Gold, Physical Gold, Physical Silver, Physical Platinum, Physical Palladium, Gold Bullion) oder ein Name, der nur ein Metall ist: Gold, Silber, Silver, Platin oder Platinum. Ein Unternehmen mit einem Metall im Namen („Muster Gold Corp“) greift hier nicht und geht weiter zur Aktien-Regel.
- Ein strukturiertes oder Hebelprodukt, jeweils als eigene Klasse. Diese
Regeln kommen vor den Aktien, weil solche Namen oft auch die Rechtsform
eines Emittenten tragen:
- knock_out — Turbo, allein oder mit einem Buchstaben dahinter (TurboC, TurboP), Knock-Out, KO, Mini Future, O.End, Open End Turbo, WAVE, Unlimited Turbo;
- discount_certificate — DiscC, DiscP, Discount-Zertifikat, Discount Cap;
- warrant — Optionsschein, Warrant;
- factor_certificate — Faktor;
- reverse_convertible — Aktienanleihe, Reverse Convertible;
- bonus_certificate — Bonus-Zertifikat, Bonus Cap;
- express_certificate — Express-Zertifikat;
- und zuletzt ein bloßes Call oder Put, das Broker als Kürzel für einen Optionsschein verwenden, also ebenfalls ein warrant („Turbo Call“ bleibt ein Knock-out).
Eine allgemeine Derivate-Klasse gibt es nicht: Ein Zertifikat, auf das keines dieser Wörter passt (etwa ein Indexzertifikat), bleibt ohne Klasse.
- bond (#1127) — der Name sagt, dass es eine Anleihe ist: Anleihe, Schuldverschreibung oder Pfandbrief, auch als letzter Teil eines zusammengesetzten Worts (Unternehmensanleihe, Inhaberschuldverschreibung, Hypothekenpfandbrief, nicht aber Anleihenfonds), oder Notes, Obligation oder Obligationen als Wort — und kein Wort eines strukturierten Produkts (die Ausschlüsse der Regel 7; ein Zertifikat ist rechtlich ebenfalls eine Schuldverschreibung). Sie kommt vor den Aktien, weil der Name einer Anleihe oft die Rechtsform ihres Emittenten trägt („Muster SE Anleihe 2030“). „Bond“ gehört nicht zu den Wörtern, weil Firmennamen es tragen, ebenso wenig ein bloßer Kupon mit Jahr („Muster AG 4,10% 2028/2033“), den auch Aktien und Fonds tragen; Aktienanleihe, Bundesanleihe und einen Namen mit ETF-Kennung entscheiden die Regeln davor.
- equity — der Name trägt eine Aktien- oder Rechtsform-Markierung — Registered Shares, Reg. Shares, Registered Part. Shares, Inhaber-Aktien, Namens-Aktien, Vorzugsaktien, Actions, Aandelen, Common Stock, Inc., Corp., Corporation, Company, Co., Ltd., AG, SE, PLC, S.p.A., S.A. oder SA, S.A.S. oder SAS, SA/NV, Aktiengesellschaft, A/S, ASA, KGaA, Azioni, Acciones, Aktier — oder eine Hinterlegungsschein-Markierung (ADR, Sp.ADR, GDR, Depos. Receipts) oder INH.ON, und kein Wort eines strukturierten Produkts (Turbo, Disc, Discount, Call, Put, Optionsschein, Zertifikat, O.End, Em.-u.Handelsg.mbH).
- fund — der Name trägt einen Fondsanbieter (iShares, Vanguard, Lyxor, Amundi, AIS-AM, Xtrackers, SPDR, Invesco, WisdomTree, VanEck, Fidelity, Deka), und keine Regel oben griff; ein Name, der zusätzlich eine Rechtsform trägt, ist nach Regel 7, die vorher läuft, eine Aktie.
- equity, aus dem Logo (#408) — ein Wertpapier, das keine Regel aufgelöst hat und das eine ISIN und ein gespeichertes Firmen-Logo hat, gilt als Aktie: Die Logo-Suche hat schon entschieden, dass es ein Unternehmen ist, und die ISIN kennzeichnet ein börsennotiertes Instrument.
- Sonst hat das Wertpapier keine Klasse: Es ist nicht klassifiziert.
Die Regeln unterscheiden nicht zwischen Groß- und Kleinschreibung, und die meisten passen nur auf ganze Wörter. Seit Issue #1078 gilt das auch für die Rechtsformen „S.A.“, „SA“, „S.A.S.“, „SAS“, „Actions“ und „Aandelen“, ein Name, der bloß die Buchstaben „sa“, „actions“ oder „aandelen“ enthält („Global Transactions Group“, „Muster Aandelenfonds“), gilt also nicht als Aktie; und für die kurzen Ausschlusswörter (Turbo, Disc, Discount, Call oder Calls, Put oder Puts, O.End, Em.-u.Handelsg.mbH), ein Unternehmen, dessen Name bloß „put“ oder „disc“ enthält („Muster Computer Corp“), gilt also als Aktie. Einige Markierungen passen weiterhin so, wie sie geschrieben sind, auch innerhalb eines längeren Tokens: die Aktien-Markierungen Registered Shares, Reg. Shares, Registered Part. Shares, Inhaber-Aktien, Namens-Aktien, Vorzugsaktien, Common Stock, S.p.A., SA/NV und Depos. Receipts sowie die Ausschlüsse Optionsschein und Zertifikat, ein „Indexzertifikat“ oder „Optionsscheine“ bleiben also ausgeschlossen. Eine Kurzform, die ein Produktwort mit einem anderen verschmilzt, etwa „TurboCall“ oder „CallOS“, wird nicht erkannt: Ein solcher Name wird nach seinen übrigen Wörtern gelesen, und eine Rechtsform darin macht ihn zur Aktie. Die Klasse von Hand zu setzen, klärt jeden Fall, den die Regeln verfehlen.
Wann eine Klasse gespeichert wird. Die Klasse wird nicht nur beim Lesen abgeleitet. Jedes Anlegen oder Ändern der Stammdaten eines Wertpapiers — in der App, über die API oder MCP oder durch einen Import — speichert die Klasse, die die Regeln 1–8 ergeben, solange noch keine gespeichert ist (die Logo-Regel läuft nur beim Lesen), und das Speichern des Formulars eines Wertpapiers speichert die Klasse, die das Formular zeigt, ob abgeleitet oder nicht. Eine gespeicherte Klasse, gleich wer sie gespeichert hat, wird unverändert zurückgegeben; eine spätere Verbesserung einer Regel erreicht dieses Wertpapier also nicht. Eine verbesserte Regel erreicht nur die Wertpapiere ohne gespeicherte Klasse: die, auf die beim letzten Schreiben keine Namensregel passte (die Logo-Regel kann sie beim Lesen noch auflösen), und die, die mit Zuordnung entfernen im eingebauten Anlageklassen-Baum (Klassifizierungen) auf automatisch zurückgesetzt wurden — das leert die gespeicherte Klasse, ohne eine abzuleiten.
Nicht klassifizierte Wertpapiere finden und korrigieren
Eine Suche oder Filterkombination ohne Treffer zeigt einen Keine-Treffer-Zustand, der die Suche bzw. die aktiven Filter benennt — die Bedienelemente bleiben sichtbar; der Onboarding-Hinweis „noch keine Wertpapiere” erscheint nur bei leerer Datenbank.
Die Wertpapierliste akzeptiert einen Filter „ist nicht klassifiziert“ auf
der Anlageklasse-Spalte (operator: :is_nil), dieselbe Bedingung wie der Chip
Ohne Anlageklasse: Er trifft jedes Wertpapier ohne gespeicherte
Klasse, ob eine Regel eine ableitet oder nicht, denn eine abgeleitete Klasse
ist eine Vermutung und keine erklärte Tatsache (#700). Eine solche Zeile zeigt
ihre abgeleitete Klasse, als abgeleitet markiert (≈), oder nichts, wenn keine
Regel griff, und in beiden Fällen ein eingebettetes
Schnellzuweisungs-Dropdown, sodass sich die Klasse direkt aus der Liste
setzen lässt, ohne die Wertpapier-Detailseite zu öffnen. Eine Zeile mit
gespeicherter Klasse zeigt sie als einfaches Badge.
Eine gespeicherte Klasse ist eine dauerhafte Überschreibung: einmal gesetzt, wird
sie von effective_asset_class zurückgegeben, unabhängig davon, was die
Heuristiken erzeugen würden, sodass die Schnellzuweisung künftige
Heuristik-Änderungen überlebt.
Buchstaben-getrennte Namen aus Portfolio Performance
Portfolio Performance exportiert Namen manchmal mit einem Leerzeichen zwischen
jedem Zeichen — z. B. I b e r d r o l a S . A . A c c i o n e s. Der
JSON-Parser erkennt dieses Muster (die Mehrheit der durch Leerzeichen getrennten
Tokens sind einzelne Zeichen, mindestens vier Tokens) und führt die Tokens
zusammen, bevor die Heuristiken laufen, sodass Rechtsform-Suffixe auch aus
solchen Exporten zuverlässig erkannt werden.
Verlinkbare Filter
Der Filterzustand der Wertpapierliste liegt in der URL; jede gefilterte Ansicht lässt sich als Lesezeichen speichern oder verlinken:
?q=…— der Suchbegriff.?holding=held|not_held— der Bestandsstatus (die Chips Im Bestand / Ohne Bestand).?filter[]=spalte:operator[:wert]— ein oder mehrere Spaltenfilter, z. B.?filter[]=asset_class:is_nil(unklassifizierte Wertpapiere) oder?filter[]=currency_code:eq:USD. Die Operatoren entsprechen dem Filter-Popover; unbekannte Spalten oder Operatoren werden verworfen.?cur[]=EUR&cur[]=USD— die Währungs-Chips; mehrere kombinieren als Entweder-oder.?class[]=etf— die Anlageklassen-Chips, geschlüsselt auf die effektive Klasse (gespeichert oder abgeleitet), sie wählen also, was die Liste anzeigt.?since=<ISO8601>— der Geändert-seit-Schnitt (siehe unten); die Chips Heute / 7 Tage / 30 Tage schreiben hier ein konkretes ISO-Datum, sodass der Link bedeutet, was er beim Teilen bedeutete.?dq=stale_quote|missing_quote|missing_logo|missing_fx|two_scales|implausible_quote— die Datenqualitäts-Schnellfilter: kein Kurs in den letzten 7 Tagen (inklusive „gar kein Kurs”); gar kein Kurs; kein hinterlegtes Logo; Kein Wechselkurs (Issue #717): bepreist, aber ohne gespeicherten Kurs von seiner Währung zur Basiswährung, das Speichern des Kurses leert also die Menge; Auf zwei Skalen bepreist (Issue #1068): die Anleihen, die der Zwei-Skalen-Wächter nennt, in beiden Richtungen (siehe Anleihen unten), die Liste, die der Zwei-Skalen-Zähler der Übersicht öffnet; und Kurs passt nicht zu Buchungen (Issue #1101): die gehaltenen Wertpapiere, deren gespeicherte Kurse ihren eigenen Buchungen widersprechen (siehe Ein Kurs, der nicht zu den Buchungen passt unter Kurse und Charts), die Liste, die der Zähler der Übersicht für sie öffnet. Die ersten drei lassen eine Benchmark und ein stillgelegtes Wertpapier in Ruhe: Ein ausverkauftes oder delistetes Wertpapier, das Sie stilllegen, verlässt alle drei, und die Zahlen der Übersicht sinken mit ihm; reaktiviert, steht es wieder in denen, auf die es passt. Dieselben Bedingungen sind im Filter-Bedienelement unter Datenqualität direkt wählbar — der Link von der Übersicht ist eine Abkürzung dorthin, nicht der einzige Weg. Der Agent fragt genau dieselben Mengen überGET /api/v1/securities?data_quality=…und das Werkzeugportfolixir.securities.listab; alle beruhen auf einer Definition, sodass eine Zahl N immer eine Liste von N adressiert.
Die häufigen Filter sind One-Tap-Chips (Issue #717): eine feste, benannte Zeile über der Tabelle — Im Bestand · Ohne Bestand · Ohne Anlageklasse · Kurs veraltet · Kein Kurs · Kein Wechselkurs, dazu je ein Chip pro genutzter Währung und Anlageklasse. Chips sind Schalter; verschiedene Familien kombinieren als UND, mehrere Chips der Währungs- oder Klassenfamilie als Entweder-oder. Zwei davon tragen eine bewusste Unterscheidung: Ohne Anlageklasse ist auf die gespeicherte Klasse geschlüsselt (eine nur abgeleitete Klasse zählt weiter als unklassifiziert, denn eine Ableitung ist eine Vermutung, kein festgehaltener Fakt), während die Anlageklassen-Chips auf die effektive Klasse geschlüsselt sind — sie wählen genau, was die Liste anzeigt. Der generische Spalte/Operator/Wert-Baukasten ist hinter Weitere Filter am Ende der Zeile zurückgestuft; er kann weiterhin alles ausdrücken, was er vorher konnte, und trägt eine Anzahl, sobald er Bedingungen hält, die die Chips nicht ausdrücken können — ein zurückgestuftes Bedienelement verbirgt nie aktiven Zustand.
Suchen, einen Chip schalten oder Filter anwenden aktualisiert die URL; die Auswahl eines Wertpapiers behält die aktiven Filter bei. Die Datenqualitätszeile der Übersicht verlinkt mit vorangewendetem Filter hierher.
Geändert seit (Issue #731) beantwortet „was hat sich zuletzt bewegt?”
aus demselben Schnitt, mit dem der Agent pollt: die Chips verengen die Liste
auf Wertpapiere, die strikt nach dem Schnitt angelegt oder geändert wurden —
nach dem Änderungszeitpunkt des Datensatzes. Die Seite nennt die Eigenschaft,
die so ein Delta ehrlich macht: Löschungen werden nicht angezeigt; Filter
entfernen für die vollständige Liste. Der URL-Parameter ist das ?since= der
API mit denselben akzeptierten Formen, ein Agenten-Link öffnet also genau die
gelesene Scheibe; ein unlesbarer Wert degradiert zur ungefilterten Liste,
statt sie stillschweigend zu verengen.
Auf dem Telefon (Issue #799, UX-DR27; Issue #800): unter 560 px weicht die Tabelle zweizeiligen Zeilen — der Name über Ticker, ISIN und Anlageklasse (das Zuordnen-Steuerelement, wo die Klasse fehlt), rechts der letzte Kurs über der Tagesänderung, die Veraltet-Markierung unter dem Kurs, „kein Kurs”, wo nichts die Zeile bepreist — sodass nichts seitwärts scrollt; die Zeile öffnet weiterhin das Detail, ihr Kebab weiterhin das Zeilenmenü, und die Spaltenauswahl behält oberhalb von 560 px ihre Bedeutung. Die Chip-Familien wandern hinter ein Filter (n)-Steuerelement, das die Zahl der aktiven Chips trägt und ein Bottom Sheet öffnet — einen Dialog mit den Familien untereinander unter ihren Namen, dem Weitere-Filter-Builder, Zurücksetzen und Fertig; ein Chip im Sheet wirkt sofort, genau wie in der Zeile.
Eine Zeile, deren Wertpapier anderswo verschwand. Hat der Agent, die API oder ein anderer Tab ein Wertpapier gelöscht oder zusammengeführt, nachdem die Liste geladen wurde, lädt eine Zeilenaktion auf dieser Zeile die Liste neu, statt nichts zu tun, schließt ein darauf geöffnetes Detail und sagt, warum die Zeile ging: „„…“ wurde inzwischen gelöscht; die Liste ist neu geladen.“ oder „„…“ wurde inzwischen in … zusammengeführt; die Liste ist neu geladen.“, das Wertpapier, das die Historie jetzt trägt, verlinkt. Der Hinweis rückt an den oberen Fensterrand und erhält den Tastaturfokus, denn das Menü, das ihn hatte, ging mit der Zeile. Der Dialog für ein neues Wertpapier antwortet genauso (Issue #1072): Wurde das Wertpapier, das seine Suche gefunden hat („Dieses Wertpapier existiert bereits“), gelöscht oder zusammengeführt, bevor Online-Felder übernehmen oder Vorhandenes aktualisieren gedrückt wurde, schließt sich der Dialog, die Liste lädt neu, und derselbe Hinweis nennt den Treffer.
Klassifikations-Spalten
Neben den Attribut- und Kursspalten bietet die Spaltenauswahl der Wertpapierliste einen Eintrag pro Klassifikationsbaum und Ebene — für eigene Bäume ebenso wie für die eingebauten Anlageklassen- und Währungsbäume, analog zu den Klassifikations-Spalten von Portfolio Performance. Eine aktivierte Spalte zeigt je Wertpapier die zugeordnete Kategorie auf dieser Ebene: Ein tiefer einsortiertes Wertpapier zeigt seinen Vorfahren auf der gewählten Ebene, ein oberhalb der Ebene (oder gar nicht) einsortiertes bleibt leer. Klassifikations-Spalten sortieren wie jede andere Spalte — nicht einsortierte Wertpapiere stets zuletzt — und werden zusammen mit der übrigen Spaltenauswahl im Browser gespeichert. Es sind reine Anzeige-Spalten; Filter bleiben auf den Attributspalten.
ISIN-Wechsel (Früher-ISIN-Aliasse)
Wenn eine Kapitalmaßnahme einem Wertpapier eine neue ISIN gibt (eine
Fusions-Umbenennung, ein Sitzwechsel), den Wechsel aufzeichnen, statt die ISIN
direkt zu editieren: POST /api/v1/securities/:security_id/isin-change (oder
das MCP-Tool portfolixir.securities.isin_change) verschiebt die aktuelle
ISIN in einen journalisierten Früher-ISIN-Alias und schreibt die neue ISIN
auf dasselbe Wertpapier. Importe treffen danach in beide Richtungen weiter:
Ein alter Export mit der früheren ISIN löst über den Alias auf, ein neuer
Export mit der neuen ISIN über die aktuelle ISIN — kein dupliziertes
Wertpapier, keine duplizierten Buchungen (der Import markiert solche Zeilen
als „über frühere ISIN zugeordnet”). Aliasse sind korrigierbar: sie werden im
Wertpapier-Detail (GET /api/v1/securities/:id) gelistet und können
(journalisiert) gelöscht werden, wenn sie versehentlich aufgezeichnet wurden.
Eine bloße Umbenennung braucht keinen ISIN-Wechsel — sie ist nur eine
Namensänderung. Die neue ISIN muss eine gültige ISIN sein, Prüfziffer
eingeschlossen, ebenso eine ISIN, eine WKN (sechs Buchstaben oder Ziffern)
oder ein Ticker (druckbares ASCII), die an einem bestehenden Wertpapier
geändert werden: Ein Doppelgänger ersetzt nie das Kennzeichen, das die
Exporte tragen. Der Name eines Wertpapiers wird ohne unsichtbare
Formatzeichen gespeichert.
Ein doppeltes Wertpapier zusammenführen (ADR-0050 §9)
Wenn ein Instrument zweimal existiert — ein Export mit neuerer ISIN wurde
importiert, bevor der ISIN-Wechsel erfasst war, und legte eine zweite Kopie
mit einer zweiten Kopie der Historie an, oder ein von Hand angelegtes
Wertpapier wurde vom nächsten Import noch einmal angelegt —, führt man das
Duplikat in das Wertpapier zusammen, das bleibt: Zusammenführen in… im
Zeilenmenü des Duplikats auf der Wertpapierseite, oder derselbe Knopf im
Dialog Kann nicht gelöscht werden, wenn Buchungen, Kurse oder Termine das
Löschen verhindern. Dieser Dialog zählt, was noch auf das Wertpapier verweist
(„„…“ hat noch 12 Buchungen, 840 Kurse und 3 Research-Einträge.“), und sagt,
warum der Ausweg der ist, der er ist: Research-Einträge werden nie entfernt
und ziehen bei keiner Zusammenführung mit, ein Wertpapier mit
Research-Einträgen wird darum stattdessen stillgelegt. Ihr Agent hat dieselbe
Zusammenführung
(GET /api/v1/securities/:id/merge_preview und
POST /api/v1/securities/:id/merge oder die MCP-Tools
portfolixir.securities.merge_preview und portfolixir.securities.merge),
und beide lesen dieselbe Vorschau.
Die Vorschau zeigt alles, was die Zusammenführung tut, bevor etwas geschrieben wird: die Position beider Wertpapiere in jedem Depot vorher und nachher, die Buchungen, die bei beiden stehen (Sie entscheiden, ob es Duplikate sind — nichts ist vorausgewählt), die Splits, die zusammenfallen, die Kurse, die Klassifizierungs- und Planzeilen, die Termine und die Kennzeichen. Was die Zusammenführung tut:
- Buchungen gehen in jedem Depot auf das Wertpapier über, das bleibt; eine Buchung, die Sie als Duplikat bestätigen, wird gelöscht, und ein Split, den beide am selben Tag tragen, bleibt einmal erhalten. Die Stückzahl jedes Tages in jedem Depot wird gegen beide Historien geprüft.
- Kurse füllen die Lücken des Wertpapiers, das bleibt; an einem Tag, an dem beide einen Kurs haben, gewinnt der des bleibenden. Ein von Hand erfasster Schlusskurs, der so entfiele, wird vorher aufgeführt. Die verworfenen Schlusskurse bleiben im Protokoll der Zusammenführung.
- Klassifizierung und Pläne: Eine Zuordnung wandert, wo das bleibende Wertpapier in dieser Klassifizierung keine hat, sonst bleibt seine; ein Positionsziel wandert, außer der Plan hat schon eines für das bleibende Wertpapier oder es läge nicht mehr unter dessen Kategorie — dann wird es entfernt, und die Vorschau sagt, warum.
- Termine wandern; zwei gleicher Art am selben Tag werden als mögliches Duplikat aufgeführt, das Sie selbst bereinigen.
- Kennzeichen: Tragen beide eine ISIN, wählen Sie ohne Vorgabe, auf welche das bleibende Wertpapier hört — seine eigene behalten (die ISIN des Duplikats wird eine frühere ISIN) oder die des Duplikats übernehmen (seine eigene wird die frühere ISIN; das repariert das Duplikat, das ein Export mit der neueren ISIN angelegt hat, bevor der Wechsel erfasst war), wahlweise mit dem Tag des ISIN-Wechsels. Eine WKN, einen Ticker oder eine Kursquelle, die dem bleibenden Wertpapier fehlen, übernimmt es — außer sie verletzen die Regel, die ein geändertes Kennzeichen erfüllen muss (eine WKN aus sechs Buchstaben oder Ziffern, ein Ticker aus einfachen ASCII-Zeichen); die Stammdaten zeigen sie dann als nicht übernommen. Name, Anlageklasse und Logo bleiben seine.
Im Dialog sucht der erste Schritt das Wertpapier, das bleibt, nach Name, ISIN, WKN oder Ticker. Ein Treffer, der die Historie des Duplikats nicht aufnehmen kann, bleibt in der Liste, gesperrt, mit seinem Grund: andere Währung, nur eines der beiden ein Benchmark, stillgelegt oder eine andere Kursbasis. Der zweite Schritt zeigt genau dieses Paar als Vorschau, zuerst als zwei Karten — die Namen sind oft gleich, deshalb zeigt jede ihre ISIN, ihre Buchungen und den Tag, an dem sie angelegt wurde. Dann folgt die Wahl der ISIN als zwei Optionen, jede mit dem Satz, welche ISIN die frühere wird; keine ist vorausgewählt, und übernehmen fragt nach dem Tag des Wechsels. Danach der Bestand in Stück vorher und nachher (und nach dem Entfernen der gleichen Buchungen), die Zahlen, die gleichen Buchungen mit ihrer eigenen Wahl, die von Hand erfassten Schlusskurse, die die Kurse des bleibenden Wertpapiers ersetzen, die Einstellungen, die wandern oder entfallen, die Termine, die bei beiden stehen, und die Stammdaten, die sich unterscheiden. In … zusammenführen bleibt gesperrt, die fehlende Wahl daneben genannt, bis jede Wahl getroffen ist, die das Paar braucht. Nach der Zusammenführung öffnet sich das Wertpapier, das bleibt, mit dem Ergebnis über der Tabelle, und seine Übersichtszeile nennt die frühere ISIN und die Zusammenführung (zusammengeführt am 2026-09-26 aus „…“ (damals …)).
Die Zusammenführung wird mit Grund abgelehnt, wo sie nicht alles exakt erhalten kann: verschiedene Währungen, eines ein Benchmark und das andere nicht, Recherche-Notizen oder eine eigene Regel am Duplikat (in die andere Richtung zusammenführen, wenn das gelingt, oder beide behalten), Positionen in verschiedenen Ansichten, Splits, die sich widersprechen (zwei Verhältnisse an einem Tag: den Split mit dem falschen Verhältnis löschen), ein Split des Duplikats, der noch einen Import-Hash aus der Zeit vor der Import-Hash-Prüfung trägt (der Dialog nennt ihn: seine Art zurücksetzen oder ihn löschen), eine ISIN des Duplikats mit falscher Prüfziffer (zuerst in seinen Stammdaten korrigieren oder leeren), oder ein Kennzeichen eines der beiden Wertpapiere — gespeichert, wie sein Portfolio-Performance-Import es aufgezeichnet hat, eine frühere ISIN oder das eines zuvor in eines der beiden zusammengeführten Wertpapiers —, das das bleibende Wertpapier nicht mehr fände. Der Dialog nennt jeden Grund auf einmal, jede Regel beim Namen, und bietet Andersherum zusammenführen an, wo diese Richtung gelingt; wird auch sie abgelehnt, stehen beide Gründe da, und nichts anderes wird angeboten. Diese letzte Prüfung macht den nächsten Import sicher: Nach einer Zusammenführung legt ein erneut importierter, schon angewendeter Export nichts an, welche ISIN er auch trägt, und neue Zeilen unter den Kennzeichen des Duplikats werden einmal gebucht, auf das Wertpapier, das bleibt. Ein Lesen der ID des Duplikats antwortet danach mit dem Wertpapier, auf dem es jetzt liegt, und der Bildschirm ebenso: Ein Link oder Lesezeichen auf die Seite des Duplikats öffnet das Wertpapier, in das es zusammengeführt wurde, mit einem Hinweis darauf und dem Tag der Zusammenführung, und ein Benchmark, der das Duplikat nannte, stellt den Vergleich der Vermögens-Seite auf dieses Wertpapier um, mit demselben Hinweis unter der Performance-Überschrift. Ein Rückgängigmachen gibt es nicht; das Protokoll der Zusammenführung und das Audit-Journal zeigen, was sie getan hat.
Identitätsfelder, die einfrieren (ADR-0050 §11)
Die Währung eines Wertpapiers friert ein, sobald es eine Transaktion oder
einen Kurs hat: Buchungen und Kurshistorie sind in dieser Währung
angegeben, eine Änderung würde sie stillschweigend umdenominieren. Jeder Weg
lehnt die Änderung mit einem Feldfehler ab, der zählt, was sie einfriert —
is frozen once referenced (120 quotes, 3 transactions) — und schreibt
nichts: das Bearbeiten-Formular (unter der Währungsauswahl), im Suchdialog
Online-Felder übernehmen und Vorhandenes aktualisieren, wenn das
gewählte Listing in einer anderen Währung handelt (ein Xetra-Listing in EUR
eines in USD gebuchten Wertpapiers ist eine andere Kursreihe, keine
Korrektur), sowie PATCH /api/v1/securities/:id mit dem MCP-Tool darüber
(422). Die übrigen Felder bleiben änderbar, und ein Wertpapier ohne
Buchungen und Kurse wechselt die Währung weiterhin. Dieselbe Regel gilt für
Konten, siehe Konten und Depots unten.
Abgeleitete Kennzahlen im Chart-Tab (ADR-0047)
Der Chart-Tab des Detailbereichs trägt die abgeleiteten Kennzahlen des Wertpapiers unter der Kurshistorie, die sie beschreiben: SMA-50 und SMA-200 mit dem Abstand des letzten Schlusskurses zu beiden — als zweite und dritte Serie im Chart gezeichnet, damit eine Kreuzung sichtbar ist — sowie Volatilität, maximaler Drawdown, Momentum und der Abstand zum 52-Wochen-Hoch und -Tief.
Ein Zeitraum-Steuerelement: die Kennzahlen folgen den Bereichs-Buttons des Charts. Die gespeicherten Fenster sind 30, 90 und 365 Tage; ein Bereich rastet auf das nächstkleinere, und jede Zelle nennt das verwendete Fenster samt Beobachtungszahl. Unterhalb ihres Minimums liest sich eine Kennzahl als nicht berechenbar und zeigt trotzdem, wie viele Beobachtungen vorlagen.
Die Zahlen stehen über den eigenen splitbereinigten Schlusskursen in der eigenen Währung, nie umgerechnet. Ein Tag ohne gespeicherten Schlusskurs erzeugt keine Renditebeobachtung. Der Block berichtet, er bewertet nicht — es gibt kein Signal, kein Rating und keine Empfehlung darin.
Anleihen: Stammdaten und Kennzahlen (ADR-0052)
Ein Wertpapier der Anlageklasse Anleihe oder Staatsanleihe — gesetzt oder aus dem Namen abgeleitet — trägt seine Stammdaten im Wertpapierdialog hinter Bearbeiten: Der Abschnitt Anleihedaten erscheint, solange die Anlageklasse eine der beiden ist, beim Anlegen wie beim Bearbeiten. Seine Felder sind der Kupon p. a. in Prozent (2,5, nicht 0,025), die Zinszahlung (jährlich oder halbjährlich), die Fälligkeit und ein optionaler Emissionstag (ISO-Datum, die Fälligkeit nach dem Emissionstag) sowie die Stückelung (Nennwert) mit ihrer Währung, die auf der Währung des Wertpapiers beginnt und nur mit einer Stückelung gespeichert wird: Ein Speichern ohne Stückelung speichert keine Währung, und das Nominal steht dann in der Währung des Wertpapiers. Pflicht ist nichts; beim Bearbeiten löscht ein geleertes Feld seinen Wert, und die Werte bleiben erhalten, wenn die Anlageklasse von einer Anleihe weg wechselt. Findet eine Suche ein Wertpapier, das der Katalog schon führt, schreiben Vorhandenes aktualisieren und Online-Felder übernehmen nur die ausgefüllten Anleihefelder: Ein leeres Feld lässt den gespeicherten Wert stehen. Ein Wert, den keine Anleihe trägt — ein Kupon über 100 %, eine Fälligkeit am Emissionstag, eine gruppierte Zahl —, wird an seinem eigenen Feld abgelehnt, und alle Ablehnungen eines Speicherns stehen zugleich da.
Die Mengenkonvention. Ein Portfolio-Performance-Export bucht die Stückzahl einer prozentnotierten Anleihe als ein Hundertstel des Nominals: 100 Stück sind 10.000 Nominal, und ein Kurs von 97,25 ist zugleich 97,25 % vom Nennwert und der Preis je Stück. Stück × Kurs ist also schon der Marktwert, und das Nominal im Bestand ist Stück × 100. Jede Stelle, die das Nominal ableitet, sagt das.
Die Übersicht der Anleihe zeigt unter den sechs Werten einen Block mehr, überschrieben mit Anleihe: die Fälligkeit mit dem Emissionstag, den Kupon mit seiner Zahlung und das Nominal im Bestand („100 Stück × 100 EUR“, die Stückelung daneben), darunter, was daraus folgt —
- Restlaufzeit: Kalendertage von heute bis zur Fälligkeit, in Jahren zu 365 Tagen und in ganzen Jahren und Monaten; fällig ab dem Fälligkeitstag;
- laufende Rendite = Kupon ÷ Kurs;
- Rendite bis Fälligkeit, linear angenähert: (Kupon + (100 − Kurs) ÷ Restlaufzeit in Jahren) ÷ Kurs, ohne Zinseszins.
Der Kurs ist der, mit dem die Bewertung rechnet: der letzte gespeicherte Kurs oder, solange es keinen gibt, der letzte eigene Handelspreis, und die Zahl sagt, welcher. Stückzinsen, Gebühren und Steuern sind nicht enthalten; die Zahlen werden berichtet, nicht bewertet. Eine Zahl, der ein Eingang fehlt, liest sich nicht erfasst oder nicht berechenbar mit dem Grund, nie als Zahl. Ganz ohne Stammdaten sagt ein Satz, was fehlt, und Anleihedaten erfassen… öffnet den Dialog.
Keine Rendite aus einem Preis je Stück. Solange kein Kurs gespeichert ist und der letzte eigene Handelspreis höchstens 5 beträgt, lesen sich beide Renditen nicht berechenbar mit dem Grund „Handelspreis … je Stück, keine Prozentnotiz“: Eine zu 0,984 je Stück gekaufte Anleihe wurde mit dem Nominal als Stückzahl gebucht, und 2,5 ÷ 0,984 läse sich als Rendite von 254 %. Die Grenze ist das Zwei-Skalen-Band unten gespiegelt, 100 ÷ 20. Ein gespeicherter Kurs ist in jeder Höhe ein Prozentkurs und wird immer verwendet.
Auf zwei Skalen bepreist. Hat ein Export das Nominal einer Anleihe als Stückzahl gebucht, ist ab dem ersten Kurs jeder Geldbetrag der Anleihe — Wert, Gewinn, Gewicht — hundertfach zu hoch, und die TTWROR kann es nicht zeigen. Eine Anleihe, deren letzter gespeicherter Kurs das 20- bis 500-Fache eines gebuchten Preises je Stück beträgt — eines Kaufs oder einer mit Preis erfassten Einlieferung — (Kurse um 100, Buchungen um 1), wird deshalb in einem Problem-Hinweis oben in ihrer Übersicht genannt, mit dem Kurs, der Buchung und einem Link auf ihren Tab Transaktionen, wo die Stückzahl gegen das Nominal der Abrechnung geprüft wird, und im Datenqualitäts-Panel unter Vermögen → Bestände, wo die Summe gelesen wird, die sie aufbläht. Umgerechnet wird nichts: Die Zahlen bleiben wie gebucht, bis die Buchungen korrigiert sind.
Auch der umgekehrte Fall wird genannt (Issue #1068): gespeicherte Kurse um 1 neben Buchungen um 100 — ein letzter Kurs von 1/500 bis 1/20 eines gebuchten Preises je Stück und selbst höchstens 5. Die Kurse sind dann kein Prozent vom Nennwert, und die Anleihe zählt hundertfach zu niedrig in jeder Summe. Vermögen nennt sie in einem eigenen Problem-Hinweis, jeder Name verlinkt auf den Tab Kurse des Wertpapiers, wo die gespeicherten Kurse geprüft werden; auch hier wird nichts umgerechnet. Die eigene Übersicht des Wertpapiers nennt den umgekehrten Fall noch nicht (#1112).
Welche Wertpapiere der Wächter liest. Ein Wertpapier gilt als Anleihe — seine Übersicht zeigt den Anleiheblock, und der Wächter liest es —, wenn seine Anlageklasse Anleihe oder Staatsanleihe ist — gesetzt oder aus dem Namen abgeleitet — oder wenn es keine Anlageklasse zeigt (keine gesetzte, keine abgeleitete) und Anleihe-Stammdaten trägt: eine Fälligkeit oder einen Kupon. Die Namensinferenz erkennt Namen von Staatsanleihen und, seit Issue #1127, die ausdrücklichen Anleihe-Wörter der Regel 6 (Anleihe, Schuldverschreibung, Pfandbrief, Notes, Obligation); eine Unternehmensanleihe ohne Klasse, deren Name keines davon trägt, kommt also unter den Wächter, sobald ihre Fälligkeit oder ihr Kupon erfasst ist (oder ihre Klasse gesetzt); der Dialog zeigt ihre Anleihedaten, solange die Klasse leer ist, sodass sie dort korrigiert werden können. Eine Anleihe, deren Name die Rechtsform ihres Emittenten, aber kein Anleihe-Wort trägt („Muster AG 4,10% 2028/2033“), wird beim Anlegen als Aktie gespeichert, ebenso eine mit Anleihe-Wort, die vor Issue #1127 angelegt wurde und ihre gespeicherte Klasse behält; die Stammdaten allein ändern daran nichts: Ihre Klasse muss auf Anleihe (oder Staatsanleihe) gesetzt werden. Ein Wertpapier ohne Klasse und ohne Stammdaten — etwa eine nicht klassifizierte Aktie, die sich verzwanzigfacht hat — wird nie genannt; ebenso wenig ein Name, den die Inferenz als strukturiertes Produkt liest, dessen Laufzeitende als Fälligkeit gespeichert sein kann; und ein Wertpapier, das eine andere Klasse zeigt, ist keine Anleihe, welche Stammdaten es auch noch trägt. Eine ohne Anlageklasse genannte Anleihe ist im Hinweis mit ohne Anlageklasse markiert. Die Datenqualitätszeile der Übersicht zählt jede auf zwei Skalen bepreiste Anleihe, in beiden Richtungen und über den ganzen Katalog, und verlinkt auf die Liste genau dieser.
Tab „Termine” (der Kalender des Wertpapiers, ADR-0048)
Der Tab Termine listet die datierten Kalenderfakten des Wertpapiers — Geschäftszahlen, Ex-Dividenden- und Zahltag, Ende einer Haltefrist, Indexüberprüfung, Hauptversammlung, Behördenentscheidung, Prognoseanpassung — in der Form der Research-Zeitleiste. Jede Zeile sagt, wie gut das Datum bekannt ist (angekündigt, geschätzt, innerhalb eines Zeitraums, Monat bekannt, Tag nicht), woher es stammt (mit dem Quellenqualitäts-Vokabular des Research-Logs), ob es stattgefunden hat und wann es zuletzt geprüft wurde.
Die letzten beiden sind verschiedene Aussagen, und die Beschriftungen halten sie bewusst auseinander. Angekündigt heißt: eine Quelle hat diesen Tag gesetzt. Hat stattgefunden heißt: das Ereignis ist tatsächlich eingetreten. Ein Termin kann Monate im Voraus angekündigt sein und trotzdem noch ausstehen, und ein nie angekündigter Termin kann genauso vergehen — deshalb zeigt der Tab „Termine“ eine Zeile mit Angekündigt ohne Kennzeichen Hat stattgefunden, und das ist kein Widerspruch.
Ein Termin bucht nichts: wird eine Dividende tatsächlich gezahlt, läuft die Buchung wie immer über das Ledger und der Termin wird als stattgefunden markiert.
Was im gesamten Katalog ansteht — gehaltene Wertpapiere und Kandidaten gleichermaßen — erscheint als Karte Fällig auf der Übersicht, neben Abweichung vom Ziel und der Datenqualität. Ein Wertpapier ohne Position wird mit ohne Bestand markiert statt herausgefiltert.
Tab „Research“ (das Research-Log des Wertpapiers)
Der Tab Research im Detailbereich ist die menschliche Sicht auf das Research-Log des Wertpapiers (ADR-0044): was Betreiber oder Agent über ein Wertpapier wissen, als datierte, belegte Einträge, die nie geändert und nie entfernt werden. Oben steht der abgeleitete Thesenstand — Status (Keine, Intakt, Zurückgezogen), der aktuelle Thesentext, die Überzeugungsstufe, die Invalidierungsbedingung, der Zeitstopp, wann und von wem zuletzt geprüft wurde und aus welchem Eintrag er abgeleitet ist —, darunter die Zeitleiste neueste zuerst. Jeder Eintrag zeigt seine Art (These, Beleg, Invalidierungsprüfung, Ereignisergebnis, Risiko, Widerruf, Entscheidung), seine Quellenqualität (Primärquelle, mehrere Sekundärquellen, Wahrnehmung, ungeprüft), sein Stichdatum und seinen Autor (Betreiber, Agent oder lokales Modell; ein maschinell erzeugter Vorschlag ist als solcher markiert).
Ein falscher Befund wird zurückgezogen, indem ein Widerruf angehängt wird, der ihn ersetzt: Der Widerruf liest sich als „Widerruft #n“ mit der Begründung, der ersetzte Eintrag bleibt in der Liste mit „Ersetzt durch #n“ markiert, und eine zurückgezogene These wird über der Zeitleiste mit dem Grund des Widerrufs hervorgehoben. Nichts auf der Oberfläche ändert oder löscht einen Eintrag — absichtlich, denn die Aufzeichnung des Irrtums ist der Zweck des Logs.
Das Formular Eintrag anhängen schreibt einen Eintrag als Betreiber: Art
wählen, Quellenqualität angeben (sie wird gesetzt, nie geraten), das
Stichdatum eintragen (den Stand der Aussage, nicht das heutige Datum, wenn
beide auseinanderfallen) und optional den Quellenlink, ein „Gültig bis“ für
eine datierte Sperre und den Eintrag, den dieser ersetzt. Die Art These
blendet die Thesenfelder ein (Überzeugung, Invalidierungsbedingung,
Zeitstopp). Dasselbe Log ist über API und MCP lesbar und beschreibbar
(/api/v1/securities/:id/notes und die portfolixir.notes.*-Tools),
einschließlich der drei Hygiene-Reads — gehaltene Positionen ohne Eintrag
seit N Tagen, Einträge, die noch bestätigt werden müssen, und datierte
Sperren, die in N Tagen ablaufen.
Unsichtbare Zeichen (E25). Kein Text wird mehr mit einem Zeichen
gespeichert, das als nichts dargestellt wird — ein Leerzeichen der Breite
null, ein Steuerzeichen der Schreibrichtung, ein Tag-Zeichen, eine Folge von
Variantenselektoren: Jedes Formular, die API, MCP und der Import lehnen es ab
und nennen es (U+200B). Ein Emoji aus mehreren, verbunden durch einen
Verbinder der Breite null (eine Person am Laptop, die Regenbogenflagge), wird
gespeichert, denn der Verbinder erscheint als das Emoji; die Flaggen von
England, Schottland und Wales, aus Tag-Zeichen gebaut, und der
Nicht-Verbinder der Breite null mancher Schriften werden abgelehnt. Ein zuvor gespeicherter Text trägt dort, wo er
steht, eine Notiz Achtung — „Der Text enthält 2 unsichtbare Zeichen.“ (ein
Name: „Der Name enthält …“) — mit der Abhilfe und, hinter Text mit sichtbar
gemachten Zeichen, dem Text in der Schreibweise, die der Agent bekommt
(Auftrags[U+200B]bestand). Im Research-Log ist die Abhilfe Eintrag
anhängen, der #n ersetzt, das den Eintrag im Formular vorwählt; der Name
eines Wertpapiers wird mit Stammdaten bearbeiten korrigiert; die Notizen
einer Buchung, Name und Notiz einer Regel sowie die Namen von Ansichten,
Buckets, Kategorien, Verrechnungskonten und Depots tragen die Notiz dort, wo
sie bearbeitet werden, und eine saubere Neueingabe entfernt sie. Weil der neu
eingegebene Name die alte Schreibweise als früheren Namen behält, markiert der
Umbenennen-Dialog eines Verrechnungskontos oder Depots auch dessen frühere
Namen — „Ein früherer Name enthält 1 unsichtbares Zeichen. Ein Import, der
ihn genau so schreibt, bucht weiter auf dieses Depot.“ —, sodass das
Entfernen dieses Eintrags eine Wahl ist, die man sieht.
Benchmark-Wertpapiere. Ein Wertpapier lässt sich aus seinem Zeilenmenü
als Benchmark markieren („Als Benchmark markieren“): eine Referenzreihe, mit
der das Portfolio verglichen wird — ein Index über einen ETF, Gold über einen
ETC —, gespeist aus der gewöhnlichen Kurssynchronisation, es gibt also keine
zweite Kursquelle. Eine Benchmark wird in keinem Buchungsformular angeboten,
und die Datenqualitäts-Hinweise des Katalogs (veralteter oder fehlender
Kurs, fehlendes Logo) lassen sie in Ruhe; sie kann trotzdem gehalten werden
und ist dann einfach beides. Die API listet Benchmarks mit
is_benchmark=true. Was der Vergleich zeigt, steht unter Performance.
Stillgelegte Wertpapiere. Ein Wertpapier, das Sie nicht mehr halten und
dessen Notierung endete — ausverkauft oder delistet —, bleibt im Katalog,
weil seine Buchungen bleiben. Stilllegen in seinem Zeilenmenü markiert
es so: Es verlässt die Datenqualitäts-Hinweise des Katalogs (veralteter oder
fehlender Kurs, fehlendes Logo) und ihre Zahlen in der Übersicht, und eine
stillgelegte Position verlässt die Datenqualitäts-Zeilen der Vermögensseite
zu veraltetem Kurs, Handelspreis und fehlendem Kurs, weil ihr versiegter
Kurs erwartet ist. Der Hinweis Kein Wechselkurs behält es, weil ein
fehlender Wechselkurs die Bewertung weiter verhindert. Die Performance-Zahl
wertet seinen veralteten Kurs nicht mehr als Marktbeobachtung, eine spätere
Buchung stellt also die Basis neu fest, statt die Lücke als Rendite zu
melden — das kann frühere TTWROR-Werte ändern (#610). Reaktivieren im
selben Menü hebt es auf. Ihr Agent legt ein Wertpapier mit
portfolixir.securities.update und is_retired still.
Konten und Depots
Die Buchhaltungs-Entitäten sind Geldkonten und Depots:
- Geldkonto: verfolgt den Kontext der verfügbaren Liquidität
- Depot/Konto: speichert Wertpapierpositionen, verknüpft mit diesem Geldkonto
Die Seite Konten & Depots (Bereich Verwaltung) zeigt beide in einer Tabelle, ein Eintrag je Zeile: jedes Depot bildet eine Zeile, sein verknüpftes Verrechnungskonto sitzt eingerückt direkt darunter — mit der Kontowährung und dem Liquiditätsrollen-Selektor je Konto (freies Cash, Kreditlinie, Reserve) — die Spaltenüberschrift beschriftet ihn einmal für die ganze Tabelle, statt in jeder Zeile daneben zu stehen (Issue #806); ein Geldkonto ohne verknüpftes Depot bekommt eine eigene Zeile. Ein von mehreren Depots geteiltes Konto trägt seine Bedienelemente nur unter seinem ersten Depot — spätere Zeilen zeigen geteilt — oben verwaltet.
Bucket-Chips (#559). Jede Zeile zeigt ihre Bucket-Zugehörigkeiten als Chips — den exklusiven Scope-Bucket als gefüllten Chip, freie Tags als Umriss-Chips, eingefärbt mit der Bucket-Farbe, wenn eine gesetzt ist. Seit Issue #806 nennt jede Gruppe ihren Geltungsbereich als Unterzeile unter den Chips — Gilt für Depot und Verrechnungskonto, Gilt für das Depot, Gilt für das Verrechnungskonto —, sodass eine Zelle gelesen werden kann, ohne sie anzufassen; eine leere Menge liest sich als Kein Bucket statt als leere Zelle. Der Spaltenkopf Buckets trägt ein ⓘ, das sagt, was ein Bucket ist — ein Tag für Depots und Verrechnungskonten, den eine Ansicht auswählt, um jede Kennzahl auf seine Konten einzugrenzen —; auf dem Telefon, wo der Kopf verborgen ist, folgt dasselbe ⓘ der Geltungszeile jeder Chip-Gruppe (Issue #1090). Getrennt taggen ist aus der Zelle in das Kebab-Menü der Zeile gewandert. Tragen Depot und Verrechnungskonto dieselben Buckets, zeigt das Paar eine zusammengeführte Chip-Gruppe mit der Marke „Beide” über beide Zeilen; der Link Getrennt taggen daneben teilt die Gruppe, sodass jede Seite eigene Tags bekommt (unterschiedliche Mengen erscheinen immer getrennt). Je Gruppe sind höchstens vier Chips sichtbar — weitere klappen in ein Bedienelement +2 anzeigen; ein Druck darauf klappt die Zelle an Ort und Stelle auf und zeigt alle Buckets, weniger klappt sie wieder zu. Auch der Picker führt die vollständige Menge. Lange Namen (etwa ein langer Bucket-Tag, beim Import vergeben) werden gekürzt; der volle Name erscheint beim Überfahren des Chips. Die Chips sind die Gruppierungs-UI: das + öffnet ein kleines Picker-Popover mit den übrigen Buckets plus einem Inline-Feld Neuer Tag, das einen Tag in einem Schritt anlegt und zuweist, und das × auf einem Chip entfernt die Zugehörigkeit. Auf einem Touchscreen sind × und + 44-Pixel-Ziele (#1085). Änderungen an einer zusammengeführten Gruppe gelten für Depot und Verrechnungskonto gemeinsam. Jede Änderung läuft durch den audit-journalisierten Bucket-Kontext; der Versuch, einen zweiten Scope-Bucket zuzuweisen, wird mit einer Inline-Meldung abgelehnt, denn die Scope-Dimension bleibt exklusiv (ADR-0024).
Ein Anlage-Dialog (#491). Der Knopf Depot & Konto anlegen öffnet einen Dialog, der ein Depot zusammen mit seinem verknüpften Verrechnungskonto in einem Fluss anlegt — oder ein Geldkonto allein, oder ein Depot verknüpft mit einem bestehenden Konto. Optional vergibt der Dialog anfängliche Buckets: bestehende Buckets ankreuzen und/oder einen neuen Tag eintippen, und jeder vom Dialog angelegte Datensatz startet mit dieser Zugehörigkeit.
Nirgendwo ist eine Portfolio-Entscheidung nötig (ADR-0024): Gruppierung passiert ausschließlich über Buckets und Ansichten. Wird ein Depot oder Geldkonto angelegt — im Dialog oder über API/MCP — löst sich die interne Bindung deterministisch auf ein Standard-Portfolio auf (den ältesten Datensatz, sonst ein frisch angelegtes „Default“), ohne nachzufragen.
Währung und Bindung frieren ein, sobald verwiesen (ADR-0050 §11). Die Währung eines Geldkontos und seine interne Portfolio-Bindung frieren ein, sobald eine Transaktion über eines ihrer beiden Konten auf das Konto verweist oder ein Depot es verknüpft; die Bindung eines Depots friert ein, sobald eine Transaktion darauf verweist. Eine Änderung wird mit einem Feldfehler abgelehnt, der die Verweise zählt, und schreibt nichts — gebuchte Historie wird nie umdenominiert oder verschoben. Name, Notizen und Liquiditätsrolle bleiben änderbar. Die API verschiebt ein Konto oder Depot ohnehin nie in ein anderes Portfolio.
Namen und frühere Namen (ADR-0050 §4). Zwei Verrechnungskonten teilen nie
einen Namen, und zwei Depots auch nicht: Ein Name, den ein anderes Konto der
Art als Namen oder als einen seiner früheren Namen trägt, wird beim Anlegen
und Umbenennen abgelehnt, weil ein Portfolio-Performance-Import, der ihn nennt,
schon auf jenes Konto bucht. Ein umbenanntes Konto behält seinen bisherigen
Namen als früheren Namen, sodass ein Export, der noch das alte Konto
nennt, auf das umbenannte bucht; die Rückbenennung auf einen früheren Namen
nimmt ihn zurück. Solange ein anderes Konto der Art den alten Namen noch als
Namen trägt, wird der alte Name nicht behalten, und ein Import, der ihn nennt,
bucht auf jenes andere Konto. Konten, die sich schon vor dieser Regel einen
Namen teilten, bleiben, wie sie sind; eines davon umzubenennen beendet die
Mehrdeutigkeit. Die früheren Namen stehen in den API- und MCP-Nutzlasten
(former_names) und lassen sich dort entfernen; ein Import, der einen
entfernten Namen noch nennt, legt dann ein neues Konto an. Auf dieser Seite
liegen beide im Zeilenmenü, siehe Umbenennen, zusammenführen und löschen
unten.
Durchgearbeitete Beispiele — Haushalts-Aufteilung, Strategie-Ansichten mit eigenen SOLL-Plänen, Übersetzen von Portfolio-Performance-Gewohnheiten und das Ausschließen einer Position aus der Steuerung — stehen im Leitfaden Buckets & Ansichten.
Umbenennen, zusammenführen und löschen (ADR-0050 §4, §7, §8, §10)
Jede Zeile — ein Depot, das Verrechnungskonto darunter, ein Geldkonto für sich — hat ihr eigenes ⋮-Menü, benannt nach ihrer Zeile (Aktionen für Tagesgeld): Umbenennen, Getrennt taggen (an einem Depot, das gemeinsam mit seinem Verrechnungskonto getaggt ist), Zusammenführen in… und Löschen, in dieser Reihenfolge. Auf einem schmalen Bildschirm öffnet sich das Menü als Blatt von unten und nennt oben seine Zeile.
Umbenennen ändert nur den Namen; Währung und Portfolio-Bindung frieren wie oben beschrieben ein, Rolle und Buckets bleiben in der Zeile. Vor dem Speichern sagt der Dialog, was mit dem aktuellen Namen geschieht: Er bleibt ein früherer Name des Kontos, sodass ein Import, der ihn noch nennt, weiter hierher bucht — oder, solange ein anderes Konto der Art noch so heißt, wird er nicht behalten, und ein solcher Import bucht auf jenes andere Konto. Ein Name, auf den ein anderes Konto hört, als Namen oder als früheren Namen, wird am Feld abgelehnt, zusammen mit dem Konto, das ihn trägt, und nichts wird geschrieben. Dass sich die Zeile ändert, ist die Bestätigung.
Derselbe Dialog listet die früheren Namen des Kontos; ein Name, der mit einer Zusammenführung kam, sagt, an welchem Tag. Entfernen nimmt einen nach einer Rückfrage weg, die sagt, was das kostet: Ein Import, der noch „Tagesgeld 2019“ nennt, legt dann ein neues Konto an. Unter dem Namen des Kontos zeigt die Zeile den neuesten früheren Namen (früher: …) und, an einem Konto, in das andere zusammengeführt wurden, die neueste Zusammenführung (zusammengeführt aus Tagesgeld (alt) · Datum), jeweils mit +N, wenn es mehr gibt. Das Datum der Zusammenführung führt als Link zu ihrem Eintrag unter Zusammenführungen am Ende der Seite.
Zusammenführen in… vereint zwei Konten, die eigentlich eines sind — typischerweise ein Konto, das ein Import unter anderem Namen ein zweites Mal angelegt hat. Das Konto, das Sie zusammenführen (die Quelle), verschwindet; das Konto, das Sie wählen (das Ziel), behält alles. Es sind zwei Schritte in einem Dialog:
- Ziel. Die Quelle steht mit Währung, Liquiditätsrolle, Buckets, Buchungen und Saldo da, und jedes andere Konto der Art ist aufgeführt. Wählbar ist nur ein Konto mit derselben Währung, derselben Liquiditätsrolle und denselben Buckets — bei einem Depot mit denselben Standard-Buckets. Die übrigen stehen unter Nicht wählbar, jedes mit seinem Grund, sodass klar ist, was zuerst anzugleichen ist. Zwei Konten gleichen Namens sind unterscheidbar wie beim Import: ein Verrechnungskonto an seinen verknüpften Depots („· bei Depot 1“), ein Depot an seinem Verrechnungskonto („· mit Giro“).
- Vorschau. Noch ist nichts geschrieben. Für Geldkonten zeigt die Vorschau beide Salden und ihre Summe, die Buchungen, die umziehen, die Umbuchungen zwischen den beiden, die entfallen (sie heben sich auf, sobald die beiden eines sind), die verknüpften Depots, die umziehen, und die gesetzten Salden, die angepasst werden — jeder mit seinem Datum und seinem Wert danach — oder entfallen. Für Depots zeigt sie je betroffener Position Stückzahl, Durchschnittskosten und realisierten Gewinn/Verlust vorher und nachher sowie einen Split, dessen Rundung sich unterscheidet, sobald beide Historien vereint sind. Buchungen, die in beiden Konten gleich sind — gleicher Tag, gleiche Art, gleiche Beträge, typischerweise ein Import, der zweimal ankam — stehen mit zwei Wahlmöglichkeiten da, als Duplikate entfernen oder beide behalten, jede mit dem Saldo, zu dem sie führt (bei Geldkonten); als Duplikate entfernen nennt außerdem, was es außerhalb der beiden ändert, etwa den Saldo eines anderen Kontos oder die Stückzahl einer Position. Keine ist vorausgewählt, und der Knopf In … zusammenführen bleibt deaktiviert, mit dem Grund daneben, bis Sie wählen.
Die Bestätigung wendet genau den Plan an, den die Vorschau zeigte: Die Buchungen, die verknüpften Depots und die angepassten gesetzten Salden ziehen zum Ziel, die Namen der Quelle werden frühere Namen des Ziels — sodass der nächste Import unter dem alten Namen auf das Ziel bucht —, und die Quelle wird gelöscht. Das Ergebnis steht über der Tabelle (Tagesgeld (alt) in Tagesgeld zusammengeführt: 151 Buchungen verschoben, 2 entfernt.). Hat sich eines der Konten geändert, während die Vorschau offen war, wird nichts zusammengeführt: Der Dialog zeigt die neue Vorschau, sagt, was sich geändert hat, und fragt die Wahl erneut ab. Eine Zusammenführung, die nicht jede Position in ihren Ansichten halten kann — zwei Depots, die ein Wertpapier in verschiedenen Buckets halten, etwa —, wird schon in der Vorschau mit Grund und Abhilfe abgelehnt; Erneut prüfen liest sie nach dem Angleichen neu. Ebenso eine Geldkonto-Zusammenführung, die einen gesetzten Saldo mit mehr Nachkommastellen speichern müsste, als ein Betrag hält — ein Kauf oder Verkauf ohne Betrag, dessen Geld Stückzahl × Kurs ist, kann das auslösen —, und eine, deren gesetzter Saldo noch einen Import-Hash aus der Zeit vor der Import-Hash-Prüfung trägt: Der Dialog nennt jeden gesetzten Saldo und jede Buchung mit Konto, Datum und Nummer und sagt, was zu ändern ist. Ein Rückgängigmachen gibt es nicht; das Protokoll der Zusammenführung und das Audit-Journal zeigen, was sie getan hat, und Zusammenführungen weiter unten listet jede Zusammenführung.
Löschen entfernt ein Konto nur, wenn nichts darauf verweist — keine Buchung und bei einem Geldkonto kein verknüpftes Depot — und fragt einmal nach, mit dem Namen des Kontos. Ein Konto mit Buchungen wird nicht gelöscht: Kann nicht gelöscht werden sagt, was es noch hat, und bietet stattdessen Zusammenführen in… an — so verschwindet ein Konto mit Historie. Ein Löschen, das auf eine gleichzeitige Änderung trifft, löscht nichts und sagt es; dann erneut versuchen.
Zusammenführungen (ADR-0050 §12)
Nach der Tabelle der Depots und Verrechnungskonten listet Zusammenführungen jede Zusammenführung, die diese Instanz festgehalten hat — von Verrechnungskonten, von Depots und von Wertpapieren —, die neueste zuerst. Die Liste ist zunächst zugeklappt unter einer Zeile, die sie zählt (5 Einträge · zuletzt 30.09.2026); bei mehr als hundert Zusammenführungen heißt es die neuesten 100. Jede Zeile nennt:
- Datum und Art (Verrechnungskonto, Depot oder Wertpapier);
- Quelle → Ziel: die Quelle grau, weil es sie nicht mehr gibt — ihr Name lebt als früherer Name des Ziels weiter —, das Ziel als Link zu seiner Zeile auf dieser Seite oder zur Seite des Wertpapiers. Ein Ziel, das eine spätere Zusammenführung aufgenommen hat, liest jetzt in … mit einem Link dorthin, wo die Buchungen heute stehen; ein inzwischen gelöschtes Ziel liest ein inzwischen gelöschtes Depot (Verrechnungskonto, Wertpapier);
- das Ergebnis in den Worten der Bestätigung (142 Buchungen verschoben, 6 entfernt; bei einem Wertpapier auch die entfernten Duplikate, die mit denen des Ziels zusammengelegten Splits, die ergänzten Kurse und die entfallenen Einstellungen). Aufgeklappt zeigt es eine Zeile je Tabelle, die die Zusammenführung geändert hat — verschobene und entfernte Buchungen, jede Entfernung mit ihrem Grund (Duplikat entfernt, interne Umbuchung entfallen, gesetzter Saldo desselben Tages entfallen, Split zusammengelegt), gesetzte Salden, frühere Namen, Kurse, Klassifizierungen, Buckets der Position und Ähnliches —, dann Ihre Wahl für gleiche Buchungen und bei einem Wertpapier die ISIN, wo die Quelle eine trug (#1067), und die bestandene Prüfung (Saldo an 211 Tagen bestätigt; nichts zu prüfen für eine Zusammenführung, deren Quelle nichts bewegt hat, gleich welcher Art);
- Von: Operator für eine Zusammenführung auf diesen Seiten, Agent für eine, die ein API- oder MCP-Token ausgeführt hat.
Zusammenführungen auf dem synthetischen Demo-Datensatz.
Das Datum in der Zeile zusammengeführt aus … · Datum eines Überlebenden und in der Grundlagenzeile zusammengeführt am … aus … eines Wertpapiers öffnet die Liste beim Ergebnis dieser Zusammenführung; eine, die älter ist als die neuesten 100, wird als außerhalb der Liste genannt. Die Liste ist nur zum Lesen: Ein Rückgängigmachen gibt es nicht, und nichts in ihr schreibt. Solange es keine Zusammenführung gibt, sagt sie, wo eine beginnt — Zusammenführen in… im Zeilenmenü jedes Kontos, Depots und Wertpapiers. Auf dem Telefon ist jede Zusammenführung zwei Zeilen, Quelle → Ziel über Datum · Art · Von, das Ergebnis darunter.
Ihr Agent liest dieselben Protokolle mit GET /api/v1/merges (MCP
portfolixir.merges.list), auch die entfernten Buchungen je Grund.
Portfoliodatensätze (Kompatibilität)
Portfolios bleiben als interne Kompatibilitätsdatensätze im Schema, in der JSON-API und im Importpfad erhalten. Die Seite Konten & Depots im Administrationsbereich trägt ein eingeklapptes, schreibgeschütztes Panel Portfoliodatensätze (Kompatibilität), das jeden Datensatz auflistet — Name, Basiswährung, Anlagedatum, Quelle (UI, API, Import oder Seed, abgeleitet aus dem Audit-Journal) sowie die Zahl der gebundenen Depots und Geldkonten — damit über API/MCP angelegte Datensätze nie unsichtbar werden. Es gibt keine Anlage- oder Bearbeitungs-UI; die API-Schreibendpunkte sind veraltet (siehe API und MCP), und eine Folge-Story verschmilzt die Datensätze nach zwei Releases ohne externe Portfolio-Writes in Buckets und Ansichten.
Transaktionen und Bestände
Manuelle Transaktionen
Transaktionen sind explizit und nachvollziehbar. Eine Transaktion definiert:
- Datum
- Wertpapier
- Richtung (Kauf/Verkauf)
- Menge (Decimal)
- Stückpreis (Decimal)
- optionale Steuern, Gebühren und Notizen
Eine Transaktion wird in der Währung ihres verknüpften Geldkontos gebucht. Ihre Währung muss der dieses Geldkontos entsprechen (und bei einer Geldübertragung auch der des Gegen-Geldkontos); eine Buchung mit Währungs-Konflikt wird abgelehnt statt stillschweigend umgerechnet. Buche gegen ein Geldkonto in derselben Währung oder lege eines an. Hier findet keine Wechselkursumrechnung gespeicherter Beträge statt — Wechselkurse werden nur angewendet, wenn ein Portfolio in seiner Basiswährung bewertet wird.
Eine Buchung erfassen (Issue #803; C6 des Reviews vom 2026-09-12, Variante C): die Seite öffnet auf der Historie, und Transaktion erfassen im Kopf der Historie öffnet eine seitliche Schublade in der Form des Wertpapier-Detailbereichs — Art, Datum, das Depot, auf das die Buchung bucht (sein Geldkonto setzt die Währung), Wertpapier, Stückzahl und Preis, Kosten und Notiz hinter einer Aufklappung, darunter die Lot-Vorschau — auf dem Telefon ein Bottom Sheet. Das Erfassen schließt die Schublade und zeigt das Ergebnis über der Historie; Abbrechen oder Esc verwirft den Entwurf und gibt den Fokus an das Steuerelement zurück.
Eine Buchung korrigieren (Issue #809): jede Zeile der Historie trägt ein Kebab-Menü, und Bearbeiten darin öffnet dieselbe Schublade, vorbefüllt mit der Buchung — dieselben Felder, dieselbe Prüfung, dieselbe Lot-Vorschau. Das Speichern korrigiert die Zeile an Ort und Stelle: es entsteht keine zweite Buchung, die abgeleiteten Bestände folgen, und die Änderung wird mit den vorherigen Werten im Audit-Journal festgehalten — die Schublade sagt es unter ihrem Titel: „Korrigiert die Buchung an Ort und Stelle; die abgeleiteten Bestände folgen, und das Journal hält die Änderung fest.“ (Issue #1074). Das ist die menschliche Sicht auf eine Fähigkeit, die API und MCP-Begleiter schon vor der Zwei-Wege-Regel hatten; an beiden wurde nichts ergänzt.
Die Arten, die die Schublade nicht bucht (Issue #912): Die Schublade erfasst und korrigiert Käufe und Verkäufe. Bearbeiten an jeder anderen Buchung — einer Dividende, einer Einlage, einer Umbuchung, einer Einlieferung, einem gesetzten Saldo, einem Split — öffnet die Schublade nur für die Notiz: Die Angaben der Buchung stehen fest da (Typ, Datum und was die Art speichert — das Wertpapier, das Verrechnungskonto oder beide Konten einer Umbuchung, das Depot, den Betrag, die Steuern, Stückzahl und Preis, jede Zahl mit den Stellen, mit denen sie gespeichert ist), und nur die Notiz ist änderbar (Notiz speichern; das Audit-Journal hält die Änderung fest wie jede andere). Eine Hilfezeile sagt, wie eine solche Buchung korrigiert wird: an Ort und Stelle über die API oder den MCP-Begleiter, oder indem sie gelöscht und neu importiert wird — bei einer Buchung aus einem Import; eine über API oder MCP gebuchte wird gelöscht und dort neu gebucht, ein gesetzter Saldo unter Konten & Depots neu gesetzt —, und trägt Löschen…, das die Schublade schließt und die Rückfrage unten öffnet. Wer die Schublade schließt — Abbrechen, Esc, die Schließen-Schaltfläche oder Notiz speichern —, findet den Fokus wieder auf der Menü-Schaltfläche der Zeile, „Notiz gespeichert“ im Blick.
Ein gebuchter Split öffnet ebenfalls nur die Notiz (E25 S6): Ein Split
ist eine Tatsache am Wertpapier, gebucht über Split erfassen am
Wertpapier, dessen Prüfungen (der Stichtag, die Bestände, ein anderes
Verhältnis am selben Tag) eine gewöhnliche Änderung umgehen würde. Seine
Schublade zeigt Typ, Stichtag, Wertpapier und Verhältnis des Splits, fest.
Ein falscher Split wird nicht an Ort und Stelle korrigiert: Er wird gelöscht
— Split löschen… in dieser Hilfezeile — und mit Split erfassen neu
erfasst. API und MCP antworten auf eine Änderung an etwas anderem als der
Notiz einer Split-Zeile mit 422.
Eine Buchung löschen (Issue #912): Das Kebab-Menü jeder Zeile trägt nach Bearbeiten den Eintrag Löschen…, in Rot. Er öffnet eine Rückfrage, die die Buchung so nennt, wie die Telefonzeile der Historie sie zeigt — Datum und Art über Wertpapier und Depot (oder Konto), der Betrag mit Vorzeichen über seiner Größe — und sagt, was sich ändert: zum Beispiel „Danach hält Depot 1 40 Stück Global Aktien ETF weniger, und Girokonto hat 2.504,90 EUR mehr.“, dass Bestände, Kontostände, Rendite und Trades ohne die Buchung neu berechnet werden und dass das Audit-Journal die Löschung mit allen Werten festhält, sich die Buchung selbst aber nicht wiederherstellen lässt (Issue #1090). Die Rückfrage entsteht aus der Buchung, wie sie beim Wählen von Löschen… gespeichert ist. Eine Stückzahl nennt sie zum heutigen Stand: Ein Kauf von 10 Stück vor einem 2:1-Split liest „20 Stück weniger“, so viel verlieren die Bestände. Wo ein später gesetzter Saldo dieses Verrechnungskonto verankert, sagt der Satz, bis wann sich das Konto ändert, und der nächste, ab wann es bleibt, wie gesetzt: „… und Girokonto hat bis zum 30.09.2026 2.504,90 EUR mehr. Ab dem am 01.10.2026 gesetzten Saldo bleibt der Stand von Girokonto unverändert.“; ein am Tag der Buchung gesetzter Saldo heißt, der Stand des Kontos bleibt, wie er gesetzt wurde. Ein Wertpapier, dessen Namen ein anderes auch trägt, wird mit seiner ISIN genannt, wie das Zeilenmenü es nennt. Transaktion löschen löscht sie; Abbrechen, Esc oder die Schließen-Schaltfläche ändern nichts und geben den Fokus an die Menü-Schaltfläche der Zeile zurück. Die Zeile verschwindet, die Anzahl im Monatskopf folgt, und das Ergebnis über der Historie lautet, als Hinweis, „Transaktion gelöscht: Kauf · Global Aktien ETF · 22.09.2026.“; eine inzwischen gelöschte Buchung (vom Agenten oder in einem anderen Tab) liest, als Problem, „Diese Transaktion existiert nicht mehr.“ — die eine Ablehnung, die die API kennt. Jedes Ergebnis trägt sein Wort und sein Zeichen, nicht nur eine Farbe, und sein × blendet es aus (#1064). Konten & Depots, Ansichten, Klassifizierungen und Risiko antworten auf ihre Aktionen ebenso. Darüber hinaus wird nichts geprüft, wie über die API: Wird ein Kauf gelöscht, dessen Stücke ein späterer Verkauf verbraucht hat, fehlt diesem Verkauf danach sein Kauf.
Eine Buchung löschen, auf dem synthetischen Demo-Datensatz.
- Eine importierte Buchung sagt es: Gelöscht, kennt der Import sie nicht mehr, ein erneuter Import derselben Datei bucht sie also wieder. Diesen Vermerk legt nur das Zusammenführen eines Kontos, Depots oder Wertpapiers still.
- Ein Split wird so gelöscht, wie er gebucht wurde, als eine Tatsache: Löschen… an einer beliebigen seiner Zeilen öffnet Split löschen mit dem Verhältnis, der Zahl der Zeilen und den Portfolios, deren Zeilen mitgehen — „Split löschen (2 Zeilen)“ löscht sie alle in einem Schritt, und das Audit-Journal hält die Löschung fest; ein Split in einem Portfolio wird ohne Zeilenzahl genannt. Die Bestätigung löscht die Zeilen, die die Rückfrage aufgezählt hat: Ist eine davon inzwischen gelöscht, gehen die übrigen trotzdem; ist inzwischen eine hinzugekommen (ein erneutes Buchen in einem weiteren Portfolio), wird nichts gelöscht, und die Rückfrage zeigt den Split, wie er jetzt ist — „Der Split hat sich geändert, während dieser Dialog offen war. Nichts wurde gelöscht; der Dialog zeigt jetzt den neuen Stand.“ —, zum erneuten Bestätigen. Danach zählen die Bestände ab seinem Stichtag ohne den Split, das Diagramm rechnet die Kursreihe ohne ihn, und gespeicherte Kurse bleiben, wie sie sind; Split erfassen nimmt danach das korrigierte Verhältnis an. Split erfassen selbst führt hierher: Ist am Tag schon ein Split mit anderem Verhältnis gebucht, nennt seine Warnung dieses Verhältnis und trägt Gebuchten Split löschen…, das dieselbe Rückfrage auf der Seite des Wertpapiers öffnet. Solange dieser Split steht, zeigen Stückzahl danach (zum Stichtag) und Resultierende Position (heute) in der Vorschau „—“ (ein Screenreader liest stattdessen „keine Stückzahl danach: an diesem Tag ist ein anderes Verhältnis gebucht“), und die Warnung sagt, dass die Vorschau keine Stückzahl danach zeigt (Issue #1066): Die Buchung wird abgelehnt, bis der gebuchte Split gelöscht ist, also träte keine Zahl danach ein.
API und MCP-Begleiter haben dieselben zwei Löschwege:
DELETE /api/v1/transactions/:id (portfolixir.transactions.delete) für eine
Buchung und DELETE /api/v1/splits/:transaction_id (portfolixir.splits.delete,
ein Admin-Werkzeug) für einen Split als Ganzes.
Während ein Verkauf erfasst wird, zeigt das Formular eine Vorschau, welche FIFO-Kauftranchen (Lots) der Verkauf verbrauchen würde und den Bruttogewinn je Tranche und in Summe — Verkaufserlös minus FIFO-Anschaffungskosten der verbrauchten Lots, vor Gebühren, zum eingegebenen Preis (oder zum zuletzt gespeicherten Preis, bis einer getippt ist). Die Zahl ist indikativ und keine Netto-Größe; das Buchen des Verkaufs ändert nichts daran, wie der Einstand gespeichert wird (Bestände behalten ihren gleitenden Durchschnitt, der Trades-Tab das FIFO-Matching). Lots werden first-in, first-out über alle Depots gematcht, wie in der Trades-Ansicht split-skaliert, und währungsübergreifende Tranchen tragen dieselbe Kurs-/Währungszerlegung wie die Bestände — oder einen ehrlichen Strich, wenn sie nicht ableitbar ist. Eine eingegebene Menge über den offenen Lots wird mit dem ungedeckten Fehlbetrag markiert.
Die Historie lesen
Die Historie enthält alle Buchungen über alle Konten und Depots, jeder Art, wie der Untertitel der Seite sagt. Sie wird über Chips oberhalb der Tabelle gefiltert: einer je Geldkonto und einer je Transaktionsart, die tatsächlich vorkommt. Chips sind Schalter. Zwei Chips derselben Familie bedeuten „eines von beiden” — zwei Konten zeigen die Buchungen beider Konten; je ein Chip aus zwei Familien schränkt auf die Schnittmenge ein. Die selteneren Bedingungen — Wertpapier, Zeitraum, Freitextsuche — liegen hinter Weitere Filter, das eine Anzahl trägt, sobald dort eine Bedingung aktiv ist. So verbirgt ein zurückgestuftes Bedienelement nie, was die Liste gerade filtert.
Die Einschränkung auf genau ein Konto blendet eine Spalte Saldo ein: den Stand des Kontos nach jeder Buchung, in der Währung des Kontos. Zwei Eigenschaften dieser Spalte sind wichtig:
- sie rechnet genauso wie der Kontosaldo selbst, die jüngste Zeile entspricht also dem Wert auf der Kontenseite;
- sie wird über die gesamte Historie des Kontos gebildet, nicht über die angezeigten Zeilen. Ein Datumsfilter ändert, welche Zeilen Sie sehen, nie den damaligen Saldo.
Eine Zeile, die das gewählte Konto nicht bewegt — eine Einlieferung, ein Split — zeigt einen Gedankenstrich statt den Wert der Vorzeile zu wiederholen.
Der Betrag jeder Zeile ist das Geld der Buchung, wie ihr Verrechnungskonto es sieht: was das Konto verlässt, ist negativ, was ankommt, positiv, und ein gesetzter Saldo zeigt den Stand, den er setzt. Eine Umbuchung bewegt zwei Konten, also trägt sie das Vorzeichen des Kontos im Blick: Solange die Chips ihr Empfängerkonto auswählen und nicht ihr Senderkonto, liest sie sich als ankommendes Geld („200,00“, wie der Saldo daneben um 200 steigt); sonst aus Sicht des Senders („-200,00“).
Die Zusammenfassung über der Tabelle nennt Anzahl und gebuchte Bruttobeträge je Art, mit einer Summe je Währung. Die Beträge werden nie umgerechnet oder über Währungen hinweg addiert — eine Umrechnung wäre eine andere Kennzahl und bräuchte ihre eigene Kursbasis. Die Zeilen sind nach Monaten gegliedert, und jeder Monatskopf trägt den Monat und allein seine Anzahl — September 2026, 6 Transaktionen (Issue #1083): Eine Summe über Käufe, Einlagen, Verkäufe und einen gesetzten Saldo wäre weder ein Geldfluss noch ein Umsatz, also bleiben die Summen in der Zusammenfassung, deren Grundlagenzeile sagt, was sie addieren.
Neben den Konto- und Art-Chips sitzen die Geändert-seit-Chips (Heute /
7 Tage / 30 Tage, Issue #731): sie verengen die Historie auf Transaktionen,
die strikt nach dem Schnitt angelegt oder geändert wurden — nach
Datensatzänderung, nicht nach Buchungsdatum: eine bearbeitete alte Buchung
taucht auf, eine unberührte junge fällt heraus. Die Notiz unter den Chips
nennt den Schnitt und die Eigenschaft, die ein Delta ehrlich macht:
Löschungen werden nicht angezeigt. Der Schnitt liegt in der URL als
?since=<ISO8601> — Parameter, Formen und Semantik des API-Delta-Reads, ein
vom Agenten weitergegebener Link öffnet also genau die gelesene Scheibe; ein
unlesbarer Wert degradiert zur vollständigen Historie. Die Spalte Saldo
bleibt von diesem Filter wie von jedem anderen unberührt: sie wird immer über
die gesamte Historie des Kontos gebildet.
Die Standardspalten sind Datum, Typ, Wertpapier, Konto, Stückzahl, Preis und Betrag. Konto (Issue #1084) nennt das Verrechnungskonto, über das der Betrag lief — das Konto, aus dessen Sicht der Betrag steht, mit dem Namen, den auch sein Chip trägt; eine Umbuchung nennt beide, den Sender zuerst („Girokonto → Tagesgeld“), und eine Wertpapierumbuchung nennt ebenso ihre beiden Depots („Depot 1 → Depot 2“); eine Buchung ohne Verrechnungskonto, etwa eine Einlieferung, nennt ihr Depot; ein Split nennt keines. Preis zeigt einen Preis mit den Stellen, mit denen er gespeichert wurde, bis zu vier Nachkommastellen: 41,1234 bleibt 41,1234, 24 liest sich 24,00, und ein Preis, den ein Import als Betrag ÷ Stückzahl abgeleitet und als 72,621176 gespeichert hat, liest sich 72,6212 — wie im Tab Transaktionen des Wertpapiers (Issue #1073). Ein Preis unter 1 behält mindestens drei signifikante Stellen und liest sich so nie als null: 0,000045 bleibt 0,000045, und 0,001234 liest sich 0,00123. Die Namen von Wertpapier und Konto brechen zwischen Wörtern um, statt die Tabelle zu verbreitern, sodass bei Desktop-Breite die ganze Zeile im Blick bleibt, Preis und Betrag eingeschlossen; Datumsangaben und Zahlen brechen nie um.
Spalten (Issue #732) öffnet die Spaltenwahl der Historie — die
menschliche Hälfte der schlanken fields=-Feldauswahl der API. Jenseits des
Standardsatzes bietet sie die Felder an, die jede Buchung schon trägt, die
die Tabelle aber nie zeigte: Währung, Gebühren, Steuern und Notizen. Eine
Spaltenwahl von vor der Spalte Konto bleibt erhalten; Konto ist dann einen
Haken entfernt, in der Gruppe Buchung der Auswahl. Die Wahl wird im Browser
gespeichert und übersteht ein Neuladen. Die Spalte Saldo steht bewusst
nicht in der Auswahl: sie folgt weiter ihrer eigenen Regel — sie erscheint
genau dann, wenn die Chips auf ein Konto verengen —, denn eine Auswahl, die
sie außerhalb dieser Verengung herbeiholen könnte, zeigte eine bedeutungslose
Zahl. Das frühere Panel Aktuelle Bestände hat diese Seite mit Issue #803
verlassen: es doppelte Vermögen → Bestände, und die Bewertungsfelder der
Bestände-Projektion bleiben über die schlanke fields=-Feldauswahl der
Bestände-API lesbar.
Auf dem Telefon (Issue #799, UX-DR27): unter 560 px weicht die Historie zweizeiligen Zeilen unter denselben Monatsköpfen — Datum und Art über dem Wertpapier oder Konto, das die Buchung berührt hat (bei einer Umbuchung beide Konten, den Sender zuerst, wie die Spalte Konto sie nennt), rechts der Betrag mit Vorzeichen und Währung über der Größe (Stückzahl × Preis, der Preis mit seinen gespeicherten Stellen; die Stückzahl allein; das Verhältnis eines Splits), darunter der laufende Saldo, solange die Chips auf ein Konto eingrenzen — sodass nichts seitwärts scrollt und ein langer Name ohne Leerzeichen in seiner Zeile umbricht (Issue #1073); die Spaltenauswahl behält oberhalb von 560 px ihre Bedeutung.
Bestandsberechnung
Aktuelle Bestände werden nicht manuell erfasst. Sie werden aus allen Transaktionen im Zeitverlauf abgeleitet, sodass der Zustand reproduzierbar und nachvollziehbar ist. Gehaltene Mengen bewegen sich mit Käufen und Verkäufen, mit ein-/ausgehenden Lieferungen (Anteile, die ohne Geld-Bein ein- oder austreten, z. B. ein Depotübertrag von einer anderen Bank) und mit Wertpapierübertragungen zwischen eigenen Depots. Jeder Bestand trägt außerdem einen gleitenden Durchschnitts-Einstandswert und den nicht realisierten Gewinn/Verlust (absolut und prozentual) gegen den zuletzt gespeicherten Preis, in der eigenen Währung des Wertpapiers. Der Einstandswert wandert mit den Anteilen: Käufe (und mit Preis erfasste Einlieferungen) fügen Einstand hinzu, Verkäufe und Auslieferungen entnehmen ihn zum laufenden Durchschnitt, und eine Wertpapierübertragung nimmt den Einstand der bewegten Anteile mit ins Zieldepot. Eine ohne Preis erfasste Lieferung bewegt die Menge zum Einstand null, da für sie kein eigener Anschaffungswert bekannt ist.
Für ein Wertpapier, das in einer anderen Währung notiert als das Geld, das es
bezahlt hat, zerlegt jeder Bestand seinen Gewinn oder Verlust in Basiswährung
zusätzlich in zwei benannte Teile (ADR-0033): den Kursbeitrag — die
Veränderung des eigenen Kurses des Wertpapiers, zum heutigen Wechselkurs
umgerechnet — und den Währungsbeitrag — die Wirkung des Wechselkurses auf
den ursprünglich investierten Betrag. Zusammen ergeben sie exakt den gesamten
Gewinn oder Verlust der Position in Basiswährung. Für Positionen in der
Basiswährung ist der Währungsbeitrag exakt null. Eine Position, deren
Zerlegung sich nicht aus den erfassten Buchungen ableiten lässt (etwa ein
importierter währungsübergreifender Handel ohne gespeicherten Kurs am
Buchungstag), zeigt einen Strich statt einer geratenen Zahl; die Aufgabe
mix portfolixir.backfill_settlement_legs leitet die fehlenden Beine für
historische Importe ab, sobald Kurse für die Buchungstage gespeichert sind.
Im Formular buchen (Issue #395). Weicht die Währung des Wertpapiers von der des Geldkontos am gewählten Depot ab, zeigt die Buchungsleiste einen Block „Abrechnung in EUR“ (benannt nach der Kontowährung) mit zwei verbundenen Feldern: dem Abrechnungsbetrag in Kontowährung und dem Kurs — Einheiten der Kontowährung je einer Einheit der Wertpapierwährung. Wer eines einträgt, sieht das andere abgeleitet, und das zuletzt eingetragene bleibt, wie es ist: Nach dem Betrag aus der Abrechnung passt eine geänderte Stückzahl oder ein geänderter Preis den Kurs an, nie den Betrag; eine Notiz, eine Gebühr oder ein Datum ändert keines von beiden. Beide sind aus den gespeicherten Wechselkursen am oder vor dem Buchungstag vorbelegt und sagen das — ein Vorschlag, die Abrechnung des Brokers gilt; ohne gespeicherten Kurs sagt der Block auch das und wartet auf den Betrag der Abrechnung. Der Preis wird in der Wertpapierwährung eingegeben, Gebühren und Steuern in der Kontowährung. Gespeichert ist die Buchung in der Wertpapierwährung, und ihr Geldbetrag wird aus Abrechnung, Gebühren und Steuern berechnet — das Formular erzeugt also nie eine Buchung, die die folgende Regel ablehnt. Ein Handel ohne Wert (eine Gratiszuteilung zum Preis 0) wird ohne Geldbetrag gebucht. Wird eine solche Buchung auf ein Wertpapier in der Kontowährung geändert, entfallen ihre Abrechnungsangaben, und der Geldbetrag folgt der neuen Stückzahl, dem Preis und den Gebühren. Vor Sprint 15 buchte das Formular einen solchen Handel in der Kontowährung und las den Preis des Wertpapiers, als wäre er in Euro.
Geldbetrag und Abrechnung stimmen überein (Issue #395). Ein
währungsübergreifender Kauf hält den bewegten Geldbetrag fest (gross_amount,
einschließlich Gebühren und Steuern) und daneben den Handelswert in der
Kontowährung (settlement_amount); ein Verkauf den zugeflossenen Betrag, nach
Gebühren und Steuern. Seit Sprint 15 wird eine Buchung abgelehnt, wenn beide um
mehr als einen Cent auseinanderliegen — beim Kauf muss der Geldbetrag die
Abrechnung plus Gebühren und Steuern sein, beim Verkauf die Abrechnung abzüglich
dieser — und die Meldung nennt den Betrag, den die Abrechnung ergibt. Die Prüfung
läuft beim Erfassen einer Buchung und bei einer Änderung, die einen dieser
Beträge oder die Art ändert; das Bearbeiten der Notiz oder des Datums einer
älteren Buchung wird deswegen nie abgelehnt. Ältere Buchungen, die die Regel
verfehlen, listet diese Abfrage auf — nur lesend, nichts wird geändert:
docker compose exec db psql -U portfolixir portfolixir_prod -c "
SELECT id, date, type, gross_amount, settlement_amount, fees, taxes
FROM transactions
WHERE type IN ('buy', 'sell')
AND settlement_amount IS NOT NULL AND gross_amount IS NOT NULL
AND abs(gross_amount - CASE type
WHEN 'buy' THEN settlement_amount + coalesce(fees, 0) + coalesce(taxes, 0)
ELSE settlement_amount - coalesce(fees, 0) - coalesce(taxes, 0)
END) > 0.01
ORDER BY date, id;"
Eine aufgelistete Buchung zu korrigieren ist eine Entscheidung über die eigenen Aufzeichnungen: ihre Beträge in der Transaktionshistorie oder über die API bearbeiten.
Klassifizierungen, Ziele und Allokation
Die Klassifizierungs-Übersicht (/classifications, Issue #808) ist eine
Zeile je Baum, und jede Zeile sagt, was dieser Baum enthält: wie viele
Kategorien und Ebenen er nutzt, wie viele Wertpapiere in ihm zugeordnet sind —
mit der Zahl der nicht zugeordneten daneben — und den Zielplan, den er trägt:
dessen Name steht unter dem Namen des Baums, dessen Status als kurzes Wort in
der rechten Spalte. Die Zeile selbst öffnet den Baum; das Kebab-Menü am Ende
trägt Öffnen und, bei eigenen Bäumen, Löschen; + in der Überschrift legt
einen neuen an. Gibt es gar keine Bäume, sagt die Übersicht das, statt eine
leere Liste zu zeigen.
Wertpapiere können in Klassifizierungsbäume geordnet werden. Eigene Bäume sind frei gestaltbare Ordner mit Farben; integrierte Bäume für Anlageklasse und Währung werden aus jedem Wertpapier abgeleitet und sind immer vorhanden. Die Namen der integrierten Bäume werden über die Locale angezeigt (Issue #729 — englisch Asset class / Currency), geschlüsselt auf den stabilen Key des Baums; eigene Bäume behalten in jeder Sprache den Namen, den du ihnen gegeben hast. Der Anlageklassen-Baum ist eine editierbare Taxonomie: die Klasse eines Wertpapiers wird aus einem inferierten Standard vorbelegt und durch Ziehen zwischen Kategorien korrigiert.
Ein Baum hat höchstens 32 Ebenen. Hinzufügen unter einer Kategorie auf Ebene 32 wird oben auf der Seite abgelehnt, mit der gewählten Oberkategorie, der Ebene, die die neue Kategorie bekommen hätte, und der Grenze; das Formular behält, was du eingegeben hast (Issue #940). Die API lehnt dasselbe für eine Kategorie ab, die sie unter Ebene 32 anlegen oder verschieben würde.
Jedes Portfolio kann ein Zielgewicht je Kategorie speichern (ein Anteil am Portfolio, zum Beispiel 25 %). Die Allokations-Aufschlüsselung vergleicht dann je Kategorie das tatsächliche Gewicht (seinen Anteil an den bewerteten Positionen) mit dem gespeicherten Ziel und meldet die Drift — Ist minus Soll (positiv = übergewichtet, negativ = untergewichtet; ADR-0023), sowohl als Gewicht als auch als Betrag in Basiswährung, d. h. wie viel zu verkaufen (positiv) oder zu kaufen (negativ) ist, um das Ziel zu erreichen. Gehaltene, aber im gewählten Baum nicht zugeordnete Wertpapiere werden in einem Topf für nicht Zugeordnetes summiert. Nur die Ziele werden gespeichert; die Ist-Seite wird beim Lesen aus der Live-Bewertung abgeleitet.
Ein Plan muss nicht 100 % ergeben. Ihn bewusst kürzer zu lassen — etwa weil eine Satelliten-Kategorie absichtlich nicht voll genutzt wird — ist ein legitimer Plan, und die Lücke wird als nicht zugeteilter Rest ausgewiesen: ein benannter Teil des Plans mit der Bedeutung „dieser Anteil wird bewusst nicht gesteuert“, kein Fehler. Die Abweichung wird dann gegen den tatsächlich gesteuerten Anteil gemessen, damit der nicht zugeteilte Rest nicht als Abweichung auf die Kategorien mit Ziel verteilt wird, mit der man nichts anfangen kann. Eine Warnung bleibt den beiden Zuständen vorbehalten, die wirklich falsch sind: einer Summe über 100 % und einem Konflikt zwischen Positions- und Kategoriegewicht.
Jede Kategorie auf der Seite Klassifikationen weist außerdem aus, was sie gekostet hat, was sie heute wert ist und was sie erwirtschaftet hat — in Euro und in Prozent. Der Prozentwert ist geldgewichtet: die Summe der Ergebnisse geteilt durch die Summe des investierten Kapitals, nie der Mittelwert der Einzelprozente. Sonst würde eine winzige Position mit +300 % eine Kategorie dominieren, die in Euro unverändert ist.
Die Basis steht einmal über dem Baum: Diese Zahlen umfassen die heute in der Kategorie eingeordneten Positionen. Es ist eine Aussage über die aktuelle Zusammensetzung, keine Periodenrendite — verschiebt man ein Wertpapier in eine andere Kategorie, wandert sein gesamtes Ergebnis mit. Eine Position, deren Ergebnis sich nicht ableiten lässt (kein brauchbarer Kurs oder kein Wechselkurs zur Basiswährung), bleibt auf beiden Seiten der Summe außen vor und wird in der Markierung „abgedeckt von gesamt” mitgezählt, statt als Null zu gelten, was die Kategorie still kleinrechnen würde.
Die Zahlen folgen dem Baum, während Sie ihn bearbeiten (Issue #1110): eine Kategorie anlegen oder löschen, ein Wertpapier zuordnen, die Zuordnung aufheben oder es verschieben, oder eine Kategorie unter eine andere verschieben, berechnet sie neu. Die Wertpapiere einer gelöschten Kategorie zählen dann nicht mehr in ihrer Elternkategorie, und der Hinweis auf ausgelassene Positionen nennt kein Wertpapier mehr, das dort nicht mehr eingeordnet ist. Die Suche im Baum und der Schalter Nur aktuelle Positionen grenzen die Zeilen ein und berechnen nichts; ebenso wenig das Umbenennen oder Umfärben einer Kategorie.
Die Zahlen sind in EUR, und die Basiszeile sagt das zuerst („in EUR · Ergebnis: heutige Zusammensetzung, …”). Eine Position in einem Portfolio, dessen Basiswährung nicht EUR ist, wurde nicht in EUR bezahlt und hat deshalb keinen EUR-Einstand, den man addieren könnte: Sie bleibt aus Einstand und Ergebnis heraus, und ihr Einstand wird nie umgerechnet — das wäre ein Einstand, den niemand bezahlt hat. Ein Hinweis zwischen Basiszeile und Baum nennt sie mit der Kategorie, in der sie eingeordnet ist, und dem Einstand in der Währung, in der er bezahlt wurde: „1 Position ist in „Einstand“ und „Ergebnis“ nicht enthalten, weil ihr Einstand nicht in EUR bezahlt wurde: Harborline Freight Inc (Plattformen), Einstand 1.500,00 USD. Im „Wert“ ist sie enthalten.” Den letzten Satz gibt es nur, wenn die Spalte Wert die Position bewerten kann. Ein Wertpapier, das in einem EUR-Portfolio und in einem anderen liegt, bleibt ganz heraus, mit beiden Einständen („Einstand 1.000,00 EUR
- 1.500,00 USD”). Derselbe Hinweis nennt jede andere Position, die die Zahlen
auslassen, mit ihrem Grund in Worten; ab zwei Positionen nennt er die Anzahl
und listet sie in einer Aufklappliste. Fehlt nichts, gibt es keinen Hinweis.
Über die API ist das Lesen über alle Portfolios, das der Bildschirm nutzt,
GET /api/v1/category-results, und das Lesen einer Ansicht (GET /api/v1/views/:view_id/category-results) wendet dieselbe EUR-Regel an (#1091). Jede Form listet jede ausgelassene Position je Kategorie mit ihrem Grund, und einmal je Baum inexcluded_members, mit der Kategorie, in der sie eingeordnet ist, und, wenn nur ihre Währung sie draußen hält, dem Einstand in der Währung, in der er bezahlt wurde — die Liste, die dieser Hinweis zeigt.
Die Zahlen folgen der gewählten Ansicht (#1091). Unter dem Namen des
Baums steht der Ansichten-Umschalter der Vermögensseite — Alles, ein Chip
je Ansicht und Ansichten —, und er ist der eine Bereich dieser Seite.
Wählt man eine Ansicht, liest jede Zahl einer Kategorie-Zeile sie:
Positionen und Wert zählen nur die Positionen, die die Ansicht hält,
und Einstand und Ergebnis sind das Ergebnis dieser Ansicht über alle
Portfolios, in EUR, nach derselben Regel — das Lesen, das GET
/api/v1/views/:view_id/category-results beantwortet, sodass Bildschirm und
Agent nie auseinanderlaufen. Die Basiszeile nennt zuerst die Ansicht
(„Ansicht Langfrist · in EUR · Ergebnis: …“; „Ansicht Alles“, wenn keine
gewählt ist), der Hinweis darüber nennt nur, was die Zahlen dieser Ansicht
auslassen, und der Plan-Editor darunter bearbeitet den Plan dieser Ansicht.
Ein Mitglied einer Kategorie, von dem die Ansicht nichts hält — in einem Konto
außerhalb der Ansicht oder gar nicht mehr gehalten —, wird mit dem Schalter
„Nur aktuelle Positionen“ ausgeblendet und neben dem Kategorienamen als
+N nicht in der Ansicht gezählt, wo Alles +N ohne Bestand zählt.
Nicht zugeordnet folgt der Ansicht genauso: Es zählt und bewertet die
nicht zugeordneten Positionen, die die Ansicht hält, und zählt den Rest
neben seinem Namen. Wie die Kategorien folgt es in jedem Bereich dem
Schalter „Nur aktuelle Positionen“: Unter Alles zählt und bewertet es die
nicht zugeordneten Positionen, die noch gehalten werden, und zählt die
übrigen neben seinem Namen als +N ohne Bestand; ist der Schalter aus,
listet es jedes nicht zugeordnete Wertpapier. Eine Ansicht, deren Buckets
kein Konto treffen, sagt das über dem
Baum, mit den Worten der Vermögensseite, statt jede Zeile bei „—“ zu lassen.
Ein Chip ist eine Navigation wie auf der Vermögensseite: Die hier gewählte
Ansicht ist auch dort die aktive, und umgekehrt. Ein Punkt auf einem Chip
markiert eine Ansicht, die einen Plan für diesen Baum trägt — den Plan, den
der Editor darunter zeigt, aktiv oder Entwurf; ein Cash-Ziel allein ist kein
Plan dieses Baums (die Chips der Vermögensseite behalten ihre eigene Regel,
siehe unten). Wird die Ansicht gelöscht, während die Seite offen ist (in
einem anderen Tab oder über die API), schreibt Speichern, Anlegen oder
Löschen eines Plans nichts: Die Seite fällt auf Alles zurück und sagt es, und
die Antwort oben auf der Seite nennt die Ansicht und sagt, dass nichts
gespeichert (angelegt, gelöscht) wurde.
Ziele je Position (ADR-0030, #481). Zielgewichte lassen sich nun bis auf eine einzelne Position setzen (ein Wertpapier unter einer Kategorie), nicht mehr nur je Kategorie. Positionen sind die Quelle der Wahrheit: das effektive Ziel einer Kategorie rollt aus ihren Positionen auf (deren Summe); trägt eine Kategorie zusätzlich ein eigenes explizites Gewicht, wird die Abweichung sichtbar gemacht statt stillschweigend verworfen. Der erste Schritt liefert das Datenmodell und die API/MCP-Oberfläche: ein Positionsziel setzt man, indem man einem Zieleintrag eine
security_idhinzufügt; die Positionszeilen und die Kategorie-Aufrollung liest man über den Positions-Ziel-Endpunkt bzw. das entsprechende Werkzeug (siehe Integrationsleitfaden). Wird ein Wertpapier später umklassifiziert oder die Zuordnung entfernt, zählt sein Positionsziel weiter unter der Kategorie, unter der es abgelegt wurde, und wird beim Lesen der Positionsziele als stale (veraltet) markiert — zum Verschieben des Gewichts legt man es neu ab. Seit Schritt 2a zeigt die Allokationsansicht die Positions-Soll/Drift an — auch für noch nicht gehaltene Positionen (IST 0, Marker ohne Bestand) — und die Kategorie-Zeilen steuern nach der effektiven Aufrollung. Seit Sprint 15 nimmt der Plan-Editor auf der Klassifizierungsseite auch Positionsziele entgegen (siehe „Positionsziele im Plan-Editor“ unten); eine gleichmäßige Auto-Verteilung ist nicht geplant.
Einen SOLL-Plan auf der Klassifizierungsseite bearbeiten
Zielgewichte sind nicht global: ein SOLL-Plan gehört zu einer Ansicht
(siehe ADR-0020). Ein Plan wird auf der Klassifizierungsseite bearbeitet, im
Bereich Soll-Plan der Detailansicht eines eigenen Baums. Er bearbeitet den
Plan der Ansicht, die die Seite liest — der im Ansichten-Umschalter unter dem
Baumnamen gewählten —, und sein Kopf sagt, welche („für Ansicht Langfrist“
neben Soll-Plan; „für Ansicht Alles“, wenn keine gewählt ist: der
portfolioweite Plan, der sich wie ein einziges globales Zielset verhält). Seit
#1091 hat der Bereich keinen eigenen Selektor mehr: Ein anderer Chip lädt die
gespeicherten Gewichte und das Cash-Ziel dieses (Ansicht,
Klassifizierung)-Plans — Alles und jede benannte Ansicht tragen
unabhängige Pläne, sodass derselbe Baum je Ansicht einen anderen
100 %-Plan oder gar keinen halten kann.
Die Zustände sind:
- Noch kein Plan. Der Bereich zeigt einen Leerzustand mit Plan anlegen und, wenn eine andere Ansicht bereits einen Plan für diesen Baum hat, einen Selektor Aus anderer Ansicht übernehmen…, der den Editor aus diesem Quellplan vorbefüllt; der Plan ohne Ansicht heißt dort Alles. Bis zum Speichern wird nichts geschrieben.
- Ein Plan existiert. Jede Kategorie erhält ein Soll %-Feld, und darunter
steht ein Cash-Zielfeld; Plan speichern schreibt den gesamten
(Ansicht, Klassifizierung)-Plan auf einmal. Eine Live-Σ-Fußzeile summiert die Kategoriegewichte plus das Cash-Ziel und aktualisiert sich beim Tippen: bei genau 100 % ein ✓, über 100 % ein ✗ mit dem gelben Abweichungshinweis. Ein Plan unter 100 % ist eine Wahl, kein Fehler (ADR-0040): Die Σ trägt kein Zeichen, und eine gedämpfte letzte Zeile Nicht verteilt zeigt, was der Plan nicht verteilt. Eine Elternkategorie, deren Kinder Gewichte tragen, zeigt deren Summe neben ihrem Namen (Kinder Σ), in der Abweichungsfarbe, wenn sie vom eigenen Gewicht der Elternkategorie abweicht; sie folgt jeder Eingabe wie die Σ-Fußzeile (ein Kind, das seinen Positionszielen folgt, zählt mit deren Summe) und blockiert das Speichern nie. - Plan löschen entfernt den Plan der Ansicht; die Vermögensseite fällt für diese Ansicht dann auf nur IST zurück (kein SOLL, keine Drift).
Gewichte werden als Prozentsätze eingegeben und angezeigt (z. B. 60) und als
Brüche in [0, 1] gespeichert. Die Felder sind beschriftet und per Tastatur
fokussierbar, und derselbe Plan ist über die API/MCP-Ziel-Endpunkte mit einem
view-Parameter gleichermaßen erreichbar.
Positionsziele im Plan-Editor (Issue #481, Sprint 15). Jede Kategorie mit
zugeordneten Wertpapieren bietet neben ihrem Namen Positionen (n) an; das
öffnet ihre Wertpapiere als Zeilen derselben Tabelle, jede mit eigenem
Soll %-Feld — dasselbe Formular, ein Plan speichern, eine Live-Σ.
Eine Kategorie öffnet sich von selbst, sobald eine ihrer Positionen ein Ziel
trägt. Trägt eine Position unter einer Kategorie ein Ziel, wird das Feld der
Kategorie zur gestrichelten, schreibgeschützten Anzeige Σ Positionen: Die
Kategorie ist die Summe ihrer Positionen (ADR-0030 §2), und die Σ-Fußzeile
zählt diese Summe an ihrer Stelle. Beim Speichern wird auch das eigene Gewicht
der Kategorie auf diese Summe gesetzt, sodass der Hinweis der Vermögensseite
„Positionsziele und Kategoriegewicht weichen ab“ durch das Speichern hier erledigt
ist. Ein leeres Positionsfeld bedeutet „kein Positionsziel“ — nie null: Wer
das Feld einer gespeicherten Position leert und speichert, löscht dieses Ziel und
gibt die Steuerung an die Kategorie zurück; 0 ist ein Ziel von null und bleibt
erhalten. Das Zuklappen der Positionen einer Kategorie blendet die Zeilen nur
aus; ihre Werte werden weiter gespeichert.
Ein Speichern ist eine Transaktion: Ein abgelehntes Speichern — ein Ziel über 100 %, ein Wertpapier unter einer Kategorie, in der es nicht mehr liegt — ändert nichts, auch nicht die Leerungen. Ein Ziel mit mehr als vier Nachkommastellen in Prozent oder außerhalb von 0–100 % wird mit seiner Zeile vorweg abgelehnt — „Positionsziel von „…“ unter „…“: höchstens vier Nachkommastellen in Prozent“, „Soll von „…“: muss zwischen 0 und 100 % liegen“, „Cash-Ziel: …“ (Issue #945) —, und die Eingaben setzen weder Bereich noch Schrittweite selbst: Es entscheidet der Speicher, nicht der Browser, und auf dem Schirm steht die Ablehnung, die die Zeile nennt. Die Antwort auf ein Speichern steht oben auf der Seite. Bei einer Ablehnung holt die Seite sie ins Bild und setzt den Fokus darauf, und die Eingabe, die sie nennt, ist bis zur nächsten Antwort als ungültig markiert; schließt man die Ablehnung, kehrt der Fokus zu dieser Eingabe zurück. „Plan gespeichert“ erscheint dort, ohne dass die Seite springt. Leert ein Speichern das letzte Positionsziel einer Kategorie und ist für die Kategorie kein Gewicht eingetragen, fällt das Gewicht der Kategorie, das nur der Summe folgte, mit weg: Die Kategorie steht dann ohne Ziel da statt mit einer Zahl, die niemand eingetragen hat. Eine veraltete Positionszeile (ihr Wertpapier wurde inzwischen einer anderen Kategorie zugeordnet) erscheint weiter dort, wo sie abgelegt wurde; unverändert zurückgeschickt bleibt sie, wie sie ist, eine Änderung wird mit dem Grund abgelehnt — leere sie stattdessen dort. Das Übernehmen eines Plans aus einer anderen Ansicht übernimmt auch dessen Positionsziele.
Plan-Versionen: duplizieren, Entwurf, aktivieren
Seit ADR-0027 ist ein Plan eine benannte Version mit Status — aktiv, Entwurf oder archiviert — und je Geltungsbereich gibt es höchstens einen aktiven Plan. So wird eine Strategie umgebaut, ohne den alten Plan zu verlieren:
- Plan duplizieren kopiert den aktuellen Plan (Kategorie- und Positionsgewichte und Cash-Ziel) in einen Entwurf; der Editor wechselt dorthin, und sobald ein Geltungsbereich mehr als eine Version hat, tritt in der Versionszeile des Editors, neben Plan duplizieren, ein Plan-Versions-Selektor an die Stelle des Plannamens.
- Einen Entwurf zu bearbeiten und zu speichern berührt den aktiven Plan nie — die Vermögensseite folgt weiter dem aktiven Plan, und ein Hinweis im Editor sagt das auch. Die Cash-Ziel-Zeile zeigt den aktiven Steuerungswert (er zählt in die Σ-Prüfung), ist aber gesperrt, solange eine Version bearbeitet wird — mit sichtbarem Hinweis: die Cash-Quote bleibt bis zum Wechsel bei der aktiven Steuerung (v1).
- Diesen Plan aktivieren schaltet den Entwurf scharf; der zuvor aktive Plan wird in derselben Transaktion archiviert — alter und neuer Plan bleiben nebeneinander einsehbar.
- Umbenennen benennt die ausgewählte Version um — z. B. um nach der Aktivierung ein „(Entwurf)”-Suffix loszuwerden.
- Plan löschen entfernt bei einem Entwurf oder archivierten Plan nur diese Version samt ihrer Kategorie- und Positionsziele; beim aktiven Plan behält es die ADR-0020-Bedeutung (der Geltungsbereich fällt auf nur IST zurück).
Jede Plan-Änderung wird im Audit-Journal festgehalten.
Migrationshinweis (ADR-0020). Der Wechsel zu Plänen je Ansicht ist verlustfrei: alle bereits vorhandenen Zielgewichte und das frühere portfolioweite Cash-Ziel werden zum Plan ohne Ansicht (
view = null), den die Seiten damals Gesamt nannten. Am Verhalten ändert sich nichts — das bestehende Setup erscheint einfach unter diesem Plan, und die Vermögensseite liest es unter der Ansicht, die damals Total hieß, genau wie zuvor. Benannte Ansichten starten ohne Plan, bis einer angelegt oder kopiert wird. (Seit #1091 heißt dieser Bereich auf jeder Seite Alles.)
Um eine Position aus der Allokations-Steuerbasis herauszuhalten, während sie weiterhin zum Gesamtvermögen zählt — zum Beispiel ein als langfristiger Wertspeicher gehaltener Bitcoin statt Teil des gesteuerten Mix — das Wertpapier mit einem Bucket versehen und diesen Bucket aus der Strategie-Ansicht ausschließen; die Allokation dann unter dieser Ansicht lesen. Die Position fällt dann aus dem Geltungsbereich der Ansicht: sie verschwindet aus den 100 % und der Drift-Tabelle und hebt den Ist-Prozentsatz jeder anderen Kategorie konsistent an, während Gesamtwert, Bestände und Performance (ohne die Ansicht gelesen) unverändert bleiben. (Dies ersetzt den früheren wertpapierbezogenen Schalter „von Allokationszielen ausgeschlossen“; siehe ADR-0013/ADR-0018.)
Klassifizierungsbäume sind hierarchisch, und die Allokation rollt sie auf: eine einer Unterkategorie zugeordnete Position zählt zu dieser Unterkategorie und jeder übergeordneten Kategorie darüber. Hält Growth also ein Ziel von 50 % und sind Bestände nur seinen Unterkategorien zugeordnet (Tech, Emerging, …), ist das Ist-Gewicht von Growth deren Summe — nicht 0 % — und seine Drift wird gegen diese Summe gemessen. Die Drift-Tabelle listet Kategorien in Baumreihenfolge mit unter ihren Eltern eingerückten Unterkategorien; da jede übergeordnete Kategorie ihre Kinder bereits enthält, summieren sich die angezeigten Ist-Prozentsätze nur über die Blätter (plus nicht Zugeordnetes) zu 100 %, nicht über jede Ebene.
Ziele bleiben bewusst locker: ein Gewicht kann auf oberster Ebene und auf Unterebenen gesetzt werden, ohne dass die App sie zur Summe 100 % zwingt. Um diese Freiheit zu bewahren und zugleich Abweichungen sichtbar zu machen, zeigt die Vermögensseite zwei beratende Konsistenzhinweise — schreibgeschützt, ein Speichern nie blockierend:
- Eine dezente Zeile unter jeder übergeordneten Kategorie mit Kind-Zielen lautet subcategories: X% of Y%, wobei X die Summe der direkten Kind-Ziele und Y das eigene Ziel der Elternkategorie ist. Sie wird gelb, wenn X und Y abweichen.
- Der Allokations-Header zeigt Σ target top level: Z% — die Summe der Ziele der obersten Kategorien plus das Cash-Ziel — hervorgehoben, wenn Z nicht 100 % ist.
Gleichheit wird exakt geprüft (auf die gespeicherte Gewichts-Präzision), sodass ein Hinweis nur dann hervorhebt, wenn die Zahlen wirklich abweichen. Die Hinweise sind reine Orientierung; der Speicherpfad der Ziele ist unverändert und lehnt frei gewählte Gewichte nie ab.
Cash ist Teil der Allokation. Ein Portfolio kann ein Cash-Ziel speichern
(cash_target_weight, z. B. 5 %) — den SOLL-Anteil von Cash innerhalb derselben
100 %-Basis wie die Kategorien. Mit gesetztem Cash-Ziel ist die 100 %-Basis der
Allokation Wertpapiere (innerhalb der aktiven Ansicht) + das Cash, das zur
Cash-Quote zählt (die als counts toward the cash quote markierten Konten). Die
Drift-Tabelle zeigt dann eine eigene Cash-Zeile in eigener neutraler Farbe mit
Cash-Ist, -Ziel und -Drift, der Sunburst erhält ein Cash-Segment, und jeder
Kategorie-Prozentsatz schrumpft entsprechend, sobald Cash zur Basis hinzukommt.
Setze das Cash-Ziel im Cash-Feld des Plan-Editors auf der
Klassifizierungsseite (je Ansicht), über die API (PATCH /api/v1/portfolios/:id)
oder MCP (portfolixir.portfolios.set_cash_target), oder lösche es mit null, um
die Steuerung einer Cash-Quote zu beenden.
Währungsallokation: Cash nach Währung. Ist die aktive Klassifizierung der eingebaute Währungs-Baum, wird das Cash jedes Geldkontos seiner eigenen Währungskategorie zugeordnet statt als separate „Cash”-Zeile zu erscheinen: EUR-Cash fließt in die EUR-Kategorie, USD-Cash in USD usw. Fremdwährungs-Salden werden vor der Addition über den EUR-Hub in die Basiswährung umgerechnet, sodass die Prozentsätze in der Portfolio-Basiswährung bleiben. Die Gesamtbasis (Wertpapiere + verfügbares Cash) bleibt unverändert — nur die Zuordnung von Cash zu einer Währungskategorie ändert sich. Die Asset-Klassen-Ansicht ist davon unberührt: sie behält eine eigene Cash-Steuerzeile.
Wechselkurse und Bewertung
Portfolios können Wertpapiere und Cash in mehreren Währungen halten. Wechselkurse werden gegen einen EUR-Hub gespeichert (mit Synchronisierung der Europäischen Zentralbank), und andere Paare werden darüber trianguliert. Die Live-Bewertung des Portfolios rechnet den Marktwert jeder Position und jeden Cash-Saldo in die Basiswährung des Portfolios um.
Die historischen Wechselkurse kommen von selbst (Issue #1120). Die
geplante Synchronisierung holt nur die Kurse des Tages. Ist eine Buchung, ein
Verrechnungskonto oder ein gehaltenes Wertpapier in einer anderen Währung vor
dem frühesten gespeicherten Kurs dieser Währung datiert — typischerweise bei
einer aus Portfolio Performance importierten Historie, auch bei einer von
einem Euro-Konto gekauften Dollar-Aktie —, holt die Instanz die
historische EZB-Reihe von selbst, einmal, im Hintergrund: nach dem Start
(direkt nach den Kursen des Tages) und nach einem Import. Niemand muss etwas
drücken, und der Import wartet nicht darauf. Ist sie gelaufen, wird die
Historie ab ihrem ersten Tag bewertet, und kein erster Kurs landet als
Sprung im Ergebnis. Das geht nicht ohne Netzwerk, nicht bei abgeschalteten
Hintergrund-Downloads (PORTFOLIXIR_BACKGROUND_FETCH=off), nicht für eine
Währung, die die EZB nicht veröffentlicht, und nicht für eine Buchung vor
1999, wo die Reihe der EZB beginnt. Ein solcher Saldo zählt dann bis zum
ersten Kurs seiner Währung null und wird unter der Beitragstabelle genannt
(siehe Beitrag je Position). Für eine Währung, die die EZB nicht
veröffentlicht, und eine Buchung vor 1999 wird einmal geholt; die Instanz
versucht es nicht bei jedem Start erneut. Ohne Netzwerk versucht sie es beim
nächsten Start oder Import wieder. Von Hand holt Historische Kurse
nachladen in den Ausschluss-Hinweisen unter Cashflow oder scope=history
am Wechselkurs-Sync-Endpunkt und MCP-Tool dieselbe Reihe.
Ein Wertpapier ohne jeden Kurs wird mit dem zuletzt eigenen Handelspreis
über alle Portfolios bepreist — ein Kauf oder Verkauf ist eine
Preisbeobachtung, genau so, wie Portfolio Performance Preise aus Buchungen
ableitet — sodass ein frisch importiertes Portfolio nicht mit null bewertet
wird, während Kurse noch geholt werden. Der Fallback ist bewusst global: die
Portfoliosummen und die Wertpapier-Detailansicht lösen Preise mit derselben
Logik auf, sodass die beiden Ansichten nie uneinig sein können, ob ein Preis
existiert. Solche Positionen tragen price_source: "trade" in der API und
werden in trade_priced_count gezählt; die Vermögensseite markiert sie als
Datenqualitäts-Hinweis und die Detailansicht nennt den Handelspreis, mit dem
bewertet wird.
Eine bepreiste Position, deren Kursquelle versiegt ist, ist der leisere
Fall: ihr letzter Schlusskurs bewertet sie weiter, als wäre er von heute.
Jede Position trägt deshalb das Datum, von dem ihr Preis stammt
(price_date in der API), die Bewertung zählt die gehaltenen Positionen,
deren Kurs älter ist als die Datenqualitäts-Schwelle (stale_priced_count),
und der Datenqualitäts-Abschnitt der Vermögensseite nennt sie mit diesem
Datum und dem Mittel: das Wertpapier als eingestellt markieren, wenn
seine Notierung endete, oder seine Kurse synchronisieren — und einmal
eingestellt, verlässt die Position Zählung und Befund, weil ihr alter
Schlusskurs dann erwartet ist. Dieselbe Schwelle markiert den Kurs überall
dort, wo er gelesen wird: ein älterer Kurs zeigt „veraltet · Datum” unter
dem Kurs in der Zeile der Wertpapierliste und im Kopf des Wertpapiers sowie
neben dem Wert in der Positionstabelle der Vermögensseite, in Achtung-Ton
mit Glyphe und Wort, und die Tagesänderung zeigt „—” statt einer aus einem
veralteten Schlusskurs berechneten Änderung. Das
Eingestellt-Kennzeichen ist zugleich das, worauf die Performance-Zahl
reagiert — der veraltete Kurs einer eingestellten Position gilt nicht mehr
als Marktbeobachtung, eine spätere Buchung stellt also die Basis neu fest,
statt die Lücke als Rendite zu melden (ADR-0010, Ergänzung vom 2026-09-15).
Eine Einlieferung oder Auslieferung mit gebuchtem Preis wird im
Performance-Lauf zu diesem Preis bewertet, sodass ein Totalverlust, der zu 0
ausgebucht wurde, als der Verlust erscheint, der er ist.
Eine Position mit weder Kurs noch Handelspreis oder ohne Kurspfad zur
Basiswährung wird als unbewertet gemeldet, sodass ein fehlender Preis oder
Kurs nie still den Gesamtwert oder die Gewichte verzerrt. Die beiden Fälle
werden ehrlich getrennt gemeldet (unvalued_reason in der API): gar kein
Preis (nichts auflösbar — kein Kurs und kein eigener Handel) oder Preis
bekannt, aber kein Wechselkurs gespeichert — der native Preis wird
weiterhin mit seiner Währung angezeigt, und eine Wechselkurs-Synchronisierung
holt die Position in die Summen. Eine Position mit Preis, aber ohne
Wechselkurs zählt in den Basiswährungs-Summen als nicht bewertet. Die
Detailansicht zeigt die passende Statuszeile (“Nicht in den Summen
berücksichtigt — …”), sodass beide Ansichten einen fehlenden Wert gleich
erklären.
Cash und Cash-Quote
Cash ist Teil des Portfolios, kein Nachgedanke. Jedes Portfolio hat ein oder mehrere Geldkonten, und die Live-Bewertung meldet das gesamte Cash, den Gesamtwert inklusive Cash und die Cash-Quote — Cash als Anteil am Gesamtportfolio — Liquidität und trockenes Pulver auf einen Blick, umgerechnet in die Basiswährung des Portfolios.
Das Verrechnungs-Cash eines Depots bleibt von selbst aktuell: Käufe, Verkäufe, Dividenden, Zinsen, Gebühren und Steuern bewegen es, sobald diese Transaktionen erfasst werden, sodass das zum Investieren gehörende Cash keine separate Pflege braucht.
Für externe Konten (ein Girokonto, Sparkonto, ein Geschäftskonto) ist das Ziel
Sichtbarkeit ohne Buchhaltung. Statt jede Buchung zu spiegeln, wird der
Saldo eines Kontos direkt gesetzt — die Zahl, die die Banking-App zeigt,
erfasst als datierter Snapshot (der Dialog Saldo setzen an der
Kontozeile auf Konten & Depots, POST /api/v1/cash_accounts/:id/balance
oder das MCP-Tool cash_accounts.set_balance). Der Saldo verankert sich dann an diesem Betrag, und
nur Buchungen mit einem Datum strikt nach dem Snapshot verändern ihn; so braucht
Geld zwischen eigenen Konten zu verschieben keine Übertragungsbuchung — jeder
Saldo wird nur ab und zu neu angegeben. Der Betrag darf negativ sein (ein
Überziehungskredit), und derselbe Snapshot kann später automatisch über die API
befüllt werden (ein Skript oder ein nur lesender Bankexport) — ohne Portfolixir in
eine Banking-App zu verwandeln. Dies folgt dem in
ADR-0009 festgehaltenen Entwurf.
Jedes Geldkonto trägt eine Liquiditätsrolle (liquidity_role; der Selektor
sitzt neben dem Konto auf der Seite Konten & Depots, und das ⓘ an ihrem
Spaltenkopf — auf dem Telefon, wo der Kopf verborgen ist, steht die
Beschriftung Liquiditätsrolle neben dem Selektor und das ⓘ daneben
(#1085) — sagt in einem Satz, wie jede Rolle zählt). Sie ist einer von drei Werten:
free cash (Standard — echtes verfügbares Cash), credit line (eine
Überziehungs- oder Lombard-Linie, deren negativer Saldo eine Verbindlichkeit ist
und deren ungenutzter Rahmen nie Liquidität ist) oder reserve (ein
sichtbarer, aber ausgeschlossener Topf, z. B. ein Geschäftskonto). Nur
free-cash-Konten mit nicht-negativem Saldo zählen als verfügbares Cash und gehen
in die Cash-Quote ein; eine Kreditlinie zählt nie (auch bei positivem Saldo —
der Typ schlägt das Vorzeichen), und eine Reserve ist immer ausgeschlossen. Jedes
Konto bleibt im gesamten Cash, sodass eine gezogene Kreditlinie das
Nettovermögen korrekt mindert, aber die Quote wird nur über das verfügbare Cash
berechnet und meldet nie Schein-Liquidität. Die Vermögensseite dämpft nicht
verfügbare Zeilen und beschriftet sie mit ihrer Rolle.
Übersichts-Seite
Der Eintrag Übersicht (die Startseite) beantwortet „Hat sich etwas geändert, braucht etwas meine Aufmerksamkeit?” (ADR-0022). Bei leerer Datenbank ist sie der Onboarding-Assistent (der geordnete Workflow-Pfad plus Zähler). Sobald Transaktionen existieren, zeigt sie eine Wert-Karte, eingegrenzt auf die Standard-Ansicht — Alles, wenn keine gesetzt ist (ADR-0024: Ansichten, nicht Portfolios, sind das, worüber die Übersicht aggregiert) — mit dem Gesamtwert inkl. Cash und der TTWROR seit Jahresbeginn als Änderungssignal, auf der Karte in Worten („seit Jahresbeginn“), denn die Karte ist ein Link und hat keinen Platz für ein ⓘ. Die Summe zählt nur, was sich bewerten lässt, und unter der Karte nennt ein Hinweis, was sie auslässt (Issue #1081, UX-DR25): die Verrechnungskonten, deren Währung keinen Wechselkurs zur Basiswährung hat, je mit ihrem Saldo in der eigenen Währung, die gehaltenen Positionen ohne Preis und die gehaltenen Positionen mit Preis, aber ohne Wechselkurs, je mit ihrem Preis in der eigenen Währung, als Kurs bezeichnet („Harborline Freight (Kurs 12,40 USD)“) — „Nicht in der Summe: 2 Verrechnungskonten ohne Wechselkurs zu EUR — USD Settlement (1.850,00 USD), US Broker (60,00 USD) · 1 gehaltene Position ohne Preis — Placeholder Anleihe 2031 3,25%. Details in Vermögen →”. Jede Gruppe nennt höchstens sechs Namen, dann „+N”; ein Konto mit Saldo null lässt nichts aus und wird nicht genannt; der Link öffnet das Vermögen, dessen Datenqualitäts-Abschnitt „Wechselkurse synchronisieren” anbietet. Lässt die Summe nichts aus, gibt es keinen Hinweis. Unter der Karte zeigt die Seite die Kennzahlenleiste (UX-DR2 in der Fassung vom 2026-09-14, Issue #798): vier Zellen, jede verlinkt auf die Oberfläche, der die Zahl gehört — die TTWROR 1J mit ihrem IRR (bei kürzerer Historie die Perioden-MWR) führt zum Vermögen, die Cashquote mit dem Cash-Betrag zum Vermögen, die letzte Buchung mit Datum, Art und Konto oder Wertpapier zu den Transaktionen, und die Kursaktualität, das Datum des neuesten gespeicherten Kurses über die gehaltenen Positionen, zur auf veraltete Kurse vorgefilterten Wertpapierliste; ihre Unterzeile „n veraltet im Katalog” erscheint nur, wenn es veraltete Kurse gibt (sonst das Datum allein — ein Fakt, kein „alles in Ordnung”), und zählt den ganzen Katalog, gehalten oder nicht, also die Liste, die ihr Link öffnet — die Worte „im Katalog” sagen das neben einer Basiszeile über die gehaltenen Positionen —, und eine Basiszeile unter der Leiste nennt Ansicht, Zeitraum und Währung — die Karte Abgeschlossene Trades (UX-DR2 in der Fassung vom 2026-10-01, Issue #984): die fünf zuletzt abgeschlossenen Rundläufe, neueste zuerst, je mit Verkaufsdatum und Haltedauer, dem realisierten Ergebnis in der Basiswährung in seiner Vorzeichenfarbe und darunter der Rendite — pro Jahr („p. a.”) ab 365 Tagen Haltedauer, über die ganze Haltedauer („gesamt”) darunter —, jede Zeile verlinkt auf den Trades-Tab ihres Wertpapiers, und Alle Trades → im Kopf der Karte führt zur Facette Trades. Ihre Basiszeile sagt, dass sie alle Depots unabhängig von der Ansicht abdeckt: der Rest der Übersicht folgt der gewählten Ansicht, die Trades nicht. Sie zeigt Ergebnisse, keine Aktivität, und fehlt, solange kein Trade abgeschlossen ist; ein Verkauf ohne gespeicherten Kurs an seinem Schlussdatum wird auf der Karte genannt, das Nachladen steht unter Alle Trades — eine Liste Ziel-Abweichungen (Issue #718 — die Karte ist nach ihrem Inhalt benannt, gemäß UX-DR21) — jede Kategorie mit Ziel, deren Allokations-Drift ±5 Prozentpunkte überschreitet (ADR-0023-Vorzeichen: positiv = übergewichtet), schlimmste zuerst, jede Zeile mit einem dekorativen Drift-Balken um die Null neben ihrem Text und verlinkt in den Tab „Allokation & Ziele” des Vermögens-Bereichs, unter einer Basiszeile, die Ansicht, Klassifikationsbaum und aktiven Plan nennt, gegen den die Drift gerechnet wird (oder dass mehrere Pläne aktiv sind oder keiner) — und die Datenqualitätszeile: ein Hinweis, der die Wertpapiere im Katalog ohne aktuellen Kurs, Anlageklasse oder Logo, die auf zwei Skalen bepreisten Anleihen und die gehaltenen Wertpapiere, deren Kurse nicht zu ihren eigenen Buchungen passen, aufzählt („25 Wertpapiere im Katalog ohne Kurs seit 7 Tagen · 4 ohne Anlageklasse · eine Anleihe auf zwei Skalen bepreist · 2 gehaltene Wertpapiere, deren Kurse nicht zu ihren Buchungen passen”), wobei jeder Zähler auf die exakt darauf vorgefilterte Wertpapierliste verlinkt — ein Zähler N öffnet eine Liste von N: Die Zähler für veraltete Kurse und fehlende Logos und ihre Listen lassen Benchmarks und stillgelegte Wertpapiere aus, der Zähler für fehlende Anlageklassen und seine Liste lassen stillgelegte Wertpapiere aus und behalten Benchmarks, und der Zähler für zwei Skalen (Issue #1068) umfasst mit Absicht den ganzen Katalog und behält beide, verkaufte Anleihen eingeschlossen, denn die gebuchte Geschichte einer solchen Anleihe — ihre früheren Werte und ihr realisiertes Ergebnis — liegt hundertfach daneben, ob sie gehalten wird oder nicht. Der Zähler der gehaltenen Wertpapiere, deren Kurse nicht zu ihren Buchungen passen (Issue #1101), sagt „gehaltene”, weil die Zeile sonst den Katalog zählt, und behält ein gehaltenes Wertpapier, das stillgelegt oder eine Benchmark ist. Der Befund, der die Zeile eröffnet, trägt das Substantiv („4 Wertpapiere ohne Anlageklasse”). Der Hinweis nimmt die höchste vorhandene Stufe an: Problem, solange eine Anleihe auf zwei Skalen bepreist ist oder die Kurse eines gehaltenen Wertpapiers nicht zu seinen Buchungen passen, Achtung, solange ein Kurs veraltet ist, sonst Hinweis. Die Zeile erscheint nur, wenn mindestens ein Zähler größer als null ist; ein sauberer Katalog zeigt nichts (kein grünes „alles in Ordnung”). Die Daten der Karte Fällig folgen der Oberflächensprache (15.10.2026 auf Deutsch). Es gibt bewusst keinen Aktivitäts-Feed: die forensischen Details gehören dem Audit-Journal, und die Karte Abgeschlossene Trades zeigt, was ein Verkauf realisiert hat, nie die Buchung selbst.
Die Übersicht auf dem synthetischen Demo-Datensatz. Jeder Screenshot in
diesem Handbuch stammt aus diesem Datensatz (priv/demo), nie von einer
echten Instanz.
Vermögens-Seite
Der Eintrag Vermögen in der Navigation öffnet die Vermögensübersicht,
organisiert in Tabs (ADR-0022): Bestände (Wert, Performance, Positionen,
Datenqualität, Cash), Allokation & Ziele (Sunburst und Drift-Tabelle) und Cashflow
(der Bericht über erhaltene Dividenden und Zinsen). Der Bestände-Tab beginnt
mit dem Kennzahlen-Band in zwei Ebenen (Issue #797): drei Leitkennzahlen
in voller Größe — der Gesamtwert inklusive Cash mit seiner Zusammensetzung
aus Wertpapieren und Cash, die TTWROR mit dem absoluten Ergebnis des
Zeitraums und der geldgewichtete IRR mit seiner Basiszeile — über vier
Nebenkennzahlen in halber Höhe: Wertpapierwert, Cashquote mit dem
Cash-Betrag, Anfangswert mit den Nettoflüssen und Vermögens-Multiplikator.
Die Währung steht als kleines Suffix hinter den Ziffern, sodass keine Zahl
umbricht. Die Renditen gelten für einen wählbaren Zeitraum (laufendes Jahr,
ein/drei/fünf Jahre oder seit der ersten Transaktion; ein Jahr ist die
Voreinstellung) mit dem kumulativen Performance-Chart. Der Tab „Allokation &
Ziele” wiederholt das Band nicht: er trägt eine Zeile — Gesamt, Cashquote,
TTWROR — mit Link zurück zu Bestände. Unter den Nebenkennzahlen stehen das
eingesetzte Kapital — immer zwei beschriftete Zahlen, der Wert zum Periodenbeginn und
die externen Nettoflüsse (Einzahlungen minus Entnahmen, Einlieferungen zum
Transaktionswert), nie eine zusammengelegte Zahl — und der
Vermögens-Multiplikator: Endwert ÷ eingesetztes Kapital, das ehrliche
„was aus dem eingezahlten Geld geworden ist”. Bei eingesetztem Kapital von
null oder darunter zeigt der Multiplikator n/a — nie einen negativen
Multiplikator. Für Zeiträume unter einem Jahr trägt die geldgewichtete
Kennzahl das Label MWR und zeigt die Periodenzahl statt einer
annualisierten, die ein kurzes Fenster aufblähen würde (ADR-0034).
Positionen (Issue #814) listet die Bestandsprojektion, die diese Instanz
über die API ausliefert — eine Zeile je Depot und Wertpapier, bewertet zum
zuletzt gespeicherten Kurs, wie die Zeile unter der Überschrift sagt — mit
einer Spalten-Auswahl über die Felder
genau dieser Projektion: neben den Vorgaben Depot, Wertpapier und Stückzahl
ISIN, WKN, Währung, durchschnittlicher Einstand, letzter Preis, Marktwert und
das unrealisierte Ergebnis in Geld und Prozent. Die Zeilen folgen dem
Geltungsbereich der Seite, wie jede Zahl auf ihr (Issue #1124): unter
Alles sind es die Bestände aller Portfolios, unter einer Ansicht die
Positionen, die diese Ansicht hält — eine Position, die die Summen und die
Hinweise zählen, ist hier eine Zeile. Es sind dieselben Felder, die
ein Agent über fields= der Bestands-API auswählt, aus derselben Projektion
gelesen — mit den Trennzeichen Ihrer Sprache und mit der Währung der Zeile
hinter jedem Geldbetrag, damit ein Marktwert seine Währung nennt, auch wenn
die Spalte Währung abgeschaltet ist. Die Auswahl liegt im Browser und
übersteht ein Neuladen; alle Haken zu entfernen fällt auf die Vorgaben
zurück. Die Auswahl steht über der Tabelle und erscheint nur, wenn es eine
Tabelle zu konfigurieren gibt. Auf dem Telefon (unter 560 px) stehen die
Positionen statt der Tabelle als zweizeilige Einträge da: der Name des
Wertpapiers über seinem Depot, rechts die Stückzahl („18 Stück“), sodass
nichts seitlich gewischt werden muss; die Einträge zeigen die Vorgabefelder,
und die Spalten-Auswahl ist dort ausgeblendet, weil sie nichts ändern
würde. Tragen zwei verschiedene Wertpapiere denselben Namen — etwa ein
Duplikat, das auf eine Zusammenführung wartet —, zeigt jede Zeile hinter dem
Namen in kleinerer, gedämpfter Schrift, was sie unterscheidet: die ISIN, wo
beide eine haben und sie sich unterscheiden, sonst ebenso die WKN, sonst die
Nummer des Datensatzes („Nr. 42“). Das gilt in einem Depot wie über zwei
Depots hinweg, denn zwei Depotnamen können gleich aussehen, und die Spalte
Depot lässt sich abschalten. Ein Name, der nur einmal vorkommt, bleibt ohne
Zusatz, ebenso ein Wertpapier, das in zwei Depots liegt.
Neben den festen Buttons verkettet ein Jahres-Dropdown jedes einzelne
Kalenderjahr mit Daten, und ein Von/Bis-Datumsbereich verkettet eine eigene
Spanne — beides sind reine Neuverkettungen der bereits berechneten Reihe,
ehrlich auf die vorhandene Historie begrenzt (ein rückwärts gerichteter Bereich
wird mit kurzem Hinweis abgelehnt).
Auf dem Tab Allokation & Ziele zeigt der Allokations-Sunburst die Klassifizierung als
konzentrische Ringe — der innere Ring sind die obersten Kategorien, jeder äußere
Ring bricht eine Ebene weiter herunter mit in ihren Eltern verschachtelten
Unterkategorie-Bögen, und der äußerste Ring zeigt die einzelnen Positionen als
schattierte Bögen in der Farbe ihrer Kategorie (der Portfolio-Performance-Stil) —
mit einem grauen Segment für nicht zugeordnete Bestände. Kategorien ohne
gewählte Farbe erhalten automatisch unterscheidbare Palettenfarben, sodass
auch ein ungestylter Baum lesbar bleibt. Wie bei PP tragen die
Segmente keinen Text im Chart: die Mitte des Charts trägt den Bezugswert
(die allokierte Summe) oder, beim Überfahren oder Antippen, Name, Wert und
Ist-Anteil gegen Soll des berührten Segments — der Tooltip des
Touch-Geräts — während ein Zeiger zusätzlich einen sofortigen, eigenen
Tooltip erhält, der ihm folgt (keine Browser-Hover-Verzögerung). Die
Legende zeigt zu jedem Anteil seinen Wert, und die Basiszeile des Charts
nennt den Plan, die Σ seiner obersten Soll-Ebene, die Ansicht und den
Stichtag. Die Drift-Tabelle darunter sitzt hinter dem Aufklappen Daten als
Tabelle, das jedes Chart trägt. Mit
deaktiviertem JavaScript fallen die Segmente auf den nativen Browser-Tooltip
zurück. Der Chart skaliert auf die verfügbare Breite. Wähle einen beliebigen
Klassifizierungsbaum aus dem Selektor. Die Drift-Tabelle darunter listet jede
Kategorie in Baumreihenfolge mit eingerückten Unterkategorien unter ihren
Eltern und vergleicht das aufgerollte Ist-Gewicht mit dem gespeicherten Ziel,
wobei die Drift in der Basiswährung neu ausgewiesen wird. Der Baum startet eingeklappt auf der obersten Ebene; jede Zeile mit Kindern
trägt einen Aufklapp-Pfeil (▸) — die ganze Namenszelle ist klickbar —, der
ihre direkten Kinder zeigt — Unterkategorien wie Positionen (auch der graue
Eimer Nicht zugeordnet klappt so in seine Wertpapiere auf) —, und ein
einzelner Umschalter Alles aus-/einklappen über der Tabelle öffnet oder
faltet den ganzen Baum bis zur Einzelposition. Daneben stehen die
Abweichungs-Chips — Abweichung ab ≥ 1 pp / ≥ 2 pp / ≥ 5 pp: Ein Klick
verengt die Tabelle auf die Kategorien, die tatsächlich um mindestens so viel
abweichen — in beide Richtungen —, ein erneuter Klick auf den aktiven Chip hebt
die Auswahl wieder auf. Drei Dinge sind wissenswert. Die Stufe 5 pp ist
dieselbe Schwelle, die die Aufmerksamkeitsliste des Dashboards verwendet;
Warnungen und Tabelle sind sich also einig, was Aufmerksamkeit braucht. Eine
gefilterte Tabelle ist flach — eine erhaltene Kategorie erscheint auch
dann, wenn ihr Elternteil unter der Schwelle liegt und damit fehlt — und sie
behält immer die Zeilen Cash und Nicht zugeordnet; die Zeile über der
Tabelle sagt das zusammen mit „wie viele von wie vielen Kategorien” an.
Schließlich steht die Schwelle in der URL (?drift=5), ein gemerkter oder
geteilter Link öffnet also wieder dieselbe gefilterte Ansicht; es ist derselbe
Filter, den API und MCP als min_drift= anbieten (dort ein Gewichtsanteil:
5 pp sind min_drift=0.05).
Worauf sich die Prozentpunkte beziehen, ist wichtig, wenn ein Plan bewusst
nicht auf 100 % summiert: Die Chips nutzen dieselbe Drift wie die
Drift-Spalte und die Aufmerksamkeitsliste des Dashboards — und die wird nach
ADR-0040 gegen den auf den zugeordneten Anteil normierten Plan gemessen, nicht
gegen die rohe Soll-Spalte. Bei einem Plan mit 83 % Summe ist eine Kategorie
mit 21,2 % Ist gegen 55 % gespeichertes Soll also 45 pp entfernt, nicht 34 —
und Chips, Drift-Spalte, Dashboard und min_drift= sind sich über diese Zahl
einig. Die Grundlagenzeile sagt das dort, wo die Zahl gelesen wird: Hinter der
Σ der obersten Ebene steht „— Abweichung gegen den verteilten Anteil”,
sobald der Plan weniger als 100 % verteilt, und die Σ steht nur dann in der
Warnfarbe, wenn der Plan mehr als 100 % verteilt — ein Plan mit bewusstem
Rest ist kein Fehler (Issue #875). Das ⓘ der Drift-Spalte sagt es ebenfalls und
rechnet eine Zahl vor: In einem Plan, der 80 % verteilt, zählen 40 % Soll als
50 % (Issue #911). Ein Umschalter Baum |
Positionen — ein Segment-Schalter, dessen aktive Option gefüllt ist —
tauscht die Hierarchie gegen eine flache Rebalancing-Arbeitsliste:
eine Zeile je Wertpapier (inkl. Cash) mit der Kategorie als Kontext,
standardmäßig nach vorzeichenbehafteter Drift sortiert (stärkstes Übergewicht
zuerst, stärkstes Untergewicht zuletzt) und über die Spaltenköpfe (Wert, Drift
oder Kategorie) umsortierbar. Unter der Drift jeder Zeile steht ihr
Rebalancing-Hinweis, in einer Zelle, die am rechten Rand der Tabelle angeheftet
bleibt, wenn die Liste auf einem schmalen Bildschirm seitlich scrollt (Issue
#911). Die Kategorie der Cash-Zeile lautet „—”: Cash hat
ein eigenes Soll und ist nie „Nicht zugeordnet”. Eine Kategorie mit direkt zugeordneten Wertpapieren klappt in
ihre Wertpapiere auf — jedes mit Wert, Gewicht, seinem Anteil an der
Kategorie-Drift und einem reinen Anzeige-Rebalancing-Hinweis: die indikative
Stückzahl, die zum Bewertungskurs zu verkaufen (positive Drift) oder zu kaufen
(negative) wäre, um die Lücke zu schließen (ADR-0023). Ein Hinweis, der auf
zwei Stellen gerundet null Stück ergibt, wird nicht gezeigt; die Drift
bleibt. Der Hinweis modelliert
keine Gebühren oder Steuern, und hinter ihm steht bewusst kein Order-Knopf —
das Handeln bleibt vollständig manuell.
Positions-Ziele erscheinen im Plan (ADR-0030 Schritt 2a). Trägt der aktive Plan Soll-Gewichte je Position, zeigt jede solche Positions-Zeile ihr eigenes Ziel und ihre eigene Drift (Ist-Gewicht minus ihr Ziel) — und eine Position mit gesetztem Soll, aber noch ohne Bestand, erscheint trotzdem: mit IST 0, dem Marker ohne Bestand (in einer benannten Ansicht ohne Bestand in dieser Ansicht, denn die Ansicht sagt nichts über das ganze Depot), der vollen Untergewichts-Drift und einem Kauf-Hinweis zum letzten gespeicherten Kurs — der Tooltip des Hinweises nennt das Kursdatum, zu dem er gepreist ist. Ganz ohne Kurs erklärt ein Chip kein Kurs den fehlenden Stück-Hinweis (Kurs hinterlegen, um einen zu bekommen). „Im Bestand” heißt: die Position wird überhaupt gehalten — ein gehaltenes Wertpapier, dessen Preis sich nicht ermitteln lässt, behält seine Datenqualitäts-Hinweise und wird nie als ohne Bestand umetikettiert. Ausgeblendet wird eine Positions-Zeile nur, wenn ihr Soll 0 oder nicht gesetzt ist und ihr Bestand null ist. Die Ziel-Spalte der Kategorie zeigt dann das effektive Ziel — die Summe ihrer Positions-Ziele (Positionen sind die Quelle der Wahrheit); weicht das gespeicherte Kategorien-Gewicht ab oder ist ein Positions-Ziel veraltet (sein Wertpapier wurde verschoben oder die Zuordnung entfernt), nennt eine Datennotiz über der Tabelle den Befund und die betroffenen Kategorien (Issue #719 — Befunde erscheinen als Notizen, nie als Pillen in Datenzellen; ein Konflikt mit Schweregrad Problem, ein veraltetes Ziel mit Achtung), und die betroffene Positions-Zeile selbst trägt einen Chip veraltetes Soll. Ein gehaltenes, aber nicht zugeordnetes Wertpapier mit einem (veralteten) Positions-Ziel zeigt dieses Ziel auch an seiner Zeile im Bereich Nicht zugeordnet. Trägt keine Top-Level-Kategorie ein Ziel, wohl aber tiefere Kategorien, ergänzt die Σ-Kopfzeile die Summe der tieferen Ziele („Ziele tiefer im Baum”) statt ein nacktes 0 % zu zeigen. Der Cash-Abschnitt listet den Saldo jedes Kontos nur lesend und verlinkt auf Konten & Depots: dort zeigt jede Geldkonto-Zeile ihren Saldo mit dem Datum seiner letzten Buchung (letzte Buchung 31.03.2026: der Saldo ist der heutige, das Datum sagt, wann eine Buchung ihn zuletzt bewegt hat, #1085) und öffnet einen kleinen Dialog Saldo setzen, in dem das Konto bereits gewählt ist — den Saldo eingeben, den die Bank zeigt, und der Snapshot wird ohne Buchung einzelner Transaktionen erfasst.
Die Seite ist auf eine Ansicht eingegrenzt (ADR-0024). Die Kopf-Summen und
der Cash-Abschnitt folgen der aktiven Ansicht über alle Portfolios hinweg —
Alles (englisch Everything) ist die eingebaute Voreinstellung und zeigt
jede Position, jedes Konto genau einmal gezählt. Wähle eine Ansicht im
Sicht-Umschalter oben auf der Seite — sein Link Ansichten (Issue
#720: umbenannt von „Verwalten…”, die Auslassungspunkte entfallen, weil er
navigiert statt einen Dialog zu öffnen) öffnet die
Ansichten-Seite, auf der Ansichten und ihre Buckets bearbeitet werden. Diese
Seite liest sich listenorientiert: jede Ansichten-Zeile sagt, was sie tut
(ihre Ein-/Ausschluss-Buckets als Chips) und was sie umfasst (Summe,
Positionen und Konten im Geltungsbereich), die eingebaute Zeile Alles
ist als Standard markiert; jede Bucket-Zeile trägt ihre Farbe und ihre
Verwendung (die Konten, auf denen sie Standard ist, die erbenden
Positionen, die direkt getaggten Positionen). Zeilenaktionen sitzen im
Zeilenmenü, die Anlegen-Formulare öffnen sich über +, die Zwei-Schritte-
Erklärung ist das ⓘ an jeder Überschrift, und Standard-Buckets werden an der
Kontozeile von Konten & Depots gesetzt, auf die die Basiszeile des
Bucket-Abschnitts verlinkt.
Als Standard festlegen merkt sich
die Wahl serverseitig, sodass Vermögensseite und Übersicht mit dieser Ansicht
öffnen, solange keine andere ausdrücklich gewählt ist (eine ausdrückliche
Wahl — auch von „Alles” — gewinnt immer). Eine Ansicht, eine Benchmark oder
eine Sprache, die mit einem Link von einer anderen Website kommt, gilt für die
Seite, die dieser Link öffnet, und wird nicht gemerkt (E25): Nur eine Wahl auf
der Instanz selbst oder eine in die Adresszeile getippte ändert, was die
nächste Seite zeigt. Die eigenen Links dieser Seite (Sprachwechsel, Reiter)
geben die fremde Ansicht nicht weiter, und eine Anmeldung dazwischen entfernt
Ansicht, Benchmark und Sprache aus der Adresse, zu der sie zurückführt. Teilen sich die Buckets der aktiven
Ansicht ein Konto, erinnert ein Badge neben der Summe — Überlappende Buckets –
Konten nur einmal gezählt — daran, dass sich Werte je Bucket überschneiden und
nicht summiert werden dürfen; die Summe selbst ist bereits dedupliziert.
Ansicht-bezogene Performance-Reihen tragen das Label Zusammensetzung per
heute: die aktuelle Bucket-Zuordnung der Ansicht gilt rückwirkend für die
gesamte Historie, und Bucket-Änderungen stehen im Audit-Journal. Nach der
einmaligen ADR-0024-Migration, die aus jedem Portfolio einen Bucket und eine
gleichnamige Ansicht gemacht hat, zeigt die Seite einen schließbaren
Hinweis mit den angelegten Ansichten; das Schließen wird gemerkt. (Leere
Datenbank migriert und Daten erst danach eingespielt? Einmal
mix portfolixir.seed_scope_buckets ausführen, um die fehlenden
Bucket/Ansicht-Paare anzulegen — der Befehl ist idempotent.) Die
Standard-Ansicht ist auch über die API (GET/PUT
/api/v1/settings/default_view) und die MCP-Tools
portfolixir.settings.get_default_view / set_default_view les- und setzbar.
Durchgearbeitete Klick-für-Klick-Setups (Haushalts-Aufteilung,
Strategie-Ansichten, PP-Migrationsgewohnheiten) stehen im Leitfaden
Buckets & Ansichten.
Die SOLL-Seite folgt der aktiven Sicht (ADR-0020). Die Spalten Ziel, Drift und Σ target top level der Drift-Tabelle spiegeln den Plan der aktiven Sicht für die gewählte Klassifizierung wider — IST und SOLL bewegen sich immer zusammen. Beim Wechsel des Sicht-Umschalters oben auf der Seite springen beide Seiten gleichzeitig auf den Plan dieser Sicht, sodass nie zwei Pläne zu einer Σ über 100 % oder einer Geisterzeile vermischt werden. Die eingebaute Ansicht Alles (früher Total) liest den portfolioweiten Plan ohne Ansicht. Ein dezenter Punkt auf einem Sicht-Chip markiert die Sichten, die bereits einen Plan für die aktuelle Klassifizierung tragen, sodass gesteuerte und reine IST-Sichten auf einen Blick unterscheidbar sind.
Kein Plan für die aktive Ansicht? Hat die aktive Ansicht keinen Plan für die
gewählte Klassifizierung, bleibt die Allokation nur IST: Sunburst und die
Spalten Wert/Ist zeigen weiter die tatsächliche Aufteilung, aber es gibt keine
Spalten Ziel, Drift oder Σ. An ihrer Stelle erklärt ein Hinweis — Kein Soll-Plan
für diese Ansicht — die leere SOLL-Seite und verlinkt direkt in den
Klassifizierungs-Plan-Editor, mit dieser Ansicht und Klassifizierung bereits
vorausgewählt (/classifications/<id>?view=<Ansicht>, der eigene Parameter
des Ansichten-Umschalters), sodass sich der Plan anlegen lässt, ohne beides
erneut zu wählen.
Auch das Ziel der Cash-Zeile stammt aus dem Cash-Ziel des Plans der aktiven Ansicht
(oder zeigt einen Strich, wenn keines gesetzt ist).
Die Seite zeichnet sich sofort und berechnet ihre Zahlen asynchron; jeder
Abschnitt füllt sich, sobald seine Daten bereit sind. Der teure tägliche
Performance-Lauf läuft einmal und wird auf der Seite zwischengespeichert — ein
Zeitraumwechsel verkettet die zwischengespeicherte Reihe neu, sodass die
Zeitraumauswahl sofort reagiert. Die Zeitraum-Tokens (YTD, 1J, 3J, 5J, Max)
und der %/Wert-Umschalter sind segmentierte Controls; ein Von/Bis-Zeitraum
(ISO-Daten, YYYY-MM-DD) und die durchlaufenen Kalenderjahre liegen hinter
dem Bedienelement Benutzerdefinierter Zeitraum … daneben. Es öffnet ein
kleines Popover am Bedienelement selbst (Issue #801): das Von/Bis-Paar in
einer Zeile, je ein Chip pro Jahr mit Daten, Abbrechen und Anwenden
— die Abschnittsüberschrift und der Chart bleiben, wo sie sind. Ein
Jahres-Chip wendet beim Klick an; Esc oder Abbrechen schließt das Popover und
gibt den Fokus an das Bedienelement zurück. Das Von/Bis-Paar ist beschriftet
und validiert als Zeitraum (Issue #721): eine verdrehte oder unlesbare
Eingabe wird mit der Meldung am korrigierbaren Feld abgelehnt, und das
Popover bleibt offen, bis sie korrigiert ist; ein angewendeter Zeitraum oder
ein Jahr schließt es und zeigt sich als aktiver Chip mit den aufgelösten
Daten (oder dem Jahr) in der Zeitraumauswahl — das Bedienelement beantwortet
immer „was sehe ich gerade”. Der Custom-Zeitraum des Wertpapier-Detailcharts
verhält sich genauso. Der Chart wird auf
eine begrenzte Punktzahl
heruntergerechnet, sodass ein Jahrzehnt täglicher Historie im Browser leicht
bleibt. Die Aufklappung Daten als Tabelle unter dem Chart enthält
zusammenfassende Zeilen — eine je Jahr, bei Zeiträumen bis zu einem Jahr je
Monat — mit Start- und Endwert, der TTWROR des Abschnitts und seinen
externen Nettoflüssen, statt eines täglichen Dumps. Geld und Prozente folgen der gewählten Sprache (Deutsch 1.234.567,89,
Englisch 1,234,567.89; Geld immer mit zwei Nachkommastellen).
Ein Datenqualitäts-Panel erscheint über dem Chart, wenn etwas die Zahlen sonst still verzerren würde: Positionen, die mit ihrem letzten Handelspreis bewertet werden, weil noch kein Kurs existiert, Positionen ganz ohne Preis (aus den Summen ausgenommen, namentlich gelistet), Positionen mit bekanntem Preis, aber ohne Wechselkurs zur Basiswährung (aus den Summen ausgenommen; mit ihrem nativen Preis gelistet, damit sichtbar ist, was eine Kurssynchronisierung einbringen würde), Wertpapiere mit negativer abgeleiteter Bestandsmenge — für einen echten Bestand unmöglich, meist Import-Altlasten aus einer nicht modellierten Kapitalmaßnahme — je Depot gelistet mit der Gesamtmenge des Wertpapiers über alle Depots und verlinkt auf die Transaktionen des Wertpapiers, damit sich die Historie reparieren lässt (nichts wird automatisch repariert; der Split-Assistent bleibt die einzige geführte Reparatur), Buchungen mit unplausiblen Daten (vor 1970), die stattdessen am ersten plausiblen Tag angewendet wurden, sowie Anleihen, die auf zwei Skalen bepreist sind — Kurse um 100 neben gebuchten Stückpreisen um 1, sodass sie hundertfach zu hoch zählen, jede verlinkt auf ihre Transaktionen; und in einem eigenen Hinweis Kurse um 1 neben gebuchten Stückpreisen um 100, sodass sie hundertfach zu niedrig zählen, jede verlinkt auf ihre Kurse (siehe Anleihen unter Wertpapiere); und Positionen, deren Kurse nicht zu ihren eigenen Buchungen passen — der Kurs am Tag einer Buchung unter der Hälfte oder über dem Doppelten ihres Preises je Stück —, jede mit dieser Buchung und dem Kurs ihres Tages genannt, „Wrenfield Gardens AG (Kauf 12.05.2026 zu 48,2 EUR · Kurs 12.05.2026: 4,87 EUR, das 0,10-Fache)“, und auf ihre Kurse verlinkt (siehe Ein Kurs, der nicht zu den Buchungen passt unter Kurse und Charts). Eine dort ohne Anlageklasse genannte Anleihe — durch ihre Fälligkeit oder ihren Kupon unter den Wächter gekommen — ist mit ohne Anlageklasse markiert. Jeder Befund ist eine Notiz in seiner eigenen Stufe — Hinweis für den Handelspreis-Rückfall, Achtung für ausgenommene und veraltete Positionen, Problem für negative Bestände, für zwei Skalen und für Kurse, die nicht zu ihren Buchungen passen — und trägt sein Mittel in der Notiz: das Bedienelement Wechselkurse synchronisieren steht im Befund zum fehlenden Wechselkurs, und ein Verrechnungskonto, das mangels Kurs ausgenommen ist, wird mit seinem Saldo in der eigenen Währung genannt — „USD Settlement (1.850,00 USD)“ — und ist auch in der Cash-Tabelle mit kein Wechselkurs markiert. Positionen mit negativer Menge sind zusätzlich überall dort mit einem Chip „negative Menge” markiert, wo sie auftauchen: in der Allokationstabelle, im Klassifikationsbaum und im Bestände-Tab des Wertpapiers.
Performance (TTWROR)
Portfolixir meldet die echte zeitgewichtete Rendite so, wie es Portfolio Performance tut: das Portfolio wird ab der ersten Transaktion jeden Tag bewertet, ein- oder ausgezahltes Geld (Einzahlungen, Entnahmen, Lieferungen und Saldo-Snapshot-Sprünge), wird neutralisiert, und die täglichen Renditen werden verkettet. Das Ergebnis misst, wie gut die Investitionen abgeschnitten haben, unabhängig davon, wann Geld bewegt wurde — Dividenden, Zinsen, Gebühren und Steuern zählen als Teil der Rendite.
Positionen ohne Kurshistorie werden mit ihrem eigenen letzten Handelspreis bewertet (derselbe Rückfall, den die Datenqualitäts-Karte auflistet). Eine solche Position liegt zwischen zwei Trades flach, und an dem Tag, an dem ein neuer Trade einen anderen Preis setzt, würde die gesamte bereits gehaltene Stückzahl in einem Schritt neu bewertet. Dieser Schritt ist ein Wechsel der Bewertungsbasis, keine Marktbewegung, und wird deshalb genauso neutralisiert wie eine Einzahlung — sonst verketten sich diese Sprünge zu einem Prozentsatz, den kein Markt je hergegeben hat. Was weiter zählt: der Verkauf. Ein Verkauf macht die Position zu echtem Geld, deshalb bleibt sein Gewinn gegenüber dem Preis, zu dem die Position geführt wurde, in der Rendite und wird nie verschluckt. Alles andere, was der Tag neu bewertet — die weiter gehaltene, die gekaufte, die ausgelieferte Stückzahl — ist Basis. Das gilt für eine Position ganz ohne Kurs. Sobald ein Kurs vorliegt, ist die Position gemessen: spätere Lücken in der Kursreihe sind nur Lücken, und die Trades darin zählen wieder als Rendite. Der erste Kurs zu einer bis dahin kurslosen Position ist selbst ein Basis-Schritt und kein Tagessprung — sonst meldete eine Kurshistorie, die nur die jüngste Zeit abdeckt, den über Jahre aufgelaufenen Versatz als Rendite eines einzigen Tages. Wert, Netto-Zahlungsströme und der €-Gewinn neben dem Prozentwert bleiben unberührt — sie melden das Geld weiterhin so, wie es gebucht wurde. Ein rein handelspreisbewertetes Portfolio kann daher einen deutlichen €-Gewinn neben einer TTWROR nahe null zeigen.
Daneben zeigt Portfolixir die geldgewichtete Rendite (IRR) — die einzelne
annualisierte Rate, die die datierten Einzahlungen, Auszahlungen und den Endwert
des Zeitraums auf null abzinst, die Zahl, die Portfolio Performance neben TTWROR
zeigt. Wo TTWROR das Timing der Geldflüsse ignoriert, spiegelt der IRR es wider,
sodass die beiden unterschiedlich ausfallen, wenn Geld zu guten oder schlechten
Zeitpunkten bewegt wurde. Der IRR zeigt —, wenn es keine Rate zu berechnen gibt
(keine Flüsse beider Vorzeichen oder der Solver konvergiert nicht).
Weil eine Max-Zeitraum-TTWROR in den Tausenden kein Vermögens-Multiplikator
ist (sie sagt, was aus einer Einheit vom ersten Tag geworden wäre, nicht, was
das tatsächliche Geld getan hat), trägt dieselbe Auswertung auch die
geldgewichteten Begleiter
(ADR-0034): das eingesetzte
Kapital (Wert zum Periodenbeginn plus externe Nettoflüsse), den
Vermögens-Multiplikator (Endwert ÷ eingesetztes Kapital; n/a bei
eingesetztem Kapital von null oder darunter — nie ein negativer
Multiplikator) und die Perioden-MWR, die nicht annualisierte Form des
IRR, die kurze Fenster anzeigen. Genau vier Buchungsarten zählen als externe
Flüsse — Einzahlung, Entnahme, Ein- und Auslieferung (zum vollen
Transaktionswert) — plus der Sprung einer Saldo-Anpassung; alles andere
(Dividenden, Zinsen, Gebühren, Steuern, Käufe/Verkäufe, interne
Überträge) ist Performance, kein Fluss. Fremdwährungsflüsse werden zum
gespeicherten Kurs des Flussdatums über den EUR-Hub umgerechnet; das
Ergebnis ist die Rendite des EUR-Anlegers inklusive Währungseffekt. Die
API-Antwort und beide Performance-MCP-Tools liefern invested_capital,
wealth_multiple und mwr als Decimal-Strings neben ttwror und irr.
Die Performance wird auf der Vermögensseite gezeigt und ist je Zeitraum
verfügbar — laufendes Jahr, ein, drei oder fünf Jahre, seit der ersten
Transaktion, ein einzelnes Kalenderjahr (year=YYYY) oder ein eigener
from/to-Datumsbereich — über die API
(GET /api/v1/portfolios/:id/performance) und das
MCP-Tool portfolixir.portfolios.performance, optional mit der vollständigen
täglichen Bewertungsreihe zum Charting. Die Methode und ihre Abwägungen sind in
ADR-0010 festgehalten.
Während eine Kurve neu berechnet wird
Die tägliche Performance-Kurve wird zwischen Seitenaufrufen gemerkt und bei Datenänderungen (Buchung, Kurs, Wechselkurs) neu berechnet. Während die Neuberechnung läuft, zeigt die Seite die zuletzt berechnete Kurve statt einer Ladeanzeige — immer beschriftet mit dem, was sie enthält: wie viele Buchungen, bis zu welchem Datum, wann berechnet, mit welchem Stand. Die Beschriftung ist der Vertrag: eine überholte Zahl erscheint nie ohne sie, der Wechsel zur frischen Kurve passiert in einem Schritt, und schlägt die Neuberechnung fehl, wird die Beschriftung zum Fehler statt die alte Zahl stehen zu lassen. Die Vermögens-Kachel der Übersicht zeigt ihre zuletzt bekannte Zahl „seit Jahresbeginn“ auf dieselbe Weise. (ADR-0032.)
Benchmark-Vergleich
(ADR-0046, FR-9) — war der
Aufwand das wert? Unter Benchmark… im Performance-Abschnitt lassen
sich bis zu zwei Benchmarks wählen: ein auf der Wertpapierseite als
Benchmark markiertes Wertpapier (ein Index über einen ETF, Gold über einen
ETC, per gewöhnlichem Kurs-Sync) oder ein fester Jahreszins als Prozentwert
(die Tagesgeld-Alternative; in dieser Version auch die Ausdrucksform der
Inflation). Die Wahl steht in der URL und wird wie die aktive View gemerkt;
ein Zins wird nur behalten, wenn der Vergleich ihn exakt verwenden kann
(zwischen −99,9999 % und 1000 % p. a., als Bruch mit höchstens 15
Nachkommastellen), und ein gemerkter Zins, der das nicht mehr erfüllt,
fällt beim nächsten Aufruf weg. Zwei Vergleiche erscheinen, beide so, wie Portfolio Performance sie zeigt.
Einmal gekauft — die auf den Periodenbeginn rebasierte Benchmark als
gestrichelte Linie über dem TTWROR-Chart, mit eigener Legende und im
Chart-Tooltip — beantwortet, ob die Auswahl den Index geschlagen hat.
Sparplan — Eröffnungswert des Zeitraums und jede Einzahlung oder Entnahme
am selben Tag zum Kurs jenes Tages in die Benchmark investiert, ohne Gebühren
und Steuern — ergibt einen Endwert; der Vergleichsblock neben TTWROR/IRR
zeigt den realen Endwert minus diesem Wert als Kennzahl, daneben das
Einmal-gekauft-Paar und die beiden IRRs auf identischen Flüssen. Ein Fluss
vor dem ersten Kurs der Benchmark bleibt außen vor, und der Block nennt das
abgedeckte Fenster. Das synthetische Portfolio ist reibungsfrei, was den
Vergleich gegen das reale Portfolio verzerrt — die konservative Richtung.
Nichts wird gespeichert: beide Vergleiche werden beim Lesen abgeleitet, je
Zeitraum und je View, und stehen über die API (…/performance/benchmark)
und die MCP-Tools portfolixir.portfolios.benchmark und
portfolixir.views.benchmark bereit.
Beitrag je Position
Direkt unter dem Performance-Diagramm unter Vermögen → Bestände beantwortet eine Tabelle, welche Position wie viel zum Ergebnis des Zeitraums beigetragen hat (ADR-0051, FR-41). Sie folgt der Zeitraum-Steuerung des Abschnitts und der Ansicht der Seite, wie das Abzeichen darüber. Je Position, in der Basiswährung und einschließlich der Währungsbewegung, gilt: Beitrag = Endwert − Anfangswert − Zu-/Abflüsse + Erträge − Kosten. Das ist der Wert am Ende des Zeitraums, abzüglich des Werts zum Schluss des Vortags, abzüglich der Käufe und zuzüglich der Verkäufe (jeweils zum Kurs des Buchungstags), zuzüglich der gutgeschriebenen Dividenden und abzüglich der Gebühren und Steuern der eigenen Käufe und Verkäufe der Position. Bei einem währungsübergreifenden Handel zählen Gebühren und Steuern in der Währung seines Verrechnungskontos, in der der Broker sie berechnet. Jede Zeile zeigt diese fünf Zahlen neben dem Beitrag, sodass sich jede Zahl von Hand nachprüfen lässt. Die Zeilen sind nach Beitrag sortiert, der größte zuerst, und ein Balken unter jeder Zahl zeigt ihre Größe im Vergleich zur größten. Auch eine Position, die nur einen Teil des Zeitraums im Bestand war, hat ihre Zeile, mit einem Vermerk unter ihrem Namen: „zu Beginn nicht im Bestand“, wenn sie im Zeitraum gekauft wurde, „am Ende nicht mehr im Bestand“, wenn sie im Zeitraum verkauft wurde, und „weder zu Beginn noch am Ende im Bestand“, wenn sie im Zeitraum gekauft und verkauft wurde.
Was keiner Position gehört, steht getrennt unter „Keiner Position zugeordnet“: Zinsen, einzelne Gebühren und Steuern sowie der Währungseffekt auf Bargeld (die Neubewertung von Fremdwährungskonten und die Abrechnungsdifferenzen von Käufen und Verkäufen). Jeder Posten wird aus seinen eigenen Buchungen summiert, und keiner ist ein Ausgleichsbetrag. Die Positionen und diese drei Posten ergeben zusammen genau das Geldergebnis des Zeitraums: die Summenzeile ist genau der Betrag im Abzeichen („+x EUR im Zeitraum“) neben der TTWROR. Einzahlungen und Entnahmen sind kein Ergebnis und stehen deshalb nirgends.
Bei mehr als zehn Positionen zeigt die Tabelle die zehn mit dem größten Betrag (nach Absolutwert) und Alle N anzeigen; die Summenzeile umfasst immer alle Positionen. Eine Position, die an einigen Tagen des Zeitraums null gezählt wurde, weil kein Kurs oder kein Wechselkurs gespeichert war, behält ihren Platz in der Tabelle und in der Summe, trägt die Zahl dieser Tage in ihrer Zeile und wird in einem Hinweis unter der Tabelle genannt. Ein Zeitraum ohne Inhalt zeigt einen Satz statt einer Tabelle voller Nullen, und auf dem Telefon wird die Tabelle zu zweizeiligen Einträgen. Dort nennt ein Eintrag die Richtung seines Flusses — „Zufluss in die Position 2.000,00“, „Abfluss aus der Position 1.420,00“ —, denn der Fluss gehört der Position: Geld, das ein Kauf in sie hineinträgt oder ein Verkauf aus ihr herausholt, nicht Geld, das das Portfolio verlässt. Zwei verschiedene Wertpapiere mit demselben Namen zeigen hinter dem Namen, was sie unterscheidet, in der Tabelle wie in den Einträgen auf dem Telefon: die ISIN, wo beide eine haben und sie sich unterscheiden, sonst ebenso die WKN, sonst die Nummer des Datensatzes („Nr. 42“), wie in der Positionstabelle. Die Tabelle hat eine Zeile je Wertpapier, gleich in welchem Depot es liegt, deshalb werden solche Wertpapiere hier auch dann unterschieden, wenn sie in verschiedenen Depots liegen; und die Prüfung umfasst alle Positionen, auch die hinter Alle N anzeigen.
Auch ein Verrechnungskonto in einer Fremdwährung zählt an jedem Tag null, an dem es Geld hält, während für seine Währung noch kein Wechselkurs zur Basiswährung gespeichert ist. Am Tag des ersten Wechselkurses kommt sein ganzer Saldo auf einmal ins Ergebnis des Zeitraums und in den Währungseffekt auf Bargeld: Geld, das sichtbar wurde, kein Währungsgewinn (bei einem überzogenen Konto kein Währungsverlust). Der Hinweis unter der Tabelle nennt ein solches Konto wie eine Position — mit seinem Saldo in der eigenen Währung, den Tagen, an denen es null zählte (der Tag vor dem Zeitraum, dessen Schluss der Anfangswert ist, eingeschlossen), und dem Grund — und sagt, wenn der erste Wechselkurs im Zeitraum kam, während das Konto noch Geld hielt, an welchem Tag der Saldo in den Währungseffekt kam; diese Zeile trägt den Vermerk des Kontos („Tagesgeld CHF: 18 Tage null“). Ein Konto, das am letzten Tag des Zeitraums noch keinen Wechselkurs hat, „zählt bis zum Ende des Zeitraums null“. Bei einem Zeitraum, der nach dem Tag des ersten Wechselkurses beginnt, verschwindet das Konto wie der Sprung aus Tabelle und Hinweis. Weil die historischen Wechselkurse von selbst kommen (siehe Wechselkurse und Bewertung), bleibt ein solches Konto nur, wo sie es nicht konnten: bei einer Währung, die die EZB nicht veröffentlicht, bei Geld vor 1999 oder auf einer Instanz, die sie noch nicht geholt hat (kein Netzwerk, Hintergrund-Downloads abgeschaltet).
Beitrag je Position auf dem synthetischen Demo-Datensatz.
Cashflow
Der Bereich Cashflow (/cashflow) ist der Ort, an dem Geldbewegungen
rückblickend gelesen werden. Er ist ein Bereich und keine einzelne
„Erträge”-Seite, weil drei der hier gehörenden Auswertungen gar keine Erträge
sind — realisierte Gewinne aus Verkäufen, Ein- und Auszahlungen sowie Kosten —
und sie unter ein Label zu stellen genau die Mehrdeutigkeit reproduziert, die
diese Anwendung vermeiden soll. Jede Auswertung ist ein eigener benannter
Bereich, und ein Bereich erscheint erst, wenn seine Daten existieren; nichts
wird als leere Hülle gezeigt. Income ist der Standard-Bereich, und
/income funktioniert weiterhin — die Adresse leitet hierher weiter, sodass
ältere Links und Lesezeichen erhalten bleiben. Seit Issue #724 trägt der
Bereich einen zweistufigen Facetten-Umschalter.
Trades (/cashflow?tab=realized, Issues #724, #807 und #984)
beantwortet „was hat Verkaufen tatsächlich gebracht — und hat sich der Trade
gelohnt”. Seit Issue #807 ist die Facette die Trades-Ansicht, und seit
Issue #984 sagt ihr Schalter das auch (die Adresse bleibt, Links und
Lesezeichen halten). Seit Issue #1082 heißt die Kopfzeile Trades, solange
die Facette offen ist — auch auf dem Telefon, wo der Untertitel fehlt —, und
auf den drei anderen Facetten Cashflow. Die Facette öffnet mit drei
Zahlen — der realisierten Summe, mit Vorzeichen und in ihrer Gewinn- oder
Verlustfarbe, der Trefferquote (dem Anteil der abgeschlossenen Trades mit Gewinn;
ein Nullergebnis zählt nicht als Treffer) und der durchschnittlichen
Haltedauer — gefolgt von den abgeschlossenen Rundläufen selbst, neuester
Schluss zuerst, je Zeile das Wertpapier (verlinkt auf seinen Trades-Tab),
gekauft → verkauft, die Haltedauer, die Stückzahl, die Kosten, der Erlös und
die Spalte p. a. und das Ergebnis in Geld und Prozent. Jedes Ergebnis,
jede Prozentzahl und jede p.-a.-Zahl der Liste, in der Tabelle wie in ihren
Telefonzeilen, trägt ihr Vorzeichen und dazu ihre Farbe — ein Gewinn liest
sich „+420,00 EUR“, „+42,0%“, „+17,8%“ —, sodass ein Gewinn nicht davon
abhängt, Grün von Rot zu unterscheiden (Issue #1089); eine Zahl, die sich
als null liest („0,00“, „0,0%“), trägt keins von beiden.
p. a. (Issue #984) ist die annualisierte Rendite
des Trades: die geldgewichtete Rendite pro Jahr seines eigenen Geldes — jedes
gekaufte Lot zu seinem Kaufdatum, der Verkauf zu seinem Verkaufsdatum — in
der Währung des Trades, wie die Prozentzahl unter dem Ergebnis. Sie steht
ab 365 Tagen Haltedauer (die Zelle Haltedauer derselben Zeile); darunter
zeigt die Zelle einen gedämpften Strich, dessen Grund ihr Tooltip nennt
(„Unter einem Jahr Haltedauer nicht annualisiert”), denn ein kurzer Trade
liest sich annualisiert absurd — 5 % in 14 Tagen wären rund 257 % im Jahr —
und seine Prozentzahl über die Haltedauer sagt bereits, was er gebracht hat.
Eine Zeile unter der Liste nennt die Regeln: Einlieferungen eröffnen keinen
Lot, Gebühren und Steuern stecken in Einstand und Erlös, Erträge während der
Haltedauer sind nicht enthalten, und p. a. erst ab 365 Tagen Haltedauer und
nur, wo ein Zinssatz die Zahlungen löst. Der
Umfang des Matchers — FIFO je Wertpapier über alle Depots — steht in der
ersten Zeile der Facette. Auf dem Telefon weicht die Tabelle zweizeiligen
Zeilen: der Name über gekauft → verkauft und den Tagen, das Ergebnis über
seiner Prozentzahl und, ab einem Jahr Haltedauer, der p.-a.-Zahl; ein Trade
ohne sie — unter einem Jahr gehalten oder ein Totalverlust, den kein Zinssatz
löst — schließt seine Prozentzahl mit gesamt („-38,9% gesamt“), dem Wort
der Übersichtskarte. Ein Trade ohne Kosten hat keine Rendite (Issue
#1142): Bonusaktien, als Kauf zu 0 gebucht und später verkauft, haben
„+330,00 EUR“ auf nichts verdient, und ein Prozentsatz von nichts ist nicht
0 %, sondern unbestimmt. Seine Prozentzahl ist der gedämpfte Strich mit dem
Grund „Keine Rendite: keine Kostenbasis“ als Tooltip, sein p.-a.-Strich
nennt denselben Grund vor jedem anderen, und auf dem Telefon liest die
Zeile, wie die Übersichtskarte, „— keine Kostenbasis“, wo die Prozentzahl
stand. Die
Jahres-/Monatsmatrix, mit der die Facette früher öffnete, behält jede Zahl —
jetzt unter Realisiert je Periode hinter der Aufklappung Matrix nach
Jahr und Monat unter der Liste. Konnte ein Verkauf nicht konvertiert
werden, führt der Hinweis, wie viele und welche, den Abschnitt an — über den
drei Zahlen, die er einschränkt, samt seiner Nachlade-Schaltfläche — statt
unter den Zahlen zu stehen, um die es geht.
Ohne abgeschlossene Trades lesen sich Trefferquote und Haltedauer als
abwesend statt als 0 % und 0 Tage. Alle drei Zahlen stammen aus
FIFO-gematchter realisierter G&V über alle Wertpapiere, gruppiert nach dem
Schlussdatum jedes Verkaufs. Die FX-Basis steht auf der Oberfläche und reist in der
API-Payload mit (Entscheidung D-1): jeder Verkauf konvertiert über den
EUR-Hub zum Wechselkurs seines eigenen Schlusstags —
die Basis des Income-Bereichs, denn eine realisierte Zahl ist ein historischer
Fakt an ihrem Datum. Ein Verkauf ohne gespeicherten Wechselkurs zu diesem Datum
wird aus jeder Summe ausgeschlossen und benannt (Achtung-Notiz mit Anzahl
und Wertpapieren) — nie zum Kurs eines Nachbardatums konvertiert, nie still
verworfen. Die tägliche Kurssynchronisation holt aktuelle Kurse und kann
einen vergangenen Tag nicht nachtragen; die Notiz trägt daher die Abhilfe, die
es kann: Historische Kurse nachladen holt die historische EZB-Reihe
einmalig, speichert jeden veröffentlichten Tag und liest die Facette neu — der
ausgeschlossene Verkauf konvertiert zum Kurs seines eigenen Schlusstags,
sobald dieses Datum einen hat (Issue #737). Die verbleibende Grenze steht
neben der Schaltfläche: Ein Tag, den die EZB nicht veröffentlicht hat (ein
Wochenende, eine nicht gelistete Währung), bleibt ausgeschlossen und benannt.
Dasselbe Backfill ist scope=history am Wechselkurs-Sync-Endpunkt und
MCP-Tool; die Facetten Ein- & Auszahlungen und Kosten tragen dieselbe
Schaltfläche in ihren Ausschluss-Hinweisen.
Ein Trade über Währungen hinweg steht in einer Währung (Issue #1108, die Ergänzung von ADR-0015 vom 07.10.2026). Ein USD-Wertpapier, über ein EUR-Konto gekauft und verkauft, hat seinen Kurs in Dollar und seine Gebühren und Steuern in Euro, der Währung des Geldes, dem sie belastet wurden. Bevor sie in Einstand und Erlös eingehen, werden sie zum eigenen Kurs des Trades in Dollar umgerechnet — dem Kurs, den seine Abrechnung festhält, dem Kurs, den der Broker auf diesen Trade angewandt hat —, nie zum Hub-Kurs des Tages, der dieselben Euro ein zweites, anderes Mal umrechnen würde. Einstand, Erlös und Ergebnis eines solchen Trades stehen also alle in Dollar, und sein Ergebnis in Euro ist das Geld, das die Runde bewegt hat, wann immer Broker- und Hub-Kurs übereinstimmen: 10 Stück, gekauft zu 100 USD für 800,00 EUR zuzüglich 6,00 EUR Gebühren und Steuern und verkauft zu 120 USD für 960,00 EUR abzüglich 3,00 EUR Gebühren, kosten 1.007,50 USD, bringen 1.196,25 USD und realisieren 188,75 USD — 151,00 EUR, die erhaltenen 957,00 EUR abzüglich der gezahlten 806,00 EUR. Ein aus Portfolio Performance importierter Trade ist in der Kontowährung gebucht, seine Gebühren mit ihm, und braucht keine Umrechnung.
Verkäufe ohne zugeordneten Kauf werden ebenfalls benannt (Issue #984). Der Matcher ordnet jeden Verkauf früheren Käufen desselben Wertpapiers zu, zuerst gekauft, zuerst verkauft, in einer Warteschlange über alle Depots, und eine Einlieferung eröffnet keinen Lot — wer Stücke aus einer Einlieferung verkauft, typisch für eine importierte Historie, hinterlässt also einen Verkauf ohne Gegenstück, und ein Verkauf über die gekauften Stücke hinaus hinterlässt seinen Rest. Diese Stückzahl ohne Gegenstück ist kein abgeschlossener Trade und steht in keiner der drei Kennzahlen, keiner Zeile und nicht in der Matrix; der zugeordnete Teil desselben Verkaufs ist ein Trade wie jeder andere. Eine Achtung-Notiz nach dem Kurs-Hinweis nennt, wie viele Verkäufe eine solche Stückzahl haben, ihre Aufklappliste jeden als Wertpapier · Datum · Stückzahl ohne Gegenstück („15,0000 Stück“). Sie trägt keine Schaltfläche, denn nichts auf der Seite kann den fehlenden Kauf liefern.
Cashflow → Trades auf dem synthetischen Demo-Datensatz.
Der Trades-Tab des Wertpapiers (Issue #1029) ist das Ziel jeder Zeile der Facette und der Übersichtskarte, und seit Sprint 18 zeigt er dieselbe Zahl: Seine Tabelle Abgeschlossene Trades (FIFO) trägt die Spalte p. a. zwischen Tage und Realisierter G/V — die annualisierte Rendite des Trades, mit Vorzeichen, ab 365 Tagen Haltedauer, darunter derselbe gedämpfte Strich mit seinem Grund als Tooltip. Ein länger gehaltener Trade, dessen Zahlungen kein Zinssatz löst (ein Totalverlust), trägt den Strich ebenfalls, mit diesem Grund. Verkäufe eingelieferter Stücke nennt dieselbe Achtung-Notiz am Kopf des Abschnitts, jeden als Datum · Stückzahl ohne Gegenstück — das Wertpapier ist das der Seite — statt der früheren Warnung „möglicherweise fehlen Daten“; gibt es nur solche Verkäufe, steht die Notiz allein, ohne Tabelle. Eine Zeile unter der Liste nennt die Regeln: über alle Depots, Einlieferungen eröffnen keinen Lot, Gebühren und Steuern stehen im realisierten G/V, nicht in Ø Kauf und Ø Verkauf, Erträge während der Haltedauer sind nicht enthalten, und p. a. erst ab 365 Tagen Haltedauer und nur, wo ein Zinssatz die Zahlungen löst. Der realisierte G/V und seine Gebühren und Steuern stehen in der Währung des Trades, bei einem Trade über Währungen hinweg zu seinem eigenen Kurs umgerechnet, wie in der Facette (Issue #1108). Ein offener Lot oder ein abgeschlossener Trade ohne Kosten zeigt in seiner Spalte „%“ den Strich mit „Keine Rendite: keine Kostenbasis“, ebenso der Tab Bestände des Wertpapiers und die optionale Spalte G&V % im Vermögen für Stücke, die ohne Kosten eingeliefert wurden, etwa aus einem Spin-off (Issue #1142); ein Bestand ohne Kurs behält den einfachen Strich. Auf dem Telefon wird die Tabelle zu zweizeiligen Zeilen: Eröffnet → Geschlossen über der Stückzahl und den Tagen, das Ergebnis über seiner Rendite und, ab einem Jahr Haltedauer, der p.-a.-Zahl. Seit Issue #1060 stehen die Daten des Tabs — der offenen Lots, der abgeschlossenen Trades, der Verkäufe ohne Gegenstück und der Telefonzeilen — im Format der Oberflächensprache (14.03.2024), und beide Spalten % lesen sich mit einer Nachkommastelle, mit Vorzeichen und direkt angefügtem Prozentzeichen („+27,1%“), wie die Spalte p. a. daneben. Auf einem Touchscreen zeigt die Pille ⓘ Kurs- & Währungsbeitrag über den offenen Lots ihre ganze Beschriftung (Issue #1059).
Der Trades-Tab eines Wertpapiers auf dem synthetischen Demo-Datensatz.
Ein- & Auszahlungen (/cashflow?tab=flows, Issue #725) ist die
„Ersparnis”: was eingezahlt und entnommen wurde, je Periode, als zwei Serien
mit Jahresnetto — getrennt von dem, was das Portfolio erwirtschaftet hat.
Gezählt werden nur die gebuchten Ein- und Auszahlungen, und das steht
dort: ein-/ausgelieferte Wertpapiere und Saldo-Snapshot-Sprünge stecken nicht
in dieser Zahl, wohl aber im investierten Kapital der Performance — die
Oberfläche nennt den Unterschied, statt zwei widersprechende Zahlen zum
Entdecken zu lassen. Gleiche FX-Basis und gleiche
Ausschluss-und-Benennungs-Regel wie die Schwester-Facetten; unkonvertierbare
Flüsse werden nach Verrechnungskonto benannt. Ein Fluss wird in der Währung
des Verrechnungskontos gelesen, auf das er gebucht wurde: eine in Dollar
erfasste Einzahlung auf ein EUR-Konto, ihr Kurs gespeichert, sind die Euro,
die ankamen (Issue #1107).
Kosten (/cashflow?tab=costs, Issue #726) ist, was das Portfolio im
Betrieb gekostet hat: Gebühren und Steuern je Periode, als zwei Serien mit
Jahressumme — nur auf Übersichtsebene, bewusst kein Kosten-Journal je
Transaktion. Summiert werden die Gebühren- und Steuer-Nebenbeträge jeder
Transaktion plus die eigenständigen Gebühren- und Steuerbuchungen;
Steuererstattungen werden gegen die Steuern verrechnet. Bruttobeträge werden
nie summiert — beim Kauf enthält das Brutto die Nebenbeträge, beim Verkauf
ist es um sie gemindert — und die Oberfläche nennt diese Regel in ihrer
Zusammensetzungszeile. Gleiche FX-Basis und gleiche
Ausschluss-und-Benennungs-Regel wie die Schwester-Facetten. Jede Gebühr und
jede Steuer wird in der Währung des Verrechnungskontos gelesen, dem sie
belastet wurde — in Euro bei einem USD-Wertpapier, das über ein EUR-Konto
gekauft wurde — und von ihr zum Kurs ihres Buchungsdatums umgerechnet, wie
die Handelskosten der Performance, sodass beide eine Zahl lesen (Issue
#1107); unkonvertierbare Kosten werden nach dieser Währung benannt.
Jede Kennzahl des Bereichs nennt, was sie enthält: der Income-Bereich schreibt, dass er Dividenden und Zinsen abdeckt und realisierte Gewinne, Ein- und Auszahlungen sowie Kosten ausschließt. Das ist keine Dekoration — genau diese Auslassungen sind der Grund, warum es die anderen Bereiche gibt, und wer sie nicht kennt, liest die Seite als „alles Geld, das hereinkam”.
Income (Dividenden und Zinsen)
Der Income-Bereich ist der retrospektive Ertragsbericht: die bereits im Ledger gebuchten Dividenden und Zinsen, ohne externe Daten oder Prognose. Sie zeigt einen Jahresüberblick — eine Jahr-×-Monat-Matrix, aufgeteilt in eine Dividends- und eine Interest-Reihe, jedes Jahr mit einer Summenspalte — und eine Pro-Position-Tabelle mit, für jedes Wertpapier, dem Brutto-Gezahlten, der einbehaltenen Steuer, dem Netto, der Anzahl der Zahlungen und dem Datum der letzten. Das Brutto einer Dividende ist das gutgeschriebene Netto-Cash plus die auf der Transaktion erfasste einbehaltene Steuer; Zinsen (Portfolio-Performance INTEREST: Kontozinsen oder Anleihekupons) tragen keine Quellensteuer und werden als eigene Reihe neben Dividenden geführt. Ein Klick auf ein Jahr öffnet das Detail je Transaktion für dieses Jahr.
Die Jahresbalken über der Matrix sind gestapelt, nicht summiert: Dividenden und Zinsen sind zwei Segmente, sodass Chart und Tabelle sich nie darüber uneinig sein können, was die Zahl ist. Eine Legende benennt die beiden Reihen, ein ausreichend hohes Segment trägt seinen Wert als Text; jedes Jahr zwischen der ersten und der letzten Buchung hat seinen Platz, ein leeres als Grundlinien-Strich mit „–”; Null-Zellen der Matrix lesen sich als stilles „–”, damit die Zellen mit Werten das sind, was das Auge findet; und sowohl die Matrix als auch die Zahlungen eines aufgeklappten Jahres sitzen hinter dem Aufklappen Daten als Tabelle, das jedes Chart trägt. Beim Aufklappen eines Jahres kommt eine kumulierte Reihe über dessen Monate hinzu — der laufende Gesamtstand, sodass ein ruhiger Monat als Plateau statt als Lücke gelesen wird und die Kurve „wo stand das Jahr im April” beantwortet statt „was kam im April herein”.
Beträge werden in der Basiswährung des Portfolios ausgewiesen; die
ursprüngliche Währung bleibt je Zeile sichtbar. Eine Zahlung wird in der
Währung des Kontos gelesen, dem sie gutgeschrieben wurde: Die Dividende
eines USD-Wertpapiers, einem EUR-Konto gutgeschrieben, sind die Euro, die
angekommen sind, und ihre Zeile unter den Zahlungen des Jahres nennt EUR,
während die Tabelle je Position die Währung der Buchung behält (die
Ergänzung von ADR-0015 vom 07.10.2026). Die Umrechnungsmethodik
(EUR-Hub zum gespeicherten Kurs des jeweiligen Buchungsdatums — dieselbe
Umrechnung wie die Bewertung) steht hinter dem ⓘ neben der Währungszeile.
Der Bericht ist auch über die API (GET /api/v1/portfolios/:id/income) und das
MCP-Tool portfolixir.portfolios.income verfügbar.
Snapshots (was wäre, wenn ich es behalten hätte?)
Der Reiter Snapshots im Vermögensbereich friert „die Bestände, die ich gerade habe” als benannten Marker ein und beantwortet später: wäre ich besser gefahren, wenn ich genau diese Bestände behalten hätte? Lege einen Snapshot an, bevor eine Strategie umgebaut wird, handle weiter, und komm zum Vergleich zurück.
Ein Snapshot ist ein reiner Ledger-Marker — ein Name, ein Geltungsbereich (eine Bucket-Sicht oder Alles) und ein Stichtag. Er kopiert keine Transaktionen, Stückzahlen oder Kurse: der Zustand, den er repräsentiert, wird bei Bedarf aus dem Transaktions-Ledger abgeleitet. Ein Snapshot kann also nie von den Daten abweichen, und ihn zu löschen berührt nie eine Transaktion. Namen sind je Geltungsbereich eindeutig; der Stichtag darf nicht in der Zukunft liegen.
Der Vergleich ist die Oberfläche. Mit mindestens einem Snapshot öffnet
die Seite auf dem Vergleich des neuesten; die Liste darunter wählt, welcher
Snapshot verglichen wird (die verglichene Zeile ist markiert, die URL trägt
?snapshot=). Der Vergleich zeigt das Kontrafaktual:
- Real (TTWROR seit Stichtag) gegen Eingefroren (Halten) — die echte zeitgewichtete Performance seit dem Stichtag gegen die Kursrendite des eingefrorenen Bestands; die eingefrorene Kennzahl trägt die Positionen des Snapshots zum Stichtag und heute bewertet, buy-and-hold über die echte gespeicherte Kurshistorie (tägliche Schlusskurse, EUR-Hub-Wechselkurse des jeweiligen Tags). TTWROR neutralisiert Ein- und Auszahlungen, frisches Geld verzerrt den Vergleich also nicht.
- Das gemeinsame Chart mit beiden Serien als prozentuale Veränderung seit dem Stichtag (durchgezogen = eingefroren, gestrichelt = real) mit Legende, einer Basiszeile, die nennt, was auf welcher Basis verglichen wird, und denselben Daten hinter dem Aufklappen Daten als Tabelle.
Die beiden Seiten werden nicht auf derselben Basis gemessen, und die Seite sagt das. Die eingefrorene Seite handelt nicht und hat keine Flüsse: sie zahlt nie etwas. Die echte Seite ist TTWROR, und dort gehören Gebühren und Steuern zur Rendite — jede Handelskosten seit dem Stichtag drücken sie also, und die eingefrorene Seite gewinnt automatisch, solange diese Kosten nicht wieder eingespielt sind. Genau in diesem Zeitfenster wird der Vergleich üblicherweise gelesen.
Wenn Handelsgeschäfte tatsächlich etwas gekostet haben, erscheinen daher drei weitere Kennzahlen gemeinsam:
- Echte TTWROR vor Transaktionskosten — derselbe Tageslauf, bei dem die Handelsgebühren und -steuern des Zeitfensters als abfließendes Geld statt als Verlust gewertet werden;
- Transaktionskosten — deren Summe in der Basiswährung;
- Wieder eingespielt? — Ja, wenn die echte Rendite bereits vor der eingefrorenen liegt; Noch nicht, mit dem verbleibenden Abstand, wenn sie vor Kosten vorne liegt und nach Kosten nicht; und Auch vor Kosten zurück, wenn die Kosten nicht der Grund sind und sich die Änderungen aus eigener Kraft nicht ausgezahlt haben.
Sie werden immer zusammen gezeigt und nie die Vor-Kosten-Zahl allein — für sich genommen ist sie eine Zahl, die schmeichelt. Transaktionskosten sind die auf einem Handelsgeschäft gebuchten Gebühren und Steuern; bei einem währungsübergreifenden Handel zählen sie in der Währung seines Verrechnungskontos, in der der Broker sie berechnet. Eigenständige Gebühren- und Steuerbuchungen bleiben auf beiden Seiten in der Rendite, denn eine Depotgebühr wird nicht von einem Handel verursacht und der eingefrorene Halter hätte sie ebenso gezahlt; die Quellensteuer auf Dividenden bleibt ebenfalls drin, sie gehört zur Dividendenlücke unten und nicht hierher.
Der Vergleich erscheint zuerst und groß, die Snapshot-Liste darunter mit Löschen im Zeilenmenü jeder Zeile, das Anlegen-Formular hinter dem geschlossenen Aufklappen Neuer Snapshot und die Erklärung hinter dem ⓘ an der Überschrift. Der Vergleich ist in v1 brutto und nur Kursentwicklung — Ausschüttungen, die die eingefrorenen Positionen gezahlt hätten, sind noch nicht enthalten; die Seite sagt das als Hinweis neben den Zahlen. Wertpapiere ohne verwendbaren Kurs oder Wechselkurs zum Stichtag werden in einem Achtung-Hinweis ausgeschlossen und aufgeführt, statt still mit null bewertet zu werden. Derselbe Vergleich steht über die API und MCP bereit.
Steuern (erfasste Bankabrechnungen)
Der Reiter Steuern im Vermögens-Bereich erfasst den Steuerblock einer
Bankabrechnung — den Abschnitt Verlustverrechnungstöpfe /
Freistellungsauftrag eines Steuerreports oder einer Erträgnisaufstellung —
und liest daraus den steuerfreien Verkaufsspielraum ab: wie viel
realisierter Aktiengewinn bei diesem Institut noch frei von
Kapitalertragsteuer ist.
Diese Zahlen werden erfasst, nicht berechnet. Portfolixir kann die deutschen Steuertöpfe nicht aus dem Buchungsbestand herleiten und versucht es auch nicht — aber nicht aus dem Grund, den man zuerst vermutet. Portfolixir rechnet sehr wohl FIFO, also nach der Methode, die das deutsche Steuerrecht vorschreibt: die Trade-Liste weist aus, welche Stücke ein Verkauf verbraucht hat und zu welchen Kosten. (Die Bestandsbewertung nutzt daneben einen laufenden Durchschnitt, weil „was hat meine Position im Schnitt gekostet” eine andere Frage ist; ADR-0004/ADR-0011.)
Was FIFO liefert, ist ein Rohgewinn — und ein Rohgewinn ist kein Steuertopf. Dazwischen stehen vier Dinge, von denen keines in den Transaktionsdaten steht: Teilfreistellung (die anteilige Befreiung je Fondstyp), Vorabpauschale, die chronologische Verrechnung des Freistellungsauftrags über alle Erträge bei dieser Bank, und der bescheinigte Verlustvortrag aus Jahren vor der ersten erfassten Buchung. Hinzu kommt: die Töpfe führt die Bank je Institut, Portfolixir modelliert Depots. Ein berechneter Topf wäre deshalb falsch, und zwar unsichtbar falsch — deshalb wird die Abrechnung übernommen. Maßgeblich bleibt die Abrechnung; dies ist keine Steuerberatung.
Erfasst werden je Institut, steuerpflichtiger Person, Steuerjahr und Stichtag: die steuerpflichtigen Kapitalerträge, der erteilte und der verbrauchte Freistellungsauftrag, die Verlustverrechnungstöpfe Aktien und Sonstige, der bescheinigte Verlustvortrag, der Quellensteuertopf und die angerechnete ausländische Quellensteuer sowie die abgeführte Kapitalertragsteuer, der Solidaritätszuschlag und die Kirchensteuer.
Alle Beträge ohne Vorzeichen eintragen. Ein Verlusttopf wird als verrechenbares Verlustvolumen gespeichert, nicht als die negative Zahl auf dem Papier. Eine negative Eingabe wird mit einem entsprechenden Hinweis abgelehnt statt still gedreht — stilles Umdrehen eines Vorzeichens macht aus einem Übertragungsfehler eine dauerhaft falsche Zahl. Die Liste der Abrechnungen stellt die Töpfe anschließend mit dem gedruckten Vorzeichen dar, damit eine erfasste Zeile mit dem Papier vergleichbar bleibt.
Die Seite ist eine Budget-Anzeige plus Prüfliste. Steuerpflichtige Person
und Steuerjahr sind segmentierte Steuerelemente (der Bereich steht in der
URL, ?holder=…&year=…). Eine steuerpflichtige Person oder ein Institut ist
eine Identität, wie auch immer sie getippt wurde: Der Name wird
zusammengesetzt, ohne unsichtbare Zeichen und mit einfachen Leerzeichen
gespeichert und ohne Rücksicht auf Groß- und Kleinschreibung abgeglichen.
„Anna Muster” und „ANNA MUSTER” sind daher ein Eintrag im Steuerelement mit
einem Budget, und eine als „Bank Eins” und als „bank eins” erfasste Bank ist
darin ein Institut (E25 S6). Namen, die vor dieser Regel erfasst wurden,
speichert das Upgrade ebenso, jede Änderung im Prüfprotokoll; ein Name, der
danach einem anderen Eintrag desselben Schlüssels gliche, bleibt, wie er war,
und wird im Log des Upgrades genannt, damit Sie einen der beiden auf dieser
Seite korrigieren oder entfernen. Das Budget erscheint als Füllstandsanzeige: der
verbleibende Betrag als Wert, die Ausschöpfung des Freistellungsauftrags als
Füllstand ohne Schwellenfärbung, Stichtag und erfasste Institute auf der
Basiszeile, daneben die Zusammensetzung — Verlusttopf Aktien, verbleibender
Freistellungsauftrag, gesetzlicher Höchstbetrag — mit einem ⓘ zur Regel
„erfasst, nicht berechnet”. Ein veraltetes oder unvollständiges Budget ist
eine Datennotiz neben der Anzeige mit dem Mittel darin („Neue Abrechnung
erfassen”). Die erfassten Abrechnungen sind eine Liste; jeder Prüfbefund ist
eine Datennotiz an seiner Zeile mit dem Prüf-Bedienelement darin, und
„Korrigieren” und „Löschen” sitzen im Zeilenmenü. Beide Eingabeformulare
öffnen sich aus einem Aufklappen und sind standardmäßig geschlossen; die
Vorzeichenregel ist Feldhilfe an den Betragsfeldern, und die hinterlegten
Freistellungsaufträge sitzen hinter einem Aufklappen, das ihren Zweck nennt.
Der Verkaufsspielraum ist der Verlusttopf Aktien plus der verbleibende
Freistellungsauftrag (erteilt − verbraucht). Er wird immer mit seinem
Stichtag gezeigt und erst dann als veraltet markiert, wenn die
Alterung belegt ist: wenn steuerrelevante Buchungen nach dem
Abrechnungsdatum Verlusttöpfe oder Freistellungsauftrag verbrauchen, oder
wenn die Abrechnung älter als 90 Tage ist. Der Hinweis nennt seinen Grund —
ein ruhiges Buchungsjournal hält eine ältere Abrechnung nutzbar, statt sie
dauerhaft zu markieren. Über mehrere Institute
wird je Person und Jahr summiert — mit Angabe der erfassten Institute, dem
Stichtag der ältesten Teilzahl und dem Hinweis unvollständig, wenn für
ein Institut ein Freistellungsauftrag hinterlegt, aber keine Abrechnung erfasst
ist. Die Zahl ist eine Entscheidungsgrundlage, keine Handlungsanweisung:
Portfolixir erteilt, speichert und überträgt keine Orders.
Selbstprüfende Übernahme. Die Abgeltungsteuer folgt der geschlossenen
Formel des § 32d Abs. 1 EStG, eine erfasste Abrechnung kann ihre eigene
Arithmetik also prüfen. Zwei Widersprüche verhindern das Speichern: ein
verbrauchter Freistellungsauftrag über dem erteilten, und Kirchensteuer bei
einem Kirchensteuersatz von null. Alles andere ist ein Hinweis, der nichts
blockiert — die aus der Abrechnung rekonstruierte Kapitalertragsteuer, der
Solidaritätszuschlag und die Kirchensteuer, sinkende Jahreswerte zwischen zwei
Abrechnungen desselben Jahres, ein erfasster Freistellungsauftrag, der vom
hinterlegten abweicht, und hinterlegte Aufträge über dem gesetzlichen
Höchstbetrag des Jahres. Ein Hinweis nennt beide Zahlen und die Abweichung; er
schlägt nie einen „korrigierten” Wert vor. Eine Toleranz von
max(1,00, 0,05 %) fängt die Cent-Beträge ab, die sich aus der Rundung je
Abrechnungsvorgang legitim ansammeln.
Die Konfiguration dahinter. Die gesetzlichen Sätze und die Sparer-Pauschbeträge sind jahresbezogene Daten, für 2009–2026 hinterlegt — der Pauschbetrag stieg 2023 von 801/1.602 € auf 1.000/2.000 €, eine ältere Abrechnung wird also gegen das Recht geprüft, das für sie galt. Ein Jahr ohne Daten wird als fehlend gemeldet und nicht aus einem Nachbarjahr geschätzt. Die eigene Situation ist ein zeitlich gültiges Profil je Person: Kirchensteuerpflicht (Voreinstellung: nicht pflichtig) sowie Einzel- oder Zusammenveranlagung. Eine erfasste Abrechnung friert den zum Stichtag geltenden Kirchensteuersatz ein, ein späteres Ändern des Profils wirkt also nur nach vorn und schreibt nie eine erfasste Abrechnung um.
Alles auf dieser Seite ist auch über API und MCP verfügbar.
Risiko (Konzentration und Schwankung)
Der Reiter Risiko im Bereich Vermögen zeigt zwei Dinge, die eine Frage beantworten — wie konzentriert ist das Portfolio, und wie stark schwankt es — über der steuerbaren Basis der aktiven Ansicht (die Ansicht steht im Kopf).
- Eigene Regeln ganz oben: die Obergrenzen, Untergrenzen und Bänder des Betreibers (ADR-0049) mit ihren Befunden, verletzte und nicht bestimmbare zuerst. Der Name einer Regel ist ein Link und öffnet ihren Dialog, den einen Ort, an dem die Regel geändert (eine neue Version ab einem Datum; die bisherige bleibt lesbar), umbenannt oder beendet wird. Umbenennen ändert nur die Bezeichnung: Es entsteht keine Version, der neue Name gilt für die Regel mit allen Versionen, und das Audit-Journal behält den bisherigen Namen. Eine beendete Regel wird genauso aus der Liste der beendeten Regeln umbenannt. Eine Regel auf ein inzwischen stillgelegtes Wertpapier nennt es weiter in ihren Worten (Issue #944); trägt ein aktives Wertpapier denselben Namen, unterscheiden die Worte jeder Regel beide an ihrer ISIN. Eine neue Regel kann kein stillgelegtes Wertpapier wählen. „Risiko“ zeigt die Regeln der aktiven Ansicht; eine Regel, die in einer anderen Ansicht gilt, steht in jener Ansicht. Wird das Löschen einer Ansicht, einer Kategorie, einer Klassifizierung oder eines Wertpapiers abgelehnt, weil Regeln es lesen, nennt die Ablehnung die Regeln mit Stand und Ansicht, und jeder Name führt auf „Risiko“ in der Ansicht, in der die Regel gilt. Eine Regel, deren gültige Linie der Agent mit seinem API-Token gezogen hat, endet in ihrer Wortzeile mit „Agent“ — geplante und beendete Regeln ebenso —, und die Versionsliste im Dialog nennt bei jeder Version den Autor, „Operator“ oder „Agent“ (E25). Eigene Regeln tragen kein Wort. Die Regeln des Agenten gelten wie die eigenen; das Wort sagt nur, wer die Linie gezogen hat. Wie man eine Regel Schritt für Schritt anlegt, liest, ändert und beendet, steht im Leitfaden Eigene Regeln.
- Kennzahlen des Portfolios, ein Jahr: die annualisierte Volatilität, der maximale Rückgang mit Beginn, Tiefpunkt und Erholung, die risikoadjustierte Rendite (bei einem risikofreien Satz von 0 ist sie Rendite je Risikoeinheit) und die höchste Korrelation unter den größten Positionen. Gemessen wird über die um Zahlungen bereinigten Tagesrenditen der TTWROR-Kette: eine Einzahlung oder Entnahme zählt nie als Schwankung, wer spart, liest bei gleichen Kursen dasselbe Risiko wie wer nur hält. Eine Zahl ohne ausreichende Historie sagt „nicht berechenbar“ mit der Zahl der vorhandenen und der nötigen Beobachtungen, statt eine Zahl zu zeigen.
- Größte Einzelpositionen mit Gewicht und der Schwelle, über oder unter der sie liegen — über 10 % für eine Einzelaktie (7 % ist die erste Linie), über 25 % für einen ETF. Die Schwelle wird genannt, nicht bewertet.
- Klumpenrisiko (HHI) auf der Skala 0–10.000 mit Band (niedrig unter 1.500, konzentriert ab 2.500).
- Anlageklassen-Obergrenzen, sofern über die API gesetzt.
- Korrelationen der größten Positionen hinter einer Aufklappfläche, zuerst in die Basiswährung umgerechnet und nur über Tage mit Kurs für beide. Die Grundlagenzeile und die Zeile über den Paaren nennen, über wie viele der größten Positionen sie laufen: die Matrix erfasst höchstens die 20 größten, wie lang die Liste auch ist.
Die Seite berichtet, sie empfiehlt nicht. Dieselben Zahlen liefert
GET /api/v1/portfolios/:portfolio_id/risk und das MCP-Werkzeug
portfolixir.portfolios.risk, mit allen drei Fenstern.
Imports
Die Imports-Seite akzeptiert Portfolio-Performance-Transaktionsexporte im Format CSV oder JSON v1. Dateien werden in eine Vorschau geparst, bevor Datensätze gespeichert werden. Die Vorschau zeigt übersetzte Transaktionsart-Labels, die Datensätze, die angelegt würden, und Konto-/Depotzuordnungen für fehlende Ziele.
Statt nach einem Zielportfolio zu fragen, bietet die Vorschau einen optionalen
Bucket-Tag für die Konten an, die der Import anlegen wird: Optional: ein
Bucket-Tag für die Konten, die dieser Import anlegt. Das Feld beginnt leer,
und bleibt es leer, bleiben die neuen Konten ohne Tag, und es entsteht kein
Bucket. Gib einen Namen wie PP Import ein, um die importierten Konten
später wiederzufinden, oder den Namen eines bestehenden Buckets, um ihn
wiederzuverwenden. Konten, die bestehenden Einträgen zugeordnet sind,
behalten ihre aktuellen Tags, und ein Import, der keine neuen Konten anlegt,
erzeugt keinen Bucket; eine Datei ohne Neues zeigt das Feld gar nicht. Die
interne Portfolio-Bindung geschieht automatisch und erfordert nie eine Auswahl
(siehe den Abschnitt Portfolios). Auf einer Instanz, die noch keinen
Portfoliodatensatz hält, sagt die Vorschau das unter dem Quellformat: Noch
kein Portfoliodatensatz: Der Import legt „Default“ (EUR) an und bucht darin.
Der Datensatz erscheint danach unter Portfoliodatensätze (Kompatibilität)
auf Konten & Depots.
Parser-Warnungen erscheinen in einer Notiz Achtung unter den Anzahlen je
Art, mit einer scrollbaren Liste der Zeilen und einem Kopier-Button. Der
kopierte Text nutzt stabile Zeile N: Meldung-Zeilen, sodass die Diagnose
beim Quell-Export verbleiben kann. In einer CSV-Datei ist Zeile N die Zeile,
die eine Tabellenkalkulation zeigt, die Kopfzeile als Zeile 1, die erste
Buchung also Zeile 2; jede Liste der Vorschau und des Ergebnisses nennt eine
CSV-Zeile genauso. Das Anwenden des Imports ist atomar und
nutzt Inhalts-Hashes, um Duplikate bei erneutem Lauf zu überspringen.
Was eine Portfolio-Performance-CSV voraussetzt
Der CSV-Weg liest den deutschen Export von Portfolio Performance. Er hat eine Voraussetzung und zwei Annahmen, die für das stehen, was die CSV nicht sagen kann:
- Nur deutsche Spaltennamen und Typ-Bezeichnungen. Die Kopfzeile nennt die
Spalten auf Deutsch (
Datum,Typ,Wertpapier,Stück,Kurs,Betrag,Gebühren,Steuern,Konto), jede Zeile trägt eine deutsche Typ-Bezeichnung (Kauf,Verkauf,Dividendeund so weiter), und Zahlen stehen im deutschen Format (1.234,56). Ein Export aus einem englisch eingestellten Portfolio Performance nennt seine Spalten auf Englisch und wird als Ganzes abgelehnt, mit den fehlenden Spalten benannt (CSV-Spalten fehlen: Datum, Typ, …): Portfolio Performance auf Deutsch umstellen und erneut exportieren. - Jede Zeile in EUR. Die CSV hat keine Währungsspalte: Jeder Betrag wird als Euro gelesen, und die Geldkonten und Wertpapiere, die der Import aus ihr anlegt, sind EUR.
- Wertpapiere nur über den Namen. Die CSV enthält keine ISIN, WKN und kein Tickersymbol, also ordnet der Import ein Wertpapier allein über seinen Namen zu, die letzte Stufe der Zuordnungsleiter (siehe „Wertpapier-Matching und der Zuordnungsschritt“ unten). Ein in Portfolio Performance umbenanntes Wertpapier wird nicht gefunden und als neues angeboten, das du in der Vorschau umordnen kannst; zwei Wertpapiere mit einem Namen sind eine Entscheidung, nach der die Vorschau fragt.
Betrag ist der Bruttowert, Gesamtpreis das Geld. Portfolio Performance
schreibt in den Betrag einer Zeile den Wert vor Gebühren und Steuern und in
den Gesamtpreis das Geld, das geflossen ist. Bei den Typen, die Geld vom
Konto abziehen (Kauf, Entnahme, Gebühren, Steuern, Umbuchung
(Ausgang)), ist der Gesamtpreis der Betrag zuzüglich Gebühren und
Steuern; bei den Typen, die Geld gutschreiben (Verkauf, Dividende,
Zinsen, Einlage, Steuerrückerstattung, Umbuchung (Eingang)), ist er
der Betrag abzüglich beider. Negative Steuern zählen mit ihrem Vorzeichen.
Der Import bucht den Gesamtpreis und prüft ihn auf den Cent gegen Betrag,
Gebühren und Steuern. Eine Zeile, in der sie nicht zusammenpassen, bleibt mit
einer Parser-Warnung draußen, die die Zellen so zitiert, wie die Datei sie
schreibt, und den Gesamtpreis nennt, den sie ergeben, in der Schreibweise der
Datei — bei einem Kauf: Gesamtpreis 1.510,00 passt nicht zu Betrag
1.502,50 und Gebühren 2,50 (erwartet 1.505,00) — Zeile nicht übernommen; der
Import rät nicht, welche Zelle falsch ist. Eine Zeile mit leerem Gesamtpreis, und jede Zeile einer Datei ohne diese
Spalte, wird als von einem Konverter geschriebene Datei gelesen und bucht
ihren Betrag als Geld: So lehrt es der Prompt import_converter. Eine
Steuererstattung, die ein negativer Wert in Steuern abspaltet, wird neben
ihrer Zeile gebucht, und beide zusammen bewegen den Gesamtpreis, in einer
Konverter-Zeile den Betrag (siehe „Eine negative Steuer in einer Zeile“
unten).
Ein Export, der importiert wurde, bevor Portfolixir den Gesamtpreis las, behält seine Inhalts-Hashes, also bucht ihn erneut abzulegen nichts. Seine Zeilen behalten den Bruttowert aus Portfolio Performance als Geld: Jede Zeile mit Gebühren oder Steuern liegt um genau diese daneben, und ihr Geldkonto mit ihr. Dieselbe Datei erneut abzulegen, listet diese Zeilen in der Vorschau auf, und diese Liste zu bestätigen, korrigiert sie (siehe Bereits importiert, mit anderem Betrag unten).
Für andere Währungen und die Zuordnung über die ISIN exportiere JSON v1: Es trägt eine Währung je Zeile und je Wertpapier ISIN, WKN und Tickersymbol.
Eine negative Steuer in einer Zeile
Portfolio Performance kann eine Steuererstattung innerhalb einer Buchung
festhalten, als negative Steuer: ein Verkauf, dessen Verlust Steuer erstattet,
oder eine Dividende, deren einbehaltene Steuer korrigiert wurde. Der Import
bucht sie in jedem Format als Steuererstattung neben ihrer Buchung. Das
Geld der Zeile enthält die Erstattung schon (der amount einer JSON-Zeile,
der Gesamtpreis einer CSV-Zeile, der Betrag einer von einem Konverter
geschriebenen Zeile), also wird der Buchung selbst dieses Geld abzüglich der
Erstattung gutgeschrieben, bei einem Kauf zuzüglich der Erstattung belastet.
Beide zusammen bewegen genau das Geld der Zeile, und jedes Konto endet auf
dem Saldo, den Portfolio Performance zeigt. Ein JSON-Handel erhält seinen
Kurs aus dem Bruttowert, wie Portfolio Performance ihn bildet, also lässt das
realisierte Ergebnis eines Verkaufs die Erstattung draußen: Die Erstattung ist
ein eigener Ertrag.
Eine Gutschrift, die nach Abzug der Erstattung nichts oder weniger buchen
würde (eine wertlose Position, zu einem symbolischen Kurs verkauft, deren
Verlust Steuer erstattet), bleibt mit einer Parser-Warnung draußen, wie unten
beschrieben, deren Abhilfe lautet: den Verkauf von Hand buchen, die
Erstattung als eigene Steuererstattung. Das eigene Geld eines Verkaufs muss
über null liegen, also heißt „von Hand“ drei Buchungen: der Verkauf zu seinem
Betrag, ohne Gebühren und Steuern; seine Gebühren als Gebührenbuchung;
und die Erstattung als Steuererstattung. Zusammen bewegen sie den
Gesamtpreis der Zeile. Für eine Zeile mit Betrag 7,50, Gebühren 9,90,
Steuern -12,40 und Gesamtpreis 10,00 heißt das: der Verkauf mit 7,50
gutgeschrieben, die Gebühr mit 9,90 belastet und die Erstattung mit 12,40
gutgeschrieben, 7,50 - 9,90 + 12,40 = 10,00.
Noch bucht keine Maske eine Gebühr oder eine Steuererstattung (Issue #1206).
Buche sie als Zeilen einer CSV in der deutschen Form des Exports, je eine
Zeile, oder über die API (POST /api/v1/transactions mit den Typen sell,
fee und tax_refund) oder den MCP-Begleiter
(portfolixir.transactions.create):
Datum;Typ;Wertpapier;Stück;Kurs;Betrag;Gebühren;Steuern;Gesamtpreis;Konto;Gegenkonto;Notiz;Quelle
2024-06-14 15:30:00;Verkauf;Arbolia Inc.;750;0,01;7,50;;;7,50;Test-Depot;Test-Cash;;
2024-06-14 15:30:00;Gebühren;;;;9,90;;;9,90;Test-Cash;;;
2024-06-14 15:30:00;Steuerrückerstattung;;;;12,40;;;12,40;Test-Cash;;;
Gib den Zeilen Datum, Wertpapier, Stückzahl und Konten der zurückgewiesenen Zeile, lege die Datei wie einen Export ab und ordne ihr Depot und ihr Verrechnungskonto denen zu, auf denen der Verkauf bucht. Wurde eine solche Zeile importiert, bevor Portfolixir sie zurückwies, sagt ihre Warnung stattdessen, dass sie bereits importiert ist und hier nicht korrigiert werden kann, da die Gutschrift 0 oder weniger wäre: nicht noch einmal erfassen; wie eine solche Buchung korrigiert wird, ist noch offen (Issue #1193).
Eine Historie, die importiert wurde, bevor Portfolixir die Erstattung aus ihrer Buchung nahm, hat eine solche Erstattung doppelt gezählt, neben einer Buchung, die sie schon enthielt, und einen JSON-Verkauf mit ihr bewertet. Denselben Export erneut abzulegen, bucht nichts doppelt. Um diese Buchungen zu korrigieren, lege den Export erneut ab, oder einen frischen Export derselben Historie aus Portfolio Performance, und bestätige den Korrekturabschnitt, den seine Vorschau zeigt (siehe Bereits importiert, mit anderem Betrag unten).
Dateien und Zeilen, die die Vorschau ablehnt
Eine Datei, die die Vorschau nicht sicher halten kann, wird als Ganzes abgelehnt, bevor etwas für den nächsten Besuch aufbewahrt wird. Der Grund steht mit seiner Abhilfe im Meldungsband über dem Ablagefeld, und das Ablagefeld nimmt sofort die nächste Datei:
- Eine Datei, die nicht in UTF-8 kodiert ist, wie sie oft entsteht, wenn eine Tabellenkalkulation einen Export neu gespeichert hat: in Portfolio Performance neu exportieren und die Datei ablegen, ohne sie vorher in einer Tabellenkalkulation zu öffnen.
- Eine Datei mit zu vielen unterschiedlichen Konto-, Depot- oder Wertpapiernamen für eine Vorschau, weit mehr, als ein gewöhnlicher Export enthält: in Portfolio Performance kleinere Exporte anlegen, etwa je Konto oder Depot, und nacheinander importieren.
- Eine Datei, die mehr Einträge ergibt, als der Import fasst, gezählt jede Zeile und jede Steuererstattung, die eine Zeile abspaltet: den Export in Portfolio Performance teilen, etwa nach Jahren.
Eine einzelne Zeile, die der Import nie buchen könnte, ist stattdessen eine Parser-Warnung: Sie steht mit ihrer Zeilennummer in der Notiz, zählt nicht zu den Einträgen, und der Rest der Datei wird angezeigt und importiert. Ein Wertpapiereintrag, der nichts benennt (kein Name, keine ISIN, WKN oder kein Ticker), ist eine solche Zeile: Wertpapier ohne Name und ohne ISIN — Zeile nicht übernommen. Ebenso eine Zeile mit einem Wert, den keine Spalte des Ledgers hält (ein Betrag, eine Gebühr, eine Steuer, eine abgespaltene Steuererstattung oder ein abgeleiteter Kurs mit mehr Stellen vor dem Komma, als die Spalte nach dem Runden auf ihre Nachkommastellen fasst), eine Zahl, die der Parser nicht lesen kann, eine CSV-Zeile, deren Gesamtpreis nicht zu Betrag, Gebühren und Steuern passt (siehe oben), und eine Transaktion mit mehr Gebühren- und Steuerpositionen, als eine Buchung trägt: Jede wird mit Feld und Zeile benannt und lässt den Import nach dem Bestätigen nie scheitern. Diese Zeilen bleiben ebenso draußen, jede mit ihrer Zeile benannt:
- Eine Zeile, deren ISIN keine gültige ISIN ist (Form oder Prüfziffer, auch ein Buchstabe aus einer anderen Schrift), damit ein Doppelgänger nie zu einem zweiten Wertpapier wird. Ein Eintrag nur mit WKN oder nur mit Ticker ist ein Wertpapier wie jedes andere und wird über die Zuordnungsleiter unten aufgelöst.
- Eine Umbuchung, die kein Konto nennt, auf das sie buchen könnte. In
einer CSV braucht eine Umbuchungszeile
KontoundGegenkonto, für Geld oder Stücke, auf jeder Seite: Umbuchung ohne Gegenkonto — Zeile nicht übernommen, Umbuchung ohne Konto — Zeile nicht übernommen. In JSON v1 ist einCASH_TRANSFERohneotherAccountoder einSECURITY_TRANSFERohneotherPortfolioder erste dieser Fälle. Eine Umbuchung, die auf beiden Seiten dasselbe Konto nennt, gehört nicht hierher: Sie ist eine interne Umbuchung und wird übersprungen und aufgeführt, wie unten beschrieben. - Ein CSV-Kauf oder -Verkauf mit leerem
Gegenkonto, dem Verrechnungskonto, gegen das der Handel abgerechnet wird: Kauf ohne Gegenkonto — Zeile nicht übernommen oder Verkauf …. - Eine Gutschrift, die nichts oder weniger buchen würde: ein Verkauf, eine
Dividende, Zinsen, eine Einlage oder eine Steuerrückerstattung, deren Geld
nach Abzug der abgespaltenen Steuererstattung (siehe „Eine negative Steuer
in einer Zeile“ oben) oder schon für sich 0 oder weniger ist. Der Import
bucht nur einen positiven Betrag, würde die Zeile also sonst überspringen,
und die Position eines Verkaufs bliebe im Bestand: Verkauf mit
Gesamtpreis 20,10 und Steuererstattung 25,00: Dem Verkauf blieben -4,90 —
Zeile nicht übernommen. Den Verkauf von Hand buchen, die Erstattung als
eigene Steuererstattung., ohne Erstattung Verkauf mit Gesamtpreis -4,90:
Dem Verkauf bliebe nichts — Zeile nicht übernommen. Den Verkauf von Hand
buchen. Jede andere Gutschrift heißt Buchung, wo ein Verkauf Verkauf
heißt (Buchung mit Gesamtpreis 0,00: Der Buchung bliebe nichts — Zeile
nicht übernommen. Die Buchung von Hand erfassen.). Eine Konverter-Zeile
nennt ihren
Betrag; eine JSON-Zeile nennt ihrenamountals Gesamtpreis, ihre Zahlen in der Schreibweise der Seite (20,10, auf Englisch 20.10), die einer CSV-Zeile so, wie die Datei sie schreibt. - Eine JSON-Zeile, deren Währung Portfolixir nicht unterstützt, benannt so,
wie die Datei sie schreibt, in Großbuchstaben: Währung „EURO“ wird nicht
unterstützt — Zeile nicht übernommen für die Währung der Buchung und
Wertpapierwährung „XEU“ wird nicht unterstützt — Zeile nicht übernommen
auf jeder Zeile, die ein Wertpapier in einer solchen Währung nennt.
Portfolixir unterstützt die Währungen, die der Wertpapier-Dialog unter
Währung anbietet (EUR, USD, GBP, CHF, die übrigen dort gelisteten
ISO-Codes und GBX für Pence). Ein echter Code außerhalb dieser Liste, etwa
THB, wird wie ein falsch geschriebener abgelehnt, weil nichts in der Instanz
ihn bewerten könnte: den Code mit dieser Liste abgleichen und damit rechnen,
dass solche Zeilen draußen bleiben, während der Rest der Datei importiert
wird. Eine Zeile ohne Währung oder mit leerer bucht weiter in der Vorgabe,
EUR; ein klein geschriebener Code wie
usdwird alsUSDgelesen. Eine CSV-Zeile bucht in EUR und wird nie wegen ihrer Währung abgelehnt.
Eine Vorschau wird für den nächsten Besuch (Sprachwechsel, Neuladen) erst aufbewahrt, wenn sie einmal angezeigt wurde.
Umbuchungen in einer Portfolio-Performance-CSV
Portfolio Performance benennt eine Umbuchung nach ihrer Seite: Umbuchung
(Ausgang) ist die Seite, die das Geld oder die Stücke verlassen, Umbuchung
(Eingang) die Seite, die sie erreichen. Konto ist immer das eigene Konto
oder Depot der Zeile, Gegenkonto die andere Seite. Eine Umbuchungszeile, die
ein Wertpapier nennt, bewegt Stücke zwischen zwei Depots; eine ohne Wertpapier
bewegt Geld zwischen zwei Verrechnungskonten. Der Import bucht jede Umbuchung
einmal, in der Richtung, in die sie ging:
- Der Export Alle Buchungen von Portfolio Performance schreibt nur die Ausgangsseite, eine Zeile je Umbuchung. Er ist der Export der Wahl.
- Die eigene Buchungsliste eines Kontos oder eines Wertpapiers in Portfolio
Performance schreibt auch die Eingangsseite. Eine Datei, die nur diese Seite
trägt, bucht die Umbuchung von
GegenkontonachKonto. - Eine Datei mit beiden Seiten einer Umbuchung, etwa aus den Listen zweier Konten zusammengesetzt, bucht sie einmal, aus der Ausgangszeile. Die Eingangszeile steht unter den Parser-Warnungen, mit der Zeile, aus der gebucht wurde. Zwei Seiten gehören nur zusammen, wenn Datum, Uhrzeit, Wertpapier, Stückzahl, Betrag und beide Namen übereinstimmen; zwei verschiedene Umbuchungen werden also nie eins. Eine Umbuchung zwischen Konten in zwei Währungen trägt zwei verschiedene Beträge und wird nicht gepaart; der CSV-Import bucht ohnehin nur in EUR, JSON v1 ist das Format für andere Währungen.
Importe mit Release 2026.10.3 oder früher haben Umbuchungen anders gelesen. Drei Arten von Buchungen daraus sind falsch:
- Eine Umbuchung zwischen zwei Depots aus dem Export Alle Buchungen wurde als Geldumbuchung zwischen zwei Verrechnungskonten mit den Namen der Depots gebucht, und die Stücke blieben im abgebenden Depot. Das Zeichen dafür ist ein Verrechnungskonto mit dem Namen eines Depots auf der Seite Konten.
- Eine Eingangsseite allein wurde in der Gegenrichtung gebucht.
- Beide Seiten einer Umbuchung wurden zweimal gebucht, je einmal in jede Richtung. Die beiden heben sich auf, also zeigt kein Saldo die Umbuchung. In der Buchungshistorie nach dem Typ Umbuchung filtern: Zwei Umbuchungen an einem Datum, mit einem Betrag, zwischen denselben zwei Konten in Gegenrichtung sind ein solches Paar.
Um eine früher importierte Datei zu prüfen, diese auf der Seite Importe erneut
ablegen. Eine bereits importierte Datei zeigt in der Vorschau nichts
anzulegen; eine Zeile, die die Vorschau jetzt als neu zählt, ist eine
Umbuchung, die der frühere Import anders gelesen hat (Fälle 1 und 2 und Fall 3
zwischen zwei Depots). Die
falsche Buchung vor dem Übernehmen entfernen: mit Löschen… in ihrem
Zeilenmenü in der Historie oder über die API oder den MCP-Begleiter löschen
(DELETE /api/v1/transactions/:id, portfolixir.transactions.delete), dann
die Datei übernehmen, die die
Umbuchung so bucht, wie sie ging. Ein Verrechnungskonto mit dem Namen eines
Depots hält danach nichts mehr und kann gelöscht werden. Fall 3 zwischen zwei
Verrechnungskonten braucht keinen erneuten Import: die Buchung in der falschen
Richtung löschen; die Ausgangszeile der Datei bleibt die bereits importierte.
Fall 3 zwischen zwei Depots hat beide Seiten als Umbuchungen der Art gebucht,
die Fall 1 beschreibt: beide löschen, dann die Datei übernehmen, die eine
Wertpapierumbuchung bucht. Ob eine Instanz solche
Buchungen hat, sagt Portfolixir nicht von selbst; die Prüfung oben ist Sache
des Betreibers.
Was ein erneuter Import bewahrt
Das erneute Anwenden desselben Portfolio-Performance-Exports ist ein No-op per Inhalts-Hash: Jede bereits vorhandene Transaktionszeile wird als Duplikat übersprungen, kein Wertpapier wird doppelt angelegt, und nichts, was nach dem ersten Import in Portfolixir gepflegt wurde, wird angefasst. Auf synthetischen Fixtures verifiziert und als dauerhafter Regressionstest festgehalten, überstehen die folgenden Dinge einen erneuten Import unverändert, mit denselben ids und exakten Werten:
- Klassifizierungs-Zuordnungen (eigene Bäume und die Kategorien, in denen ein Wertpapier sitzt);
- jede Zielplan-Version mit ihren Kategorie- und Positionszielgewichten sowie das Cash-Ziel;
- die Notiz und die Attribute jedes Wertpapiers, einschließlich eigener Attributschlüssel;
- das Research-Log des Wertpapiers (die Einträge des Tabs „Research“ und der daraus abgeleitete Thesenstand);
- Wertpapier-ids und ihr
updated_at— nichts wird stillschweigend überschrieben.
Ein veränderter erneuter Import (ein umbenanntes Wertpapier, ein erfasster ISIN-Wechsel) hält dieselbe Garantie für die zugeordneten Wertpapiere; die eine wirklich neue Buchung landet, sonst ändert sich nichts. Was diese Garantie nicht abdeckt, ist eine in der Quelle geänderte Buchung: Eine bearbeitete Transaktion hasht anders und wird als neue Zeile neben der alten importiert — die alte Buchung von Hand entfernen oder korrigieren. Dieselbe Aussage steht in der API- und MCP-Referenz, damit ein Agent sie dort liest, wo er die Endpunkte liest.
Was ein erneuter Import zuerst prüft (ADR-0050)
Der Inhalts-Hash jeder Zeile wird geprüft, bevor irgendetwas aufgelöst oder angelegt wird. Eine Zeile, die die Datenbank schon hält, steht bei den bereits gebuchten Datensätzen und legt nichts an: kein Wertpapier, kein Konto, keine Transaktion. Dasselbe gilt für eine Zeile, die eine Zusammenführung entfernt hat: Ihr Hash bleibt als stillgelegter Inhalts-Hash erhalten, und das Ergebnis nennt ihn so.
Verrechnungskonten und Depots entstehen mit ihrer ersten importierten Buchung, nie vorab. Ein Konto, das auf + Neu anlegen zugeordnet ist und dessen Zeilen alle schon gebucht oder aus einem anderen Grund übersprungen sind, wird nicht angelegt, und der Bucket-Tag landet auf genau den Konten, die der Import angelegt hat. Ein importiertes Konto umzubenennen und denselben Export erneut abzulegen, legt kein leeres Konto unter dem alten Namen an.
Konten werden über den Namen gefunden, dann über einen früheren Namen. Die Vorschau belegt jedes Verrechnungskonto und Depot der Datei mit dem Konto genau dieses Namens vor, sonst mit dem Konto, das ihn als früheren Namen trägt (siehe Konten und Depots). Eine Umbenennung behält den bisherigen Namen, sodass auch ein Export, der sich in Portfolio Performance verändert hat (eine andere Nachkommagenauigkeit, eine bearbeitete Buchung), das umbenannte Konto findet und nichts doppelt bucht. Ein Name, den zwei Konten tragen, wird mit nichts vorbelegt: Die Auswahl zeigt Entscheiden…, und der Import wartet, bis das Konto gewählt ist; er rät nie. Wird eine Vorbelegung auf ein Konto anderen Namens geändert, wird die Zuordnung standardmäßig gemerkt: Der Name wird früherer Name dieses Kontos, den ein Import selbst zuordnet, sobald eine Buchung unter dem Namen importiert ist (siehe Ein Name, unter dem nichts importiert ist unten). Eine unveränderte Vorbelegung merkt nichts. Ist der Name der Name eines anderen Kontos, gilt die Wahl nur für diesen Import. Ist er früherer Name eines anderen Kontos, verschiebt das Merken ihn, und die Zeile sagt das vor dem Bestätigen („X“ wird früherer Name von A und ist dann kein früherer Name von B mehr). Das Kästchen Zuordnung merken der Zeile — angehakt und nur dort gezeigt, wo Sie eine Vorbelegung geändert haben — lässt die Zuordnung für diesen Import allein gelten, wenn Sie es abwählen. Wird ein in der Vorschau zugeordnetes Konto vor dem Bestätigen zusammengeführt oder gelöscht, hält der Import an, bevor er etwas schreibt, und die Kontenzuordnung wird neu vorbelegt.
Ein Name, unter dem nichts importiert ist. Konto- und Depotnamen gehen in den Inhalts-Hash jeder Zeile ein; wird ein Konto oder ein Depot in Portfolio Performance umbenannt und erneut exportiert, gleicht daher keine Zeile unter dem neuen Namen einer gespeicherten Buchung. Gleicht keine Zeile eines Namens einer gespeicherten Buchung, während die anderen Namen der Datei es tun, rät die Vorschau nicht, wohin der Name gehört: Die Auswahl zeigt Entscheiden…, gleich womit der Name sonst vorbelegt worden wäre — + Neu anlegen oder ein Konto, das ihn als Namen oder als früheren Namen trägt —, und die Zeile sagt Unter diesem Namen ist noch keine Buchung importiert, unter den anderen Namen dieser Datei schon. Wurde das Konto in Portfolio Performance umbenannt, hier das bestehende Konto wählen, sonst „+ Neu anlegen“. (bei einem Depot das bestehende Depot). Import bestätigen wartet, bis Sie wählen, und der Hinweis „Vor dem Import noch zuzuordnen“ darüber nennt die Zeile. Wählen Sie das bestehende Konto, das umbenannt wurde: Seine früheren Buchungen werden als bereits gebucht erkannt, nichts wird doppelt gebucht, und Zuordnung merken (angehakt) behält den neuen Namen als früheren Namen dieses Kontos, den ein Import selbst zuordnet, sobald eine Buchung unter dem neuen Namen importiert ist; bis dahin fragt die Zeile erneut, und dasselbe Konto erneut zu wählen, bucht weiterhin nichts doppelt. + Neu anlegen bucht die Zeilen auf ein neues Konto; wählen Sie es nur für ein Konto, das wirklich neu ist. Ein erster Import und eine Datei, in der kein Name oder jeder Name gespeicherten Buchungen gleicht, wird wie bisher vorbelegt.
Was jede Zeile des Zuordnungsschritts sagt. Jedes Verrechnungskonto und Depot der Datei zählt seine Buchungen: wie viele bereits importiert sind, wie viele interne Umbuchungen entfallen und wie viele neu sind, oder nichts anzulegen, wenn keine neu ist. Die Zählung ist das, was der Import unter der Vorbelegung tun wird: Eine Buchung ist bereits importiert, wenn ihr Inhalt einer früher gespeicherten gleicht oder wenn auf dem Konto, zu dem der Name führt, schon eine Buchung mit demselben Tag, derselben Art und denselben Beträgen steht — der Fall eines erneut gespeicherten Exports, nachdem Sie zwei seiner Konten zusammengeführt haben —, und eine Umbuchung zwischen zwei Namen, die jetzt zu einem Konto führen, entfällt. Eine Entscheidung, die Sie in der Vorschau noch treffen (ein Wertpapier, ein anderes Konto), kann ändern, was mit den neuen Buchungen einer Zeile geschieht. Eine Vorbelegung über einen früheren Namen sagt das unter der Auswahl. Eine Zeile, von deren Buchungen keine neu ist, zeigt gar keine Auswahl: Sie sagt Keine Zuordnung nötig: Der Import bucht unter diesem Namen nichts, behält das Konto, dem sie zugeordnet wurde, und hält Import bestätigen nie auf. Zwei Zeilen behalten ihre Auswahl trotzdem: ein Name, den die gespeicherte Historie nie gesehen hat (oben), und ein Verrechnungskonto, mit dem ein Depot mit neuen Buchungen abrechnet. Eine Datei ganz ohne Neues sagt das am Kopf der Vorschau, zeigt keinen Bucket-Tag, und ihre Bestätigung bucht nichts. Zwei Konten gleichen Namens werden in der Liste durch das unterschieden, was abweicht — bei einem Verrechnungskonto seine verknüpften Depots, sonst seine Währung, sonst der Tag, an dem es angelegt wurde; bei einem Depot sein Verrechnungskonto —, und eine mehrdeutige Zeile nennt ihre Kandidaten ebenso. Namen, die gleich gedruckt werden, gelten dort als ein Name, etwa einer mit doppeltem Leerzeichen, obwohl der Import die Namen einer Datei exakt vergleicht. + Neu anlegen für einen Namen, den der Import nicht anlegen darf (der Name eines anderen Kontos, ein früherer Name eines anderen Kontos oder der Name mehrerer Konten), bleibt in der Liste, gesperrt, mit dem Grund, sodass nichts, was Sie wählen, den Import am Ende scheitern lässt.
Umbenennungen von vor diesem Release werden ebenfalls gemerkt: das Update spielt die Umbenennungen nach, die das Audit-Journal hält. Einen Namen, den ein neueres Konto schon trägt (etwa ein leeres Konto, das ein früherer Import unter dem alten Namen angelegt hat), protokolliert das Update und lässt ihn, wo er ist; dieses Konto in das umbenannte zusammenzuführen, behebt das. Eine Umbenennung, die älter ist als das Audit-Journal der Konten, hat keine Spur hinterlassen; ihr alter Name wird einmal von Hand zugeordnet.
Eine Umbuchung, deren beide Seiten auf dasselbe Konto oder Depot führen (etwa zwei Portfolio-Performance-Konten, die auf ein Portfolixir-Konto zugeordnet sind), ist nichtig. Sie wird übersprungen und bei den internen Umbuchungen mit Zeile, Art, Datum und beiden Namen aus der Datei aufgeführt, und der Rest der Datei wird importiert; sie lässt nicht mehr den ganzen Import scheitern.
Das Ergebnis listet jeden übersprungenen Datensatz, gruppiert nach der Prüfung, die ihn übersprungen hat: eine identische, schon importierte Zeile (gespeicherter Inhalts-Hash; die erwartete Masse eines erneuten Imports, deshalb bleibt ihre Gruppe zugeklappt), eine Zeile, die eine Zusammenführung entfernt hat (stillgelegter Inhalts-Hash), oder eine bestehende Buchung mit demselben Datum, Wertpapier, derselben Stückzahl und demselben Betrag. Es listet außerdem die gemerkten Namen (und bei einem verschobenen Namen das Konto, das ihn abgab) und jede Buchung, die am oder vor einem gesetzten Stand liegt, den eine Zusammenführung angepasst hat: Diese Buchung wird importiert, und dieser Stand nimmt ihren Betrag auf, sodass der Saldo des Kontos bleibt, wo der gesetzte Stand ihn festlegt.
Eine von einer Zeile abgespaltene Steuererstattung (etwa eine negative Steuer auf einen Verkauf) wird mit dieser Zeile gehasht und für sich geprüft: Zwei gleiche Erstattungen zweier verschiedener Verkäufe werden beide gebucht, und ein erneuter Import der Datei bucht keine doppelt. Ein von Hand gelöschter Verkauf wird wieder gebucht, ohne dass seine Erstattung ein zweites Mal gebucht wird, und eine Erstattung, die in Portfolio Performance zu einem schon importierten Verkauf hinzukam, wird beim nächsten Import gebucht. Eine Erstattung, deren Zeile nicht importiert wird, wird mit ihr übersprungen. Innerhalb einer Datei wird eine Zeile, die eine frühere genau wiederholt, einmal gebucht, und die Wiederholung steht bei den bereits gebuchten.
Bereits importiert, mit anderem Betrag
Eine Buchung behält den Inhalts-Hash, mit dem sie importiert wurde: Denselben Export erneut abzulegen, bucht nichts, und der Hash findet diese Buchung auch wieder. Zwei Lesarten einer Portfolio-Performance-Zeile haben sich nach den ersten Versionen geändert (ADR-0053 und seine Ergänzung vom 07.10.2026):
- eine CSV-Zeile bucht ihren
Gesamtpreis, wo sie früher den Bruttowert aus Portfolio Performance buchte, denBetrag; - eine Zeile mit negativer Steuer bucht ihr Geld abzüglich der daneben
gebuchten Erstattung, wo sie früher ihr ganzes Geld buchte und die
Erstattung noch einmal dazu (der
amounteiner JSON-Zeile, derBetrageiner von einem Konverter geschriebenen Zeile), und ein JSON-Kauf oder -Verkauf erhält seinen Kurs aus dem Bruttowert.
Enthält eine abgelegte Datei (eine Portfolio-Performance-CSV, eine von einem Konverter geschriebene CSV oder ein JSON-v1-Export) Zeilen, deren Inhalts-Hash eine gespeicherte Buchung trägt, und weicht das Geld dieser Buchung von dem ab, was die Zeile heute bucht, listet die Vorschau sie in einem eigenen Abschnitt auf, Bereits importiert, mit anderem Betrag, vor der Kontenzuordnung. Jede Zeile nennt die Zeilennummer, das Datum und die Buchung (ihre Art, ihr Wertpapier und ihr Konto) sowie ihr Geld gebucht, korrigiert (was die Korrektur schreibt, das Geld, das die Zeile heute bucht) und die Differenz, mit Vorzeichen, wie das Konto sie sieht (eine Belastung ist negativ). Ein Handel in fremder Währung zeigt zusätzlich seine Abrechnung vorher und nachher, ein JSON-Handel seinen Kurs. Unter der Liste stehen die Summe je Konto und N Buchungen korrigieren….
Die Korrektur ist ein eigener Schritt, unabhängig von Import
bestätigen: Den Import zu bestätigen, ändert nie eine Buchung, die er als
bereits importiert findet, ob der Abschnitt gezeigt wird oder nicht. N
Buchungen korrigieren… öffnet einen Dialog, der sagt, wie sich jedes Konto
ändert und was sich mit einem Handel ändert. Seine Bestätigung schreibt dann
für jede aufgelistete Buchung ihr Geld neu; bei einem JSON-Kauf oder -Verkauf
auch seinen Kurs; und bei einem Handel in fremder Währung auch seinen
Abrechnungsbetrag, seinen Betrag in Wertpapierwährung und den Kurs der
Abrechnung, im selben Schreibvorgang. Sonst ändert sich nichts: nicht die ID
der Buchung, ihr Inhalts-Hash, ihre Gebühren oder Steuern, auch nicht der
Kurs einer CSV-Zeile (ihr Kurs). Jede Änderung wird mit den Werten, die sie
ersetzt, im Audit-Journal unter dem Betreiber festgehalten, gekennzeichnet
als import correction; Kontostände, Bewertung, Renditen und Erträge werden
aus den korrigierten Buchungen neu berechnet. Eine Zeile an der Stelle des
Abschnitts sagt danach, wie viele Buchungen korrigiert wurden und was sich
auf jedem Konto bewegt hat.
Die Inhalts-Hashes bleiben, wie sie sind: Dieselbe Datei erneut abzulegen, bucht nichts und zeigt keinen Abschnitt, denn es bleibt nichts zu korrigieren. Stimmt jede gespeicherte Buchung mit der Datei überein, gibt es keinen Abschnitt. Bestätigst du zuerst den Import, sagt sein Ergebnis, wie viele Buchungen unkorrigiert geblieben sind; lege dieselbe Datei erneut ab, um sie zu korrigieren.
Die Korrektur braucht die Datei, weil keine gespeicherte Buchung festhält, aus welchem Format sie stammt. Sie findet eine Buchung über den Inhalts-Hash, den ihre Zeile noch trägt: Eine Zeile, die sich seither in Portfolio Performance geändert hat (eine bearbeitete Buchung, eine verschobene Uhrzeit), trifft keinen gespeicherten Hash, wird über Datum, Wertpapier, Stückzahl und Betrag als bereits gebucht erkannt und nicht aufgelistet. Wie der Import ist die Korrektur eine Handlung des Betreibers, ohne API-Route und ohne MCP-Tool; ein Agent liest die korrigierten Buchungen über jeden bestehenden Lesezugriff.
Wertpapier-Matching und der Zuordnungsschritt
Wertpapiere in der Datei werden über eine deterministische Leiter stabiler Identitäten (ADR-0029) gegen die bestehenden Einträge aufgelöst: zuerst ISIN — aktuelle ISINs, dann erfasste Alt-ISIN-Aliase —, dann WKN, dann Ticker+Währung, dann Name+Währung. Jede Stufe greift nur, wenn der Identifikator auf beiden Seiten vorhanden ist und genau einen Kandidaten auswählt. Das Matching verändert die Stammdaten des getroffenen Wertpapiers nie: eine Umbenennung im Export ändert implizit nichts.
Das Vorschau-Panel Wertpapiere aus dem Export zeigt das Ergebnis:
- Treffer werden als aufklappbare Liste zusammengefasst, jeder mit der Stufe beschriftet, die ihn getroffen hat (zum Beispiel über frühere ISIN zugeordnet nach einem erfassten ISIN-Wechsel).
- Einfache neue Wertpapiere bleiben als Zusammenfassung eingeklappt; die Liste aufklappen, um einzelne stattdessen auf ein bestehendes Wertpapier umzumappen.
- Entscheidungen werden prominent angezeigt und blockieren den Import, bis sie aufgelöst sind: ein mehrdeutiger Identifikator (zwei Wertpapiere teilen eine WKN oder Name+Währung) oder ein Kandidat, der einem stärkeren Identifikator widerspricht — die typische Form eines noch nicht erfassten ISIN-Wechsels. Der Import wählt in diesen Fällen nie stillschweigend aus.
- Konfigurations-Warnungen: Wenn ein anzulegendes Wertpapier einem bestehenden ähnelt, das Kategorie-Zuordnungen oder Positionsziele trägt, verlangt die Zeile eine eigene ausdrückliche Bestätigung — ein Duplikat würde diese Konfiguration auf einer bestandslosen Zeile stranden lassen. Ein Name, der einem gespeicherten nur ähnlich sieht (unsichtbare Zeichen, Doppelgänger-Buchstaben aus einer anderen Schrift, andere Groß- und Kleinschreibung oder Leerzeichen), gilt als solche Ähnlichkeit, und die Zuordnung selbst übergeht unsichtbare Zeichen in Namen.
- Keine Entscheidung, wo nichts gebucht würde: Ist jede Buchung eines Wertpapiers, das eine Entscheidung oder Bestätigung verlangt, bereits importiert — ihr Inhalt gleicht einer gespeicherten Buchung, einer, die eine Zusammenführung entfernt hat, oder einer früheren Zeile derselben Datei — oder eine Zeile, die der Import ohnehin überspringt (ein Betrag von null), zeigt die Zeile N Buchungen bereits importiert · nichts anzulegen und dass keine Entscheidung nötig ist, und sie blockiert den Import nicht mehr; auch unter den neuen Wertpapieren zählt ein solches nicht mit. Der Import prüft den Inhalt einer Buchung, bevor er ihr Wertpapier zuordnet, eine Wahl dort würde also nie verwendet: Nur ein ISIN-Wechsel, den Sie auf der Zeile erfassen, wird trotzdem wirksam. Ein Wertpapier mit einer neuen Buchung braucht weiter seine Entscheidung, und zwei Wertpapiere der Datei, die sich nicht unterscheiden lassen, lassen den Import weiter scheitern.
Wird ein Eintrag ummappt, dessen ISIN von der aktuellen ISIN des gewählten Wertpapiers abweicht, bietet die Vorschau an, die Differenz im selben Schritt als ISIN-Wechsel zu erfassen, sodass die Entscheidung für künftige Importe erhalten bleibt statt jedes Mal wiederholt zu werden.
Ein zweites Panel listet jedes konfigurierte Wertpapier, das der Import nicht berührt: Wertpapiere mit Zuordnungen oder Positionszielen, die zu keinem Eintrag der Datei passen — vermutlich eine Umbenennung oder ein ISIN-Wechsel in Portfolio Performance. Abhilfe: den ISIN-Wechsel am Wertpapier erfassen (oder, ohne ISIN, das Wertpapier in der App passend umbenennen bzw. in der Vorschau neu zuordnen), dann den Import erneut starten.
Zwei weitere Sicherungen greifen beim Anwenden: Das Matching wird in der Import-Transaktion erneut geprüft, und das Anwenden bricht zur Vorschau ab, wenn sich etwas anders auflöst als im bestätigten Stand (Vorschauen können länger offen stehen); und Zeilen, die sich zur selben Buchung auf demselben Wertpapier auflösen — ein Export, der ein Papier unter alter und neuer ISIN führt — werden zu einer Transaktion zusammengefasst und ausgewiesen, nie doppelt importiert. Zusammengefasst werden nur Zeilen desselben Portfolio-Performance-Kontos: Zwei gleiche Buchungen aus zwei verschiedenen Konten der Datei, die auf ein Konto zugeordnet sind (etwa zwei gleiche Gebühren), werden beide importiert.
Ein-/Auslieferungszeilen behalten ihren geparsten Stückpreis (die
CSV-Spalte Kurs), sodass eine Einlieferung mit Preis mit ihrem echten
Einstand in den Einstandswert der Bestände eingeht. Eine Lieferzeile ohne
Preis wird weiterhin importiert und bewegt die Menge zum Einstand null, wie
unter Bestandsberechnung beschrieben.
Zeilen mit unplausiblen Daten (vor 1900, z. B. ein 0219-03-07-Tippfehler für
2019) werden je Zeile mit einer klaren Meldung abgelehnt, statt jede abgeleitete
Kennzahl zu vergiften — korrigiere die Buchung in der Quelle und importiere
erneut; die Inhalts-Hashes halten den Wiederholungslauf frei von Duplikaten. Nach
einem Import läuft die Kurs- und Logo-Anreicherung für die angelegten Wertpapiere
als ein gedrosselter Hintergrund-Job, sodass die App reaktionsschnell bleibt,
während Hunderte Wertpapiere synchronisiert werden.
Kurse und Charts
Kurshistorie
Jeder Kurseintrag erfasst ein Datum und einen Decimal-Schlusskurs. Die Preishistorie wird persistiert, sodass Wertpapier-Detailcharts aus lokalen Datensätzen gebaut werden.
Zwei Wege, auf denen Kurse ins System gelangen:
- Automatische Synchronisierung: ein Hintergrund-Scheduler tickt alle sechs
Stunden (konfigurierbar in
config :portfolixir, Portfolixir.Catalog.QuoteSync) und zieht tägliche Schlusskurse vom konfigurierten Anbieter jedes Wertpapiers. - Jetzt synchronisieren: der Button Sync prices in der Toolbar (und der Button je Wertpapier auf der Detailseite) löst eine sofortige Synchronisierung aus, ohne auf den nächsten Tick zu warten.
Kursquellen in dieser Iteration:
- Der Suchschritt (aus welchem Katalog das Wertpapier stammt) nutzt Portfolio
Performance für Aktien/ETFs/Fonds und CoinGecko für Krypto. Der
Anlage-Dialog bietet zusätzlich Manuelle Eingabe (auch aus dem
Suchschritt verlinkt) für Instrumente, die kein Anbieter kennt — direkt
zum Detailformular, gespeichert mit dem Provider-Marker
manual. Handelt ein gefundenes Wertpapier an mehreren Märkten, wird der empfohlene Markt (XETR, sonst der erste EUR-Markt) zuerst mit seinem Börsen-Klarnamen angeboten; die übrigen Märkte liegen hinter einer Aufklappung Weitere Märkte. - Neue Wertpapiere starten bei Konfiguration eine Hintergrund-Kurs-/Logo-
Anreicherung. Die Logo-Erkennung läuft über eine einzelne Hintergrund-
Warteschlange, scannt beim Start fehlende Logo-Kandidaten und wird auch nach
Importen ausgelöst. Die ETF-Logo-Erkennung probiert bekannte Emittentennamen
vor dem einzelnen Fondsnamen (zum Beispiel iShares, Vanguard, Lyxor, Amundi,
Xtrackers, SPDR, Invesco). Staatsanleihen nutzen die Anlageklasse
government_bondfür ISIN-Länderflaggen-Fallbacks. - Der Kurshistorien-Abruf nutzt Yahoo Finance für beide. Zwei Gründe:
- PPs eigene API bietet nur Suche, keine Preishistorie.
- CoinGeckos kostenlose öffentliche API begrenzt die Historie auf 365 Tage
(
error_code 10012); Yahoo liefert die volle tägliche Reihe für Krypto über die Symbolform<TICKER>-<CURRENCY>(z. B.BTC-USD).
- Portfolio Performance search can provide symbols for some bonds and leveraged products. Yahoo remains usable when a suitable symbol exists und auf dem Wertpapier gespeichert ist.
- Ariva is not used as a quote adapter. Sein historischer Endpunkt für Hebelprodukte ist derzeit für diesen lokalen Standard-Anwendungsfall blockiert.
- Bundesbank is relevant for German federal securities and yield data, not a general ISIN quote provider.
- No API-key-based providers und keine inoffizielle Scraping-Abhängigkeit werden als Standard-Kursquellen verwendet.
- No new bond or leveraged-product quote adapter is implemented in this batch.
Yahoo wird mit period1=0 und period2=<now> abgefragt, sodass es die volle
verfügbare tägliche Historie liefert — range=max rechnet bei Tickern mit langer
Historie still auf monatlich herunter.
Wertpapiere, deren Anbieter keinen Kurs-Adapter hat oder deren Adapter nicht laufen kann, weil Pflichtfelder wie der Ticker fehlen, werden mit einem Grund als übersprungen gemeldet. Fehlgeschlagene Adapter-Aufrufe werden getrennt von erfolgreichen Synchronisierungen gemeldet.
Von Hand eingetragene Kurse gewinnen gegen synchronisierte: Die
Synchronisierung überschreibt nie eine gespeicherte Zeile mit der Quelle
manual, auch wenn die Anbieter-Historie dasselbe Datum abdeckt. Jede
Synchronisierung meldet, wie viele manuelle Zeilen sie unangetastet gelassen
hat, und protokolliert eine Warnung, wenn diese Zahl größer als null ist.
Wer einen Kurs von Hand bearbeitet, überschreibt weiterhin den gespeicherten
Wert — auch zuvor synchronisierte.
Ein Kurs, der nicht zu den Buchungen passt (Issue #1101)
Ein Ticker oder eine Online-ID, die auf eine andere Notierung zeigt, speichert frische Kurse des falschen Instruments. Der Bestand wird mit ihnen bewertet, und weil der Kurs aktuell ist, markiert ihn sonst nichts. Deshalb werden die gespeicherten Kurse jedes gehaltenen Wertpapiers mit seinen eigenen Buchungen verglichen: Für jeden Kauf, Verkauf und jede bepreiste Einlieferung wird der gespeicherte Kurs am Tag der Buchung, oder der letzte innerhalb von 7 Tagen davor, mit dem Preis je Stück der Buchung in der Währung des Wertpapiers verglichen (eine Buchung in anderer Währung mit ihrem Bein in der Wertpapierwährung). Das Wertpapier wird genannt, wenn dieser Kurs bei mindestens einer Buchung unter der Hälfte oder über dem Doppelten des Preises je Stück der Buchung liegt. Eine Aktie, die auf das Zwanzigfache gestiegen ist, wird nie genannt, weil jede ihrer Buchungen zum Kurs ihres eigenen Tages passte; ein vom ersten Tag an falsch zugeordneter Ticker wird genannt, ebenso ein Pence-/Pfund-Fehler.
- Eine Buchung zum Preis 0 — Gratisaktien, eine Einlieferung ohne Kosten — hat kein Verhältnis und wird übersprungen, und eine Buchung ohne Kurs in ihrem Fenster wird nicht verglichen.
- Kurse und Preise werden auf einer Split-Basis verglichen: Die rückwirkend bereinigten Kurse eines Anbieters werden so gelesen, wie am Tag der Buchung gehandelt wurde, ein erfasster Split wird also nicht genannt. Ein nicht erfasster Split wird genannt: den Split erfassen (der Split-Assistent auf der Seite des Wertpapiers), dann verschwindet der Befund.
- Eine Anleihe, die der Zwei-Skalen-Wächter nennt (siehe Anleihen), wird hier nicht noch einmal gezählt. Eine Anleihe mit 1.000er Stückelung, je Stück gebucht neben Prozentkursen, etwa ein Zehntel ihres gebuchten Preises, liegt außerhalb beider Zwei-Skalen-Bänder und wird hier genannt; ihre Korrektur ist die gebuchte Stückzahl.
Der Befund ist ein Problem: Gebuchter Preis und Kurs sind zwei
gespeicherte Fakten über einen Tag, mehr als einen Faktor zwei auseinander,
also ist entweder der Wert (ein falscher Kurs) oder Einstand und Ergebnis
(eine falsche Buchung) in den Summen falsch. Die Datenqualitätszeile der
Übersicht zählt die gehaltenen Wertpapiere, die er nennt („2 gehaltene
Wertpapiere, deren Kurse nicht zu ihren Buchungen passen”), und verlinkt auf
?dq=implausible_quote, wo sie unter dem entfernbaren Chip Kurs passt
nicht zu Buchungen stehen; Vermögen → Bestände nennt jede Position seines
Bereichs mit der Buchung und dem Kurs ihres Tages und verlinkt auf den Tab
Kurse des Wertpapiers. Der Agent liest dieselbe Menge, mit der Buchung,
der jedes Wertpapier widerspricht, und der Regel, über
GET /api/v1/securities?data_quality=implausible_quote. Nichts wird
umgerechnet.
Was ihn aufhebt. Zuerst die Kursquelle prüfen (Ticker, Börse), dann die Buchung. Der Yahoo-Adapter holt bei jeder Synchronisierung die ganze Reihe, die erste Synchronisierung nach korrigierter Zuordnung schreibt also die Kurse an den Buchungstagen neu. Ein Tag, an dem die neue Notierung nicht handelt, behält den alten Kurs, und ein manueller Kurs wird nicht überschrieben, bis er freigegeben (siehe Manuelle Kurse freigeben unten) oder von Hand korrigiert wird.
Manuelle Kurse freigeben (T-9)
Jeder Kurs, den die API oder Ihr Agent schreibt, wird als manuell gespeichert, und ein manueller Kurs gewinnt gegen den des Anbieters. Um Tage an den Anbieter zurückzugeben, öffnen Sie den Tab Kurse des Wertpapiers. Hat das Wertpapier manuelle Kurse, zählt eine Notiz über der Tabelle sie über die ganze gespeicherte Historie — nicht nur über den Zeitraum der Tabelle — mit dem ersten und letzten Datum (7 manuelle Kurse in der gespeicherten Historie, vom 2026-06-30 bis 2026-09-16.; alle gespeicherten Kurse sind manuell, wenn das so ist). Ihr Freigeben… öffnet einen Dialog mit dem Wertpapier im Titel:
- Von und Bis sind mit dem ersten und letzten manuellen Datum vorbelegt; beide sind eingeschlossen. Chips darunter füllen das Paar: Alle und jeder Abschnitt manueller Kurse (eine Folge ohne Kurs des Anbieters dazwischen, die fünf jüngsten), jeweils mit seiner Zahl; sind es mehr als fünf, sagt eine Zeile unter den Chips, wie viele es sind, und Alle umfasst jeden.
- Ein Satz sagt, was geschieht: Die manuellen Schlusskurse im Zeitraum werden entfernt und mit ihren Werten im Audit-Journal festgehalten, die Kurse des Anbieters im Zeitraum bleiben, und die nächste Kursaktualisierung speichert für diese Tage den Schlusskurs des Anbieters — bis dahin haben sie keinen Kurs. Kann die Kursaktualisierung das Wertpapier nicht abfragen — kein Adapter für seinen Anbieter, oder ein Anbieter, der einen Ticker braucht, den das Wertpapier nicht hat —, sagt eine Achtung-Notiz, dass die freigegebenen Tage ohne Kurs bleiben.
- Die Bestätigung nennt, wie viele manuelle Kurse der Zeitraum enthält (7 manuelle Kurse freigeben), und nur sie gibt frei: Enter in einem Datumsfeld zählt neu und prüft das Paar, mehr nicht. Ein Zeitraum ohne manuellen Kurs lässt die Bestätigung deaktiviert, mit dem Grund daneben; ein Bis vor seinem Von oder ein Feld, das kein Datum ist, wird am Feld genannt, und nichts wird geschrieben. Enthält der Zeitraum beim Bestätigen inzwischen eine andere Zahl manueller Kurse (Ihr Agent hat einen geschrieben oder freigegeben), wird ebenfalls nichts geschrieben: Der Dialog nennt die neue Zahl und bittet, erneut zu bestätigen.
Manuelle Kurse freigeben, auf dem synthetischen Demo-Datensatz.
Nach der Freigabe sagt der Tab, wie viele Kurse von wann bis wann freigegeben wurden, mit Kurse aktualisieren als nächstem Schritt, wo eine Aktualisierung helfen kann — sie aktualisiert nur dieses Wertpapier —, bis Sie die Meldung schließen oder weitergehen. Nichts auf der Seite stellt einen freigegebenen Kurs wieder her; das Journal hält ihn fest. Auf dem Telefon öffnet sich der Dialog als Blatt von unten.
Das Ergebnis einer Kursaktualisierung sagt, wie viele manuelle Kurse stehen
blieben, wo der Anbieter für denselben Tag einen Schlusskurs lieferte (2
manuelle Kurse blieben stehen, wo der Anbieter einen Schlusskurs lieferte.);
eine Aktualisierung, die ein Wertpapier übersprungen hat, sagt in Worten,
warum. Auf dem Telefon zeigt der Kurse-Tab jeden Kurs als zweizeilige Zeile —
das Datum über seiner Quelle, rechts der Schlusskurs und darunter der
gespeicherte Wert, wo ein Split den Kurs angepasst hat —, sodass die Quelle
jedes Kurses ohne Wischen durch die Tabelle lesbar ist, und die Kursbasis-Zeile
über den Zeilen nennt diese Zeile statt der Spalte Gespeichert der Tabelle.
Ihr Agent liest dieselbe Zusammenfassung mit
GET /api/v1/securities/:security_id/quotes/manual (MCP
portfolixir.quotes.manual) und gibt mit portfolixir.quotes.release frei.
Wertpapier-Detailchart
Ohne ausgewähltes Wertpapier füllt die Wertpapierliste den Arbeitsbereich der
Seite. Ein Klick auf eine Zeile öffnet /securities/:id in einem vertikal
geteilten Arbeitsbereich: die Liste bleibt im oberen scrollbaren Bereich und der
gewählte Detailbereich öffnet sich darunter. Der horizontale Trenner kann am
Desktop gezogen oder per Tastatur angepasst werden; mobil wird ein gestapeltes
Layout genutzt.
Die Reiterzeile des Detailbereichs ist ein einziger Tastaturstopp: Tab landet auf dem gewählten Reiter, Pfeil links/rechts wechseln zum vorigen oder nächsten Reiter (am Ende geht es von vorn weiter), Pos1 und Ende springen zum ersten und letzten, und der Reiter, der den Fokus erhält, öffnet seinen Bereich. Öffnet die Seite auf einem Reiter — über einen Link, ein Neuladen, Zurück oder Vor oder eine geteilte Adresse —, rollt die Zeile diesen Reiter ins Bild; das zählt auf dem Telefon, wo die neun Reiter nicht hineinpassen.
Der Detailbereich zeigt einen serverseitig gerenderten SVG-Preischart mit:
- Zeitraum-Buttons (1M / 3M / 6M / YTD / 1J / 3J / 5J / Max). Der Kurse-Tab nennt denselben Zeitraum.
- Einem Schalter Log scale (logarithmische Y-Achse).
- Einem Schalter Show transactions, der Kauf-/Verkauf-Marker aus dem Ledger überlagert — formcodierte Dreiecke (▲ Kauf, ▼ Verkauf), die Richtung ist also ohne Farbe erkennbar.
- Einem Button Sync prices for this security.
Aktiensplits und die Kursbasis (ADR-0028). Nach dem Buchen eines Splits zeigen Chart und Kurse-Tab eine split-bereinigte Serie, die zur Lesezeit abgeleitet wird: manuell erfasste (rohe, wie gehandelte) Schlusskurse vor dem Wirksamkeitsdatum werden durch das kumulierte Verhältnis aller späteren Splits geteilt, während anbieter-synchronisierte Zeilen — vom Anbieter bereits rückwirkend angepasst — unverändert durchlaufen; nichts wird doppelt angepasst. Die wirksame Basis („split-bereinigt“, „anbieterbereinigt“ oder gemischt) steht unter dem Chart und auf dem Kurse-Tab, dessen Tabelle eine Spalte Gespeichert mit den unveränderten Werten behält — gespeicherte Kurshistorie wird nie verändert, und das Löschen eines versehentlich gebuchten Splits stellt jeden Chart und jede Kennzahl exakt wieder her. Bestände, Bewertungen, Performance-Serien, Snapshot-Vergleiche und die Kennzahlen der Wertpapierliste preisen über dieselbe basisbewusste Engine, sodass ein alter Vor-Split-Kurs (oder der Rückgriff auf den letzten eigenen Handelspreis) eine Nach-Split-Position nie zum unbereinigten Preis bewertet. Für Anbieter, die ihre Historie nie rückwirkend anpassen, bieten die Stammdaten des Wertpapiers (hinter Bearbeiten in der Kopfzeile der Detailansicht) den Schalter Synchronisierte Kurse als roh behandeln, der die Roh-Basis für dessen synchronisierte Zeilen erzwingt. Die Splits eines Wertpapiers, jeder mit seinem eigenen Betrag gezählt (2:1 und 1:2 zählen beide 2), multiplizieren sich auf höchstens 10^12: Der Split-Assistent lehnt ein Verhältnis darüber ab und bucht nichts, denn keine echte Aktienhistorie kommt in die Nähe.
Der Reiter Übersicht liest, Bearbeiten schreibt. Die Detailansicht öffnet auf Übersicht, einer Lesefläche (Issue #804): sechs Kennzahlen — letzter Kurs mit Datum oder Veraltet-Marker, Tagesänderung, die Ein-Jahres-Kursrendite, die gehaltene Stückzahl mit dem Depot, der Wert der Position und das unrealisierte Ergebnis mit seinem Prozentsatz gegen den Durchschnittseinstand — darunter der Kursverlauf als kleiner Chart und eine Basiszeile mit Kursquelle, Anlageklasse, der zugeordneten Kategorie eines eigenen Klassifizierungsbaums sowie WKN und Börse, die die Kopfzeile nicht trägt. Der aus dem Research-Log abgeleitete Thesenstand (ADR-0044) und die persönliche Notiz stehen als Karten daneben; die Thesenkarte führt zum Reiter Research, und die Notiz zeigt erst nach Hinzufügen oder Bearbeiten ein Feld. Vorher rendert der Reiter kein Eingabefeld. Die Stammdaten — Name, Identifikatoren, Währung, Börse, Anlageklasse, Kursquelle und deren URL, der Roh-Kurse-Schalter und die Notiz — liegen im Dialog, den Bearbeiten in der Kopfzeile öffnet; es ist derselbe Dialog wie im Zeilenmenü der Liste.
Einen Split erfassen. Der Button Split erfassen in der Detailansicht öffnet einen geführten Assistenten: Verhältnis als neu:alt eingeben (2:1 verdoppelt die Stückzahl, 1:10 ist ein Reverse Split) und den Stichtag wählen — der Dialog zeigt die Wirkung live als Vorschau: Stückzahl vor und nach dem Stichtag plus die resultierende aktuelle Position, eine Zeile je betroffenem Portfolio — zusammen mit jeder Warnung, bevor irgendetwas geschrieben wird: ein Stichtag vor der importierten Historie (die Stückzahlen können bereits nach-Split sein) und die Kursbasis-Prüfung der gespeicherten Schlusskurse rund um den Stichtag (Widerspruch oder zu wenige Kurse zur Prüfung). Das Bestätigen bucht dasselbe erstklassige Split-Ledger-Ereignis, das auch API und MCP-Werkzeuge anlegen — eine journalisierte Transaktion je positioniertem Portfolio, atomar — und Chart, Bestände und Transaktionen aktualisieren sich sofort. Ungültige Eingaben (ein 1:1-Verhältnis, ein Datum in der Zukunft, keine gehaltene Position oder ein zweiter Split am selben Tag, der unter Nennung des bereits gebuchten Ereignisses abgelehnt wird) bleiben inline im Dialog.
Verhalten der Oberfläche
- Der aktive Seitentitel und eine kurze Kontextzeile leben in der oberen Leiste. Der Seiteninhalt beginnt direkt mit einem Arbeitsbereich über die volle Breite, sodass jede aktive Menü-Route den verfügbaren Platz ohne wiederholte Seitenüberschrift oder äußere Seitenränder nutzt.
- Die Wertpapierliste nutzt einen Arbeitsbereich über die volle Breite statt generischer Panel-Optik; die Toolbar bleibt am oberen Rand des Arbeitsbereichs fixiert, und die Tabelle nutzt darunter die volle horizontale Breite.
- Aktions-Feedback erscheint im Seitenfluss, nicht als schwebender Toast: Während eine Hintergrund-Aktion läuft (Kurs-Sync, Logo-Suche), zeigt das auslösende Bedienelement einen Beschäftigt-Zustand, und das Ergebnis erscheint im Seitenfluss nahe den Bedienelementen — Erfolg als Hinweis, ein Fehlschlag als Problem-Hinweis mit Begründung. Ein Ergebnis bleibt sichtbar bis zur nächsten Aktion, einer Navigation oder dem expliziten Schließen-Knopf; nichts verschwindet über einen Timer.
- In einem Klassifizierungsbaum sind Kategorien standardmäßig eingeklappt (klicke eine Kategorie, um sie aufzuklappen); die Suche klappt die passenden Kategorien auf. Lange Wertpapiernamen werden auf eine Zeile gekürzt, mit dem vollen Namen beim Überfahren, und der Ticker wird neben dem Namen gezeigt.
- Jedes zugeordnete Wertpapier zeigt seine aktuelle Menge (über jedes Wertpapierkonto jedes Portfolios summiert) und seinen aktuellen Marktwert im EUR-Hub, bewertet aus dem letzten Kurs (mit Rückfall auf den zuletzt eigenen Handelspreis, wie die Portfoliobewertung). Bestände und Werte werden einmal für den ganzen Baum geladen, nachdem die Seite verbunden ist, sodass ein großer Baum nie eine Abfrage je Zeile auslöst.
- Ein Schalter Current positions only ist standardmäßig an. Er verbirgt Wertpapiere, die nicht mehr gehalten werden (aktuelle Menge null), sodass alte oder vollständig verkaufte Zuordnungen den Baum nicht überladen. Nichts wird still verworfen: jede Kategorie zeigt einen Zähler +N without holdings für die verborgenen Wertpapiere, und das Ausschalten des Schalters zeigt sie wieder.
- Jede Kategoriezeile aggregiert den Wert und die Positionsanzahl der aktuell in ihr und ihren Unterkategorien sichtbaren Wertpapiere, sodass die Summen dem Schalter folgen. Seit Issue #805 (C8 des Reviews vom 2026-09-12, Variante A) stehen die Zahlen in benannten, rechtsbündigen Spalten unter einem Kopf — Positionen · Wert · Einstand · Ergebnis — eine leere Kategorie zeigt 0 Positionen und für Wert, Einstand und Ergebnis ein gedämpftes „—” statt einer Reihe Nullen (eine Anzahl ist immer eine Zahl; der Strich sagt, dass es keine Zahl zu nennen gibt), der Prozentwert des Ergebnisses lautet „+13,7%”, der Zähler der verborgenen Positionen ist ein gedämpftes Suffix des Kategorienamens, und die Basis des Ergebnisses („heutige Zusammensetzung, keine Periodenrendite”) ist eine Basiszeile mit ⓘ; auf dem Telefon behält die Zeile Wert und Ergebnis, auf zwei Zeilen: der Kategoriename (umbrochen statt abgeschnitten) mit dem Zähler der verborgenen Positionen oben, Wert und Ergebnis darunter unter ihren Spaltenköpfen.
- Die Seitenleiste ist in aufgabenorientierte Bereiche organisiert (ADR-0022): Übersicht, Vermögen, Wertpapiere und Transaktionen auf der obersten Ebene, plus eine Gruppe Verwaltung mit Konten & Depots, Ansichten und Klassifizierungen. Sie listet nur existierende Routen — keine deaktivierten Roadmap-Platzhalter. Erträge sind ein Tab des Vermögens-Bereichs und der Import ein Tab des Transaktions-Bereichs, keine eigenen Menüeinträge. Buckets haben keinen eigenen Seitenleisten-Eintrag (ADR-0024): sie werden als Chips auf den Zeilen von Konten & Depots und auf der Ansichten-Seite verwaltet, die der Link Ansichten des Sicht-Umschalters öffnet.
- Auf dem Telefon scrollt die Reiterzeile eines Bereichs (Vermögen, Transaktionen) seitlich, statt umzubrechen: Der Reiter, auf dem man steht, ist beim Öffnen einer Seite sichtbar, ein Verlauf markiert jede Seite, hinter der weitere Reiter liegen, und die Zeile kommt immer mit einem ganzen Reiter am linken Rand zur Ruhe — auch an ihrem Ende, wo nach dem letzten Reiter ein wenig Leerraum folgt.
- Theme: System-, hell- und dunkel-Modus werden unterstützt (das Menü heißt Erscheinungsbild).
- Akzent: violette, türkise und korallenfarbene Logo-Akzentwahlen werden unterstützt.
- Sprache: der erste Aufruf folgt der Browsersprache, wenn sie Englisch oder Deutsch ist. Explizite EN/DE-Links überschreiben die Browsersprache und sichern diese Wahl.
- Theme, Akzent und Sprache sind Nutzerpräferenzen und beeinflussen gespeicherte Finanzwerte nicht.
- Datumsfelder nehmen ISO-Daten (
YYYY-MM-DD) entgegen und zeigen sie auch so an; der lokalisierte Browser-Datumswähler kommt nicht zum Einsatz. Jedes Datum, das die Seite nur anzeigt, folgt ihrer Sprache:TT.MM.JJJJauf einer deutschen Seite, ISO auf einer englischen; ein Monat allein liest sich10.2026bzw.2026-10. API, MCP und jede Datei, die die App liest oder schreibt, bleiben bei ISO. - Die Achsen der Diagramme folgen ihr ebenso: das erste und das letzte Datum,
die Werte mit den Trennzeichen der Seite (
12.500bzw.12,500) und ein Prozentwert als+10,4%bzw.+10.4%. Die Achsenbeschriftung behält bei jeder Diagrammbreite eine Größe, 9 px; in einem schmalen Diagramm (bis etwa 760 px, wie auf dem Telefon) oder wo ein Wert breiter ist als der Platz neben dem Diagramm, stehen die Werte im Diagramm auf ihren Gitterlinien. Die eine Ausnahme von der Sprache der Seite ist die Anzeige beim Überfahren des Diagramms: Sie zeigt das Datum noch in ISO-Form und den Kurs unformatiert. - Zahlenfelder (Stückzahl, Preis, Gebühren und Steuern, Abrechnungsbetrag und
Kurs, die Grenze einer Regel, die Zahlen unter Steuern, ein Kontosaldo)
zeigen und lesen Zahlen in der Sprache der Seite: auf einer deutschen Seite
mit Dezimalkomma (
1664,40), auf einer englischen mit Punkt. Sie zeigen nie einen Tausenderpunkt und stehen rechtsbündig in Tabellenziffern. Das Trennzeichen der anderen Sprache wird ebenfalls gelesen (45.60auf einer deutschen,45,60auf einer englischen Seite) — außer wenn die Zahl eine Tausendergruppe sein könnte (1.664auf einer deutschen,1,664auf einer englischen Seite): Eine solche Zahl ist mehrdeutig und wird am Feld mit der Bitte abgelehnt, sie ohne Tausendertrennzeichen einzugeben, ebenso eine Zahl mit zwei Trennzeichen (1.664,40) oder eine mit Leerzeichen oder Apostroph gruppierte (1 664,40,1'664.40, wie Bankseiten und PDFs Zahlen drucken). Eine abgelehnte Zahl speichert nichts, und das Getippte bleibt, wie es getippt wurde. - Während Werte berechnet werden, zeigt der betroffene Platz einen Platzhalter plus den Hinweis „wird berechnet” statt eines Ladetexts; Kopfzahlen zählen kurz sichtbar hoch. Bei reduzierter Bewegung als Systemeinstellung entfällt alle dekorative Bewegung und Endwerte erscheinen sofort.
- Aufwändige Kennzahlen werden von der Buchung neu berechnet, die sie ungültig gemacht hat, nicht von der nächsten Seite, die Sie öffnen: nach einer Buchung, einem Import oder einer Kursaktualisierung werden sie im Hintergrund aufgefrischt, sodass der obige Hinweis normalerweise einmal erscheint statt nach jeder Änderung. Ein Schwung von Schreibvorgängen — der Import eines ganzen Exports — kostet eine Auffrischung, nicht eine pro Zeile. Bis sie eintrifft, wird der vorherige Wert gezeigt, beschriftet mit dem Zeitpunkt seiner Berechnung.
- Vorzeichenbehaftete Kennzahlen (TTWROR, IRR/MWR, Nettoflüsse, das Veränderungssignal der Übersicht) tragen ein explizites Vorzeichen und Gewinn-/Verlustfarbe auf jeder Ebene; vorzeichenlose Beträge behalten die Akzentfarbe.
Audit-Journal
Jede Änderung an Finanzdaten wird in einem append-only Audit-Journal in derselben
Datenbanktransaktion wie die Änderung selbst festgehalten, sodass jedes Anlegen,
Bearbeiten oder Löschen zurechenbar (wer und wann) und durch Einsicht
nachvollziehbar bleibt (Werte vorher/nachher) — das Sicherheitsnetz dafür, einen
Agenten über die API/MCP schreiben zu lassen. Marktdaten-Synchronisierung (Kurse
und Wechselkurse) ist betrieblich und wird nicht journalisiert. Das Journal ist
über GET /api/v1/journal und das passende MCP-Tool portfolixir.journal.list
abfragbar (siehe API und MCP). Es deckt jeden
Bereich ab, der Finanzdaten schreibt: Wertpapiere und die Kurse, die jemand
eingibt, Portfolios, Geldkonten und Depots, Buchungen (auch die eines Imports),
Klassifizierungen und SOLL-Pläne, Steuerdaten, Recherche-Notizen und Termine,
eigene Regeln, Zusammenführungen sowie Buckets und Views. Eine eigene Ansicht
in der App ist als Folgeschritt geplant.
Das Löschen eines Geldkontos, eines Depots oder eines Wertpapiers nimmt nie
stillschweigend etwas mit (ADR-0050 §11). Eine Zeile, auf die noch Buchungen
verweisen — bei einem Wertpapier auch Kurse, Recherche-Notizen oder
Ereignisse —, wird gar nicht gelöscht: Der Weg ist dann, sie mit der Zeile
zusammenzuführen, die bleibt. Bei einer unreferenzierten Zeile werden
Bucket-Verknüpfungen, Positions-Overrides und Kategorie-Zuordnungen vorher
entfernt, jeweils über ihren eigenen journalisierten Schreibpfad, sodass das
Journal jede Mitgliedschaft zeigt, die das Löschen beendet hat. Ein Löschen,
das auf eine gleichzeitige Änderung durch einen anderen Schreibvorgang trifft,
behält die Zeile und sagt es auf der Seite — „
Heutige Nicht-Ziele
- Kein automatischer Handel und keine Orderausführung.
- Keine Bank-, Broker- oder Wallet-Integrationen.
- Keine Zahlungsplanung oder Abwicklungs-Workflows.
- Keine Broker-PDFs, keine binären Portfolio-Performance-Arbeitsbereiche, keine Bank-Synchronisierung, keine Broker-Synchronisierung und keine Dokumentenerfassung über den Portfolio-Performance-CSV/JSON-v1- Transaktionsexport-Workflow hinaus.
Sparpläne werden bewusst nicht unterstützt. Ein Sparplan beschreibt nur einen beabsichtigten wiederkehrenden Beitrag, und seine Zielwerte weichen unweigerlich von den realen Ausführungen ab, die ein Broker durchführt — typischerweise um Cent-Unterschiede bei Preis, Gebühr und Menge. Portfolixir behandelt die importierten, realen Transaktionen als einzige Quelle der Wahrheit für Bestände und Performance, sodass das Modellieren separater Sparplan-Ziele einen parallelen Satz Zahlen hinzufügen würde, der nie ganz zur Realität passt. Wiederkehrende Beiträge werden daher schlicht als die Transaktionen erfasst, die sie tatsächlich erzeugt haben.






