Beancount (uno strumento di contabilità in partita doppia in testo semplice) e Fava (la sua interfaccia web) sono altamente estensibili e programmabili. Il loro design ti permette di automatizzare attività finanziarie, generare report personalizzati e impostare avvisi scrivendo script Python. Secondo un utente, "Mi piace molto avere i miei dati in un formato così comodo, e mi piace poter automatizzare le cose a mio piacimento. Non esiste API migliore di un file sul tuo disco; è facile integrarlo." Questa guida illustrerà come creare flussi di lavoro programmabili—dall'automazione per principianti ai plugin Fava avanzati.
Esplora un ledger di esempio dal vivo:
Inizia con la linea di comando bea
Prima di scrivere qualsiasi Python, verifica se bea fa già il lavoro. Convalida il ledger, esegue query BQL, produce i quattro report finanziari e importa estratti conto bancari, e l'opzione globale --json trasforma ciascuno di questi in un envelope analizzabile che la tua shell può inviare a jq. I suoi codici di uscita sono il contratto su cui si dirama un job pianificato, quindi cron o CI non necessitano affatto di uno script di caricamento. Vedi automatizzare la contabilità con bea per la risoluzione dei target, l'envelope e la diramazione sui codici di uscita, e torna qui quando ti serve un calcolo personalizzato che la CLI non espone.
Primi passi: eseguire Beancount come script Python
Per gli script Python personalizzati di seguito, installa le librerie di scripting (pip install beancount beanquery beangulp). I flussi di lavoro del comando bea usano invece il motore gestito; segui la guida rapida della CLI per installarlo. Poiché Beancount è scritto in Python, puoi usarlo come libreria nei tuoi script. Gli script seguenti sono stati eseguiti con Beancount 3.2.3, beanquery 0.2.0 e beangulp 0.2.0. L'approccio generale è:
-
Carica il tuo ledger Beancount: usa il loader di Beancount per analizzare il file
.beancountin oggetti Python. Per esempio:from beancount import loader entries, errors, options = loader.load_file("myledger.beancount") if errors: for error in errors: print(error) raise SystemExit(1)Il loader restituisce insieme voci ed errori. Un file sbilanciato o non valido restituisce comunque delle voci, quindi controlla
errorse fermati prima di fidarti dei dati. Ora tutti i tuoi conti, transazioni e saldi sono accessibili nel codice. -
Sfrutta il Beancount Query Language (BQL): invece di iterare manualmente, puoi eseguire query simili a SQL sui dati. Le query risiedono nel pacchetto separato
beanquery. Non esiste un modulobeancount.queryin Beancount 3.2.3. Per esempio, per ottenere le spese totali per mese, collega le voci caricate ed esegui la query direttamente: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)Questo usa beanquery per aggregare i dati. È lo stesso motore dietro
bea query, ma qui lo chiami in uno script. Ciò evita di invocare un comando esterno in un ciclo. -
Configura una struttura di progetto: organizza i tuoi script insieme al tuo ledger. Una disposizione comune prevede directory per importers (per recuperare/analizzare dati esterni), reports o queries (per script di analisi) e documents (per archiviare estratti conto scaricati). Per esempio, un utente mantiene:
importers/– script di import Python personalizzati (con test),queries/– script per generare report (eseguibili tramitepython3 queries/...),documents/– CSV/PDF bancari scaricati organizzati per conto.
Con questa configurazione, puoi eseguire gli script manualmente (es. python3 queries/cash_flow.py) o pianificarli (tramite cron o un task runner) per automatizzare il tuo flusso di lavoro.
Automazione delle attività di riconciliazione
La riconciliazione significa assicurarsi che il tuo ledger corrisponda ai registri esterni (estratti conto bancari, report delle carte di credito, ecc.). Il ledger in testo semplice e l'API Python di Beancount rendono possibile automatizzare gran parte di questo processo.
Importazione e abbinamento delle transazioni (principianti)
Per i principianti, l'approccio consigliato è usare gli importer dal pacchetto separato beangulp. Beancount 3 ha rimosso il modulo di ingest v2 e il suo comando extract. Scrivi una piccola classe Python che eredita da beangulp.Importer per analizzare un dato formato (CSV, OFX, PDF, ecc.) e produrre transazioni. Registrala in un breve script di ingest, poi eseguilo tramite bea ingest nel motore gestito:
- Scrivi un importer (una classe Python con i metodi
identify(),account()edextract()) per il formato CSV della tua banca. - Aggiungi uno script di ingest che registra i tuoi importer.
bea ingestesegue i comandiidentify,extractearchivedello script. Per esempio, un flusso di lavoro esegueextractsu tutti i file in~/Downloadse produce le transazioni in un file temporaneo. - Rivedi manualmente e copia le transazioni dal file temporaneo nel tuo ledger principale, poi esegui
bea checkper assicurarti che i saldi si riconcilino.
Un esempio minimale: un statement.csv con le colonne date,description,amount, analizzato da questo 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 entriesLo script di ingest (ingest.py) lo collega:
from checking_importer import CheckingImporter
from beangulp import Ingest
ingest = Ingest([CheckingImporter()])
if __name__ == "__main__":
ingest()Eseguilo su un file scaricato. Non servono credenziali per un CSV locale. Installa prima la libreria di sistema libmagic. Il comando di abilitazione una tantum scarica Beangulp nel motore gestito:
bea engine enable beangulp
bea ingest identify --config ingest.py statement.csv
bea ingest extract --config ingest.py statement.csv -o new.beancountidentify segnala checking_importer.CheckingImporter per il file. extract scrive le transazioni in formato Beancount:
2024-01-08 * "Grocery Store"
Expenses:Food:Groceries 120.00 USD
Assets:Bank:Checking -120.00 USDRivedi new.beancount, copia le voci nel tuo ledger principale ed esegui bea check.
Non hai bisogno di scrivere un importer per convertire un singolo estratto conto. Incolla il file nel convertitore da CSV a Beancount, oppure usa OFX & QIF to Beancount per i download in .ofx, .qfx e .qif. Entrambi funzionano interamente nel tuo browser, quindi l'estratto conto non lascia mai la tua macchina.
Sebbene questo processo comporti ancora una fase di revisione, gran parte del lavoro noioso di analisi e formattazione delle voci è automatizzato. Gli script importer possono anche assegnare automaticamente le categorie e persino impostare asserzioni di saldo (dichiarazioni di saldi attesi) per individuare discrepanze. Per esempio, dopo l'importazione, potresti avere una riga come 2025-04-30 balance Assets:Bank:Checking 1234.56 USD che dichiara il saldo di chiusura. Quando esegui bea check, Beancount verificherà che tutte queste asserzioni di saldo siano corrette e segnalerà eventuali errori se mancano o sono duplicate delle transazioni. Questa è una best practice: genera automaticamente le asserzioni di saldo per ogni periodo di estratto conto per far individuare al computer le differenze non riconciliate per te.
Script di Riconciliazione Personalizzati (Intermedio)
Per un maggiore controllo, puoi scrivere uno script Python personalizzato per confrontare la lista delle transazioni di una banca (CSV o tramite API) con le voci del tuo ledger:
- Leggi i dati esterni: analizza il file CSV della banca usando il modulo
csvdi Python (o Pandas). Normalizza i dati in una lista di transazioni, ciascuna con data, importo e descrizione. - Carica le transazioni del ledger: usa
loader.load_filecome mostrato prima per ottenere tutte le voci del ledger. Filtra questa lista per il conto di interesse (es. il tuo conto corrente) e magari l'intervallo di date dell'estratto conto. - Confronta e trova le discrepanze:
- Per ogni transazione esterna, verifica se esiste una voce identica nel ledger (corrispondenza per data e importo, magari descrizione). Se non trovata, contrassegnala come "nuova" e magari producila come una transazione in formato Beancount da rivedere.
- Al contrario, individua eventuali voci del ledger in quel conto che non compaiono nella fonte esterna – potrebbero essere errori di inserimento dati o transazioni che non sono ancora state saldate dalla banca.
- Emettere i risultati: stampa un report o crea un nuovo estratto
.beancountcon le transazioni mancanti.
Come esempio, uno script della community chiamato reconcile.py fa esattamente questo: dato un file Beancount e un CSV di input, stampa una lista di nuove transazioni che dovrebbero essere importate, così come eventuali registrazioni del ledger esistenti che non sono nell'input (potenzialmente un segnale di classificazione errata). Con un simile script, la riconciliazione mensile può essere semplice come eseguirlo e poi accodare le transazioni suggerite al ledger. Un utente di Beancount nota che "eseguo un processo di riconciliazione su tutti i conti ogni mese" e usa una raccolta crescente di codice Python per eliminare gran parte del lavoro manuale nell'importazione e nella riconciliazione dei dati.
Suggerimento: durante la riconciliazione, sfrutta gli strumenti di Beancount per l'accuratezza:
- Usa le asserzioni di saldo come menzionato, per avere controlli automatici sui saldi dei conti.
- Usa la direttiva
padse lo desideri, che può inserire automaticamente voci di bilanciamento per piccole differenze di arrotondamento (usare con cautela). - Scrivi unit test per il tuo importer o la tua logica di riconciliazione (Beancount fornisce helper per i test). Per esempio, un flusso di lavoro prevedeva prendere un CSV di esempio, scrivere test falliti con le transazioni attese, poi implementare l'importer finché tutti i test non passavano. Questo garantisce che il tuo script di importazione funzioni correttamente per vari casi.
Generazione di Report e Riepiloghi Personalizzati
Sebbene Fava fornisca molti report standard (conto economico, stato patrimoniale, ecc.), puoi creare report personalizzati usando gli script. Questi possono variare da semplici output su console a file formattati ricchi o grafici.
Query dei dati per i report (Principiante)
A un livello base, puoi usare il Beancount Query Language (BQL) per ottenere dati di riepilogo e stamparli o salvarli. Per esempio:
-
Riepilogo del flusso di cassa: usa una query per calcolare il flusso di cassa netto. Il "flusso di cassa" potrebbe essere definito come la variazione del saldo di certi conti in un periodo. Usando BQL, potresti fare:
SELECT year, month, sum(position) WHERE account ~ 'Income' OR account ~ 'Expenses' GROUP BY year, monthQuesto somma al netto tutte le registrazioni di entrate e spese per mese. Filtra con
~e un'espressione regolare:LIKEè un errore di sintassi in beanquery 0.2.0. Le registrazioni portanoposition, nonamount. Ogni riga contiene un Inventory, quindi ogni valuta è elencata separatamente invece di essere convertita. Le entrate arrivano negative e le spese positive. Potresti eseguire questo tramitebea queryo tramite l'API Python di beanquery mostrata prima, e poi formattare il risultato. -
Report delle spese per categoria: interroga le spese totali per categoria:
SELECT account, sum(position) WHERE account ~ 'Expenses' GROUP BY account ORDER BY sum(position) ASCQuesto produce una tabella delle spese per categoria. Ogni totale è un Inventory nella sua valuta originale. Non racchiudere l'aggregato in
round(): non esiste una funzioneround(inventory, int), quindiround(sum(position), 2)non compila. Puoi eseguire più query in uno script e produrre i risultati come testo, CSV o persino JSON per ulteriori elaborazioni.
Un utente ha trovato "banale" analizzare i dati finanziari con Fava o con gli script, citando che usa uno script Python per estrarre dati da Beancount tramite il Query Language e poi inserirli in un DataFrame Pandas per preparare un report personalizzato. Per esempio, potresti recuperare i totali mensili con una query e poi usare Pandas/Matplotlib per tracciare un grafico del flusso di cassa nel tempo. La combinazione di BQL e librerie di data science ti permette di costruire report oltre ciò che Fava offre di default.
Report avanzati (Grafici, performance, ecc.)
Per esigenze più avanzate, i tuoi script possono calcolare metriche come la performance degli investimenti o creare output visivi:
-
Performance degli investimenti (IRR/XIRR): poiché il tuo ledger contiene tutti i flussi di cassa (acquisti, vendite, dividendi), puoi calcolare i tassi di rendimento del portafoglio. Per esempio, potresti scrivere uno script che filtra le transazioni dei tuoi conti di investimento e poi calcola il Tasso Interno di Rendimento. Esistono librerie (o formule) per calcolare l'IRR dati i dati sui flussi di cassa. Alcune estensioni Fava sviluppate dalla community (come PortfolioSummary o fava_investor) fanno esattamente questo, calcolando l'IRR e altre metriche per i portafogli di investimento. Come script, potresti usare una funzione IRR (da NumPy o tua) sulla serie di contributi/prelievi più il valore finale.
-
Metriche multi-periodo o personalizzate: vuoi un report del tuo tasso di risparmio (rapporto tra risparmi ed entrate) ogni mese? Uno script Python può caricare il ledger, sommare tutti i conti di Entrata e tutti i conti di Spesa, poi calcolare risparmi = entrate - spese e la percentuale. Questo potrebbe produrre una bella tabella o persino generare un report HTML/Markdown per i tuoi archivi.
-
Visualizzazione: puoi generare grafici al di fuori di Fava. Per esempio, usa
matplotliboaltairin uno script per creare un grafico del patrimonio netto nel tempo, usando i dati del ledger. Poiché il ledger ha tutti i saldi storici (o puoi accumularli iterando le voci), puoi produrre grafici di serie temporali. Salva questi grafici come immagini o HTML interattivo. (Se preferisci visualizzazioni in-app, vedi la sezione sulle estensioni Fava di seguito per aggiungere grafici all'interno di Fava.)
Opzioni di output: decidi come consegnare il report:
- Per un'analisi una tantum, stampare sullo schermo o salvare in un file CSV/Excel potrebbe bastare.
- Per le dashboard, considera di generare un file HTML con i dati (possibilmente usando una libreria di template come Jinja2 o anche solo scrivendo Markdown) che puoi aprire in un browser.
- Puoi anche integrarti con Jupyter Notebooks per un ambiente di reporting interattivo, anche se questo è più per l'esplorazione che per l'automazione.
Attivare Avvisi dal tuo Ledger
Un altro potente uso dei flussi di lavoro programmabili è impostare avvisi basati su condizioni nei tuoi dati finanziari. Poiché il tuo ledger è aggiornato regolarmente (e può includere voci con date future come bollette imminenti o budget), puoi scansionarlo con uno script e ricevere notifiche di eventi importanti.
Avvisi di Bilancio Conto Basso
Per evitare scoperti o mantenere un saldo minimo, potresti volere un avviso se un conto (es. corrente o risparmio) scende sotto una soglia. Ecco come implementarlo:
-
Determina i saldi attuali: dopo aver caricato le
entriestramite il loader, calcola il saldo più recente dei conti di interesse. Puoi farlo aggregando le registrazioni o usando una query. Per esempio, usa una query BQL per il saldo di un conto specifico:SELECT sum(position) WHERE account = 'Assets:Bank:Checking'Questo restituisce il saldo attuale di quel conto (somma di tutte le sue registrazioni). In alternativa, usa le funzioni interne di Beancount per costruire uno stato patrimoniale. Per esempio:
from beancount.core import realization tree = realization.realize(entries) acct = realization.get_or_create(tree, "Assets:Bank:Checking") balance = acct.balance # an Inventory of commoditiesPassa solo le entries: il secondo parametro è
min_accounts, non la mappa delle opzioni. Poi estrai il valore numerico (es.balance.get_currency_units('USD')restituisce l'importo in Decimal in USD). Come un aggregato di query, il saldo mantiene ogni valuta separatamente. Tuttavia, usare la query è più semplice nella maggior parte dei casi. -
Verifica la soglia: confronta il saldo con il tuo limite predefinito. Se sotto, attiva un avviso.
-
Attiva la notifica: questo potrebbe essere semplice come stampare un avviso sulla console, ma per avvisi reali potresti inviare un'email o una notifica push. Puoi integrarti con l'email (tramite
smtplib) o un servizio come IFTTT o l'API webhook di Slack per inviare l'avviso. Per esempio:if balance < 1000: send_email("Low balance alert", f"Account XYZ balance is {balance}")(Implementa
send_emailcon i dettagli del tuo server email.)
Eseguendo questo script ogni giorno (tramite un cron job o Windows Task Scheduler), otterrai avvisi proattivi. Poiché usa il ledger, può considerare tutte le transazioni, incluse quelle appena aggiunte.
Scadenze di Pagamento Imminenti
Se usi Beancount per tracciare bollette o scadenze, puoi contrassegnare pagamenti futuri e far sì che gli script te li ricordino. Due modi per rappresentare obbligazioni imminenti in Beancount:
-
Eventi: Beancount supporta una direttiva
eventper note datate arbitrarie. Per esempio:2025-05-10 event "BillDue" "Mortgage payment due"Questo non influisce sui saldi ma registra una data con un'etichetta. Uno script può scansionare
entriesper le vociEventdoveEvent.type == "BillDue"(o qualsiasi tipo personalizzato tu scelga) e verificare se la data rientra, diciamo, nei prossimi 7 giorni da oggi. Se sì, attiva un avviso (email, notifica o persino un popup). -
Transazioni future: alcune persone inseriscono transazioni con data futura (post-datate) per cose come pagamenti programmati. Queste non compaiono nei saldi finché la data non passa (a meno che tu non esegua report a date future). Uno script può cercare transazioni datate nel prossimo futuro e elencarle.
Usando queste, potresti creare uno script "tickler" che, quando eseguito, produce una lista di attività o bollette in scadenza. Integra con un'API come Google Calendar o un task manager se vuoi creare automaticamente promemoria lì.
Rilevamento di Anomalie
Oltre alle soglie o alle date note, puoi programmare avvisi personalizzati per schemi insoliti. Per esempio, se una spesa normalmente mensile non si è verificata (magari hai dimenticato di pagare una bolletta), o se la spesa di una categoria è anormalmente alta questo mese, il tuo script potrebbe segnalarlo. Questo tipicamente comporta l'interrogazione di dati recenti e il confronto con la storia (che potrebbe essere un argomento avanzato – possibilmente impiegando statistiche o ML).
In pratica, molti utenti si affidano alla riconciliazione per individuare anomalie (transazioni inattese). Se ricevi notifiche bancarie (come email per ogni transazione), potresti analizzarle con uno script e aggiungerle automaticamente a Beancount, o almeno verificare che siano registrate. Un appassionato ha persino configurato la propria banca per inviare email di avviso sulle transazioni, con il piano di analizzarle e accodarle automaticamente al ledger. Questo tipo di avviso guidato dagli eventi può garantire che nessuna transazione rimanga non registrata.
Estendere Fava con Plugin e Visualizzazioni Personalizzate
Fava è già programmabile tramite il suo sistema di estensioni. Se vuoi che la tua automazione o i tuoi report si integrino direttamente nell'interfaccia web, puoi scrivere un'estensione Fava (chiamata anche plugin) in Python.
Come funzionano le estensioni Fava: un'estensione è un modulo Python che definisce una classe che eredita da fava.ext.FavaExtensionBase. La registri nel tuo file Beancount tramite un'opzione personalizzata. Per esempio, se hai un file myextension.py con una classe MyAlerts(FavaExtensionBase), puoi abilitarla aggiungendo al tuo ledger:
1970-01-01 custom "fava-extension" "myextension"Quando Fava si carica, importerà quel modulo e inizializzerà la tua classe MyAlerts.
Le estensioni possono fare diverse cose:
- Hook: possono agganciarsi agli eventi del ciclo di vita di Fava. Per esempio,
after_load_file()viene chiamato dopo che il ledger è caricato. Potresti usarlo per eseguire controlli o precalcolare dati. Se volessi implementare il controllo del saldo basso all'interno di Fava,after_load_filepotrebbe iterare sui saldi dei conti e magari memorizzare avvisi (anche se farli emergere nell'interfaccia utente potrebbe richiedere un po' più di lavoro, come sollevare un FavaAPIError o usare Javascript per mostrare una notifica). - Report/Pagine personalizzati: se la tua classe di estensione imposta un attributo
report_title, Fava aggiungerà una nuova pagina nella barra laterale per essa. Poi fornisci un template (HTML/Jinja2) per il contenuto di quella pagina. È così che crei viste completamente nuove, come una dashboard o un riepilogo che Fava non ha di default. L'estensione può raccogliere tutti i dati di cui ha bisogno (puoi accedere aself.ledgerche ha tutte le voci, i saldi, ecc.) e poi renderizzare il template.
Per esempio, l'estensione integrata portfolio_list in Fava aggiunge una pagina che elenca le posizioni del tuo portafoglio. Le estensioni della community vanno oltre:
- Dashboard: il plugin fava-dashboards permette di definire grafici e pannelli personalizzati (usando librerie come Apache ECharts). Legge una configurazione YAML delle query da eseguire, le esegue tramite Beancount e genera una pagina dashboard dinamica in Fava. In sostanza, unisce i dati di Beancount e una libreria di grafici JavaScript per produrre visualizzazioni interattive.
- Analisi del portafoglio: l'estensione PortfolioSummary (contribuita dagli utenti) calcola riepiloghi degli investimenti (raggruppando conti, calcolando l'IRR, ecc.) e li mostra nell'interfaccia di Fava.
- Revisione delle transazioni: un'altra estensione, fava-review, aiuta a rivedere le transazioni nel tempo (es. per assicurarti di non aver perso qualche ricevuta).
Per creare tu stesso una semplice estensione, inizia ereditando da FavaExtensionBase. Per esempio, un'estensione minimale che aggiunge una pagina potrebbe apparire come:
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")Se mettessi questo in hello.py e aggiungessi custom "fava-extension" "hello" al tuo ledger, Fava mostrerebbe una nuova pagina "Hello World" (avresti anche bisogno di un file template HelloReport.html in una sottocartella templates per definire il contenuto della pagina, a meno che l'estensione usi solo gli hook). Il template può usare i dati che alleghi alla classe dell'estensione. Fava usa template Jinja2, quindi potresti renderizzare i tuoi dati in una tabella HTML o in un grafico in quel template.
Nota: il sistema di estensioni di Fava è potente ma considerato "instabile" (soggetto a cambiamenti). Richiede una certa familiarità con lo sviluppo web (HTML/JS) se crei pagine personalizzate. Se il tuo obiettivo è semplicemente eseguire script o analisi, potrebbe essere più facile mantenerli come script esterni. Usa le estensioni Fava quando vuoi un'esperienza in-app su misura per il tuo flusso di lavoro.
Integrazione di API e Dati di Terze Parti
Uno dei vantaggi dei flussi di lavoro programmabili è la capacità di attingere a dati esterni. Ecco le integrazioni comuni:
Per i prezzi di valutazione ospitati, Live Prices offre include gestiti senza uno script pianificato per il recupero dei prezzi. Scegli le coppie di asset supportate e una valuta di quotazione nel selettore. I flussi di lavoro locali basati su file di seguito restano utili per Beancount upstream, Fava e report riproducibili. Un aggiornamento gestito non crea un commit Git nel tuo ledger.
-
Tassi di cambio e materie prime: Beancount upstream non recupera i prezzi da solo, ma fornisce una direttiva
priceper fornire i tassi. Puoi automatizzare il recupero di questi prezzi. Per esempio, uno script può interrogare un'API (Yahoo Finance, Alpha Vantage, ecc.) per l'ultimo tasso di cambio o il prezzo di un'azione e aggiungere una voce di prezzo al tuo ledger:2025-04-30 price BTC 30000 USD 2025-04-30 price EUR 1.10 USDEsistono strumenti come
bea price, supportati da Beanprice nel motore gestito, che recuperano quotazioni giornaliere e le producono in formato Beancount. Potresti abilitarlo una volta conbea engine enable beanprice, poi pianificarebea price main.beancountper l'esecuzione ogni notte per aggiornare un file includeprices.beancount. Oppure usa Python: ad esempio, con la libreriarequestsper chiamare un'API. La documentazione di Beancount suggerisce che per gli asset quotati pubblicamente, puoi "invocare del codice che scaricherà i prezzi e scriverà le direttive per te." In altre parole, lascia che uno script faccia la ricerca e inserisca le righeprice, invece di farlo manualmente. -
Dati sul portafoglio azionario: simile ai tassi di cambio, puoi integrarti con API per recuperare dati dettagliati sulle azioni o sui dividendi. Per esempio, l'API di Yahoo Finance (o librerie della community come
yfinance) può recuperare dati storici per un ticker. Uno script potrebbe aggiornare il tuo ledger con lo storico dei prezzi mensili per ogni azione che possiedi, consentendo report storici accurati del valore di mercato. Alcune estensioni personalizzate (come fava_investor) recuperano persino i dati sui prezzi al volo per la visualizzazione, ma la cosa più semplice è importare regolarmente i prezzi nel ledger. -
API bancarie (Open Banking/Plaid): invece di scaricare CSV, puoi usare API per recuperare le transazioni automaticamente. Servizi come Plaid aggregano conti bancari e permettono l'accesso programmatico alle transazioni. In una configurazione avanzata, potresti avere uno script Python che usa l'API di Plaid per recuperare nuove transazioni ogni giorno e salvarle in un file (o importarle direttamente nel ledger). Un power-user ha costruito un sistema in cui Plaid alimenta la sua pipeline di importazione, rendendo i suoi libri quasi automatici. Nota che "nulla ti impedisce di registrarti con l'API di Plaid e fare lo stesso localmente" – cioè, puoi scrivere uno script locale per ottenere i dati bancari, poi usare la tua logica di importer Beancount per analizzarli in voci del ledger. Alcune regioni hanno API di open banking fornite dalle banche; quelle potrebbero essere usate in modo simile.
-
Altre API: potresti integrare strumenti di budgeting (esportando budget pianificati per confrontarli con gli effettivi in Beancount), o usare un'API OCR per leggere le ricevute e abbinarle automaticamente alle transazioni. Poiché i tuoi script hanno pieno accesso all'ecosistema Python, puoi integrare tutto, dai servizi email (per inviare avvisi) a Google Sheets (es. aggiornare un foglio con metriche finanziarie mensili) alle app di messaggistica (inviarti un report di riepilogo tramite bot Telegram).
Quando usi API di terze parti, ricorda di proteggere le tue credenziali (usa variabili d'ambiente o file di configurazione per le chiavi API) e gestisci gli errori (problemi di rete, downtime delle API) con grazia nei tuoi script. Spesso è saggio mettere in cache i dati (per esempio, memorizzare i tassi di cambio recuperati per non richiedere ripetutamente lo stesso tasso storico).
Best Practices per Script Modulari e Manutenibili
Mentre costruisci flussi di lavoro programmabili, mantieni il tuo codice organizzato e robusto:
-
Modularità: suddividi diverse preoccupazioni in script o moduli diversi. Per esempio, abbia script separati per "importazione/riconciliazione dati" vs. "generazione report" vs. "avvisi". Puoi persino creare un piccolo pacchetto Python per il tuo ledger con moduli come
ledger_import.py,ledger_reports.py, ecc. Questo rende ogni parte più facile da capire e testare. -
Configurazione: evita di codificare i valori. Usa un file di configurazione o variabili in cima allo script per cose come nomi dei conti, soglie, chiavi API, intervalli di date, ecc. Questo rende facile regolare senza modificare profondamente il codice. Per esempio, definisci
LOW_BALANCE_THRESHOLDS = {"Assets:Bank:Checking": 500, "Assets:Savings": 1000}in cima, e il tuo script di avviso può scorrere questo dict. -
Testing: tratta la tua automazione finanziaria come codice mission-critical – perché lo è! Scrivi test per la logica complessa. Beancount fornisce alcuni helper per i test (usati internamente per il testing degli importer) che puoi sfruttare per simulare input del ledger. Anche senza framework elaborati, puoi avere un CSV fittizio e transazioni di output attese, e asserire che il tuo script di importazione produca le voci corrette. Se usi
pytest, puoi integrare facilmente questi test (come ha fatto Alex Watt tramite un comandojust testche avvolge pytest). -
Controllo di versione: mantieni il tuo ledger e i tuoi script sotto controllo di versione (git). Questo non solo ti dà backup e cronologia, ma ti incoraggia a fare modifiche in modo controllato. Puoi taggare le release dei tuoi "script finanziari" o rivedere le differenze durante il debug di un problema. Alcuni utenti tracciano persino i loro registri finanziari in Git per vedere i cambiamenti nel tempo. Fai solo attenzione a ignorare i dati sensibili (come file di estratto conto grezzi o chiavi API) nel tuo repo.
-
Documentazione: documenta i tuoi flussi di lavoro personalizzati per il te stesso futuro. Un README nel tuo repository che spiega come configurare l'ambiente, come eseguire ogni script e cosa fa ciascuno sarà inestimabile dopo che sono passati mesi. Commenta anche il tuo codice, specialmente qualsiasi logica contabile non ovvia o interazione con API.
-
Manutenzione dei plugin Fava: se scrivi un'estensione Fava, mantienila semplice. Fava potrebbe cambiare, quindi estensioni più piccole con funzionalità mirate sono più facili da aggiornare. Evita di duplicare troppa logica – usa il motore di query di Beancount o le funzioni helper esistenti quando possibile, invece di codificare calcoli che potrebbero essere sensibili ai cambiamenti del ledger.
-
Sicurezza: poiché i tuoi script potrebbero gestire dati sensibili e connettersi a servizi esterni, trattali con cura. Non esporre le chiavi API e considera di eseguire la tua automazione su una macchina sicura. Se usi una soluzione ospitata o il cloud (come pianificare GitHub Actions o un server per eseguire Fava), assicurati che i tuoi dati del ledger siano crittografati a riposo e che tu sia a tuo agio con le implicazioni sulla privacy.
Seguendo queste pratiche, garantisci che il tuo flusso di lavoro rimanga affidabile anche mentre le tue finanze (e gli strumenti stessi) evolvono. Vuoi script che puoi riutilizzare anno dopo anno, con modifiche minime.
Conclusione
Beancount e Fava forniscono una piattaforma potente e flessibile per gli utenti esperti di tecnologia per personalizzare completamente il loro monitoraggio delle finanze personali. Scrivendo script Python, puoi automatizzare attività noiose come la riconciliazione degli estratti conto, produrre report ricchi su misura per le tue esigenze e rimanere al passo con le tue finanze tramite avvisi tempestivi. Abbiamo coperto una gamma di esempi da base ad avanzati – iniziando con semplici query e importazioni CSV, e passando a plugin Fava completi e integrazioni con API esterne. Mentre li implementi, inizia semplice e costruisci gradualmente. Anche solo alcuni piccoli script di automazione possono risparmiare ore di lavoro e migliorare notevolmente l'accuratezza. E ricorda, poiché tutto è testo semplice e Python, hai il pieno controllo – il tuo sistema finanziario cresce con te, piegandosi alle tue esigenze specifiche. Buono scripting!
Fonti: Le tecniche sopra sono tratte dalla documentazione di Beancount e dalle esperienze della community. Per ulteriori letture, vedi la documentazione ufficiale di Beancount, le guide e i blog della community, e il repository Awesome Beancount per link a plugin e strumenti utili.