Salta al contenuto principale

Come gli script Python automatizzano Beancount e Fava

Beancount e Fava restano scriptabili: usa Python per automatizzare report, saldi e flussi di lavoro personalizzati sul tuo registro.

Beancount (uno strumento di contabilità a doppia entrata in testo semplice) e Fava (la sua interfaccia web) sono altamente estensibili e scriptabili. Il loro design consente di automatizzare attività finanziarie, generare report personalizzati e impostare avvisi scrivendo script in Python. Nelle parole di un utente, “Mi piace davvero avere i miei dati in un formato così conveniente, e mi piace poter automatizzare le cose a mio piacimento. Non c’è API come un file sul tuo disco; è facile da integrare.” Questa guida spiega come creare workflow scriptabili, dall'automazione per principianti ai plugin avanzati per Fava.

Esplora un registro esempio in tempo reale:

Apri Example Ledger in una nuova scheda

Inizia con la linea di comando bea

Prima di scrivere qualsiasi codice Python, verifica se bea fa già il lavoro. Valida il registro, esegue query BQL, produce i quattro report finanziari e importa esportazioni bancarie; e globalmente --json trasforma ciascuno di questi in una busta analizzabile che la tua shell può inviare a jq. I suoi codici di uscita costituiscono il contratto su cui si basa il ramo di un lavoro pianificato, quindi cron o CI non necessitano affatto di uno script loader. Consulta automate bookkeeping with bea per la risoluzione target, busta e ramificazione tramite codici d’uscita, e torna qui quando hai bisogno di un calcolo personalizzato che la CLI non espone.

Primi passi: eseguire Beancount come script Python

Per gli script Python personalizzati qui sotto, installa le librerie di scripting (pip install beancount beanquery beangulp). I workflow da riga di comando bea utilizzano invece il motore gestito; segui il quick start CLI per installarlo. Poiché Beancount è scritto in Python, puoi usarlo come libreria nei tuoi script. Gli script qui sotto sono stati eseguiti con Beancount 3.2.3, beanquery 0.2.0, e beangulp 0.2.0. L’approccio generale è:

  • Carica il tuo registro Beancount: usa il loader di Beancount per analizzare il file .beancount in 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 voci e errori insieme. Un file non bilanciato o non valido restituisce comunque voci, quindi controlla errors e 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 si trovano nel pacchetto separato beanquery. Non esiste un modulo beancount.query in Beancount 3.2.3. Per esempio, per ottenere le spese totali per mese, collega le voci caricate ed esegui direttamente la query:

    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 utilizza beanquery per aggregare i dati. È lo stesso motore dietro bea query, ma qui lo chiami in uno script. Ciò evita di chiamare un comando esterno in un ciclo.

  • Configura una struttura di progetto: organizza i tuoi script insieme al tuo libro mastro. Una disposizione comune è avere directory per importatori (per recuperare/analizzare dati esterni), report o query (per script di analisi), e documenti (per archiviare estratti conto scaricati). Per esempio, un utente mantiene:

    • importers/ – script Python personalizzati per importazione (con test),
    • queries/ – script per generare report (eseguibili tramite python3 queries/...),
    • documents/ – CSV/PDF bancari scaricati organizzati per conto.

Con questa configurazione, puoi eseguire gli script manualmente (es. python3 queries/cash_flow.py) o programmarli (tramite cron o un task runner) per automatizzare il flusso di lavoro.

Automazione delle attività di riconciliazione

Riconciliazione significa assicurarsi che il tuo libro mastro corrisponda ai registri esterni (estratti conto bancari, rapporti carte di credito, ecc.). Il libro mastro in testo semplice di Beancount e la sua API Python consentono di automatizzare gran parte di questo processo.

Importazione e abbinamento delle transazioni (principianti)

Per i principianti, l'approccio consigliato è usare importatori dal pacchetto separato beangulp. Beancount 3 ha rimosso il modulo ingest v2 e il suo comando extract. Scrivi una piccola classe Python che derivi da beangulp.Importer per analizzare un formato specifico (CSV, OFX, PDF, ecc.) e produrre transazioni. Registrala in un breve script di ingestione, quindi eseguila tramite bea ingest nel motore gestito:

  • Scrivi un importer (una classe Python con i metodi identify(), account() e extract()) per il formato CSV della tua banca.
  • Aggiungi uno script di ingestione che registra i tuoi importers. bea ingest esegue i comandi identify, extract e archive dello script. Per esempio, un flusso di lavoro esegue extract su tutti i file in ~/Downloads e scrive le transazioni in un file temporaneo.
  • Rivedi manualmente e copia le transazioni dal file temporaneo nel tuo libro mastro principale, poi esegui bea check per assicurarti che i saldi combacino.

