Pular para o conteúdo principal

Como scripts Python automatizam Beancount e Fava

Beancount e Fava permanecem scriptáveis: use Python para automatizar relatórios, saldos e fluxos de trabalho personalizados em seu ledger.

Beancount (uma ferramenta de contabilidade de partidas dobradas em texto simples) e Fava (sua interface web) são altamente extensíveis e programáveis. Seu design permite automatizar tarefas financeiras, gerar relatórios personalizados e configurar alertas escrevendo scripts em Python. Nas palavras de um usuário: "Eu realmente gosto de ter meus dados em um formato tão conveniente, e gosto de poder automatizar coisas à vontade. Não há API como um arquivo no seu disco; é fácil de integrar." Este guia abordará a criação de fluxos de trabalho com scripts—desde automação para iniciantes até plugins avançados do Fava.

Explore um exemplo de livro-razão ao vivo:

Abrir Example Ledger em uma nova aba

Comece com a linha de comando bea

Antes de escrever qualquer código Python, verifique se o bea já faz o trabalho. Ele valida o livro-razão, executa consultas BQL, produz os quatro relatórios financeiros e importa exportações bancárias, e a opção global --json transforma cada um deles em um envelope analisável que seu shell pode canalizar para o jq. Seus códigos de saída são o contrato no qual um trabalho agendado se baseia, então o cron ou CI não precisa de script de carregamento algum. Consulte automatize a contabilidade com bea para resolução de alvo, envelope e ramificação por código de saída, e volte aqui quando precisar de um cálculo personalizado que a CLI não expõe.

Primeiros Passos: Executando Beancount como Script Python

Para os scripts Python personalizados abaixo, instale as bibliotecas de script (pip install beancount beanquery beangulp). Os fluxos de trabalho do comando bea usam o mecanismo gerenciado; siga o início rápido da CLI para instalá-lo. Como o Beancount é escrito em Python, você pode usá-lo como uma biblioteca em seus próprios scripts. Os scripts abaixo foram executados com Beancount 3.2.3, beanquery 0.2.0 e beangulp 0.2.0. A abordagem geral é:

  • Carregue seu livro-razão Beancount: Use o carregador do Beancount para analisar o arquivo .beancount em objetos Python. Por exemplo:

    from beancount import loader
    entries, errors, options = loader.load_file("myledger.beancount")
    if errors:
        for error in errors:
            print(error)
        raise SystemExit(1)

    O carregador retorna entradas e erros juntos. Um arquivo desbalanceado ou inválido ainda retorna entradas, então verifique errors e pare antes de confiar nos dados. Todas as suas contas, transações e saldos agora estão acessíveis no código.

  • Aproveite a Linguagem de Consulta Beancount (BQL): Em vez de iterar manualmente, você pode executar consultas semelhantes a SQL nos dados. As consultas vivem no pacote separado beanquery. Não há módulo beancount.query no Beancount 3.2.3. Por exemplo, para obter despesas totais por mês, conecte as entradas carregadas e execute a consulta diretamente:

    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)

    Isso usa beanquery para agregar dados. É o mesmo mecanismo por trás de bea query, mas aqui você o chama em um script. Isso evita chamar um comando externo em um loop.

  • Configure uma estrutura de projeto: Organize seus scripts junto ao seu livro-razão. Um layout comum é ter diretórios para importadores (para buscar/analisar dados externos), relatórios ou consultas (para scripts de análise) e documentos (para armazenar extratos baixados). Por exemplo, um usuário mantém:

    • importers/ – scripts Python de importação personalizados (com testes),
    • queries/ – scripts para gerar relatórios (executáveis via python3 queries/...),
    • documents/ – CSVs/PDFs bancários baixados organizados por conta.

Com essa configuração, você pode executar scripts manualmente (por exemplo, python3 queries/cash_flow.py) ou agendá-los (via cron ou um executor de tarefas) para automatizar seu fluxo de trabalho.

Automatizando Tarefas de Conciliação

Conciliação significa garantir que seu livro-razão corresponda aos registros externos (extratos bancários, relatórios de cartão de crédito, etc.). O livro-razão em texto simples e a API Python do Beancount tornam possível automatizar grande parte desse processo.

Importando e Conciliando Transações (Iniciante)

