Fixkosten im Blick, ohne Zettel
Der Ausgangspunkt war Papier. Ein Excel-Bogen mit 33 Fixkostenpositionen, ausgedruckt, am Küchentisch mit Kugelschreiber abgehakt: pro Position zwölf Kästchen, grau für „abgebucht", und bei den jährlichen Posten ein Strich über die Monate, die diese eine Zahlung mit abdeckt.
Das Verfahren funktioniert — bis ein Abo dazukommt, ein Preis steigt oder ein Ratenkauf endet. Dann stimmt der Ausdruck nicht mehr, und man merkt es erst, wenn man ihn braucht. Was unten steht, ist der Versuch, denselben Bogen automatisch zu füllen.
Nicht selbst bauen, was es fertig gibt
Der erste Entwurf war ein Eigenbau in Python. Verworfen, aus einem Grund, der sich schnell zeigt, wenn man die Begriffe nebeneinanderlegt: Was hier gebraucht wird, ist ein Haushaltsbuch mit doppelter Buchführung.
| gemeint ist | in Firefly III |
|---|---|
| Fixkostenposition | Bill: Betragsspanne, Rhythmus, Start, Ende |
| „erkennt selbst, was dazugehört" | Regel-Engine |
| Kategorie mit Monatsbudget | zwei Dinge: Kategorie und Budget |
| Geld vom Sparkonto zurückholen | Transfer zwischen zwei eigenen Konten |
Der letzte Punkt ist der stärkste. Doppelte Buchführung macht aus „Geld vom Sparkonto holen" automatisch eine Umbuchung und keine Einnahme. Im Eigenbau wäre das eine Sonderregel gewesen, die irgendwann falsch greift.
Dass Kategorie und Budget zwei getrennte Dinge sind, hat eine fremde KI im Entwurf korrigiert, bevor etwas gebaut war. Der Unterschied ist nicht akademisch: Eine Regel, die nur die Kategorie setzt, lässt den Budgetbalken leer — und ein leerer Balken sieht aus wie „nichts ausgegeben".
Was die fertige Anwendung nicht kann, ist die Abdeckung. Sie kennt Zahlungstermine, aber nicht den Gedanken „diese eine Jahreszahlung deckt die nächsten elf Monate mit ab". Genau das ist aber die Aussage des Papierbogens. Diese Rechnung bleibt eigener Code — und damit die Stelle, die gepflegt werden muss.
Der Bankzugang ist der eigentliche Engpass
Die Umsätze automatisch zu bekommen, ist in Deutschland der unangenehmste Teil. Der Reihe nach:
- GoCardless (früher Nordigen), der bekannte kostenlose Zugang, nimmt seit Mitte 2025 keine Neukunden mehr an.
- Direkt an die PSD2-Schnittstelle der Bank kommt man nur mit einem eIDAS-Zertifikat — für Privatpersonen unerreichbar.
- FinTS verlangt eine Registrierungsnummer der Deutschen Kreditwirtschaft. Die bekommt man als Privatperson tatsächlich, kostenlos, in zehn bis fünfzehn Werktagen. Es ist aber ein Formular und Wartezeit.
Der Weg, der blieb: Enable Banking, ein PSD2-Aggregator mit einem kostenlosen Modus für die eigenen Konten. Man legt dort eine eigene Anwendung an und verbindet damit ausschließlich seine eigenen Konten — ausdrücklich vorgesehen, nicht bloß geduldet, und im Data Importer von Firefly III offiziell dokumentiert.
Vier Dinge, die man vorher wissen will:
- Das Verknüpfen der eigenen Konten ist ein eigener Schritt im Portal des Anbieters. Wer ihn überspringt, bekommt beim Import eine leere Kontoliste und sucht den Fehler an der falschen Stelle.
- Volle Historie gibt es nur in der ersten Stunde nach der Freigabe. Danach liefern viele Banken 90 Tage. Für eine Jahresmatrix heißt das: der erste Import muss sofort alles holen, der Rest kommt per CSV-Export aus dem Online-Banking.
- Die Zustimmung läuft nach spätestens 180 Tagen ab und wird per Bank-Login erneuert. Danach sind die Konto-Kennungen andere, und die Importkonfiguration muss neu zugeordnet werden. Das ist der eigentliche Pflegeaufwand — nicht die Freigabe selbst.
- FinTS erspart das nicht. Das Gegenargument „FinTS läuft ohne 90-Tage-Zustimmung durch" klingt gut, stimmt aber nicht: Die Bank verlangt auch dort regelmäßig einen erfolgreichen Login im Online-Banking.
Die Brücke zum Dashboard
Die Anzeige läuft in Home Assistant, weil dort ohnehin alles andere steht. Die fertige Integration liefert Kontostände und Kategorien, aber keine Fixkostenpositionen — und erst recht keine Matrix.
Also ein Skript auf demselben Rechner wie das Haushaltsbuch: Es holt in einem einzigen API-Aufruf sämtliche Positionen samt aller bisherigen Zahlungen, rechnet Matrix, Monatssummen, Vorschau und Kennzahlen selbst aus und veröffentlicht das Ergebnis per MQTT — retained, damit die Anzeige einen Neustart übersteht. Das Dashboard rechnet nichts; es liest nur.
Die Zeilen sind nach Rhythmus gruppiert, hinter jedem Namen steht der Betrag seines eigenen Takts: monatlich der Monatsbetrag, vierteljährlich der Quartalsbetrag. Die Gruppensumme zählt nur, was noch läuft — sonst schleppt man beendete Ratenkäufe jahrelang in der Monatsumlage mit.
Budgets: erst messen, dann vornehmen
Der zweite Teil sind die variablen Ausgaben. Hier lag die eigentliche Überraschung nicht in der Technik, sondern in den Zahlen.
Die Budgetbeträge stammten aus einem gekündigten Finanz-Werkzeug — gesetzt nach Gefühl, nie geprüft. Ein Skript hat deshalb zwölf volle Monate rückwirkend ausgewertet: Fixkosten abziehen, den Rest nach Gegenpartei gruppieren. Ergebnis: Der größte Topf lag dauerhaft über seinem Soll, und zwar in jedem der zwölf Monate. Zwei Ausgabengruppen hatte das alte Werkzeug gar nicht gekannt.
Drei Regeln sind daraus geworden:
- Median statt Durchschnitt bei schwankenden Töpfen. Ein einzelner Technikkauf hebt den Monatsschnitt so weit an, dass das Budget unerreichbar wird. Der Median beschreibt den normalen Monat.
- Ein Budget bekommt nur, was steuerbar ist. Apotheke und Werkstattrechnungen bekommen eine Kategorie, aber keine Grenze — eine rote Linie unter Unvermeidbarem stumpft nur ab.
- Was bewusst aus der Rücklage bezahlt wird, darf das Monatsbudget nicht auffressen. Das Merkmal dafür ist nicht der Betrag, sondern die Umbuchung davor; die kennt nur der Mensch. Also wird bei größeren Beträgen nachgefragt statt geraten.
Eine Kennzahl ist dabei entstanden, die es so fertig nirgends gibt: verfügbares Guthaben = Kontostand minus noch offen. Also das, was bis Monatsende wirklich frei ist, ohne dass eine erwartete Abbuchung ins Minus führt. Das Sparkonto zählt bewusst nicht mit.
Drei Fehlgriffe
Farbe und Rechnung waren dasselbe Feld. Jede Zelle der Matrix hatte einen Zustand, der beides steuerte: die Einfärbung und die Frage, ob der Betrag zur Monatssumme zählt. Dann endete ein Ratenkauf — die grüne Endmarkierung überschrieb „erwartet", und die Schlussrate fiel aus „noch offen" heraus. Kein Fehler, keine Meldung, nur eine Summe, die 60 € zu niedrig war. Seitdem führt jede Zelle zwei Zustände: einen fürs Rechnen, einen fürs Aussehen.
Der Durchschnitt ist der falsche Wert für eine Vorschau. Die Prognose auf den Folgemonat zog alte Preise mit, weil sie den Mittelwert aller bisherigen Zahlungen nahm. Eine Versicherung stand mit einem Beitrag da, den es seit anderthalb Jahren nicht mehr gibt. Richtig ist die letzte tatsächliche Zahlung; der Durchschnitt bleibt nur der Rückfall, wenn es noch keine gibt.
Auf Papier ist Grau die Abbuchung — auf dunklem Grund nicht. Die erste Fassung hat die Farblogik des Ausdrucks wörtlich übernommen. Im dunklen Dashboard leuchteten dadurch die abgedeckten Monate heller als die echten Abbuchungen: Das Auge liest auf Schwarz Helligkeit als Gewicht, auf Weiß genau umgekehrt. Ebenso bei den Budgetbalken: In der ersten Fassung war ein Balken so lang wie sein Soll, dadurch sah gleiche Auslastung verschieden aus. Jetzt läuft die Achse in Prozent, jeder Balken ist gleich lang, und die Füllung ist der Anteil.
Was noch nicht fertig ist
Das Depot fehlt, das Rücklagenkonto ist noch kein eigenes Konto in der Buchhaltung, und der tägliche Lauf muss sich noch über mehrere Wochen bewähren. Der Beitrag beschreibt also keinen Endzustand, sondern einen Stand — was dazukommt, steht unten im Verlauf.
Technischer Anhang
- Alle Zahlen in Text und Bildern sind Beispiele. Die Größenordnungen stimmen, die Beträge nicht.
- Die Positionen kommen über
GET /bills?start=&end=— ein Aufruf liefert sämtliche Positionen samt Zahlungsdaten und Beträgen im Zeitraum. Das ist der Fund, an dem die ganze Brücke hängt; einzeln abzufragen wäre zu langsam. - Die Fälligkeitsprognose rechnet Firefly III aus dem Ankerdatum der Position hoch, nicht aus den tatsächlichen Buchungen. Steht der Anker auf dem falschen Tag, zeigt die Anwendung Termine an, die nie eintreten — und das fällt nur in unbezahlten Perioden auf.
- In der Regel-Engine gibt es keinen Trigger auf „gehört zu einer Fixkostenposition". Der Umweg: Jede Fixkostenregel setzt eine Kategorie, die Budgetregeln verlangen zusätzlich „hat noch keine Kategorie".
- Der Importer meldet Exit-Code 1 als Normalfall, weil jede abgewiesene Dublette als Fehler zählt. Die Überwachung muss also das Protokoll bewerten, nicht den Rückgabewert.
- Der Zielrechner hatte keine MQTT-Bibliothek und keinen Paketmanager, den man
dafür bemühen wollte. Statt etwas zu installieren: rund 60 Zeilen MQTT auf
Socket-Ebene — CONNECT, PUBLISH mit
retain, DISCONNECT. Für QoS 0 reicht das. Antwortcode 5 der Gegenstelle heißt „nicht berechtigt", also falscher Benutzer. - Die Matrix ist eine Heatmap in einer Diagrammkarte, die eigentlich für Zeitreihen gedacht ist. Zwei Kniffe: eine diskrete Farbskala braucht je Stufe zwei Einträge mit derselben Farbe, sonst blendet die Bibliothek über und aus den Zuständen wird ein Farbverlauf. Und für zeilenweise verschiedene Schriftfarben liefert das Skript die Beschriftungen zweimal — einmal als Werte, einmal als eingefärbtes Markup.