Un esempio minimo: un statement.csv con 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 entries

Lo script di ingestione (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 sono necessarie 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.beancount

identify riporta checking_importer.CheckingImporter per il file. extract scrive le transazioni nel formato Beancount:

2024-01-08 * "Grocery Store"
  Expenses:Food:Groceries   120.00 USD
  Assets:Bank:Checking     -120.00 USD

Rivedi new.beancount, copia le voci nel tuo libro mastro principale ed esegui bea check.

Salta l’importer per un’operazione isolata

Non è necessario scrivere un importer per convertire un singolo estratto conto. Incolla il file nel convertitore CSV in Beancount, o usa OFX & QIF in Beancount per download .ofx, .qfx e .qif. Entrambi vengono eseguiti interamente nel tuo browser, quindi l’estratto conto non lascia mai la tua macchina.

Mentre questo processo richiede ancora una fase di revisione, gran parte del lavoro pesante di analisi e formattazione delle voci è automatizzato. Gli script importer possono anche assegnare automaticamente categorie e persino impostare assertion di saldo (dichiarazioni di saldi attesi) per rilevare discrepanze. Per esempio, dopo l’importazione, potresti avere una riga come 2025-04-30 balance Assets:Bank:Checking 1234.56 USD che asserisce il saldo di chiusura. Quando esegui bea check, Beancount verifica che tutte queste assertion di saldo siano corrette, segnalando errori se mancano o sono duplicate transazioni. Questa è una best practice: genera automaticamente assertion di saldo per ogni periodo di estratto conta per far rilevare 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 libro mastro:

  1. Leggi i dati esterni: Analizza il file CSV della banca usando il modulo csv di Python (o Pandas). Normalizza i dati in una lista di transazioni, ad esempio ciascuna con una data, un importo e una descrizione.
  2. Carica le transazioni del libro mastro: Usa loader.load_file come mostrato in precedenza per ottenere tutte le scritture del libro mastro. Filtra questa lista per il conto di interesse (ad esempio il tuo conto corrente) e forse per l'intervallo di date dell'estratto conto.
  3. Confronta e trova le discrepanze:
  • Per ogni transazione esterna, verifica se una voce identica esiste nel libro mastro (confronta per data e importo, magari per descrizione). Se non trovata, contrassegnala come “nuova” e possibilmente stampala come transazione in formato Beancount per la tua revisione.
  • Al contrario, identifica tutte le scritture del libro mastro in quel conto che non compaiono nella fonte esterna – potrebbero essere errori di inserimento dati o transazioni non ancora contabilizzate dalla banca.
  1. Stampa i risultati: Stampa un report o crea un nuovo frammento .beancount con 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 da importare, così come tutte le scritture esistenti nel libro mastro che non sono presenti nell’input (potenzialmente segno di un’errata classificazione). Con uno script del genere, la riconciliazione mensile può essere semplice come eseguirlo e poi aggiungere le transazioni suggerite al libro mastro. Un utente di Beancount osserva che “fa un processo di riconciliazione su tutti i conti ogni mese” e usa una crescente collezione 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 accuratezza:

  • Usa asserzioni di saldo come menzionato, per avere controlli automatizzati sui saldi dei conti.
  • Usa la direttiva pad se desideri, che può inserire automaticamente scritture di bilanciamento per piccole differenze di arrotondamento (usare con cautela).
  • Scrivi test unitari per il tuo importer o la logica di riconciliazione (Beancount fornisce helper per i test). Ad esempio, un flusso di lavoro prevedeva di prendere un CSV di esempio, scrivere test fallenti con le transazioni attese, quindi implementare l’importatore finché tutti i test non passavano. Questo garantisce che lo script di import funzioni correttamente in vari casi.

Generazione di Report e Riepiloghi Personalizzati

Sebbene Fava offra molti report standard (Conto Economico, Stato Patrimoniale, ecc.), puoi creare report personalizzati usando script. Questi possono andare da semplici output 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 riepilogativi e stamparli o salvarli. Per esempio:

  • Riepilogo del flusso di cassa: Usa una query per calcolare il flusso di cassa netto. “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, month

    Questo netta tutte le registrazioni di entrate e uscite per mese. Filtra con ~ e un'espressione regolare: LIKE è un errore di sintassi in beanquery 0.2.0. Le registrazioni contengono position, non amount. Ogni riga contiene un singolo Inventario, così ogni valuta è elencata separatamente invece di essere convertita. Le entrate compaiono negative e le spese positive. Potresti eseguire questo tramite bea query o tramite l'API Python di beanquery mostrata in precedenza, e poi formattare il risultato.

  • Report delle spese per categoria: Query totale delle spese per categoria:

    SELECT account, sum(position)
    WHERE account ~ 'Expenses'
    GROUP BY account
    ORDER BY sum(position) ASC

    Questo produce una tabella delle spese per categoria. Ogni totale è un Inventario nella sua valuta originale. Non racchiudere l'aggregato in round(): non esiste la funzione round(inventory, int), quindi round(sum(position), 2) non compila. Puoi eseguire più query in uno script e outputtare i risultati come testo, CSV o perfino JSON per un'elaborazione successiva.

Un utente ha trovato “banale” analizzare dati finanziari con Fava o con script, citando che usa uno script Python per estrarre dati da Beancount tramite il Query Language e poi inserirli in un DataFrame di 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 permette di creare report oltre quanto offre Fava 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 visuali:

  • Performance degli investimenti (IRR/XIRR): Dal momento che il tuo libro mastro 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 di flusso di cassa. Alcune estensioni comunitarie di Fava (come PortfolioSummary o fava_investor) fanno proprio questo, calcolando IRR e altre metriche per portafogli d'investimento. Come script, potresti usare una funzione IRR (da NumPy o tua propria) sulla serie di contributi/prelievi più il valore finale.

  • Metriche multi-periodo o personalizzate: Vuoi un report del tuo tasso di risparmio (rapporto fra risparmio e reddito) ogni mese? Uno script Python può caricare il ledger, sommare tutti i conti delle Entrate e tutte le Spese, quindi calcolare il risparmio = entrate - spese e la percentuale. Questo può produrre una bella tabella o anche generare un report HTML/Markdown per i tuoi archivi.

  • Visualizzazione: Puoi generare grafici al di fuori di Fava. Ad esempio, usa matplotlib o altair in uno script per creare un grafico del patrimonio netto nel tempo, usando i dati del ledger. Poiché il ledger contiene tutti i saldi storici (o puoi accumularli iterando le registrazioni), puoi produrre grafici a serie temporali. Salva questi grafici come immagini o HTML interattivi. (Se preferisci visualizzazioni integrate nell’app, vedi la sezione sull’estensione di Fava sotto per aggiungere grafici all’interno di Fava.)

Opzioni di output: Decidi come produrre il report:

  • Per analisi una tantum, stampare a schermo o salvare in un file CSV/Excel potrebbe bastare.
  • Per dashboard, considera di generare un file HTML con i dati (possibilmente usando una libreria di template come Jinja2 o anche semplicemente scrivendo Markdown) che puoi aprire in un browser.
  • Puoi anche integrare con Jupyter Notebook per un ambiente di report interattivo, sebbene sia più indicato per esplorazioni che per automazioni.

Attivare Avvisi dal tuo Ledger

Un altro uso potente dei workflow scriptabili è impostare avvisi basati su condizioni nei tuoi dati finanziari. Poiché il tuo ledger viene aggiornato regolarmente (e può includere voci datate in futuro come bollette imminenti o budget), puoi scansionarlo con uno script e ricevere notifiche per eventi importanti.

Avvisi di Bilancio Conto Basso

Per evitare scoperti o mantenere un saldo minimo, potresti voler ricevere un avviso se un qualsiasi conto (es. conto corrente o di risparmio) scende sotto una soglia. Ecco come puoi implementarlo:

  1. Determina i saldi correnti: Dopo aver caricato entries tramite 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 uno specifico conto:

    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 commodities

    Passa solo le voci: il secondo parametro è min_accounts, non la mappa delle opzioni. Poi estrai il valore numerico (es. balance.get_currency_units('USD') restituisce l'importo Decimal in USD). Come un aggregate di query, il saldo mantiene ogni valuta separatamente. Tuttavia, usare la query è più semplice nella maggior parte dei casi.

  2. Controlla la soglia: Confronta il saldo con il tuo limite predefinito. Se è inferiore, attiva un avviso.

  3. Attiva la notifica: Questo può essere semplice come stampare un avviso sulla console, ma per avvisi veri potresti inviare un'email o una notifica push. Puoi integrare con 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_email con i dettagli del tuo server email.)

Eseguendo questo script quotidianamente (tramite un cron job o con Windows Task Scheduler), riceverai avvisi proattivi. Poiché usa il ledger, può considerare tutte le transazioni inclusi quelle appena aggiunte.

Scadenze di Pagamento Imminenti

Se usi Beancount per tenere traccia di bollette o scadenze, puoi segnare pagamenti futuri e far sì che gli script ti ricordino. Due modi per rappresentare obblighi futuri in Beancount:

  • Eventi: Beancount supporta una direttiva event per 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 entries per voci Event dove Event.type == "BillDue" (o qualsiasi tipo personalizzato che scegli) e verificare se la data è entro, per esempio, i prossimi 7 giorni da oggi. Se sì, attiva un avviso (email, notifica o persino un popup).

  • Transazioni Future: Alcune persone inseriscono transazioni a data futura (post-datate) per cose come pagamenti programmati. Queste non appariranno nei saldi fino al passaggio della data (a meno che non esegui report con date future). Uno script può cercare transazioni datate nel prossimo futuro e elencarle.

Usando questi, potresti creare uno script “tickler” che, quando eseguito, produce una lista di compiti o bollette in scadenza a breve. Integra con un'API come Google Calendar o un task manager se vuoi creare automaticamente promemoria lì.

Rilevamento di Anomalie

Oltre le soglie o le date note, puoi scrivere avvisi personalizzati per schemi anomali. Ad esempio, se una spesa normalmente mensile non è avvenuta (forse hai dimenticato di pagare una bolletta), o se la spesa di una categoria è anormalmente alta questo mese, il tuo script potrebbe segnalarlo. Questo in genere comporta il reperimento 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 rilevare 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 sua banca per inviare email di avviso per le transazioni, con il piano di analizzarle e aggiungerle automaticamente al libro mastro. Questo tipo di avviso guidato dagli eventi può garantire che nessuna transazione rimanga non registrata.

Estendere Fava con Plugin e Visualizzazioni Personalizzate

Fava è già scriptabile tramite il suo sistema di estensioni. Se vuoi che la tua automazione o i tuoi rapporti si integrino direttamente nell'interfaccia web, puoi scrivere una 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 libro mastro:

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 nel ciclo di vita di Fava. Per esempio, after_load_file() viene chiamato dopo il caricamento del libro mastro. Potresti usarlo per eseguire controlli o pre-calcolare dati. Se volessi implementare il controllo di saldo basso all'interno di Fava, after_load_file potrebbe iterare sui saldi dei conti e forse memorizzare avvisi (anche se mostrarli nell'interfaccia utente potrebbe richiedere un lavoro extra, come sollevare un FavaAPIError o usare Javascript per mostrare una notifica).
  • Report/Pagine Personalizzate: Se la tua classe di estensione imposta un attributo report_title, Fava aggiungerà una nuova pagina nella barra laterale per essa. Poi fornisci un modello (HTML/Jinja2) per il contenuto di quella pagina. Questo è come creare viste completamente nuove, come un cruscotto o un riassunto che Fava non ha di default. L'estensione può raccogliere qualunque dato necessario (puoi accedere a self.ledger che contiene tutte le voci, i saldi, ecc.) e poi renderizzare il modello.

Per esempio, l’estensione integrata portfolio_list in Fava aggiunge una pagina che elenca le posizioni del tuo portfolio. Le estensioni della comunità fanno di più:

  • Cruscotti: Il plugin fava-dashboards permette di definire grafici e pannelli personalizzati (usando librerie come Apache ECharts). Legge una configurazione YAML di query da eseguire, le esegue tramite Beancount, e genera una pagina dinamica di cruscotto in Fava. In sostanza, collega i dati di Beancount e una libreria di grafici JavaScript per produrre visualizzazioni interattive.
  • Analisi del portfolio: L'estensione PortfolioSummary (contributo utente) calcola riassunti degli investimenti (raggruppando conti, calcolando 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 assicurarsi di non aver perso alcuna ricevuta).

Per creare una semplice estensione da solo, inizia sottoclasseando FavaExtensionBase. Per esempio, un'estensione minima che aggiunge una pagina potrebbe assomigliare a:

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 piazzassi questo in hello.py e aggiungessi custom "fava-extension" "hello" al tuo libro mastro, Fava mostrerebbe una nuova pagina "Hello World" (avresti anche bisogno di un file modello HelloReport.html in una sottocartella templates per definire il contenuto della pagina, a meno che l’estensione usi solo hook). Il modello può usare dati che alleghi alla classe dell’estensione. Fava usa modelli Jinja2, quindi potresti rendere i tuoi dati in una tabella HTML o un grafico in quel modello.

Nota: Il sistema di estensioni di Fava è potente ma considerato “instabile” (soggetto a modifiche). Richiede una certa familiarità con lo sviluppo web (HTML/JS) se si vogliono creare pagine personalizzate. Se il tuo obiettivo è semplicemente eseguire script o analisi, potrebbe essere più semplice mantenerli come script esterni. Usa le estensioni di Fava quando desideri 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 scriptabili è la possibilità di importare dati esterni. Ecco alcune integrazioni comuni:

  • Tassi di Cambio e Materie Prime: Beancount non recupera automaticamente i prezzi per progettazione (per mantenere i report deterministici), ma fornisce una direttiva Price per inserire 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 azionario e aggiungere una voce di prezzo al tuo registro:

    2025-04-30 price BTC 30000 USD
    2025-04-30 price EUR 1.10 USD

    Esistono strumenti come bea price, supportati da Beanprice nel motore gestito, che recuperano quotazioni giornaliere e le esportano in formato Beancount. Potresti attivarlo una volta con bea engine enable beanprice, quindi programmare bea price main.beancount per l’esecuzione notturna e aggiornare un file di inclusione prices.beancount. Oppure usare Python: ad esempio con la libreria requests per chiamare un’API. La documentazione di Beancount suggerisce che per asset quotati pubblicamente, puoi “invocare del codice che scaricherà i prezzi e scriverà le direttive per te.” In altre parole, lascia che uno script esegua la ricerca e inserisca le righe price, invece che farlo manualmente.

  • Dati del Portafoglio Azionario: Analogamente ai tassi di cambio, puoi integrare API per recuperare dati dettagliati sulle azioni o 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 registro con la cronologia mensile dei prezzi per ogni azione posseduta, consentendo report storici accurati del valore di mercato. Alcune estensioni personalizzate (come fava_investor) estraggono i prezzi in tempo reale per la visualizzazione, ma la soluzione più semplice è importare regolarmente i prezzi nel registro.

  • API Bancarie (Open Banking/Plaid): Invece di scaricare CSV, puoi usare API per recuperare automaticamente le transazioni. Servizi come Plaid aggregano conti bancari e permettono accesso programmatico alle transazioni. In una configurazione avanzata, potresti avere uno script Python che usa l'API di Plaid per estrarre nuove transazioni quotidianamente e salvarle in un file (o importarle direttamente nel libro mastro). Un utente esperto ha costruito un sistema in cui Plaid alimenta la loro pipeline di importazione, rendendo i loro libri quasi automatici. Notano che “nulla ti impedisce di iscriverti con l'API di Plaid e fare lo stesso localmente” – cioè, puoi scrivere uno script locale per ottenere dati bancari e poi usare la logica del tuo importatore Beancount per convertirli in voci di libro mastro. Alcune regioni hanno API di open banking fornite dalle banche; queste potrebbero essere usate in modo simile.

  • Altre API: Potresti integrare strumenti di budgeting (esportando budget pianificati da confrontare con gli effettivi in Beancount), o usare un'API OCR per leggere ricevute e associare automaticamente a 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 riepilogativo tramite bot Telegram).

Quando usi API di terze parti, ricorda di proteggere le tue credenziali (usa variabili di ambiente o file di configurazione per le chiavi API) e gestisci gli errori (problemi di rete, downtime API) in modo elegante negli script. Spesso è saggio memorizzare in cache i dati (per esempio, salvare i tassi di cambio recuperati per non richiedere ripetutamente lo stesso tasso storico).

Best Practices per Script Modulari e Manutenibili

Man mano che sviluppi workflow scriptabili, tieni il codice organizzato e robusto:

  • Modularità: Dividi le diverse responsabilità in script o moduli separati. Per esempio, crea script distinti per “importazione/riconciliazione dati” vs. “generazione report” vs. “avvisi”. Puoi persino creare un piccolo pacchetto Python per il tuo libro mastro con moduli come ledger_import.py, ledger_reports.py, ecc. Questo rende ogni parte più facile da capire e testare.

  • Configurazione: Evita valori hardcoded. Usa un file di configurazione o variabili in cima allo script per nomi account, soglie, chiavi API, intervalli di date, ecc. Questo rende semplice modificare senza editare 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ò iterare attraverso 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 libro mastro. Anche senza framework sofisticati, puoi avere un CSV di prova e le transazioni di output attese, e verificare 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 comando just test che esegue pytest).

  • Controllo della versione: Tieni il tuo libro mastro e gli script sotto controllo di versione (git). Questo non solo ti offre backup e cronologia, ma ti incoraggia a fare modifiche in modo controllato. Puoi taggare release dei tuoi “finance scripts” o revisionare le differenze durante il debug di un problema. Alcuni utenti tengono persino i loro record finanziari su Git per vedere l’evoluzione nel tempo. Fai solo attenzione a ignorare dati sensibili (come file di estratti conto grezzi o chiavi API) nel tuo repository.

  • Documentazione: Documenta i tuoi workflow personalizzati per te in futuro. Un README nel tuo repository che spieghi come configurare l’ambiente, come eseguire ogni script e cosa fa ciascuno sarà preziosissimo dopo mesi. Commenta anche il tuo codice, specialmente qualsiasi logica contabile non ovvia o interazione con API.

  • Manutenzione plugin Fava: Se scrivi un’estensione per Fava, mantienila semplice. Fava potrebbe cambiare, quindi estensioni piccole con funzionalità mirate sono più facili da aggiornare. Evita di duplicare troppa logica – usa il motore di query di Beancount o funzioni helper esistenti quando possibile, anziché hardcodare calcoli che potrebbero essere sensibili a cambiamenti nel libro mastro.

  • Sicurezza: Dal momento che i tuoi script possono 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 hosted o cloud (come schedulare GitHub Actions o un server per eseguire Fava), assicurati che i dati del libro mastro siano criptati a riposo e che tu sia a tuo agio con le implicazioni sulla privacy.

