Salta al contenuto principale

Gestione dell'Inventario

Impara come gestire efficacemente l'inventario in Beancount, concentrandoti sul tracciamento di asset come azioni e valute, comprendendo il costo di acquisizione e calcolando le plusvalenze per una migliore performance del portafoglio.

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

  1. 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
  2. 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:

  1. 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 USD

    Qui, compriamo 50 unità di STOCK al costo per unità di $25,00 USD. Questo crea un lotto nel conto Assets:Invest:STOCK.

  2. 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 USD

    In questa transazione, stiamo vendendo 25 unità di STOCK dal 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 AmbiguousMatchError invece 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:Gains

Si 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:Gains

Beancount 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:Gains

Questo 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:Gains

Carica senza errori e registra un guadagno totale di $1.400,00, suddiviso come segue:

ContoMetodoLotto registratoBase costoGuadagno realizzatoLotti rimanenti
Assets:Broker:FifoFIFOlotto A, 2024-01-10$100,00$500,0010 @ $120,00, 10 @ $90,00
Assets:Broker:LifoLIFOlotto C, 2024-03-10$90,00$600,0010 @ $100,00, 10 @ $120,00
Assets:Broker:HifoHIFOlotto B, 2024-02-10$120,00$300,0010 @ $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:Gains

Questo 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:Gains

Nel momento in cui quella riduzione deve essere registrata, il caricatore si interrompe con:

AVERAGE method is not supported

Non 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. Con FIFO, LIFO o HIFO è il lotto corrispondente più vecchio, più nuovo o più costoso; con il STRICT predefinito è un AmbiguousMatchError a 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:

  1. Annotazione del Prezzo (Conversione): Usa @ per convertire da una valuta all'altra.

    Assets:Forex     1000 USD @ 0.85 EUR
  2. Cost Basis (Acquisizione): Usa {} quando acquisti un bene per stabilirne il costo.

    Assets:Invest    10 STOCK {100.00 USD}
  3. 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 USD

    Questa voce vende 10 STOCK dal lotto che è costato $100.00 ciascuno, a un prezzo di vendita di $105.00 ciascuno.

Regole per l'Uso del Prezzo

  1. 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.
  2. 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

  1. 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  VFIAX

    Evita di mescolare azioni o fondi diversi nello stesso conto, poiché complica la gestione dell'inventario. La lista delle commodity su open fa sì che Beancount rifiuti una registrazione errante invece di mescolare silenziosamente due inventari.

  2. 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%
  1. 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 42 per 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 check valida l'intero file. Rileverà eventuali errori di registrazione, come abbinamenti di lotti ambigui in modalità STRICT.

Fonte: https://beancount.io/it/docs/Basics/inventories