Il sistema di inventario di Beancount è una funzione potente per tracciare gli asset che vengono comprati e venduti nel tempo, come azioni, fondi comuni o valute estere. Permette un monitoraggio preciso del costo di acquisto, fondamentale per calcolare i guadagni da capitale e comprendere la performance del portafoglio. Questo tutorial copre i meccanismi di base per gestire gli inventari nel tuo libro mastro.
Concetti Fondamentali
Il fulcro della gestione dell'inventario ruota attorno al tracciamento delle posizioni. Una "posizione" è semplicemente una quantità di una merce detenuta in un conto. Beancount distingue tra due tipi fondamentali di posizioni.
Tipi di Posizione
-
Posizione Semplice (Senza Costo): Questo è un normale saldo. Rappresenta una quantità di una merce senza alcun costo di acquisizione associato. È adatta per contante o semplici asserzioni di saldo.
Assets:Bank:Checking 100.00 USD -
Posizione con Costo di Base: Questo tipo di posizione include non solo il numero di unità e la merce, ma anche il costo al quale è stata acquisita. Questa è la base del tracciamento dell'inventario. Il costo è specificato all'interno delle parentesi graffe
{}.Assets:Invest:VTSAX 10 VTSAX {100.00 USD, "lot-1"}In questo esempio, deteniamo 10 unità di
VTSAX. Ogni unità è stata acquisita al costo di $100,00 USD. Questo specifico lotto di azioni è identificato come un "lotto".
Operazioni sull'Inventario
Ci sono due principali operazioni che puoi eseguire su un inventario:
-
Aumenti (Aggiungere all'inventario): Quando acquisti una merce, aumenti il tuo inventario. Crei un nuovo lotto con un numero specifico di unità e un costo di base.
2024-01-15 * "Buy shares" Assets:Invest:STOCK 50 STOCK {25.00 USD, "lot-1"} Assets:Bank:Checking -1250.00 USDQui, compriamo 50 unità di
STOCKal costo per unità di $25,00 USD. Questo crea un lotto nel contoAssets:Invest:STOCK. -
Riduzioni (Rimuovere dall'inventario): Quando vendi una merce, riduci il tuo inventario. Devi specificare da quale lotto stai vendendo. Questo si fa fornendo le informazioni corrispondenti nelle parentesi graffe.
2024-01-20 * "Sell shares" Assets:Invest:STOCK -25 STOCK {25.00 USD} Assets:Bank:Checking 625.00 USDIn questa transazione, stiamo vendendo 25 unità di
STOCKdal lotto acquistato a $25,00 USD per unità.
Metodi di Registrazione
Quando riduci un inventario, Beancount necessita di una regola per decidere da quale specifico lotto prelevare se diversi lotti corrispondono alla riduzione. Questa regola è chiamata "metodo di registrazione". Puoi impostare un valore predefinito per tutto il file con un'opzione, o assegnare a un account un metodo proprio tramite la direttiva open.
Beancount 3.2.3 accetta sette nomi di metodi: STRICT (il predefinito), STRICT_WITH_SIZE, NONE, FIFO, LIFO, HIFO e AVERAGE. Sei di essi sono implementati; AVERAGE analizza ma genera un errore nel momento in cui deve contabilizzare una riduzione, come mostra la sezione AVERAGE qui sotto.
1. STRICT (Predefinito)
Il metodo STRICT è il predefinito e il metodo di contabilizzazione più sicuro. Impone un abbinamento esplicito e non ambiguo.
2024-01-01 open Assets:Invest:STOCK "STRICT"- Richiede Corrispondenza Esatta del Lotto: lo specificatore di costo della registrazione di riduzione (
{...}) deve identificare un singolo lotto — per costo, per data di acquisizione, per etichetta, o per qualsiasi combinazione di questi. - Errori su Corrispondenze Ambigue: se lo specificatore corrisponde a più di un lotto, Beancount genera un
AmbiguousMatchErrorinvece di indovinare. - Eccezione: se una riduzione rimuove esattamente il numero totale di unità corrispondenti allo specificatore, è consentito uno specificatore vuoto (
{}), e la riduzione viene ripartita tra quei lotti.
Questo libro contabile contiene due lotti e ne vende uno nominando il suo costo, che è non 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:GainsSi carica senza errori, contabilizza un guadagno di $300.00 su Income:Gains, e lascia 10 STK {100.00 USD} nel conto.
Sostituire quell'ultima registrazione con uno specificatore vuoto fa fallire lo stesso file:
; 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 segnala Ambiguous matches for "-10 STK {}" e elenca i candidati. Vendere l'intera posizione va bene, però, perché non rimane nulla su cui scegliere:
; 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:GainsQuesto contabilizza un guadagno di $800.00 — $3,000.00 di proventi contro $1,000.00 + $1,200.00 di base — e lascia il conto vuoto. Questa è una proprietà dello stesso STRICT, non qualcosa per cui devi passare a STRICT_WITH_SIZE.
2. FIFO (First-In, First-Out)
Il metodo FIFO contabilizza automaticamente le riduzioni iniziando dai lotti più vecchi disponibili.
2024-01-01 open Assets:Invest:STOCK "FIFO"- Risoluzione Automatica: Risolve le ambiguità selezionando i lotti corrispondenti più vecchi.
- Corrispondenza Cronologica: Si assume di vendere gli asset detenuti da più tempo. Diverse autorità fiscali considerano questo il comportamento predefinito quando non hai identificato un lotto.
3. LIFO (Last-In, First-Out)
Il metodo LIFO è l'opposto di FIFO. Contabilizza le riduzioni iniziando dai lotti disponibili più recenti.
2024-01-01 open Assets:Invest:STOCK "LIFO"- Ordine cronologico inverso: seleziona i lotti corrispondenti acquisiti più recentemente.
- Il più nuovo, non il più costoso: LIFO sceglie solo in base alla data di acquisizione. Capita di vendere le azioni al costo più elevato quando i prezzi sono cresciuti, ma se il lotto più recente è il più economico — come mostra l'esempio sottostante — LIFO realizzerà il maggior guadagno, non il più piccolo. Il metodo che vende sempre le azioni più costose è
HIFO, descritto di seguito.
4. HIFO (Highest-In, First-Out)
Il metodo HIFO registra le riduzioni prima contro i lotti più costosi disponibili, indipendentemente dalla data.
2024-01-01 open Assets:Invest:STOCK "HIFO"- Corrispondenza per costo: seleziona i lotti corrispondenti con la base di costo più alta.
- Minimo guadagno realizzato: Per un dato prezzo di vendita, vendere le azioni al costo più alto realizza il guadagno più piccolo (o la perdita maggiore). La possibilità di usarlo dipende dalla giurisdizione — negli Stati Uniti, ad esempio, scegliere un lotto richiede l'identificazione specifica al momento della vendita — perciò trattate il metodo come un meccanismo contabile e confermate separatamente l'elezione fiscale.
5. Confronto tra FIFO, LIFO e HIFO sugli stessi lotti
I tre metodi differiscono solo quando il lotto più vecchio, quello più recente e quello più costoso sono tre lotti distinti. Questo libro contabile dispone esattamente così — il lotto A è il più vecchio, il lotto C il più recente, e il lotto intermedio B è il più costoso — e poi vende 10 azioni da tre conti che differiscono solo nel metodo di registrazione:
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:GainsCarica senza errori e registra un guadagno totale di $1.400,00, suddiviso come segue:
| Conto | Metodo | Lotto registrato | Base costo | Guadagno realizzato | Lotti rimanenti |
|---|---|---|---|---|---|
Assets:Broker:Fifo | FIFO | lotto A, 2024-01-10 | $100,00 | $500,00 | 10 @ $120,00, 10 @ $90,00 |
Assets:Broker:Lifo | LIFO | lotto C, 2024-03-10 | $90,00 | $600,00 | 10 @ $100,00, 10 @ $120,00 |
Assets:Broker:Hifo | HIFO | lotto B, 2024-02-10 | $120,00 | $300,00 | 10 @ $100,00, 10 @ $90,00 |
La riga LIFO è quella che merita attenzione: ha realizzato il maggiore guadagno dei tre, perché il lotto più nuovo era anche il più economico.
6. STRICT_WITH_SIZE
STRICT_WITH_SIZE è STRICT con un ulteriore criterio di spareggio: quando più lotti corrispondono ma esattamente uno di essi contiene precisamente il numero di unità che state rimuovendo, quel lotto viene scelto.
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:GainsQuesto contabilizza $210,00 di guadagno contro il lotto da $120,00. Il file identico con "STRICT" sulla riga open fallisce con Ambiguous matches for "-7 STK {}".
7. AVERAGE (accettato, ma non implementato)
AVERAGE è un nome valido — option "booking_method" "AVERAGE" e open … "AVERAGE" si analizzano entrambi — ma Beancount 3.2.3 non ha ancora un'implementazione alle spalle. Tutto qui si carica fino alla vendita:
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:GainsNel momento in cui quella riduzione deve essere registrata, il caricatore si interrompe con:
AVERAGE method is not supportedNon pianificare un libro mastro intorno a questo. Se vuoi un comportamento a costo medio oggi, mantieni la posizione in un conto NONE e calcola tu stesso la media, oppure segui ogni lotto e accetta i guadagni a livello di lotto.
8. NONE
Il metodo NONE disabilita completamente il matching dei lotti.
2024-01-01 open Assets:Invest:STOCK "NONE"- Nessun abbinamento dei lotti: Beancount non tenta di abbinare riduzioni ad aumenti.
- Consente segni misti: Questo permette a un conto di avere contemporaneamente saldi positivi e negativi della stessa merce. Questo comportamento è simile a come lo strumento Ledger CLI gestisce le merci.
Specifica del lotto
Un "lotto" è un blocco specifico di una merce acquisita in un momento e a un prezzo particolari. Quando crei o riduci una posizione, puoi specificarne in dettaglio gli attributi del lotto.
Specifica completa
Quando aumenti un inventario (acquisto), puoi specificare fino a tre attributi per il lotto, separati da virgole all'interno di una singola coppia di parentesi graffe:
Assets:Invest:STOCK 10 STOCK {100.00 USD, 2024-01-15, "lot-identifier"}100.00 USD— il costo base, espresso per unità.2024-01-15— la data di acquisizione. Beancount la riempie con la data della transazione se la ometti, motivo per cui i messaggi di errore sopra mostrano una data per ogni lotto."lot-identifier"— un'etichetta opzionale in forma di stringa.
Sebbene tutti e tre siano opzionali, fornire almeno il costo base è una pratica standard. Le parentesi graffe devono restare su una linea e i commenti all'interno di un libro mastro iniziano con ;, mai con #.
Metodi di abbinamento
Quando riduci un inventario (vendita), usi la stessa sintassi per specificare da quale(i) lotto(i) vendere.
-
Abbinamento per costo: questo è il metodo più comune.
Assets:Invest:STOCK -5 STOCK {100.00 USD} -
Abbinamento per data: se i costi sono identici, puoi distinguere usando la data di acquisizione.
Assets:Invest:STOCK -5 STOCK {2024-01-15} -
Abbinamento per etichetta: le etichette forniscono un modo infallibile per identificare un lotto.
Assets:Invest:STOCK -5 STOCK {"lot-identifier"} -
Lascia il lotto al metodo di registrazione: un insieme vuoto di parentesi graffe
{}non nomina alcun lotto, quindi sceglie il metodo di registrazione del conto. ConFIFO,LIFOoHIFOè il lotto corrispondente più vecchio, più nuovo o più costoso; con ilSTRICTpredefinito è unAmbiguousMatchErrora meno che la riduzione non svuoti esattamente i lotti corrispondenti.Assets:Invest:STOCK -5 STOCK {}
Gestione dei prezzi
È fondamentale comprendere la differenza tra cost basis ({}) e price (@). Servono a scopi diversi e non sono intercambiabili.
Prezzo vs Costo
{cost}: Definisce il costo di acquisizione di un bene. Fa parte del lotto di inventario stesso ed è usato per registrare riduzioni e calcolare plusvalenze.@ price: Un'annotazione che registra un prezzo di mercato al momento di una transazione. È usata per conversioni di valuta o per annotare il valore di mercato in una data specifica.
Ecco i tre scenari:
-
Annotazione del Prezzo (Conversione): Usa
@per convertire da una valuta all'altra.Assets:Forex 1000 USD @ 0.85 EUR -
Cost Basis (Acquisizione): Usa
{}quando acquisti un bene per stabilirne il costo.Assets:Invest 10 STOCK {100.00 USD} -
Entrambi (Vendita con Registro del Prezzo): Quando vendi un bene, usa
{}per identificare il lotto venduto e@per registrare il prezzo di vendita. Questo permette il calcolo automatizzato delle plusvalenze.Assets:Invest -10 STOCK {100.00 USD} @ 105.00 USDQuesta voce vende 10
STOCKdal lotto che è costato $100.00 ciascuno, a un prezzo di vendita di $105.00 ciascuno.
Regole per l'Uso del Prezzo
- Le annotazioni di prezzo (
@) non influenzano quale lotto viene registrato. L'abbinamento del lotto è gestito esclusivamente dal cost basis ({}) e dal metodo di registrazione dell'account. - Il simbolo
@è usato soltanto per:
- Conversioni di valuta.
- Registrare il valore di mercato di un bene al momento di una transazione.
- Fornire il prezzo di vendita per i calcoli delle plusvalenze.
Configurazione
Puoi configurare i metodi di registrazione globalmente o per ogni singolo account.
Metodo di Registrazione Globale
Puoi impostare un metodo di registrazione predefinito per l'intero file Beancount usando la direttiva option.
option "booking_method" "STRICT"I valori accettati sono "STRICT" (il default se non imposti nulla), "STRICT_WITH_SIZE", "NONE", "FIFO", "LIFO", "HIFO" e "AVERAGE". Qualsiasi altra stringa viene rifiutata al caricamento con Error for option 'booking_method'. "AVERAGE" è accettato qui e su open, ma registrare una riduzione con esso fallisce, come mostra la sezione AVERAGE sopra.
Override per Account
Spesso è utile avere metodi diversi per account diversi. Per esempio, potresti voler FIFO per un conto pensionistico ma STRICT per un conto di intermediazione fiscale per assicurarti di vendere specifici lotti fiscali. Puoi impostare il metodo di registrazione all'apertura dell'account.
2024-01-01 open Assets:Retirement:401K "FIFO"
2024-01-01 open Assets:Taxable:Stock "STRICT"Migliori Pratiche
-
Organizzazione dell'Inventario: Per mantenere il tuo libro mastro pulito e semplice, è altamente raccomandato usare account separati per ogni commodity unica che possiedi, e vincolare ciascuno a quella commodity nella sua direttiva
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 di mescolare azioni o fondi diversi nello stesso conto, poiché complica la gestione dell'inventario. La lista delle commodity su
openfa sì che Beancount rifiuti una registrazione errante invece di mescolare silenziosamente due inventari. -
Gestione dei Lotti:
-
Usa etichette significative per i lotti, specialmente per transazioni specifiche come il tax-loss harvesting o le assegnazioni di azioni ai dipendenti.
Assets:Invest:STOCK 10 STOCK {100.00 USD, "tax-loss-harvest-2024"} -
Documenta i tuoi scambi con commenti. Questo rende il tuo libro mastro più facile da leggere e comprendere successivamente.
Assets:Invest:STOCK -10 STOCK {100.00 USD} @ 110.00 USD ; Gain: 10%
- Debugging: Se incontri errori o comportamenti inaspettati, Beancount fornisce strumenti per ispezionare lo stato del tuo inventario.
-
Esamina lo Stato dell'Inventario: Usa
bea doctor context main.beancount 42per ispezionare la transazione alla riga 42, inclusi i suoi movimenti e i saldi dei conti interessati. Sostituisci il nome del file e il numero di riga con la transazione che vuoi esaminare.Sostituisci
<LINENO>con il numero di riga subito dopo una transazione per vedere il suo effetto. -
Verifica l'Abbinamento dei Lotti: Lo strumento
bea checkvalida l'intero file. Rileverà eventuali errori di registrazione, come abbinamenti di lotti ambigui in modalitàSTRICT.