Beancount (een puur-tekst boekhoudtool met dubbele boekhouding) en Fava (de webinterface ervan) zijn zeer uitbreidbaar en programmeerbaar. Hun ontwerp stelt je in staat financiële taken te automatiseren, aangepaste rapporten te genereren en meldingen in te stellen door Python-scripts te schrijven. In de woorden van een gebruiker: "Ik vind het echt fijn om mijn gegevens in zo'n handig formaat te hebben, en ik vind het fijn dat ik dingen naar hartelust kan automatiseren. Er is geen API zoals een bestand op je schijf; het is gemakkelijk te integreren." Deze gids leidt je door het maken van programmeerbare workflows—van beginnersvriendelijke automatisering tot geavanceerde Fava-plugins.
Bekijk een live voorbeeldgrootboek:
Begin met de bea opdrachtregel
Controleer voordat je Python schrijft of bea het werk al doet. Het valideert het grootboek, voert BQL-query's uit, produceert de vier financiële rapporten en importeert bankexports, en de globale --json zet elk daarvan om in een parseerbare envelope die je shell naar jq kan pipen. De exitcodes zijn het contract waarop een geplande taak kan takken, dus cron of CI heeft helemaal geen loader-script nodig. Zie automatiseren van boekhouding met bea voor de target-resolutie, envelope- en exitcode-vertakkingen, en kom hier terug als je een aangepaste berekening nodig hebt die de CLI niet blootstelt.
Aan de slag: Beancount uitvoeren als een Python-script
Voor de onderstaande aangepaste Python-scripts installeer je de scripting-libraries (pip install beancount beanquery beangulp). De bea command workflow gebruikt in plaats daarvan de beheerde engine; volg de CLI snelstart om deze te installeren. Aangezien Beancount in Python is geschreven, kun je het als een bibliotheek in je eigen scripts gebruiken. De scripts hieronder werden uitgevoerd met Beancount 3.2.3, beanquery 0.2.0, en beangulp 0.2.0. De algemene aanpak is:
-
Laad je Beancount-grootboek: Gebruik Beancount’s loader om het
.beancountbestand te parseren naar Python-objecten. Bijvoorbeeld:from beancount import loader entries, errors, options = loader.load_file("myledger.beancount") if errors: for error in errors: print(error) raise SystemExit(1)De loader retourneert entries en fouten samen. Een niet-gebalanceerd of ongeldig bestand retourneert nog steeds entries, dus controleer
errorsen stop voordat je de data vertrouwt. Al je rekeningen, transacties en saldi zijn nu in code toegankelijk. -
Benut Beancount Query Language (BQL): In plaats van handmatig te itereren, kun je SQL-achtige queries op de data uitvoeren. Queries bevinden zich in het aparte
beanquerypakket. Er is geenbeancount.querymodule in Beancount 3.2.3. Om bijvoorbeeld de totale uitgaven per maand te krijgen, verbind je de geladen boekingen en voer je de query direct uit:import beanquery conn = beanquery.connect("beancount:", entries=entries, errors=errors, options=options) cur = conn.execute( "SELECT year, month, sum(position) WHERE account ~ 'Expenses' GROUP BY year, month" ) for row in cur.fetchall(): print(row)Dit gebruikt beanquery om data samen te vatten. Het is dezelfde engine achter
bea query, maar hier roep je het aan in een script. Dat voorkomt dat je in een lus een extern commando aanroept. -
Stel een projectstructuur in: Organiseer je scripts naast je grootboek. Een veelvoorkomende indeling is om mappen te hebben voor importers (voor het ophalen/parsen van externe data), reports of queries (voor analysescripts), en documents (om gedownloade overzichten op te slaan). Bijvoorbeeld, een gebruiker houdt bij:
importers/– aangepaste Python-importscripts (met tests),queries/– scripts om rapporten te genereren (uitvoerbaar viapython3 queries/...),documents/– gedownloade bank-CSV’s/PDF’s georganiseerd per rekening.
Met deze opzet kun je scripts handmatig uitvoeren (bijv. python3 queries/cash_flow.py) of ze plannen (via cron of een taakplanner) om je workflow te automatiseren.
Taken voor reconciliatie automatiseren
Reconciliatie betekent ervoor zorgen dat je grootboek overeenkomt met externe overzichten (bankafschriften, creditcardrapporten, enz.). Beancounts plain-text grootboek en Python-API maken het mogelijk om veel van dit proces te automatiseren.
Transacties importeren en koppelen (beginner)
Voor beginners is de aanbevolen aanpak het gebruik van importers uit het aparte beangulp pakket. Beancount 3 heeft de v2 ingest module en het extract commando verwijderd. Je schrijft een kleine Python-klasse die beangulp.Importer subscrijft om een gegeven formaat (CSV, OFX, PDF, enz.) te parseren en transacties te produceren. Registreer deze in een kort ingest-script en voer dit uit via bea ingest in de beheerde engine:
- Schrijf een importer (een Python-klasse met methoden
identify(),account()enextract()) voor het CSV-formaat van je bank. - Voeg een ingest-script toe dat je importers registreert.
bea ingestvoert deidentify,extractenarchivecommando's van het script uit. Bijvoorbeeld, één workflow draaitextractop alle bestanden in~/Downloadsen schrijft transacties naar een tijdelijk bestand. - Controleer handmatig en kopieer transacties van het tijdelijke bestand naar je hoofdboek, en voer dan
bea checkuit om te zorgen dat saldi kloppen.
Een minimaal voorbeeld: een statement.csv met date,description,amount kolommen, geparset door deze importer (checking_importer.py):
import csv
import datetime
from beancount.core import data
from beancount.core.amount import Amount
from beancount.core.number import D
import beangulp
class CheckingImporter(beangulp.Importer):
def identify(self, filepath: str) -> bool:
return filepath.endswith("statement.csv")
def account(self, filepath: str) -> str:
return "Assets:Bank:Checking"
def extract(self, filepath: str, existing):
entries = []
with open(filepath, newline="") as f:
for row in csv.DictReader(f):
date = datetime.date.fromisoformat(row["date"])
amount = Amount(D(row["amount"]), "USD")
meta = data.new_metadata(filepath, 0)
entries.append(
data.Transaction(
meta, date, "*", None, row["description"],
data.EMPTY_SET, data.EMPTY_SET, [
data.Posting("Expenses:Food:Groceries", amount,
None, None, None, None),
data.Posting("Assets:Bank:Checking",
Amount(-amount.number, "USD"),
None, None, None, None),
]))
return entriesHet ingest-script (ingest.py) koppelt het aan elkaar:
from checking_importer import CheckingImporter
from beangulp import Ingest
ingest = Ingest([CheckingImporter()])
if __name__ == "__main__":
ingest()Voer het uit op een gedownload bestand. Geen inloggegevens nodig voor een lokale CSV. Installeer eerst de system libmagic bibliotheek. Het eenmalige inschakelcommando downloadt Beangulp in de beheerde engine:
bea engine enable beangulp
bea ingest identify --config ingest.py statement.csv
bea ingest extract --config ingest.py statement.csv -o new.beancountidentify rapporteert checking_importer.CheckingImporter voor het bestand. extract schrijft de transacties in Beancount-formaat:
2024-01-08 * "Grocery Store"
Expenses:Food:Groceries 120.00 USD
Assets:Bank:Checking -120.00 USDBekijk new.beancount, kopieer de boekingen naar je hoofdboek en voer bea check uit.
Je hoeft geen importer te schrijven voor het omzetten van een enkele afschrift. Plak het bestand in de CSV naar Beancount converter of gebruik OFX & QIF naar Beancount voor .ofx, .qfx en .qif downloads. Beide werken volledig in je browser, zodat het afschrift nooit je apparaat verlaat.
Hoewel dit proces nog een controlestap vereist, wordt veel van het zware werk van het parsen en formatteren van boekingen geautomatiseerd. Importer scripts kunnen ook automatisch categorieën toewijzen en zelfs balans asserties (verklaringen van verwachte saldi) instellen om afwijkingen op te sporen. Bijvoorbeeld, na het importeren, kun je een regel hebben zoals 2025-04-30 balance Assets:Bank:Checking 1234.56 USD die het eindsaldo bevestigt. Wanneer je bea check uitvoert, zal Beancount controleren of al deze balansasserties correct zijn en eventuele fouten aanwijzen als er transacties missen of dubbel zijn. Dit is een best practice: genereer automatisch balansasserties voor elke afschriftperiode, zodat de computer niet-gereconcilieerde verschillen voor je opspoort.
Aangepaste Reconciliatiescripts (Gemiddeld niveau)
Voor meer controle kun je een aangepaste Python-script schrijven om de transactielijst van een bank (CSV of via API) te vergelijken met je boekingen:
- Lees de externe gegevens in: Parseer het CSV-bestand van de bank met behulp van Python’s
csv-module (of Pandas). Normaliseer de gegevens tot een lijst met transacties, bijvoorbeeld elk met een datum, bedrag en omschrijving. - Laad grootboektransacties: Gebruik
loader.load_filezoals eerder getoond om alle grootboekboekingen te verkrijgen. Filter deze lijst op de relevante rekening (bijv. uw betaalrekening) en mogelijk het datumbereik van het overzicht. - Vergelijk en vind discrepanties:
- Voor elke externe transactie, controleer of een identieke boeking in het grootboek bestaat (match op datum en bedrag, eventueel omschrijving). Als deze niet gevonden wordt, markeer deze als “nieuw” en geef hem mogelijk uit als een in Beancount-formaat geschreven transactie om te beoordelen.
- Identificeer omgekeerd alle grootboekboekingen op die rekening die niet in de externe bron voorkomen – dit kunnen invoerfouten zijn of transacties die nog niet door de bank zijn geboekt.
- Output resultaten: Print een rapport of maak een nieuw
.beancount-fragment met de ontbrekende transacties.
Als voorbeeld doet een communityscript dat reconcile.py heet precies dit: gegeven een Beancount-bestand en een input-CSV, print het een lijst van nieuwe transacties die geïmporteerd moeten worden, evenals bestaande grootboekinschrijvingen die niet in de input voorkomen (mogelijk een teken van misclassificatie). Met zo’n script kan maandelijkse afstemming zo simpel zijn als het script draaien en vervolgens de voorgestelde transacties toevoegen aan je grootboek. Een Beancount-gebruiker merkt op dat zij “elke maand een afstemmingsproces op alle rekeningen doen” en een groeiende verzameling Python-code gebruiken om veel handmatig werk bij het importeren en afstemmen van gegevens te elimineren.
Tip: Gebruik bij het afstemmen de hulpmiddelen van Beancount voor nauwkeurigheid:
- Gebruik balansbeweringen zoals vermeld om geautomatiseerde controles op rekeningstanden te hebben.
- Gebruik de
pad-directive indien gewenst, die automatische salderingsboekingen kan invoegen voor kleine afrondingsverschillen (gebruik dit met voorzichtigheid). - Schrijf unittests voor je importer of afstemmingslogica (Beancount biedt testhelpers). Bijvoorbeeld, een workflow omvatte het nemen van een voorbeeld-CSV, het schrijven van mislukte tests met verwachte transacties, en daarna het implementeren van de importer totdat alle tests slaagden. Dit zorgt ervoor dat je importscript correct werkt voor verschillende gevallen.
Aangepaste rapporten en samenvattingen genereren
Hoewel Fava veel standaardrapporten biedt (resultatenrekening, balans, enz.), kunt u aangepaste rapporten maken met scripts. Deze kunnen variëren van simpele console-uitvoer tot rijkelijk geformatteerde bestanden of grafieken.
Gegevens opvragen voor rapporten (Beginner)
Op een eenvoudig niveau kun je de Beancount Query Language (BQL) gebruiken om samenvattende gegevens op te halen en deze af te drukken of op te slaan. Bijvoorbeeld:
-
Overzicht kasstroom: Gebruik een query om de netto kasstroom te berekenen. "Kasstroom" kan gedefinieerd worden als de wijziging in het saldo van bepaalde rekeningen over een periode. Met BQL zou je kunnen doen:
SELECT year, month, sum(position) WHERE account ~ 'Income' OR account ~ 'Expenses' GROUP BY year, monthDit berekent alle inkomsten- en uitgavenboekingen per maand netto. Filter met
~en een reguliere expressie:LIKEis een syntaxisfout in beanquery 0.2.0. Boekingen dragenposition, nietamount. Elke rij bevat één Inventory, dus elke valuta wordt apart vermeld in plaats van geconverteerd. Inkomen wordt negatief weergegeven en uitgaven positief. Je zou dit kunnen verwerken viabea queryof via de eerder getoonde beanquery Python API, en daarna het resultaat formatteren. -
Categorie-uitgavenrapport: Vraag totale uitgaven per categorie op:
SELECT account, sum(position) WHERE account ~ 'Expenses' GROUP BY account ORDER BY sum(position) ASCDit levert een tabel met uitgaven per categorie. Elke totaalwaarde is een Inventory in de originele valuta. Voeg de som niet toe aan
round(): er is geenround(inventory, int)functie, dusround(sum(position), 2)compileert niet. Je kunt meerdere queries in een script uitvoeren en de resultaten als tekst, CSV of zelfs JSON voor verdere verwerking uitvoer.
Een gebruiker vond het "triviaal" om financiële data te analyseren met Fava of met scripts, en gaf aan dat zij één Python-script gebruiken om data uit Beancount via de Query Language te halen en vervolgens in een Pandas DataFrame te plaatsen om een aangepast rapport voor te bereiden. Je kunt bijvoorbeeld maandelijkse totalen ophalen met een query en dan Pandas/Matplotlib gebruiken om een kasstroomgrafiek over tijd te maken. De combinatie van BQL en datawetenschapsbibliotheken stelt je in staat rapporten te maken die verder gaan dan wat Fava standaard biedt.
Geavanceerde rapportage (grafieken, prestaties, enz.)
Voor meer geavanceerde behoeften kunnen je scripts statistieken berekenen zoals beleggingsprestaties of visuele output genereren:
-
Beleggingsprestaties (IRR/XIRR): Omdat je grootboek alle kasstromen bevat (aankopen, verkopen, dividenden), kun je de opbrengst van je portefeuille berekenen. Bijvoorbeeld, je zou een script kunnen schrijven dat transacties van je beleggingsrekeningen filtert en vervolgens het Internal Rate of Return berekent. Er zijn bibliotheken (of formules) om IRR te berekenen op basis van kasstroomgegevens. Sommige door de gemeenschap ontwikkelde Fava-uitbreidingen (zoals PortfolioSummary of fava_investor) doen precies dit, ze berekenen IRR en andere statistieken voor beleggingsportefeuilles. Als script kun je een IRR-functie gebruiken (van NumPy of je eigen functie) op de reeks bijdrages/opnames plus de eindwaarde.
-
Meerperiode- of Aangepaste Maatstaven: Wil je een rapport van je spaarratio (verhouding spaargeld tot inkomen) per maand? Een Python-script kan de grootboek laden, alle inkomstenrekeningen en uitgavenrekeningen optellen, vervolgens sparen = inkomen - uitgaven berekenen en het percentage bepalen. Dit kan een mooie tabel opleveren of zelfs een HTML/Markdown-rapport genereren voor je administratie.
-
Visualisatie: Je kunt grafieken genereren buiten Fava. Gebruik bijvoorbeeld
matplotlibofaltairin een script om een netto waarde in de tijd grafiek te maken met grootboekgegevens. Omdat het grootboek alle historische saldi bevat (of je kunt ze accumuleren door posten te doorlopen), kun je tijdreeksgrafieken produceren. Bewaar deze grafieken als afbeeldingen of interactieve HTML. (Als je liever in-app visuals wilt, zie de Fava extensie sectie hieronder voor het toevoegen van grafieken binnen Fava.)
Uitvoeropties: Bepaal hoe je het rapport wilt afleveren:
- Voor eenmalige analyse kan afdrukken naar het scherm of opslaan als CSV/Excel bestand voldoende zijn.
- Voor dashboards kun je overwegen een HTML-bestand met de gegevens te genereren (mogelijk met een templatingbibliotheek zoals Jinja2 of zelfs gewoon Markdown) dat je in een browser kunt openen.
- Je kunt ook integreren met Jupyter Notebooks voor een interactieve rapporteeromgeving, hoewel dat meer voor verkenning dan automatisering is.
Melding Triggeren vanuit Je Grootboek
Een andere krachtige toepassing van scriptbare workflows is het instellen van meldingen op basis van voorwaarden in je financiële gegevens. Omdat je grootboek regelmatig wordt bijgewerkt (en toekomstige items zoals aanstaande rekeningen of budgetten kan bevatten), kun je het scannen met een script en meldingen krijgen over belangrijke gebeurtenissen.
Waarschuwingen bij Laag Rekeningsaldo
Om overlopende rekeningen te vermijden of een minimumsaldo te behouden, wil je misschien een melding krijgen als een rekening (bijvoorbeeld betaal- of spaarrekening) onder een drempelwaarde zakt. Zo kun je dit implementeren:
-
Bepaal de huidige saldi: Nadat
entriesvia de loader is geladen, bereken je het meest recente saldo van de rekeningen van belang. Dit kan door het aggregateren van posten of met een query. Gebruik bijvoorbeeld een BQL-query voor het saldo van een specifieke rekening:SELECT sum(position) WHERE account = 'Assets:Bank:Checking'Dit geeft het huidige saldo van die rekening terug (som van alle posten). Gebruik alternatief de interne functies van Beancount om een balans op te bouwen. Bijvoorbeeld:
from beancount.core import realization tree = realization.realize(entries) acct = realization.get_or_create(tree, "Assets:Bank:Checking") balance = acct.balance # an Inventory of commoditiesGeef alleen de boekingen door: de tweede parameter is
min_accounts, niet de opties map. Haal dan de numerieke waarde eruit (bijvoorbeeldbalance.get_currency_units('USD')geeft het decimale bedrag in USD terug). Net als bij een queryaggregate houdt het saldo elke valuta afzonderlijk bij. Het gebruik van de query is echter voor de meeste gevallen eenvoudiger. -
Controleer de drempel: Vergelijk het saldo met je vooraf gedefinieerde limiet. Als het lager is, activeer dan een waarschuwing.
-
Activeer notificatie: Dit kan zo simpel zijn als een waarschuwing naar de console printen, maar voor echte waarschuwingen wil je misschien een e-mail of push-notificatie versturen. Je kunt integreren met e-mail (via
smtplib) of een dienst zoals IFTTT of Slack’s webhook API om de waarschuwing te verzenden. Bijvoorbeeld:if balance < 1000: send_email("Low balance alert", f"Account XYZ balance is {balance}")(Implementeer
send_emailmet de details van je e-mailserver.)
Door dit script dagelijks uit te voeren (via een cron-job of Windows Taakplanner), ontvang je proactieve waarschuwingen. Omdat het de ledger gebruikt, kan het alle transacties in overweging nemen, inclusief degene die je net hebt toegevoegd.
Aankomende betalingsdeadlines
Als je Beancount gebruikt om rekeningen of deadlines bij te houden, kun je toekomstige betalingen markeren en je laten herinneren door scripts. Twee manieren om aankomende verplichtingen in Beancount weer te geven:
-
Evenementen: Beancount ondersteunt een
event-directive voor willekeurige genoteerde data. Bijvoorbeeld:2025-05-10 event "BillDue" "Mortgage payment due"Dit beïnvloedt de saldi niet maar registreert een datum met een label. Een script kan
entriesscannen opEvent-boekingen waarEvent.type == "BillDue"(of elk ander typen dat je kiest) voorkomt en controleren of de datum binnen bijvoorbeeld de komende 7 dagen vanaf vandaag valt. Zo ja, activeer dan een waarschuwing (e-mail, notificatie of zelfs een popup). -
Toekomstige transacties: Sommige mensen voeren transacties met een toekomstige datum in (postdated) in voor bijvoorbeeld geplande betalingen. Deze verschijnen niet in de saldi tot de datum is gepasseerd (tenzij je rapporten draait per toekomstige datum). Een script kan zoeken naar transacties met een datum in de nabije toekomst en deze opsommen.
Met deze methoden kun je een “tickler” script maken dat, wanneer uitgevoerd, een lijst geeft van taken of rekeningen die binnenkort betaald moeten worden. Integreer met een API zoals Google Calendar of een takenbeheerder als je automatisch herinneringen daar wilt aanmaken.
Detectie van anomalieën
Buiten bekende drempels of datums kunt u aangepaste waarschuwingen voor ongebruikelijke patronen programmeren. Bijvoorbeeld, als een normaal maandelijks uitgave niet heeft plaatsgevonden (misschien bent u vergeten een rekening te betalen), of als de uitgaven in een categorie deze maand abnormaal hoog zijn, kan uw script dit signaleren. Dit houdt meestal in dat recente gegevens worden opgevraagd en vergeleken met de geschiedenis (wat een geavanceerd onderwerp kan zijn – mogelijk met gebruik van statistiek of ML).
In de praktijk vertrouwen veel gebruikers op afstemming om afwijkingen (ongewenste transacties) op te sporen. Als u bankmeldingen ontvangt (zoals e-mails voor elke transactie), kunt u die met een script verwerken en automatisch aan Beancount toevoegen, of op zijn minst verifiëren dat ze zijn vastgelegd. Een enthousiasteling stelde zijn bank zelfs zo in dat deze transactie-waarschuwingse-mails stuurde, met de intentie deze automatisch te verwerken en aan het grootboek toe te voegen. Dit soort gebeurtenisgestuurde waarschuwingen kan garanderen dat geen enkele transactie ongeregistreerd blijft.
Fava uitbreiden met aangepaste plugins en weergaven
Fava is al scriptbaar via zijn extensiesysteem. Als u wilt dat uw automatisering of rapporten direct in de webinterface integreren, kunt u een Fava-extensie (ook plugin genoemd) in Python schrijven.
Hoe Fava-extensies werken: Een extensie is een Python-module die een klasse definieert die erft van fava.ext.FavaExtensionBase. U registreert deze in uw Beancount-bestand via een aangepaste optie. Bijvoorbeeld, als u een bestand myextension.py heeft met een klasse MyAlerts(FavaExtensionBase), kunt u deze inschakelen door aan uw grootboek toe te voegen:
1970-01-01 custom "fava-extension" "myextension"Wanneer Fava laadt, importeert het die module en initialiseert het uw MyAlerts klasse.
Extensies kunnen verschillende dingen doen:
- Hooks: Ze kunnen inhaken op gebeurtenissen in de levenscyclus van Fava. Bijvoorbeeld,
after_load_file()wordt aangeroepen nadat de boekhouding is geladen. Je zou dit kunnen gebruiken om controles uit te voeren of data voor te berekenen. Als je de controle op een laag saldo binnen Fava wilde implementeren, konafter_load_fileover rekeningsaldi itereren en mogelijk waarschuwingen opslaan (hoewel het weergeven hiervan in de UI iets meer werk kan vereisen, zoals het oproepen van een FavaAPIError of het gebruik van Javascript om een notificatie te tonen). - Aangepaste rapporten/pagina's: Als je uitbreidingsklasse een
report_titleattribuut instelt, zal Fava een nieuwe pagina aan de zijbalk toevoegen daarvoor. Je levert dan een template (HTML/Jinja2) voor de inhoud van die pagina. Hiermee maak je volledig nieuwe weergaven, zoals een dashboard of samenvatting die Fava standaard niet heeft. De extensie kan alle benodigde data verzamelen (je kuntself.ledgerbenaderen dat alle transacties, saldi, enz. bevat) en vervolgens de template renderen.
Bijvoorbeeld, de ingebouwde portfolio_list extensie in Fava voegt een pagina toe die je portefeuillestanden opsomt. Community-extensies gaan verder:
- Dashboards: De fava-dashboards plugin maakt het mogelijk om aangepaste grafieken en panelen te definiëren (met bibliotheken zoals Apache ECharts). Het leest een YAML-configuratie van queries om uit te voeren, voert ze uit via Beancount, en genereert een dynamische dashboardpagina in Fava. In feite koppelt het Beancount-gegevens aan een JavaScript-grafiekbibliotheek om interactieve visualisaties te maken.
- Portefeuille-analyse: De PortfolioSummary extensie (door gebruikers bijgedragen) berekent beleggingssamenvattingen (rekeninggroepen, IRR-berekeningen, enzovoort) en toont deze in de UI van Fava.
- Transactiebeoordeling: Een andere extensie, fava-review, helpt om transacties over tijd te beoordelen (bijvoorbeeld om na te gaan of je geen bonnetjes gemist hebt).
Om zelf een eenvoudige extensie te maken, begin je met het subclassen van FavaExtensionBase. Bijvoorbeeld, een minimale extensie die een pagina toevoegt, kan eruit zien als:
from fava.ext import FavaExtensionBase
class HelloReport(FavaExtensionBase):
report_title = "Hello World"
def __init__(self, ledger, config):
super().__init__(ledger, config)
# any initialization, perhaps parse config if provided
def after_load_file(self):
# (optional) run after ledger is loaded
print("Ledger loaded with", len(self.ledger.entries), "entries")Als je dit in hello.py plaatst en custom "fava-extension" "hello" toevoegt aan je boekhouding, zou Fava een nieuwe "Hello World" pagina tonen (je zou ook een template-bestand HelloReport.html nodig hebben in een templates submap om de content van de pagina te definiëren, tenzij de extensie alleen hooks gebruikt). De template kan data gebruiken die je aan de extensieklasse toevoegt. Fava gebruikt Jinja2-templates, dus je kunt je data in die template renderen in een HTML-tabel of grafiek.
Opmerking: Het extensiesysteem van Fava is krachtig maar wordt als "onstabiel" beschouwd (onderhevig aan verandering). Het vereist enige bekendheid met webontwikkeling (HTML/JS) als je aangepaste pagina's maakt. Als je doel simpelweg is om scripts of analyses uit te voeren, is het misschien makkelijker om ze als externe scripts te houden. Gebruik Fava-extensies wanneer je een op maat gemaakte in-app ervaring voor je workflow wilt.
Integratie van Derde Partij API's en Gegevens
Een van de voordelen van scriptbare workflows is het vermogen om externe gegevens binnen te halen. Hier zijn veelvoorkomende integraties:
-
Wisselkoersen & Grondstoffen: Beancount haalt prijzen niet automatisch op (om rapporten deterministisch te houden), maar biedt een Price richtlijn zodat je tarieven kunt aanleveren. Je kunt het ophalen van deze prijzen automatiseren. Bijvoorbeeld, een script kan een API (Yahoo Finance, Alpha Vantage, enz.) raadplegen voor de meest recente wisselkoers of aandelenprijs en een prijsvermelding aan je grootboek toevoegen:
2025-04-30 price BTC 30000 USD 2025-04-30 price EUR 1.10 USDEr zijn tools zoals
bea price, ondersteund door Beanprice in de beheerde engine die dagelijkse koersen ophalen en ze in Beancount-formaat uitgeven. Je kunt het één keer activeren metbea engine enable beanprice, daarnabea price main.beancountplannen om elke avond uit te voeren om eenprices.beancountinclude-bestand bij te werken. Of gebruik Python: bijvoorbeeld met derequestsbibliotheek om een API aan te roepen. De documentatie van Beancount suggereert dat je voor publiek verhandelde activa “code kunt aanroepen die prijzen downloadt en de richtlijnen voor je schrijft.” Met andere woorden, laat een script de opzoeking doen en depriceregels invoegen, in plaats van het handmatig te doen. -
Aandelenportefeuillegegevens: Net als bij wisselkoersen kun je integreren met API's om gedetailleerde aandelengegevens of dividenden op te halen. Bijvoorbeeld, de Yahoo Finance API (of community bibliotheken zoals
yfinance) kan historische data voor een ticker ophalen. Een script kan je grootboek bijwerken met maandelijkse prijsgeschiedenis voor elk aandeel dat je bezit, waardoor nauwkeurige historische rapporten van marktwaarde mogelijk zijn. Sommige aangepaste extensies (zoals fava_investor) halen zelfs in real-time prijsgegevens op voor weergave, maar het eenvoudigst is om prijzen regelmatig in het grootboek te importeren. -
Bank-API's (Open Banking/Plaid): In plaats van CSV-bestanden te downloaden, kun je API's gebruiken om transacties automatisch op te halen. Diensten zoals Plaid aggregeren bankrekeningen en bieden programmatologische toegang tot transacties. In een geavanceerde opzet kun je een Python-script hebben dat Plaid’s API gebruikt om dagelijks nieuwe transacties op te halen en op te slaan in een bestand (of direct te importeren in het grootboek). Een gevorderde gebruiker bouwde een systeem waarbij Plaid in hun import-pijplijn voedt, waardoor hun boeken bijna automatisch zijn. Ze merken op dat "niets je ervan weerhoudt om je aan te melden bij Plaid API en hetzelfde lokaal te doen" – oftewel, je kunt een lokaal script schrijven om bankgegevens te verkrijgen en vervolgens je Beancount-importlogica gebruiken om deze om te zetten in grootboekboekingen. Sommige regio's hebben open banking-API's die door banken worden aangeboden; deze kunnen op vergelijkbare wijze worden gebruikt.
-
Andere API's: Je kunt budgetteringstools integreren (om geplande budgetten te exporteren en te vergelijken met de werkelijke cijfers in Beancount), of een OCR-API gebruiken om bonnetjes te lezen en automatisch te koppelen aan transacties. Omdat je scripts volledige toegang hebben tot het Python-ecosysteem, kun je alles integreren van e-maildiensten (voor het verzenden van waarschuwingen) tot Google Sheets (bijvoorbeeld het bijwerken van een sheet met maandelijkse financiële statistieken) tot berichtendiensten (stuur jezelf een samenvattend rapport via een Telegram-bot).
Bij het gebruik van API's van derden, vergeet niet je inloggegevens te beveiligen (gebruik omgevingsvariabelen of configuratiebestanden voor API-sleutels), en behandel fouten (netwerkproblemen, uitval van de API) op een nette manier in je scripts. Het is vaak verstandig om data te cachen (bijvoorbeeld opgehaalde wisselkoersen opslaan zodat je niet steeds dezelfde historische koers opnieuw opvraagt).
Best practices voor modulaire, onderhoudbare scripts
Terwijl je scriptbare workflows ontwikkelt, houd je code georganiseerd en robuust:
-
Modulariteit: Verdeel verschillende verantwoordelijkheden over aparte scripts of modules. Bijvoorbeeld, aparte scripts voor “data-import/reconciliatie” versus “rapportagegeneratie” versus “waarschuwingen”. Je kunt zelfs een klein Python-pakket maken voor je grootboek met modules zoals
ledger_import.py,ledger_reports.py, enzovoort. Dit maakt elk onderdeel makkelijker te begrijpen en te testen. -
Configuratie: Voorkom harde codering van waarden. Gebruik een configuratiebestand of variabelen bovenaan het script voor zaken als rekeningnamen, drempelwaarden, API-sleutels, datumbereiken, enzovoort. Dit maakt het eenvoudig om aan te passen zonder diep in de code te hoeven wijzigen. Definieer bijvoorbeeld
LOW_BALANCE_THRESHOLDS = {"Assets:Bank:Checking": 500, "Assets:Savings": 1000}bovenaan, zodat je waarschuwingsscript door deze dict kan itereren. -
Testen: Behandel je financiële automatisering als missie-kritische code – omdat het dat is! Schrijf tests voor complexe logica. Beancount biedt enkele testhulpmiddelen (intern gebruikt voor importer-testing) die je kunt gebruiken om grootboekinvoer te simuleren. Zelfs zonder geavanceerde frameworks kun je een dummy CSV en verwachte uitvoertransacties hebben, en controleren of je importscript de juiste boekingen genereert. Als je
pytestgebruikt, kun je deze tests eenvoudig integreren (zoals Alex Watt deed via eenjust test-commando dat pytest omvat). -
Versiebeheer: Houd je grootboek en scripts onder versiebeheer (git). Dit geeft je niet alleen back-ups en geschiedenis, maar moedigt je ook aan veranderingen gecontroleerd door te voeren. Je kunt releases van je “financiële scripts” taggen of verschillen bekijken bij het debuggen van problemen. Sommige gebruikers houden zelfs hun financiële administratie bij in Git om veranderingen in de loop van de tijd te volgen. Wees voorzichtig om gevoelige gegevens te negeren (zoals ruwe rekeningafschriftbestanden of API-sleutels) in je repository.
-
Documentatie: Documenteer je aangepaste workflows voor de toekomstige jij. Een README in je repository die uitlegt hoe je de omgeving opzet, hoe je elk script uitvoert, en wat elk doet, is onschatbaar na verloop van maanden. Voeg ook commentaar toe aan je code, vooral bij niet voor de hand liggende boekhoudkundige logica of API-interacties.
-
Fava Plugins Onderhoud: Als je een Fava-extensie schrijft, houd het simpel. Fava kan veranderen, dus kleinere extensies met gerichte functionaliteit zijn makkelijker bij te werken. Vermijd dat je te veel logica dupliceert – gebruik de query-engine van Beancount of bestaande hulp functies waar mogelijk, in plaats van hardcoded berekeningen die gevoelig kunnen zijn voor grootboekwijzigingen.
-
Beveiliging: Omdat je scripts mogelijk gevoelige gegevens verwerken en verbinding maken met externe diensten, behandel ze met zorg. Maak API-sleutels niet openbaar, en overweeg je automatisering op een beveiligde machine uit te voeren. Als je een gehoste oplossing of cloud gebruikt (zoals het plannen van GitHub Actions of een server om Fava te draaien), zorg dan dat je grootboekgegevens versleuteld zijn in opgeslagen toestand en dat je je comfortabel voelt bij de privacy-implicaties.
Door deze praktijken te volgen, zorg je ervoor dat je workflow betrouwbaar blijft, zelfs als je financiën (en de tools zelf) evolueren. Je wilt scripts die je jaar na jaar kunt hergebruiken, met minimale aanpassingen.
Conclusie
Beancount en Fava bieden een krachtig, flexibel platform waarmee technisch onderlegde gebruikers hun persoonlijke financiële tracking volledig kunnen aanpassen. Door Python-scripts te schrijven, kunt u saaie taken zoals het afstemmen van afschriften automatiseren, rijke rapporten produceren die zijn afgestemd op uw behoeften, en uw financiën goed in de gaten houden met tijdige waarschuwingen. We hebben een reeks voorbeelden behandeld van basis tot gevorderd - te beginnen met eenvoudige queries en CSV-imports, en vervolgens overgaand naar volwaardige Fava-plugins en externe API-integraties. Tijdens het implementeren hiervan, begin eenvoudig en bouw geleidelijk op. Zelfs een paar kleine automatiseringsscripts kunnen uren werk besparen en de nauwkeurigheid aanzienlijk verbeteren. En vergeet niet, omdat alles platte tekst en Python is, hebt u volledige controle - uw financieële systeem groeit met u mee, en past zich aan uw specifieke behoeften aan. Veel succes met het schrijven van scripts!
Bronnen: De bovenstaande technieken zijn ontleend aan de Beancount-documentatie en ervaringen uit de community. Voor verdere lectuur, zie de officiële Beancount-docs, community-gidsen en blogs, en de Awesome Beancount-repository voor links naar nuttige plugins en tools.