Seguendo queste pratiche, assicuri che il tuo workflow resti affidabile anche mentre le tue finanze (e gli strumenti stessi) evolvono. Vuoi script che puoi riusare anno dopo anno, con modifiche minime.

Conclusione

Beancount e Fava offrono una piattaforma potente e flessibile per utenti esperti di tecnologia per personalizzare completamente il tracciamento delle proprie finanze personali. Scrivendo script Python, puoi automatizzare attività tediose come la riconciliazione degli estratti conto, produrre report dettagliati su misura per le tue esigenze e mantenere il controllo delle tue finanze con avvisi tempestivi. Abbiamo trattato una serie di esempi dal base all'avanzato – iniziando con semplici query e importazioni CSV, per passare a plugin completi per Fava e integrazioni con API esterne. Man mano che implementi queste soluzioni, inizia in modo semplice e aumenta gradualmente la complessità. Anche pochi piccoli script di automazione possono farti risparmiare ore di lavoro e migliorare notevolmente l'accuratezza. E ricorda, poiché tutto è testo semplice e Python, sei al pieno controllo – il tuo sistema finanziario cresce con te, adattandosi alle tue esigenze specifiche. Buona scrittura di script!

Fonti: Le tecniche sopra sono tratte dalla documentazione di Beancount e dalle esperienze della comunità. Per ulteriori letture, consulta la documentazione ufficiale di Beancount, le guide e i blog della comunità, e il repository Awesome Beancount per link a plugin e strumenti utili.

Fonte: https://beancount.io/it/docs/Solutions/scriptable-workflows