Para iniciantes, a abordagem recomendada é usar importadores do pacote separado beangulp. O Beancount 3 removeu o módulo de ingestão v2 e seu comando extract. Você escreve uma pequena classe Python que herda de beangulp.Importer para analisar um determinado formato (CSV, OFX, PDF, etc.) e produzir transações. Registre-a em um script curto de ingestão e execute-o via bea ingest no mecanismo gerenciado:

  • Escreva um importador (uma classe Python com métodos identify(), account() e extract()) para o formato CSV do seu banco.
  • Adicione um script de ingestão que registre seus importadores. bea ingest executa os comandos identify, extract e archive do script. Por exemplo, um fluxo de trabalho executa extract em todos os arquivos em ~/Downloads e envia as transações para um arquivo temporário.
  • Revise e copie manualmente as transações do arquivo temporário para seu livro-razão principal e execute bea check para garantir que os saldos conciliam.

Um exemplo mínimo: um statement.csv com colunas date,description,amount, analisado por este importador (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

O script de ingestão (ingest.py) conecta tudo:

from checking_importer import CheckingImporter
from beangulp import Ingest
 
ingest = Ingest([CheckingImporter()])
 
if __name__ == "__main__":
    ingest()

Execute-o contra um arquivo baixado. Nenhuma credencial é necessária para um CSV local. Instale primeiro a biblioteca libmagic do sistema. O comando único de habilitação baixa o Beangulp para o mecanismo gerenciado:

bea engine enable beangulp
bea ingest identify --config ingest.py statement.csv
bea ingest extract --config ingest.py statement.csv -o new.beancount

identify reporta checking_importer.CheckingImporter para o arquivo. extract escreve as transações no formato Beancount:

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

Revise new.beancount, copie as entradas para seu livro-razão principal e execute bea check.

Pule o importador para um caso único

Você não precisa escrever um importador para converter um único extrato. Cole o arquivo no conversor de CSV para Beancount ou use OFX e QIF para Beancount para downloads .ofx, .qfx e .qif. Ambos são executados inteiramente no seu navegador, então o extrato nunca sai da sua máquina.

Embora esse processo ainda envolva uma etapa de revisão, grande parte do trabalho braçal de analisar e formatar entradas é automatizado. Scripts de importador também podem atribuir categorias automaticamente e até definir asserções de saldo (declarações de saldos esperados) para detectar discrepâncias. Por exemplo, após a importação, você pode ter uma linha como 2025-04-30 balance Assets:Bank:Checking 1234.56 USD que afirma o saldo final. Quando você executa bea check, o Beancount verificará se todas essas asserções de saldo estão corretas e sinalizará erros se houver transações faltando ou duplicadas. Esta é uma melhor prática: gerar automaticamente asserções de saldo para cada período de extrato para deixar o computador encontrar diferenças não conciliadas por você.

Scripts de Conciliação Personalizados (Intermediário)

Para mais controle, você pode escrever um script Python personalizado para comparar a lista de transações de um banco (CSV ou via API) com suas entradas no livro-razão:

  1. Leia os dados externos: Analise o arquivo CSV do banco usando o módulo csv do Python (ou Pandas). Normalize os dados em uma lista de transações, por exemplo, cada uma com data, valor e descrição.
  2. Carregue as transações do livro-razão: Use loader.load_file como mostrado anteriormente para obter todas as entradas do livro-razão. Filtre esta lista para a conta de interesse (por exemplo, sua conta corrente) e talvez o intervalo de datas do extrato.
  3. Compare e encontre divergências:
  • Para cada transação externa, verifique se existe uma entrada idêntica no livro-razão (corresponda por data e valor, talvez descrição). Se não for encontrada, marque-a como "nova" e possivelmente produza-a como uma transação formatada em Beancount para sua revisão.
  • Inversamente, identifique quaisquer entradas do livro-razão nessa conta que não apareçam na fonte externa—estas podem ser erros de lançamento ou transações que ainda não foram compensadas pelo banco.
  1. Produza os resultados: Imprima um relatório ou crie um novo trecho .beancount com as transações faltantes.

Como exemplo, um script da comunidade chamado reconcile.py faz exatamente isso: dado um arquivo Beancount e um CSV de entrada, ele imprime uma lista de novas transações que devem ser importadas, bem como quaisquer lançamentos existentes no livro-razão que não estão na entrada (potencialmente um sinal de classificação incorreta). Com esse script, a conciliação mensal pode ser tão simples quanto executá-lo e depois anexar as transações sugeridas ao seu livro-razão. Um usuário do Beancount observa que "faz um processo de conciliação em todas as contas a cada mês" e usa uma coleção crescente de código Python para eliminar grande parte do trabalho manual na importação e conciliação de dados.

Dica: Durante a conciliação, aproveite as ferramentas do Beancount para precisão:

  • Use asserções de saldo como mencionado, para ter verificações automatizadas nos saldos das contas.
  • Use a diretiva pad se desejar, que pode inserir automaticamente entradas de balanceamento para pequenas diferenças de arredondamento (use com cautela).
  • Escreva testes unitários para seu importador ou lógica de conciliação (o Beancount fornece auxiliares de teste). Por exemplo, um fluxo de trabalho envolvia pegar um CSV de amostra, escrever testes falhando com transações esperadas e então implementar o importador até que todos os testes passassem. Isso garante que seu script de importação funcione corretamente para vários casos.

Gerando Relatórios e Resumos Personalizados

Embora o Fava forneça muitos relatórios padrão (Demonstração de Resultados, Balanço Patrimonial, etc.), você pode criar relatórios personalizados usando scripts. Eles podem variar de simples saídas de console a arquivos ricos formatados ou gráficos.

Consultando Dados para Relatórios (Iniciante)

Em um nível básico, você pode usar a Linguagem de Consulta Beancount (BQL) para obter dados resumidos e imprimi-los ou salvá-los. Por exemplo:

  • Resumo de Fluxo de Caixa: Use uma consulta para calcular o fluxo de caixa líquido. "Fluxo de caixa" poderia ser definido como a mudança no saldo de certas contas em um período. Usando BQL, você pode fazer:

    SELECT year, month, sum(position)
    WHERE account ~ 'Income' OR account ~ 'Expenses'
    GROUP BY year, month

    Isso soma todos os lançamentos de receitas e despesas por mês. Filtre com ~ e uma expressão regular: LIKE é um erro de sintaxe no beanquery 0.2.0. Lançamentos carregam position, não amount. Cada linha contém um Inventory, então cada moeda é listada separadamente em vez de ser convertida. Receitas entram negativas e despesas positivas. Você pode executar isso via bea query ou pela API Python do beanquery mostrada anteriormente e formatar o resultado.

  • Relatório de Gastos por Categoria: Consulte o total de despesas por categoria:

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

    Isso produz uma tabela de despesas por categoria. Cada total é um Inventory na moeda original. Não envolva a agregação em round(): não existe função round(inventory, int), então round(sum(position), 2) falha ao compilar. Você pode executar várias consultas em um script e produzir os resultados como texto, CSV ou até JSON para processamento adicional.

Um usuário considerou "trivial" analisar dados financeiros com Fava ou scripts, citando que usa um script Python para extrair dados do Beancount via Linguagem de Consulta e depois colocá-los em um DataFrame Pandas para preparar um relatório personalizado. Por exemplo, você pode buscar totais mensais com uma consulta e usar Pandas/Matplotlib para plotar um gráfico de fluxo de caixa ao longo do tempo. A combinação de BQL e bibliotecas de ciência de dados permite criar relatórios além do que o Fava oferece por padrão.

Relatórios Avançados (Gráficos, Desempenho, etc.)

Para necessidades mais avançadas, seus scripts podem calcular métricas como desempenho de investimentos ou criar saídas visuais:

  • Desempenho de Investimentos (TIR/TIRX): Como seu livro-razão contém todos os fluxos de caixa (compras, vendas, dividendos), você pode calcular taxas de retorno da carteira. Por exemplo, você pode escrever um script que filtra transações de suas contas de investimento e calcula a Taxa Interna de Retorno. Existem bibliotecas (ou fórmulas) para calcular TIR dados os fluxos de caixa. Algumas extensões desenvolvidas pela comunidade (como PortfolioSummary ou fava_investor) fazem exatamente isso, calculando TIR e outras métricas para carteiras de investimento. Como script, você poderia usar uma função TIR (do NumPy ou própria) na série de contribuições/retiradas mais o valor final.

  • Métricas Personalizadas ou Multiperíodo: Quer um relatório da sua taxa de poupança (proporção de poupança em relação à renda) a cada mês? Um script Python pode carregar o livro-razão, somar todas as contas de Receitas e todas as contas de Despesas e calcular poupança = receitas - despesas e a porcentagem. Isso pode produzir uma tabela bonita ou até gerar um relatório HTML/Markdown para seus registros.

  • Visualização: Você pode gerar gráficos fora do Fava. Por exemplo, use matplotlib ou altair em um script para criar um gráfico de patrimônio líquido ao longo do tempo, usando dados do livro-razão. Como o livro-razão tem todos os saldos históricos (ou você pode acumulá-los iterando entradas), você pode produzir gráficos de séries temporais. Salve esses gráficos como imagens ou HTML interativo. (Se preferir visuais no aplicativo, consulte a seção de extensões do Fava abaixo para adicionar gráficos dentro do Fava.)

Opções de Saída: Decida como entregar o relatório:

  • Para análises pontuais, imprimir na tela ou salvar em um arquivo CSV/Excel pode ser suficiente.
  • Para painéis, considere gerar um arquivo HTML com os dados (possivelmente usando uma biblioteca de templates como Jinja2 ou até escrevendo Markdown) que você pode abrir no navegador.
  • Você também pode integrar com Jupyter Notebooks para um ambiente de relatório interativo, embora isso seja mais para exploração do que automação.

Acionando Alertas a Partir do Seu Livro-Razão

Outro uso poderoso de fluxos de trabalho com scripts é configurar alertas com base em condições nos seus dados financeiros. Como seu livro-razão é atualizado regularmente (e pode incluir itens com datas futuras, como contas a pagar ou orçamentos), você pode escaneá-lo com um script e ser notificado de eventos importantes.

Avisos de Saldo Baixo em Contas

Para evitar cheques sem fundos ou manter um saldo mínimo, você pode querer um alerta se qualquer conta (por exemplo, corrente ou poupança) cair abaixo de um limite. Veja como implementar:

  1. Determine os saldos atuais: Após carregar entries via o carregador, calcule o saldo mais recente das contas de interesse. Você pode fazer isso agregando lançamentos ou usando uma consulta. Por exemplo, use uma consulta BQL para o saldo de uma conta específica:

    SELECT sum(position) WHERE account = 'Assets:Bank:Checking'

    Isso retorna o saldo atual dessa conta (soma de todos os seus lançamentos). Alternativamente, use as funções internas do Beancount para construir um balanço patrimonial. Por exemplo:

    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

    Passe apenas as entradas: o segundo parâmetro é min_accounts, não o mapa de opções. Então extraia o valor numérico (por exemplo, balance.get_currency_units('USD') retorna o valor Decimal em USD). Como um agregado de consulta, o saldo mantém cada moeda separadamente. No entanto, usar a consulta é mais simples para a maioria dos casos.

  2. Verifique o limite: Compare o saldo com seu limite predefinido. Se estiver abaixo, acione um alerta.

  3. Acione a notificação: Isso pode ser tão simples quanto imprimir um aviso no console, mas para alertas reais você pode enviar um e-mail ou notificação push. Você pode integrar com e-mail (via smtplib) ou um serviço como IFTTT ou a API de webhook do Slack para enviar o alerta. Por exemplo:

    if balance < 1000:
        send_email("Low balance alert", f"Account XYZ balance is {balance}")

    (Implemente send_email com os detalhes do seu servidor de e-mail.)

Ao executar este script diariamente (via cron ou Agendador de Tarefas do Windows), você receberá avisos proativos. Como ele usa o livro-razão, pode considerar todas as transações, incluindo as que você acabou de adicionar.

Prazos de Pagamento Próximos

Se você usa Beancount para rastrear contas ou prazos, pode marcar pagamentos futuros e ter scripts para lembrá-lo. Duas maneiras de representar obrigações futuras no Beancount:

  • Eventos: O Beancount suporta a diretiva event para notas datadas arbitrárias. Por exemplo:

    2025-05-10 event "BillDue" "Mortgage payment due"

    Isso não afeta saldos, mas registra uma data com um rótulo. Um script pode escanear entries em busca de entradas Event onde Event.type == "BillDue" (ou qualquer tipo personalizado que você escolher) e verificar se a data está dentro, digamos, dos próximos 7 dias a partir de hoje. Se sim, acione um alerta (e-mail, notificação ou até um popup).

  • Transações Futuras: Algumas pessoas inserem transações com data futura (pós-datadas) para coisas como pagamentos agendados. Elas não aparecerão nos saldos até que a data passe (a menos que você execute relatórios em datas futuras). Um script pode procurar transações datadas no futuro próximo e listá-las.

Usando isso, você pode criar um script "lembrete" que, quando executado, produz uma lista de tarefas ou contas a vencer em breve. Integre com uma API como Google Agenda ou um gerenciador de tarefas se quiser criar lembretes automaticamente lá.

Detecção de Anomalias

Além de limites ou datas conhecidos, você pode criar alertas personalizados para padrões incomuns. Por exemplo, se uma despesa normalmente mensal não ocorreu (talvez você esqueceu de pagar uma conta), ou se o gasto de uma categoria está anormalmente alto neste mês, seu script pode sinalizar isso. Isso geralmente envolve consultar dados recentes e comparar com o histórico (o que pode ser um tópico avançado—possivelmente empregando estatística ou ML).

Na prática, muitos usuários dependem da conciliação para detectar anomalias (transações inesperadas). Se você recebe notificações bancárias (como e-mails para cada transação), pode analisá-las com um script e adicioná-las automaticamente ao Beancount, ou pelo menos verificar se estão registradas. Um entusiasta até configurou seu banco para enviar e-mails de alerta de transação, com o plano de analisá-los e anexá-los ao livro-razão automaticamente. Esse tipo de alerta orientado a eventos pode garantir que nenhuma transação fique sem registro.

Estendendo o Fava com Plugins e Visualizações Personalizados

O Fava já é programável através de seu sistema de extensões. Se você quiser que sua automação ou relatórios se integrem diretamente à interface web, pode escrever uma extensão do Fava (também chamada de plugin) em Python.

Como Funcionam as Extensões do Fava: Uma extensão é um módulo Python que define uma classe herdando de fava.ext.FavaExtensionBase. Você a registra em seu arquivo Beancount via uma opção personalizada. Por exemplo, se você tem um arquivo myextension.py com uma classe MyAlerts(FavaExtensionBase), pode habilitá-lo adicionando ao seu livro-razão:

1970-01-01 custom "fava-extension" "myextension"

Quando o Fava carrega, ele importará esse módulo e inicializará sua classe MyAlerts.

As extensões podem fazer várias coisas:

  • Hooks: Elas podem se conectar a eventos no ciclo de vida do Fava. Por exemplo, after_load_file() é chamado após o livro-razão ser carregado. Você pode usar isso para executar verificações ou pré-calcular dados. Se você quisesse implementar a verificação de saldo baixo dentro do Fava, after_load_file poderia iterar sobre os saldos das contas e talvez armazenar avisos (embora exibi-los na interface possa exigir um pouco mais de trabalho, como lançar um FavaAPIError ou usar Javascript para mostrar uma notificação).
  • Relatórios/Páginas Personalizados: Se sua classe de extensão define um atributo report_title, o Fava adicionará uma nova página na barra lateral para ela. Você então fornece um template (HTML/Jinja2) para o conteúdo dessa página. É assim que você cria visualizações totalmente novas, como um painel ou resumo que o Fava não tem por padrão. A extensão pode coletar os dados que precisar (você pode acessar self.ledger, que tem todas as entradas, saldos, etc.) e então renderizar o template.

Por exemplo, a extensão portfolio_list embutida no Fava adiciona uma página listando suas posições de carteira. Extensões da comunidade vão além:

  • Painéis: O plugin fava-dashboards permite definir gráficos e painéis personalizados (usando bibliotecas como Apache ECharts). Ele lê uma configuração YAML de consultas a executar, as executa via Beancount e gera uma página de painel dinâmica no Fava. Em essência, ele une dados do Beancount e uma biblioteca de gráficos em JavaScript para produzir visualizações interativas.
  • Análise de carteira: A extensão PortfolioSummary (contribuída por usuários) calcula resumos de investimentos (agrupando contas, calculando TIR, etc.) e os exibe na interface do Fava.
  • Revisão de transações: Outra extensão, fava-review, ajuda a revisar transações ao longo do tempo (por exemplo, para garantir que você não perdeu nenhum recibo).

Para criar uma extensão simples você mesmo, comece herdando de FavaExtensionBase. Por exemplo, uma extensão mínima que adiciona uma página poderia ser:

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 você colocar isso em hello.py e adicionar custom "fava-extension" "hello" ao seu livro-razão, o Fava mostraria uma nova página "Olá Mundo" (você também precisaria de um arquivo de template HelloReport.html em uma subpasta templates para definir o conteúdo da página, a menos que a extensão use apenas hooks). O template pode usar dados que você anexa à classe de extensão. O Fava usa templates Jinja2, então você pode renderizar seus dados em uma tabela HTML ou gráfico nesse template.

Nota: O sistema de extensões do Fava é poderoso, mas considerado "instável" (sujeito a mudanças). Ele requer alguma familiaridade com desenvolvimento web (HTML/JS) se você estiver criando páginas personalizadas. Se seu objetivo é simplesmente executar scripts ou análises, pode ser mais fácil mantê-los como scripts externos. Use extensões do Fava quando quiser uma experiência sob medida dentro do aplicativo para seu fluxo de trabalho.

Integrando APIs e Dados de Terceiros

Uma das vantagens dos fluxos de trabalho com scripts é a capacidade de trazer dados externos. Aqui estão integrações comuns:

  • Taxas de Câmbio e Mercadorias: O Beancount não busca preços automaticamente por design (para manter os relatórios determinísticos), mas fornece uma diretiva Price para você fornecer as taxas. Você pode automatizar a busca desses preços. Por exemplo, um script pode consultar uma API (Yahoo Finance, Alpha Vantage, etc.) pela taxa de câmbio mais recente ou preço de ação e anexar uma entrada de preço ao seu livro-razão:

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

    Existem ferramentas como bea price, apoiada pelo Beanprice no mecanismo gerenciado, que busca cotações diárias e as produz no formato Beancount. Você pode habilitá-la uma vez com bea engine enable beanprice e agendar bea price main.beancount para executar todas as noites e atualizar um arquivo de inclusão prices.beancount. Ou use Python: por exemplo, com a biblioteca requests para chamar uma API. A documentação do Beancount sugere que, para ativos negociados publicamente, você pode "invocar algum código que baixará preços e escreverá as diretivas para você." Em outras palavras, deixe um script fazer a busca e inserir as linhas de price, em vez de fazer manualmente.

  • Dados de Carteira de Ações: Semelhante às taxas de câmbio, você pode integrar APIs para buscar dados detalhados de ações ou dividendos. Por exemplo, a API do Yahoo Finance (ou bibliotecas da comunidade como yfinance) pode recuperar dados históricos para um ticker. Um script pode atualizar seu livro-razão com o histórico mensal de preços de cada ação que você possui, permitindo relatórios históricos precisos de valor de mercado. Algumas extensões personalizadas (como fava_investor) até buscam dados de preços em tempo real para exibição, mas o mais simples é importar regularmente os preços para o livro-razão.

  • APIs Bancárias (Open Banking/Plaid): Em vez de baixar CSVs, você pode usar APIs para buscar transações automaticamente. Serviços como Plaid agregam contas bancárias e permitem acesso programático a transações. Em uma configuração avançada, você pode ter um script Python que usa a API do Plaid para puxar novas transações diariamente e salvá-las em um arquivo (ou importá-las diretamente para o livro-razão). Um usuário avançado construiu um sistema onde o Plaid alimenta seu pipeline de importação, tornando seus livros quase automáticos. Eles observam que "nada impede você de se inscrever na API do Plaid e fazer o mesmo localmente" – ou seja, você pode escrever um script local para obter dados bancários e depois usar sua lógica de importador Beancount para analisá-los em entradas do livro-razão. Algumas regiões têm APIs de open banking fornecidas pelos bancos; elas podem ser usadas de forma semelhante.

  • Outras APIs: Você pode integrar ferramentas de orçamento (exportando orçamentos planejados para comparar com os reais no Beancount), ou usar uma API de OCR para ler recibos e automaticamente casá-los com transações. Como seus scripts têm acesso total ao ecossistema Python, você pode integrar desde serviços de e-mail (para envio de alertas) até Google Sheets (por exemplo, atualizar uma planilha com métricas financeiras mensais) e aplicativos de mensagens (enviar a si mesmo um relatório resumido via bot do Telegram).

Ao usar APIs de terceiros, lembre-se de proteger suas credenciais (use variáveis de ambiente ou arquivos de configuração para chaves de API) e trate erros (problemas de rede, indisponibilidade da API) com elegância em seus scripts. Muitas vezes é sensato armazenar dados em cache (por exemplo, guardar taxas de câmbio buscadas para não solicitar repetidamente a mesma taxa histórica).

Melhores Práticas para Scripts Modulares e Manteníveis

Ao construir fluxos de trabalho com scripts, mantenha seu código organizado e robusto:

  • Modularidade: Separe diferentes preocupações em diferentes scripts ou módulos. Por exemplo, tenha scripts separados para "importação/conciliação de dados" vs. "geração de relatórios" vs. "alertas". Você pode até criar um pequeno pacote Python para seu livro-razão com módulos como ledger_import.py, ledger_reports.py, etc. Isso torna cada parte mais fácil de entender e testar.

  • Configuração: Evite valores codificados. Use um arquivo de configuração ou variáveis no topo do script para coisas como nomes de contas, limites, chaves de API, intervalos de datas, etc. Isso facilita ajustes sem editar o código profundamente. Por exemplo, defina LOW_BALANCE_THRESHOLDS = {"Assets:Bank:Checking": 500, "Assets:Savings": 1000} no topo, e seu script de alerta pode percorrer este dicionário.

  • Testes: Trate sua automação financeira como código de missão crítica—porque é! Escreva testes para lógica complexa. O Beancount fornece alguns auxiliares de teste (usados internamente para testes de importadores) que você pode aproveitar para simular entradas do livro-razão. Mesmo sem frameworks sofisticados, você pode ter um CSV fictício e transações de saída esperadas, e afirmar que seu script de importação produz as entradas corretas. Se você usa pytest, pode integrar esses testes facilmente (como Alex Watt fez com um comando just test envolvendo pytest).

  • Controle de Versão: Mantenha seu livro-razão e scripts sob controle de versão (git). Isso não só fornece backups e histórico, mas incentiva você a fazer mudanças de forma controlada. Você pode marcar versões de seus "scripts financeiros" ou revisar diferenças ao depurar um problema. Alguns usuários até rastreiam seus registros financeiros no Git para ver mudanças ao longo do tempo. Apenas tome cuidado para ignorar dados sensíveis (como arquivos de extrato bruto ou chaves de API) no seu repositório.

  • Documentação: Documente seus fluxos de trabalho personalizados para o "você do futuro". Um README no seu repositório explicando como configurar o ambiente, como executar cada script e o que cada um faz será inestimável após meses. Também comente seu código, especialmente qualquer lógica contábil não óbvia ou interação com API.

  • Manutenção de Plugins do Fava: Se você escrever uma extensão do Fava, mantenha-a simples. O Fava pode mudar, então extensões menores com funcionalidade direcionada são mais fáceis de atualizar. Evite duplicar muita lógica—use o mecanismo de consulta do Beancount ou funções auxiliares existentes sempre que possível, em vez de cálculos codificados que possam ser sensíveis a mudanças no livro-razão.

  • Segurança: Como seus scripts podem lidar com dados sensíveis e se conectar a serviços externos, trate-os com cuidado. Não exponha chaves de API e considere executar sua automação em uma máquina segura. Se você usa uma solução hospedada ou em nuvem (como agendar GitHub Actions ou um servidor para executar o Fava), garanta que seus dados do livro-razão estejam criptografados em repouso e que você esteja confortável com as implicações de privacidade.

Seguindo essas práticas, você garante que seu fluxo de trabalho permaneça confiável mesmo à medida que suas finanças (e as próprias ferramentas) evoluem. Você quer scripts que possa reutilizar ano após ano, com ajustes mínimos.

Conclusão

Beancount e Fava fornecem uma plataforma poderosa e flexível para usuários com conhecimentos técnicos personalizarem completamente seu rastreamento financeiro pessoal. Ao escrever scripts em Python, você pode automatizar tarefas tediosas como conciliar extratos, produzir relatórios ricos adaptados às suas necessidades e ficar por dentro das suas finanças com alertas oportunos. Cobrimos uma variedade de exemplos do básico ao avançado—começando com consultas simples e importações CSV, e avançando para plugins completos do Fava e integrações com APIs externas. Ao implementar, comece simples e construa gradualmente. Mesmo alguns pequenos scripts de automação podem economizar horas de trabalho e melhorar muito a precisão. E lembre-se, como tudo é texto simples e Python, você está no controle total—seu sistema financeiro cresce com você, adaptando-se às suas necessidades específicas. Boa programação!

Fontes: As técnicas acima são extraídas da documentação do Beancount e experiências da comunidade. Para leitura adicional, consulte a documentação oficial do Beancount, guias e blogs da comunidade, e o repositório Awesome Beancount para links de plugins e ferramentas úteis.

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