Um Guia para Precisão e Tolerâncias no Beancount
Gerenciar a precisão numérica é uma pedra angular da contabilidade de partidas dobradas. Na escrituração contábil digital, especialmente ao lidar com múltiplas moedas, preços de ações e ações fracionárias, pequenas discrepâncias de arredondamento podem rapidamente levar a erros de balanceamento frustrantes. O Beancount fornece um sistema sofisticado, mas intuitivo, para lidar com a precisão e definir tolerâncias aceitáveis. Este guia irá explicar como ele funciona. ⚙️
Conceitos Essenciais de Precisão
O objetivo principal do Beancount é garantir que cada transação seja balanceada a zero. No entanto, cálculos envolvendo preços ou custos frequentemente produzem resultados com mais casas decimais do que é prático registrar. O sistema de tolerância permite pequenos desequilíbrios aceitáveis.
Inferência Automática de Tolerância
Por padrão, o Beancount infere a tolerância necessária para cada transação automaticamente. Esta inferência é tratada individualmente para cada transação e calculada separadamente para cada moeda envolvida.
A regra é simples: a tolerância é metade do último dígito significativo dos números presentes nas lançamentos da transação.
Por exemplo, considere esta compra:
2013-04-03 * "Comprar Fundo"
Assets:Fund 10.22626 FUND {37.61 USD}
Assets:Cash -384.61 USD
O Beancount infere as tolerâncias da seguinte forma:
- Para a commodity
FUND, o número10.22626tem 5 casas decimais. A tolerância é metade do último dígito, entãoFUND. - Para a commodity
USD, o número-384.61tem 2 casas decimais. A tolerância é metade do último dígito, entãoUSD.
Regras de Peso da Transação
Ao verificar se uma transação está balanceada, o Beancount calcula o "peso" de cada lançamento. As regras para este cálculo são:
- Valor Simples: Se um lançamento tem apenas um valor (por exemplo,
Assets:Cash -100.00 USD), seu peso é esse valor exato. - Lançamento de Preço: Se um lançamento tem um preço por unidade (por exemplo,
10 FUND @ 38.46 USD), seu peso évalor × preço. - Lançamento de Custo: Se um lançamento tem um custo total (por exemplo,
10 FUND {384.61 USD}), seu peso é o valor do custo total. - Custo e Preço: Se um lançamento tem tanto um custo total quanto um preço por unidade (por exemplo,
10 FUND {384.61 USD} @ 38.46 USD), apenas o custo total é usado para balanceamento. O preço por unidade é tratado como um comentário ou memo.
Regras de Inferência de Precisão
O sistema de inferência automática segue algumas regras específicas:
- Formato do Número
- Valores inteiros (por exemplo,
10 USD) não contribuem para a inferência de precisão. - A tolerância máxima que pode ser automaticamente inferida é
0.05unidades (por exemplo, de um número como10.1 USD). Se você precisar de uma tolerância maior, você deve especificá-la manualmente. - Custos e preços (por exemplo,
{37.61 USD}) são excluídos da inferência de tolerância. Apenas os valores primários dos lançamentos são usados. - Se lançamentos para a mesma moeda têm diferentes precisões (por exemplo,
-10.10 USDe5.123 USD), o Beancount usa a tolerância mais grosseira (maior). Neste caso, seria baseado em-10.10 USD, resultando em uma tolerância deUSD.
-
Tratamento Padrão Você pode definir uma tolerância padrão global ou específica para uma moeda se uma transação não tiver números com casas decimais dos quais inferi-la.
; Define uma tolerância padrão para todas as moedas sem regras explícitas
option "inferred_tolerance_default" "*:0.001"
; Define uma tolerância padrão específica para USD
option "inferred_tolerance_default" "USD:0.003" -
Multiplicador de Tolerância Você pode aumentar globalmente todas as tolerâncias inferidas por um multiplicador fixo. Isso é útil para afrouxar as verificações em todo o seu arquivo sem alterar cada transação. Um multiplicador de
1.2aumenta todas as tolerâncias inferidas em 20%.option "inferred_tolerance_multiplier" "1.2" -
Inferência Baseada em Custo Embora os custos sejam normalmente ignorados para inferência de tolerância, você pode instruir o Beancount a usá-los. Isso é útil quando o valor final (por exemplo, um saque em dinheiro) é o número mais preciso em uma transação.
option "infer_tolerance_from_cost" "TRUE"
Asserções de Balanço
As asserções de balanço (balance) são usadas para verificar se o balanço da sua conta corresponde a um valor conhecido em uma data específica. Elas também têm uma tolerância associada.
Formato Básico
Semelhante às transações, a tolerância para uma asserção balance é inferida do número de casas decimais no valor.
; Assegura que o balanço é 4.271 RGAGX com uma tolerância de ±0.0005
2015-05-08 balance Assets:Fund 4.271 RGAGX
; Assegura que o balanço é 4.27 RGAGX com uma tolerância de ±0.005
2015-05-08 balance Assets:Fund 4.27 RGAGX
O balanço calculado deve estar dentro deste intervalo. Para o segundo exemplo, qualquer balanço entre e passaria na verificação.
Tolerâncias Explícitas
Se a tolerância inferida não for adequada, você pode especificar uma explicitamente usando o caractere til (~).
; Assegura que o balanço é 4.271 RGAGX com uma tolerância customizada de ±0.01 RGAGX
2015-05-08 balance Assets:Fund 4.271 ~ 0.01 RGAGX
Aqui, a asserção passará se o balanço calculado estiver entre e RGAGX.
Gerenciamento de Arredondamento
Para casos onde pequenos resíduos de cálculos são esperados e aceitáveis, o Beancount fornece ferramentas para gerenciá-los sistematicamente.
Rastreamento de Erros de Arredondamento
Você pode designar uma conta especial para coletar automaticamente erros de arredondamento. Isso mantém suas transações perfeitamente balanceadas, direcionando pequenas quantias restantes para um único lugar.
Primeiro, habilite a opção e abra a conta:
option "account_rounding" "Equity:RoundingError"
2000-01-01 open Equity:RoundingError
Agora, o Beancount adicionará automaticamente uma terceira perna a qualquer transação que não balanceie dentro de sua tolerância, lançando a diferença em Equity:RoundingError.
2013-02-23 * "Compra"
Assets:Invest 1.245 RGAGX {43.23 USD}
Assets:Cash -53.82 USD
Nesta transação, . A transação está desbalanceada em USD. Com a opção de arredondamento habilitada, o Beancount internamente trata como:
2013-02-23 * "Compra"
Assets:Invest 1.245 RGAGX {43.23 USD}
Assets:Cash -53.82 USD
Equity:RoundingError -0.00135 USD ; Adicionado automaticamente
Precisão Numérica Inferida
O Beancount também pode usar as configurações de tolerância para arredondar automaticamente os números antes mesmo de serem inseridos nas estruturas de dados do livro razão.
-
Nenhuma Tolerância Especificada: Se nenhuma tolerância for definida, os números são usados em sua precisão total. Nenhum arredondamento ocorre.
-
Com Tolerância Padrão: Se você definir uma tolerância padrão, os números serão quantizados para esse nível.
option "default_tolerance" "USD:0.001"Com esta configuração, um número como
53.82135 USDseria arredondado e armazenado como53.821 USD. -
Com Conta de Arredondamento: Se tanto uma tolerância padrão quanto uma conta de arredondamento estiverem ativas, o Beancount quantiza o número e captura o resíduo.
option "default_tolerance" "USD:0.01"
option "account_rounding" "Equity:RoundingError"Um número como
53.82135 USDseria armazenado como53.82 USD, e o resíduo de-0.00135 USDseria lançado emEquity:RoundingError.
Detalhes da Implementação
Alguns pontos técnicos esclarecem como o Beancount alcança esta confiabilidade.
-
Representação Numérica: O Beancount usa o módulo
decimaldo Python, não números de ponto flutuante. Isso permite até 28 casas decimais de precisão e evita os erros de representação binária comuns aos floats. -
Classe DisplayContext: Esta classe interna lida com toda a formatação de números para fins de exibição. Ela respeita as configurações de precisão específicas da moeda e pode formatar a saída com colunas alinhadas e vírgulas.
-
Precisão vs. Tolerância: É crucial distinguir estes dois conceitos:
- Precisão se refere ao formato de exibição de um número (quantas casas decimais são mostradas).
- Tolerância é a margem para desequilíbrio usada durante as verificações de validação.
Melhores Práticas ✨
Aqui estão algumas recomendações práticas para gerenciar a precisão em seu livro razão.
Configuração Inicial
Para a maioria dos novos livros razão, esta é uma configuração inicial robusta:
; Um padrão razoável para a maioria das moedas (por exemplo, USD, EUR)
option "inferred_tolerance_default" "*:0.005"
; Um buffer de 10% em todas as tolerâncias inferidas
option "inferred_tolerance_multiplier" "1.1"
; Uma conta para capturar toda a poeira de arredondamento
option "account_rounding" "Equity:RoundingError"
2000-01-01 open Equity:RoundingError
Dicas de Solução de Problemas
Se você encontrar erros de balanceamento:
- Adicione casas decimais ao valor de um lançamento para criar uma inferência de tolerância local mais precisa.
- Use tolerâncias explícitas (
~) em asserçõesbalanceque falham devido a discrepâncias previsíveis. - Rastreie erros de arredondamento em uma conta dedicada para ver onde e com que frequência eles ocorrem.
- Considere definir padrões específicos para cada moeda se você lida frequentemente com moedas que têm convenções diferentes (por exemplo, JPY não tem decimais).
Estratégia de Migração
Ao aplicar estes conceitos a um livro razão existente e confuso:
- Comece com uma tolerância global generosa (por exemplo,
*:0.05) e um multiplicador alto para fazer o arquivo ser validado. - Gradualmente aperte as tolerâncias e corrija os erros que aparecem.
- Adicione dígitos explícitos aos valores em transações problemáticas para deixar a inferência fazer seu trabalho.
- Monitore o balanço da conta de arredondamento. Um balanço grande ou em rápido crescimento pode sinalizar um problema sistêmico que precisa de investigação.