O sistema de inventário do Beancount é uma funcionalidade poderosa para acompanhamento de ativos que são comprados e vendidos ao longo do tempo, como ações, fundos mútuos ou moedas estrangeiras. Ele permite um rastreamento preciso do custo base, o que é essencial para calcular ganhos de capital e entender o desempenho da carteira. Este tutorial cobre os conceitos básicos do gerenciamento de inventários em seu livro razão.
Conceitos Fundamentais
Essencialmente, o gerenciamento de inventário gira em torno do acompanhamento de posições. Uma "posição" é simplesmente uma quantidade de uma mercadoria mantida em uma conta. O Beancount distingue dois tipos fundamentais de posições.
Tipos de Posição
-
Posição Simples (Sem Custo): Esta é uma contabilização padrão de saldo. Representa uma quantidade de uma mercadoria sem qualquer custo de aquisição associado. É adequada para dinheiro em espécie ou simples declarações de saldo.
Assets:Bank:Checking 100.00 USD -
Posição com Custo Base: Este tipo de posição inclui não apenas o número de unidades e a mercadoria, mas também o custo pelo qual foi adquirida. Esta é a base do acompanhamento de inventário. O custo é especificado dentro de chaves
{}.Assets:Invest:VTSAX 10 VTSAX {100.00 USD, "lot-1"}Neste exemplo, mantemos 10 unidades de
VTSAX. Cada unidade foi adquirida a um custo de $100,00 USD. Este lote específico de ações é identificado como um "lote."
Operações de Inventário
Existem duas operações principais que você pode realizar em um inventário:
-
Aumentos (Adição ao inventário): Quando você compra uma mercadoria, aumenta seu inventário. Você cria um novo lote com um número específico de unidades e um custo base.
2024-01-15 * "Buy shares" Assets:Invest:STOCK 50 STOCK {25.00 USD, "lot-1"} Assets:Bank:Checking -1250.00 USDAqui, compramos 50 unidades de
STOCKa um custo por unidade de $25,00 USD. Isso cria um lote na contaAssets:Invest:STOCK. -
Reduções (Remoção do inventário): Quando você vende uma mercadoria, reduz seu inventário. Você deve especificar de qual lote está vendendo. Isso é feito fornecendo informações correspondentes nas chaves.
2024-01-20 * "Sell shares" Assets:Invest:STOCK -25 STOCK {25.00 USD} Assets:Bank:Checking 625.00 USDNesta transação, estamos vendendo 25 unidades de
STOCKdo lote que foi adquirido a $25,00 USD por unidade.
Métodos de Contabilização
Quando você reduz um inventário, o Beancount precisa de uma regra para decidir de qual lote específico retirar se vários lotes corresponderem à redução. Essa regra é chamada de "método de contabilização." Você pode definir um padrão para o arquivo inteiro com uma opção, ou atribuir a uma conta seu próprio método na diretiva open.
Beancount 3.2.3 aceita sete nomes de método: STRICT (o padrão), STRICT_WITH_SIZE, NONE, FIFO, LIFO, HIFO e AVERAGE. Seis deles estão implementados; AVERAGE analisa, mas gera um erro no momento em que precisa registrar uma redução, como a seção AVERAGE abaixo mostra.
1. STRICT (Padrão)
O método STRICT é o padrão e o método de registro mais seguro. Ele impõe correspondência explícita e inequívoca.
2024-01-01 open Assets:Invest:STOCK "STRICT"- Exige Correspondência Exata do Lote: O especificador de custo do lançamento de redução (
{...}) deve identificar um único lote — pelo custo, pela data de aquisição, pela etiqueta ou por qualquer combinação destes. - Erros em Correspondências Ambíguas: Se o especificador corresponder a mais de um lote, Beancount gera um
AmbiguousMatchErrorem vez de fazer suposições. - Exceção: Se uma redução remove exatamente o número total de unidades correspondentes ao especificador, um especificador vazio (
{}) é permitido, e a redução é repartida entre esses lotes.
Este razão contém dois lotes e vende um deles nomeando seu custo, o que é inequívoco:
1970-01-01 commodity STK
1970-01-01 open Assets:Broker:Strict STK "STRICT"
1970-01-01 open Assets:Broker:Cash USD
1970-01-01 open Income:Gains USD
2024-01-10 * "Buy the first lot"
Assets:Broker:Strict 10 STK {100.00 USD}
Assets:Broker:Cash -1000.00 USD
2024-02-10 * "Buy the second lot"
Assets:Broker:Strict 10 STK {120.00 USD}
Assets:Broker:Cash -1200.00 USD
; The cost identifies exactly one lot, so STRICT is satisfied.
2024-06-01 * "Sell the $120.00 lot"
Assets:Broker:Strict -10 STK {120.00 USD} @ 150.00 USD
Assets:Broker:Cash 1500.00 USD
Income:GainsEle carrega sem erros, registra um ganho de $300,00 como Income:Gains, e deixa 10 STK {100.00 USD} na conta.
Substitua esse último lançamento por um especificador vazio e o mesmo arquivo falha:
; Rejected under STRICT: "-10 STK {}" matches both lots.
2024-06-01 * "Sell 10 shares"
Assets:Broker:Strict -10 STK {} @ 150.00 USD
Assets:Broker:Cash 1500.00 USD
Income:GainsBeancount reporta Ambiguous matches for "-10 STK {}" e lista os candidatos. Vender a posição inteira é aceitável, porque não resta nada para escolher:
; Allowed under STRICT: -20 STK is the entire holding, so the empty
; specifier is split across both lots.
2024-06-01 * "Close the position"
Assets:Broker:Strict -20 STK {} @ 150.00 USD
Assets:Broker:Cash 3000.00 USD
Income:GainsIsso registra um ganho de $800,00 — $3.000,00 de receita contra $1.000,00 + $1.200,00 de base — e deixa a conta vazia. Esta é uma propriedade do próprio STRICT, não algo que você tenha que mudar para STRICT_WITH_SIZE para obter.
2. FIFO (Primeiro a Entrar, Primeiro a Sair)
O método FIFO registra automaticamente reduções contra os lotes mais antigos disponíveis primeiro.
2024-01-01 open Assets:Invest:STOCK "FIFO"- Resolução Automática: Resolve ambiguidade selecionando os lotes correspondentes mais antigos.
- Correspondência Cronológica: Você supõe que está vendendo os ativos que manteve por mais tempo. Várias autoridades fiscais tratam isso como padrão quando você não identifica um lote.
3. LIFO (Último a Entrar, Primeiro a Sair)
O método LIFO é o oposto do FIFO. Ele registra reduções contra os lotes mais novos disponíveis primeiro.
2024-01-01 open Assets:Invest:STOCK "LIFO"- Ordem Cronológica Reversa: Seleciona os lotes correspondentes mais recentemente adquiridos.
- Mais novo, não o mais caro: LIFO seleciona pela data de aquisição apenas. Acontece de vender as ações de maior custo quando os preços vêm subindo, mas se o seu lote mais novo for o mais barato — que é o que o exemplo abaixo foi feito para mostrar — LIFO vai realizar o maior ganho, não o menor. O método que sempre vende as ações mais caras é
HIFO, descrito a seguir.
4. HIFO (Highest-In, First-Out)
O método HIFO registra reduções contra os lotes mais caros disponíveis primeiro, independente da data.
2024-01-01 open Assets:Invest:STOCK "HIFO"- Correspondência Classificada por Custo: Seleciona os lotes correspondentes com maior custo base.
- Menor Ganho Realizado: Para um dado preço de venda, vender as ações de maior custo realiza o menor ganho (ou a maior perda). Se você pode usá-lo é uma questão de jurisdição — nos Estados Unidos, por exemplo, escolher um lote exige identificação específica no momento da venda — então trate o método como um mecanismo contábil e confirme a eleição fiscal separadamente.
5. Comparando FIFO, LIFO e HIFO nos mesmos lotes
Os três métodos só diferem quando o lote mais antigo, o mais novo e o mais caro são três lotes distintos. Este livro contábil organiza exatamente isso — o lote A é o mais antigo, o lote C é o mais novo, e o lote do meio B é o mais caro — e então vende 10 ações de três contas que diferem apenas no método de lançamento:
1970-01-01 commodity STK
1970-01-01 open Assets:Broker:Fifo STK "FIFO"
1970-01-01 open Assets:Broker:Lifo STK "LIFO"
1970-01-01 open Assets:Broker:Hifo STK "HIFO"
1970-01-01 open Assets:Broker:Cash USD
1970-01-01 open Income:Gains USD
; Lot A - the oldest, at $100.00 per share
2024-01-10 * "Buy lot A"
Assets:Broker:Fifo 10 STK {100.00 USD}
Assets:Broker:Lifo 10 STK {100.00 USD}
Assets:Broker:Hifo 10 STK {100.00 USD}
Assets:Broker:Cash -3000.00 USD
; Lot B - the most expensive, at $120.00 per share
2024-02-10 * "Buy lot B"
Assets:Broker:Fifo 10 STK {120.00 USD}
Assets:Broker:Lifo 10 STK {120.00 USD}
Assets:Broker:Hifo 10 STK {120.00 USD}
Assets:Broker:Cash -3600.00 USD
; Lot C - the newest, at $90.00 per share
2024-03-10 * "Buy lot C"
Assets:Broker:Fifo 10 STK {90.00 USD}
Assets:Broker:Lifo 10 STK {90.00 USD}
Assets:Broker:Hifo 10 STK {90.00 USD}
Assets:Broker:Cash -2700.00 USD
; Sell 10 shares out of each account at $150.00 and let each
; account's booking method choose which lot leaves.
2024-06-01 * "Sell 10 shares from each account"
Assets:Broker:Fifo -10 STK {} @ 150.00 USD
Assets:Broker:Lifo -10 STK {} @ 150.00 USD
Assets:Broker:Hifo -10 STK {} @ 150.00 USD
Assets:Broker:Cash 4500.00 USD
Income:GainsEle carrega sem erros e registra $1.400,00 de ganho no total, dividido assim:
| Conta | Método | Lote registrado | Custo base | Ganho realizado | Lotes remanescentes |
|---|---|---|---|---|---|
Assets:Broker:Fifo | FIFO | lote A, 2024-01-10 | $100,00 | $500,00 | 10 @ $120,00, 10 @ $90,00 |
Assets:Broker:Lifo | LIFO | lote C, 2024-03-10 | $90,00 | $600,00 | 10 @ $100,00, 10 @ $120,00 |
Assets:Broker:Hifo | HIFO | lote B, 2024-02-10 | $120,00 | $300,00 | 10 @ $100,00, 10 @ $90,00 |
A linha LIFO é a que vale a pena observar: ela realizou o maior ganho dos três, porque o lote mais novo também foi o mais barato.
6. STRICT_WITH_SIZE
STRICT_WITH_SIZE é STRICT mais um critério de desempate extra: quando vários lotes correspondem, mas exatamente um deles contém precisamente o número de unidades que você está removendo, esse lote é escolhido.
1970-01-01 commodity STK
1970-01-01 open Assets:Broker:Sized STK "STRICT_WITH_SIZE"
1970-01-01 open Assets:Broker:Cash USD
1970-01-01 open Income:Gains USD
2024-01-10 * "Buy 10 shares"
Assets:Broker:Sized 10 STK {100.00 USD}
Assets:Broker:Cash -1000.00 USD
2024-02-10 * "Buy 7 shares"
Assets:Broker:Sized 7 STK {120.00 USD}
Assets:Broker:Cash -840.00 USD
; Only one lot holds exactly 7 units, so the empty specifier resolves.
2024-06-01 * "Sell 7 shares"
Assets:Broker:Sized -7 STK {} @ 150.00 USD
Assets:Broker:Cash 1050.00 USD
Income:GainsIsso lança um ganho de $210,00 contra o lote de $120,00. O arquivo idêntico com "STRICT" na linha open falha com Ambiguous matches for "-7 STK {}".
7. AVERAGE (aceito, mas não implementado)
AVERAGE é um nome válido — option "booking_method" "AVERAGE" e open … "AVERAGE" são ambos analisados — mas o Beancount 3.2.3 não tem implementação para isso. Tudo aqui carrega até a venda:
1970-01-01 commodity STK
1970-01-01 open Assets:Broker:Avg STK "AVERAGE"
1970-01-01 open Assets:Broker:Cash USD
1970-01-01 open Income:Gains USD
2024-01-10 * "Buy 10 shares at $10.00"
Assets:Broker:Avg 10 STK {10.00 USD}
Assets:Broker:Cash -100.00 USD
2024-02-10 * "Buy 10 more at $8.00"
Assets:Broker:Avg 10 STK {8.00 USD}
Assets:Broker:Cash -80.00 USD
; An average-cost engine would book this at $9.00 per share. This one refuses.
2024-06-01 * "Sell 5 shares"
Assets:Broker:Avg -5 STK {}
Assets:Broker:Cash 45.00 USD
Income:GainsNo momento em que essa redução precisa ser registrada, o carregador para com:
AVERAGE method is not supportedNão planeje um razão em torno disso. Se você quer comportamento de custo médio hoje, mantenha a posição em uma conta NONE e calcule a média você mesmo, ou acompanhe cada lote e aceite ganhos em nível de lote.
8. NONE
O método NONE desabilita totalmente a correspondência de lotes.
2024-01-01 open Assets:Invest:STOCK "NONE"- Sem Correspondência de Lote: Beancount não tenta casar reduções com aumentos.
- Permite Sinais Mistos: Isso permite que uma conta tenha saldos positivos e negativos da mesma commodity simultaneamente. Esse comportamento é semelhante à forma como a ferramenta Ledger CLI trata commodities.
Especificação de Lote
Um "lote" é um bloco específico de uma commodity adquirido em um determinado momento e preço. Quando você cria ou reduz uma posição, pode especificar seus atributos de lote em detalhes.
Especificação Completa
Ao aumentar um inventário (comprar), você pode especificar até três atributos para o lote, separados por vírgula dentro de um único par de chaves:
Assets:Invest:STOCK 10 STOCK {100.00 USD, 2024-01-15, "lot-identifier"}100.00 USD— o custo base, expresso por unidade.2024-01-15— a data de aquisição. Beancount preenche isso a partir da data da transação quando você omite, por isso as mensagens de erro acima mostram uma data em cada lote."lot-identifier"— uma etiqueta de texto opcional.
Embora os três sejam opcionais, fornecer pelo menos o custo base é prática padrão. As chaves devem permanecer em uma linha, e comentários dentro do razão começam com ;, nunca #.
Métodos de Correspondência
Ao reduzir um inventário (vender), você usa a mesma sintaxe para especificar de qual(is) lote(s) vender.
-
Correspondência por custo: Este é o método mais comum.
Assets:Invest:STOCK -5 STOCK {100.00 USD} -
Correspondência por data: Se os custos forem idênticos, você pode desambiguar usando a data de aquisição.
Assets:Invest:STOCK -5 STOCK {2024-01-15} -
Correspondência por etiqueta: Etiquetas fornecem uma maneira infalível de identificar um lote.
Assets:Invest:STOCK -5 STOCK {"lot-identifier"} -
Deixe o lote para o método de lançamento: Um conjunto vazio de chaves
{}não nomeia nenhum lote, então o método de lançamento da conta escolhe. SobFIFO,LIFOouHIFOé o lote mais antigo, mais novo ou mais caro que bate; sob o padrãoSTRICTé umAmbiguousMatchErrora menos que a redução esvazie exatamente os lotes casados.Assets:Invest:STOCK -5 STOCK {}
Tratamento de Preço
É crucial entender a diferença entre base de custo ({}) e preço (@). Eles têm propósitos diferentes e não são intercambiáveis.
Preço vs Custo
{cost}: Define o custo de aquisição de um ativo. Faz parte do lote em estoque e é usado para registrar reduções e calcular ganhos de capital.@ price: Uma anotação que registra um preço de mercado na hora de uma transação. É usado para conversões de moeda ou para registrar o valor de mercado numa data específica.
Aqui estão os três cenários:
-
Anotação de Preço (Conversão): Use
@para converter de uma moeda para outra.Assets:Forex 1000 USD @ 0.85 EUR -
Base de Custo (Aquisição): Use
{}ao comprar um ativo para estabelecer seu custo.Assets:Invest 10 STOCK {100.00 USD} -
Ambos (Venda com Registro de Preço): Ao vender um ativo, use
{}para identificar o lote vendido e@para registrar o preço da venda. Isso permite o cálculo automático de ganhos de capital.Assets:Invest -10 STOCK {100.00 USD} @ 105.00 USDEsta entrada vende 10
STOCKdo lote que custou $100,00 cada, ao preço de venda de $105,00 cada.
Regras de Uso do Preço
- Anotações de preço (
@) não afetam qual lote é registrado. O pareamento de lotes é tratado exclusivamente pela base de custo ({}) e pelo método de registro da conta. - O símbolo
@é usado apenas para:
- Conversões de moeda.
- Registrar o valor de mercado de um ativo no momento de uma transação.
- Fornecer o preço de venda para cálculos de ganhos de capital.
Configuração
Você pode configurar métodos de lançamento globalmente ou por conta.
Método Global de Registro
Você pode definir um método de lançamento padrão para todo o seu arquivo Beancount usando a diretiva option.
option "booking_method" "STRICT"Os valores aceitos são "STRICT" (o padrão ao não definir nada), "STRICT_WITH_SIZE", "NONE", "FIFO", "LIFO", "HIFO" e "AVERAGE". Qualquer outra string é rejeitada na carga com Error for option 'booking_method'. "AVERAGE" é aceito aqui e em open, mas lançar uma redução sob ele falha, como a seção AVERAGE acima mostra.
Substituição por Conta
Frequentemente é útil ter métodos diferentes para contas distintas. Por exemplo, você pode querer FIFO para uma conta de aposentadoria, mas STRICT para uma conta de corretagem tributável para garantir que esteja vendendo lotes fiscais específicos. Você pode definir o método de lançamento ao abrir a conta.
2024-01-01 open Assets:Retirement:401K "FIFO"
2024-01-01 open Assets:Taxable:Stock "STRICT"Melhores Práticas
-
Organização do Estoque: Para manter seu livro contábil limpo e simples, é altamente recomendado usar contas separadas para cada mercadoria única que você possui e restringir cada uma a essa mercadoria em sua diretiva
open.; GOOD: separate accounts by commodity, each constrained to one 2024-01-01 open Assets:Invest:VTSAX VTSAX 2024-01-01 open Assets:Invest:VFIAX VFIAXEvite misturar ações ou fundos diferentes na mesma conta, pois isso complica o gerenciamento de inventário. A lista de commodities no
openfaz com que o Beancount rejeite uma contabilização fora do lugar em vez de misturar silenciosamente dois inventários. -
Gerenciamento de Lotes:
-
Use rótulos significativos para lotes, especialmente para transações específicas como colheita de perdas fiscais ou concessões de ações para empregados.
Assets:Invest:STOCK 10 STOCK {100.00 USD, "tax-loss-harvest-2024"} -
Documente suas negociações com comentários. Isso torna seu livro razão mais fácil de ler e entender posteriormente.
Assets:Invest:STOCK -10 STOCK {100.00 USD} @ 110.00 USD ; Gain: 10%
- Depuração: Se você encontrar erros ou comportamentos inesperados, o Beancount oferece ferramentas para inspecionar o estado do seu inventário.
-
Examine o Estado do Inventário: Use o
bea doctor context main.beancount 42para inspecionar a transação na linha 42, incluindo suas contabilizações e os saldos das contas afetadas. Substitua o nome do arquivo e número da linha pela transação que deseja inspecionar.Substitua
<LINENO>pelo número da linha logo após uma transação para ver seu efeito. -
Verifique a Correspondência dos Lotes: A ferramenta
bea checkvalida seu arquivo inteiro. Ela irá capturar quaisquer erros de lançamento, como correspondências ambíguas de lotes no modoSTRICT.