El sistema de inventario de Beancount es una función potente para rastrear activos que se compran y venden a lo largo del tiempo, como acciones, fondos mutuos o divisas extranjeras. Permite un seguimiento preciso de la base de costo, lo cual es esencial para calcular ganancias de capital y comprender el rendimiento de la cartera. Este tutorial cubre la mecánica central de la gestión de inventarios en tu libro contable.
Conceptos Básicos
En esencia, la gestión de inventario gira en torno al seguimiento de posiciones. Una "posición" es simplemente una cantidad de un commodity mantenida en una cuenta. Beancount distingue entre dos tipos fundamentales de posiciones.
Tipos de Posición
-
Posición simple (sin costo): Este es un registro de saldo estándar. Representa una cantidad de un commodity sin ningún costo de adquisición asociado. Es adecuado para efectivo o aserciones de saldo simples.
Assets:Bank:Checking 100.00 USD -
Posición con base de costo: Este tipo de posición incluye no solo el número de unidades y el commodity, sino también el costo al que se adquirió. Esta es la base del seguimiento de inventario. El costo se especifica dentro de llaves
{}.Assets:Invest:VTSAX 10 VTSAX {100.00 USD, "lot-1"}En este ejemplo, tenemos 10 unidades de
VTSAX. Cada unidad se adquirió a un costo de $100.00 USD. Este lote específico de acciones se identifica como un "lote".
Operaciones de Inventario
Hay dos operaciones principales que puedes realizar sobre un inventario:
-
Aumentos (agregar al inventario): Cuando compras un commodity, aumentas tu inventario. Creas un nuevo lote con un número específico de unidades y una base de costo.
2024-01-15 * "Buy shares" Assets:Invest:STOCK 50 STOCK {25.00 USD, "lot-1"} Assets:Bank:Checking -1250.00 USDAquí, compramos 50 unidades de
STOCKa un costo por unidad de $25.00 USD. Esto crea un lote en la cuentaAssets:Invest:STOCK. -
Reducciones (quitar del inventario): Cuando vendes un commodity, reduces tu inventario. Debes especificar de qué lote estás vendiendo. Esto se hace proporcionando información coincidente en las llaves.
2024-01-20 * "Sell shares" Assets:Invest:STOCK -25 STOCK {25.00 USD} Assets:Bank:Checking 625.00 USDEn esta transacción, vendemos 25 unidades de
STOCKdel lote que se compró a $25.00 USD por unidad.
Métodos de Registro
Cuando reduces un inventario, Beancount necesita una regla para decidir de qué lote específico tomar si varios lotes coinciden con la reducción. Esta regla se llama "método de asignación". Puedes establecer un valor predeterminado para todo el archivo con una opción, o dar a una cuenta su propio método en la directiva open.
Beancount 3.2.3 acepta siete nombres de métodos: STRICT (el predeterminado), STRICT_WITH_SIZE, NONE, FIFO, LIFO, HIFO y AVERAGE. Seis de ellos están implementados; AVERAGE se analiza sintácticamente pero genera un error en el momento en que tiene que asignar una reducción, como muestra la sección AVERAGE a continuación.
1. STRICT (Predeterminado)
El método STRICT es el predeterminado y el método de asignación más seguro. Impone una coincidencia explícita e inequívoca.
2024-01-01 open Assets:Invest:STOCK "STRICT"- Requiere una coincidencia exacta de lote: El especificador de costo del registro de reducción (
{...}) debe identificar un único lote — por costo, por fecha de adquisición, por etiqueta o por cualquier combinación de ellos. - Errores en coincidencias ambiguas: Si el especificador coincide con más de un lote, Beancount genera un
AmbiguousMatchErroren lugar de adivinar. - Excepción: Si una reducción elimina exactamente el número total de unidades con el que coincide el especificador, se permite un especificador vacío (
{}), y la reducción se divide entre esos lotes.
Este libro contable tiene dos lotes y vende uno de ellos nombrando su costo, lo cual no es ambiguo:
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:GainsSe carga sin errores, registra $300.00 de ganancia en Income:Gains y deja 10 STK {100.00 USD} en la cuenta.
Reemplaza ese último registro con un especificador vacío y el mismo archivo falla:
; 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 informa Ambiguous matches for "-10 STK {}" y enumera los candidatos. Vender la posición completa sí está bien, sin embargo, porque no queda nada entre lo que elegir:
; 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:GainsEso registra $800.00 de ganancia — $3,000.00 de ingresos contra $1,000.00 + $1,200.00 de base — y deja la cuenta vacía. Esta es una propiedad de STRICT en sí mismo, no algo para lo que tengas que cambiar a STRICT_WITH_SIZE.
2. FIFO (Primero en entrar, primero en salir)
El método FIFO registra automáticamente las reducciones contra los lotes disponibles más antiguos primero.
2024-01-01 open Assets:Invest:STOCK "FIFO"- Resolución automática: Resuelve la ambigüedad seleccionando los lotes coincidentes más antiguos.
- Coincidencia cronológica: Asumes que estás vendiendo los activos que has mantenido durante más tiempo. Varias autoridades fiscales lo tratan como el predeterminado cuando no has identificado un lote.
3. LIFO (Último en entrar, primero en salir)
El método LIFO es lo opuesto a FIFO. Registra las reducciones contra los lotes disponibles más recientes primero.
2024-01-01 open Assets:Invest:STOCK "LIFO"- Orden cronológico inverso: Selecciona los lotes coincidentes adquiridos más recientemente.
- El más reciente, no el más caro: LIFO elige solo por fecha de adquisición. Da la casualidad de que vende las acciones de mayor costo cuando los precios han estado subiendo, pero si tu lote más reciente es el más barato — que es lo que el ejemplo siguiente está diseñado para mostrar — LIFO realizará la ganancia más grande, no la más pequeña. El método que siempre vende las acciones más caras es
HIFO, descrito a continuación.
4. HIFO (Highest-In, First-Out)
El método HIFO registra las reducciones contra los lotes disponibles más caros primero, sea cual sea su fecha.
2024-01-01 open Assets:Invest:STOCK "HIFO"- Coincidencia clasificada por costo: Selecciona los lotes coincidentes con la base de costo más alta.
- Ganancia realizada más pequeña: Para un precio de venta dado, vender las acciones de mayor costo realiza la ganancia más pequeña (o la pérdida más grande). Si puedes usarlo es una cuestión de jurisdicción — en Estados Unidos, por ejemplo, elegir un lote en absoluto requiere identificación específica en el momento de la venta — así que trata el método como un mecanismo de contabilidad y confirma la elección fiscal por separado.
5. Comparando FIFO, LIFO y HIFO sobre las mismas partidas
Los tres métodos solo difieren cuando el lote más antiguo, el más reciente y el más caro son tres lotes diferentes. Este libro contable organiza exactamente eso — el lote A es el más antiguo, el lote C es el más reciente, y el lote intermedio B es el más caro — y luego vende 10 acciones de tres cuentas que difieren solo en su método de asignación:
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:GainsSe carga con cero errores y registra $1,400.00 de ganancia en total, dividida así:
| Cuenta | Método | Lote asignado | Base de costo | Ganancia realizada | Lotes restantes |
|---|---|---|---|---|---|
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 |
La fila de LIFO es la que vale la pena mirar fijamente: realizó la ganancia más grande de las tres, porque el lote más reciente también era el más barato.
6. STRICT_WITH_SIZE
STRICT_WITH_SIZE es STRICT más un desempate adicional: cuando varios lotes coinciden pero exactamente uno de ellos tiene precisamente el número de unidades que estás eliminando, se elige ese lote.
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:GainsEso registra $210.00 de ganancia contra el lote de $120.00. El archivo idéntico con "STRICT" en la línea open falla con Ambiguous matches for "-7 STK {}".
7. PROMEDIO (aceptado, pero no implementado)
AVERAGE es un nombre válido — tanto option "booking_method" "AVERAGE" como open … "AVERAGE" se analizan sintácticamente — pero Beancount 3.2.3 no tiene ninguna implementación detrás. Todo aquí se carga hasta la venta:
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:GainsEn el momento en que esa reducción tiene que asignarse, el cargador se detiene con:
AVERAGE method is not supportedNo planifiques un libro contable en torno a él. Si quieres un comportamiento de costo promedio hoy, mantén la posición en una cuenta NONE y calcula el promedio tú mismo, o rastrea cada lote y acepta ganancias a nivel de lote.
8. NINGUNO
El método NONE desactiva por completo la coincidencia de lotes.
2024-01-01 open Assets:Invest:STOCK "NONE"- Sin coincidencia de lotes: Beancount no intenta hacer coincidir reducciones con aumentos.
- Permite signos mixtos: Esto permite que una cuenta mantenga saldos tanto positivos como negativos del mismo commodity simultáneamente. Este comportamiento es similar a cómo la herramienta de CLI Ledger maneja los commodities.
Especificación de Lotes
Un "lote" es un bloque específico de un commodity adquirido en un momento y precio particulares. Cuando creas o reduces una posición, puedes especificar sus atributos de lote en detalle.
Especificación Completa
Al aumentar un inventario (comprar), puedes especificar hasta tres atributos para el lote, separados por comas dentro de un único par de llaves:
Assets:Invest:STOCK 10 STOCK {100.00 USD, 2024-01-15, "lot-identifier"}100.00 USD— la base de costo, expresada por unidad.2024-01-15— la fecha de adquisición. Beancount la completa a partir de la fecha de la transacción cuando la omites, que es por lo que los mensajes de error anteriores muestran una fecha en cada lote."lot-identifier"— una etiqueta de cadena opcional.
Aunque los tres son opcionales, proporcionar al menos la base de costo es una práctica estándar. Las llaves deben permanecer en una sola línea, y los comentarios dentro de un libro contable comienzan con ;, nunca con #.
Métodos de Coincidencia
Al reducir un inventario (vender), usas la misma sintaxis para especificar de qué lote(s) vender.
-
Coincidir por costo: Este es el método más común.
Assets:Invest:STOCK -5 STOCK {100.00 USD} -
Coincidir por fecha: Si los costos son idénticos, puedes desambiguar usando la fecha de adquisición.
Assets:Invest:STOCK -5 STOCK {2024-01-15} -
Coincidir por etiqueta: Las etiquetas proporcionan una forma infalible de identificar un lote.
Assets:Invest:STOCK -5 STOCK {"lot-identifier"} -
Dejar el lote al método de asignación: Un conjunto vacío de llaves
{}no nombra ningún lote, así que el método de asignación de la cuenta elige. BajoFIFO,LIFOoHIFOese es el lote coincidente más antiguo, más reciente o más caro; bajo elSTRICTpredeterminado es unAmbiguousMatchErrora menos que la reducción vacíe exactamente los lotes coincidentes.Assets:Invest:STOCK -5 STOCK {}
Manejo de Precios
Es crucial entender la diferencia entre base de costo ({}) y precio (@). Sirven a propósitos diferentes y no son intercambiables.
Precio vs Costo
{cost}: Define el costo de adquisición de un activo. Es parte del propio lote de inventario y se usa para asignar reducciones y calcular ganancias de capital.@ price: Una anotación que registra un precio de mercado en el momento de una transacción. Se usa para conversiones de divisas o para anotar el valor de mercado en una fecha particular.
Aquí están los tres escenarios:
-
Anotación de precio (conversión): Usa
@para convertir de una divisa a otra.Assets:Forex 1000 USD @ 0.85 EUR -
Base de costo (adquisición): Usa
{}al comprar un activo para establecer su costo.Assets:Invest 10 STOCK {100.00 USD} -
Ambos (venta con registro de precio): Al vender un activo, usa
{}para identificar el lote que se vende y@para registrar el precio de venta. Esto permite el cálculo automatizado de ganancias de capital.Assets:Invest -10 STOCK {100.00 USD} @ 105.00 USDEste asiento vende 10
STOCKdel lote que costó $100.00 cada uno, a un precio de venta de $105.00 cada uno.
Una directiva price independiente proporciona datos de referencia para la valoración de mercado. Precios en vivo puede mantener estas directivas para activos compatibles en libros contables alojados. Una actualización deja tus lotes, método de asignación, costos de adquisición e ingresos de venta registrados sin cambios.
Reglas de Uso del Precio
- Las anotaciones de precio (
@) no afectan qué lote se asigna. La coincidencia de lotes se maneja exclusivamente por la base de costo ({}) y el método de asignación de la cuenta. - El símbolo
@se usa solo para:
- Conversiones de divisas.
- Registrar el valor de mercado de un activo en el momento de una transacción.
- Proporcionar el precio de venta para los cálculos de ganancias de capital.
Configuración
Puedes configurar los métodos de asignación globalmente o por cuenta.
Método de Registro Global
Puedes establecer un método de asignación predeterminado para todo tu archivo de Beancount usando la directiva option.
option "booking_method" "STRICT"Los valores aceptados son "STRICT" (el predeterminado cuando no estableces nada), "STRICT_WITH_SIZE", "NONE", "FIFO", "LIFO", "HIFO" y "AVERAGE". Cualquier otra cadena se rechaza en el momento de la carga con Error for option 'booking_method'. "AVERAGE" se acepta aquí y en open, pero asignar una reducción bajo él falla, como muestra la sección AVERAGE anterior.
Anulación Por Cuenta
A menudo es útil tener métodos diferentes para cuentas diferentes. Por ejemplo, podrías querer FIFO para una cuenta de jubilación pero STRICT para una cuenta de corretaje gravable para asegurarte de vender lotes fiscales específicos. Puedes establecer el método de asignación cuando abres la cuenta.
2024-01-01 open Assets:Retirement:401K "FIFO"
2024-01-01 open Assets:Taxable:Stock "STRICT"Mejores Prácticas
-
Organización del inventario: Para mantener tu libro contable limpio y simple, se recomienda encarecidamente usar cuentas separadas para cada commodity único que poseas, y restringir cada una a ese commodity en su directiva
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 VFIAXEvita mezclar diferentes acciones o fondos en la misma cuenta, ya que complica la gestión del inventario. La lista de commodities en
openhace que Beancount rechace un asiento errante en lugar de mezclar silenciosamente dos inventarios. -
Gestión de lotes:
-
Usa etiquetas significativas para los lotes, especialmente para transacciones específicas como recolección de pérdidas fiscales o concesiones de acciones de empleados.
Assets:Invest:STOCK 10 STOCK {100.00 USD, "tax-loss-harvest-2024"} -
Documenta tus operaciones con comentarios. Esto hace que tu libro contable sea más fácil de leer y entender después.
Assets:Invest:STOCK -10 STOCK {100.00 USD} @ 110.00 USD ; Gain: 10%
- Depuración: Si encuentras errores o comportamiento inesperado, Beancount proporciona herramientas para inspeccionar el estado de tu inventario.
-
Examinar el estado del inventario: Usa
bea doctor context main.beancount 42para inspeccionar la transacción en la línea 42, incluidos sus asientos y los saldos de cuenta afectados. Reemplaza el nombre del archivo y el número de línea con la transacción que quieres inspeccionar.Reemplaza
<LINENO>con el número de línea justo después de una transacción para ver su efecto. -
Verificar la coincidencia de lotes: La herramienta
bea checkvalida todo tu archivo. Detendrá cualquier error de asignación, como coincidencias de lote ambiguas en modoSTRICT.