Система інвентарю Beancount — це потужна функція для відстеження активів, які купуються та продаються з часом, як-от акції, пайові фонди чи іноземні валюти. Вона дозволяє точно відстежувати базу витрат, що є важливим для розрахунку приросту капіталу та розуміння ефективності портфеля. Цей підручник охоплює основні механізми управління запасами у вашому журналі.
Основні поняття
У своїй основі управління запасами обертається навколо відстеження позицій. "Позиція" — це просто кількість певного товару, що утримується на рахунку. Beancount розрізняє два фундаментальні типи позицій.
Типи позицій
-
Проста позиція (без собівартості): Це стандартний запис балансу. Вона представляє кількість товару без будь-якої пов'язаної вартості придбання. Підходить для готівки або простих перевірок балансу.
Assets:Bank:Checking 100.00 USD -
Позиція з базою витрат: Цей тип позиції включає не лише кількість одиниць і товар, але й вартість, за якою їх було придбано. Це основа відстеження запасів. Вартість вказується у фігурних дужках
{}.Assets:Invest:VTSAX 10 VTSAX {100.00 USD, "lot-1"}У цьому прикладі ми утримуємо 10 одиниць
VTSAX. Кожна одиниця була придбана за ціною $100.00 USD. Ця конкретна партія акцій ідентифікується як "лот".
Операції з запасами
Існує дві основні операції, які можна виконувати з інвентарем:
-
Збільшення (додавання до інвентарю): Коли ви купуєте товар, ви збільшуєте свій інвентар. Ви створюєте новий лот із певною кількістю одиниць і базою витрат.
2024-01-15 * "Buy shares" Assets:Invest:STOCK 50 STOCK {25.00 USD, "lot-1"} Assets:Bank:Checking -1250.00 USDТут ми купуємо 50 одиниць
STOCKза ціною $25.00 USD за одиницю. Це створює лот на рахункуAssets:Invest:STOCK. -
Зменшення (видалення з інвентарю): Коли ви продаєте товар, ви зменшуєте свій інвентар. Ви повинні вказати, з якого лоту ви продаєте. Це робиться шляхом надання відповідної інформації у фігурних дужках.
2024-01-20 * "Sell shares" Assets:Invest:STOCK -25 STOCK {25.00 USD} Assets:Bank:Checking 625.00 USDУ цій транзакції ми продаємо 25 одиниць
STOCKз лоту, який був придбаний за $25.00 USD за одиницю.
Методи резервування
Коли ви зменшуєте інвентар, Beancount потрібне правило, щоб вирішити, з якого саме лоту взяти, якщо кілька лотів відповідають зменшенню. Це правило називається "методом бронювання". Ви можете встановити типове значення для всього файлу за допомогою опції або надати окремому рахунку власний метод у директиві open.
Beancount 3.2.3 приймає сім назв методів: STRICT (типовий), STRICT_WITH_SIZE, NONE, FIFO, LIFO, HIFO та AVERAGE. Шість із них реалізовано; AVERAGE розбирається, але видає помилку в момент, коли йому доводиться бронювати зменшення, як показує розділ AVERAGE нижче.
1. STRICT (за замовчуванням)
Метод STRICT є типовим і найбезпечнішим методом бронювання. Він вимагає явної та однозначної відповідності.
2024-01-01 open Assets:Invest:STOCK "STRICT"- Вимагає точної відповідності лоту: Специфікатор вартості запису зменшення (
{...}) повинен ідентифікувати єдиний лот — за вартістю, за датою придбання, за міткою або за будь-якою їх комбінацією. - Помилки при неоднозначних збігах: Якщо специфікатор відповідає більш ніж одному лоту, Beancount видає
AmbiguousMatchErrorзамість того, щоб вгадувати. - Виняток: Якщо зменшення видаляє рівно загальну кількість одиниць, якій відповідає специфікатор, порожній специфікатор (
{}) дозволений, і зменшення розподіляється між цими лотами.
Цей журнал утримує два лоти та продає один із них, називаючи його вартість, що є однозначним:
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Він завантажується без помилок, бронює $300.00 прибутку на Income:Gains і залишає 10 STK {100.00 USD} на рахунку.
Замініть останній запис на порожній специфікатор, і той самий файл зазнає невдачі:
; 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 повідомляє Ambiguous matches for "-10 STK {}" і перелічує кандидатів. Продаж усієї позиції, однак, є прийнятним, оскільки вибирати вже нема з чого:
; 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Це бронює $800.00 прибутку — $3,000.00 надходжень проти $1,000.00 + $1,200.00 бази — і залишає рахунок порожнім. Це властивість самого STRICT, а не те, для чого вам доведеться перемикатися на STRICT_WITH_SIZE.
2. FIFO (перший надійшов — перший витрачений)
Метод FIFO автоматично бронює зменшення проти найстаріших доступних лотів.
2024-01-01 open Assets:Invest:STOCK "FIFO"- Автоматичне розв'язання: Він вирішує неоднозначність, вибираючи найстаріші відповідні лоти.
- Хронологічна відповідність: Ви припускаєте, що продаєте активи, які утримували найдовше. Кілька податкових органів вважають це типовим, коли ви не ідентифікували лот.
3. LIFO (останній надійшов — перший витрачений)
Метод LIFO є протилежністю FIFO. Він бронює зменшення проти найновіших доступних лотів.
2024-01-01 open Assets:Invest:STOCK "LIFO"- Зворотний хронологічний порядок: Він вибирає найнещодавніше придбані відповідні лоти.
- Найновіший, а не найдорожчий: LIFO вибирає лише за датою придбання. Він випадково продає акції з найвищою вартістю, коли ціни зростали, але якщо ваш найновіший лот є найдешевшим — а саме це побудовано показати в прикладі нижче — LIFO реалізує найбільший прибуток, а не найменший. Метод, який завжди продає найдорожчі акції, — це
HIFO, описаний далі.
4. HIFO (Найвища вартість першою)
Метод HIFO бронює зменшення проти найдорожчих доступних лотів, незалежно від їхньої дати.
2024-01-01 open Assets:Invest:STOCK "HIFO"- Відповідність за ранжуванням вартості: Він вибирає відповідні лоти з найвищою базою витрат.
- Найменший реалізований прибуток: Для даної ціни продажу продаж акцій з найвищою вартістю реалізує найменший прибуток (або найбільший збиток). Чи можете ви його використовувати — це питання юрисдикції — у Сполучених Штатах, наприклад, вибір лоту взагалі вимагає конкретної ідентифікації на момент продажу — тож ставтеся до методу як до механізму бухгалтерського обліку та підтверджуйте податковий вибір окремо.
5. Порівняння FIFO, LIFO та HIFO на одних і тих же партіях
Ці три методи відрізняються лише тоді, коли найстаріший, найновіший і найдорожчий лот є трьома різними лотами. Цей журнал влаштовує саме це — лот A є найстарішим, лот C є найновішим, а середній лот B є найдорожчим — і потім продає 10 акцій із трьох рахунків, які відрізняються лише методом бронювання:
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Він завантажується без помилок і бронює $1,400.00 прибутку загалом, розподіленого так:
| Рахунок | Метод | Заброньований лот | База витрат | Реалізований прибуток | Залишок лотів |
|---|---|---|---|---|---|
Assets:Broker:Fifo | FIFO | lot A, 2024-01-10 | $100.00 | $500.00 | 10 @ $120.00, 10 @ $90.00 |
Assets:Broker:Lifo | LIFO | lot C, 2024-03-10 | $90.00 | $600.00 | 10 @ $100.00, 10 @ $120.00 |
Assets:Broker:Hifo | HIFO | lot B, 2024-02-10 | $120.00 | $300.00 | 10 @ $100.00, 10 @ $90.00 |
Рядок LIFO варто розглянути уважніше: він реалізував найбільший прибуток із трьох, тому що найновіший лот був також найдешевшим.
6. STRICT_WITH_SIZE
STRICT_WITH_SIZE — це STRICT плюс один додатковий вирішальний фактор: коли кілька лотів відповідають, але рівно один із них містить точно ту кількість одиниць, яку ви видаляєте, вибирається цей лот.
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Це бронює $210.00 прибутку проти лоту за $120.00. Ідентичний файл із "STRICT" у рядку open зазнає невдачі з Ambiguous matches for "-7 STK {}".
7. AVERAGE (прийнято, але не реалізовано)
AVERAGE — це дійсна назва — і option "booking_method" "AVERAGE", і open … "AVERAGE" розбираються — але за нею в Beancount 3.2.3 немає реалізації. Усе тут завантажується до продажу:
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У момент, коли це зменшення має бути заброньовано, завантажувач зупиняється з:
AVERAGE method is not supportedНе плануйте журнал навколо цього. Якщо вам сьогодні потрібна поведінка середньої вартості, тримайте позицію на рахунку NONE і обчисліть середнє самостійно, або відстежуйте кожен лот і прийміть прибутки на рівні лотів.
8. NONE
Метод NONE повністю вимикає відповідність лотів.
2024-01-01 open Assets:Invest:STOCK "NONE"- Без відповідності лотів: Beancount не намагається зіставляти зменшення зі збільшеннями.
- Дозволяє змішані знаки: Це дозволяє рахунку утримувати одночасно як додатні, так і від'ємні баланси одного товару. Ця поведінка схожа на те, як інструмент командного рядка Ledger обробляє товари.
Специфікація лоту
"Лот" — це конкретний блок товару, придбаний у певний час за певною ціною. Коли ви створюєте або зменшуєте позицію, ви можете детально вказати її атрибути лоту.
Повна специфікація
Коли ви збільшуєте інвентар (купуючи), ви можете вказати до трьох атрибутів для лоту, розділених комами всередині однієї пари фігурних дужок:
Assets:Invest:STOCK 10 STOCK {100.00 USD, 2024-01-15, "lot-identifier"}100.00 USD— база витрат, виражена за одиницю.2024-01-15— дата придбання. Beancount заповнює її з дати транзакції, коли ви її пропускаєте, тому повідомлення про помилки вище показують дату на кожному лоті."lot-identifier"— необов'язкова текстова мітка.
Хоча всі три є необов'язковими, надання принаймні бази витрат є стандартною практикою. Фігурні дужки повинні залишатися в одному рядку, а коментарі в журналі починаються з ;, ніколи з #.
Методи збігання
Коли ви зменшуєте інвентар (продаючи), ви використовуєте той самий синтаксис, щоб вказати, з якого лоту(ів) продавати.
-
Відповідність за вартістю: Це найпоширеніший метод.
Assets:Invest:STOCK -5 STOCK {100.00 USD} -
Відповідність за датою: Якщо вартості ідентичні, ви можете усунути неоднозначність за допомогою дати придбання.
Assets:Invest:STOCK -5 STOCK {2024-01-15} -
Відповідність за міткою: Мітки забезпечують безпомилковий спосіб ідентифікувати лот.
Assets:Invest:STOCK -5 STOCK {"lot-identifier"} -
Залиште лот методу бронювання: Порожній набір фігурних дужок
{}не називає жодного лоту, тож метод бронювання рахунку вибирає. ЗаFIFO,LIFOабоHIFOце найстаріший, найновіший або найдорожчий відповідний лот; за типовимSTRICTцеAmbiguousMatchError, якщо тільки зменшення не спорожнює відповідні лоти точно.Assets:Invest:STOCK -5 STOCK {}
Обробка цін
Важливо розуміти різницю між базою витрат ({}) і ціною (@). Вони служать різним цілям і не є взаємозамінними.
Ціна проти собівартості
{cost}: Визначає вартість придбання активу. Вона є частиною самого лоту інвентарю та використовується для бронювання зменшень і розрахунку приросту капіталу.@ price: Анотація, яка фіксує ринкову ціну на момент транзакції. Вона використовується для конвертації валют або для зазначення ринкової вартості на певну дату.
Ось три сценарії:
-
Анотація ціни (конвертація): Використовуйте
@для конвертації з однієї валюти в іншу.Assets:Forex 1000 USD @ 0.85 EUR -
База витрат (придбання): Використовуйте
{}при купівлі активу, щоб встановити його вартість.Assets:Invest 10 STOCK {100.00 USD} -
Обидва (продаж із записом ціни): При продажу активу використовуйте
{}для ідентифікації лоту, що продається, і@для запису ціни продажу. Це дозволяє автоматично розрахувати приріст капіталу.Assets:Invest -10 STOCK {100.00 USD} @ 105.00 USDЦей запис продає 10
STOCKз лоту, який коштував $100.00 кожен, за ціною продажу $105.00 кожен.
Окрема директива price надає довідкові дані для ринкової оцінки. Живі ціни можуть підтримувати ці директиви для підтримуваних активів у розміщених журналах. Оновлення залишає ваші лоти, метод бронювання, витрати на придбання та зафіксовані надходження від продажу без змін.
Правила використання ціни
- Анотації цін (
@) не впливають на те, який лот бронюється. Відповідність лотів обробляється виключно базою витрат ({}) і методом бронювання рахунку. - Символ
@використовується лише для:
- Конвертації валют.
- Запису ринкової вартості активу на момент транзакції.
- Надання ціни продажу для розрахунку приросту капіталу.
Конфігурація
Ви можете налаштувати методи бронювання глобально або на рівні окремого рахунку.
Глобальний метод обліку
Ви можете встановити типовий метод бронювання для всього вашого файлу Beancount за допомогою директиви option.
option "booking_method" "STRICT"Прийнятними значеннями є "STRICT" (типове, коли ви нічого не встановлюєте), "STRICT_WITH_SIZE", "NONE", "FIFO", "LIFO", "HIFO" та "AVERAGE". Будь-який інший рядок відхиляється під час завантаження з Error for option 'booking_method'. "AVERAGE" приймається тут і в open, але бронювання зменшення за ним зазнає невдачі, як показує розділ AVERAGE вище.
Індивідуальне перевизначення для рахунку
Часто корисно мати різні методи для різних рахунків. Наприклад, ви можете захотіти FIFO для пенсійного рахунку, але STRICT для оподатковуваного брокерського рахунку, щоб переконатися, що ви продаєте конкретні податкові лоти. Ви можете встановити метод бронювання при відкритті рахунку.
2024-01-01 open Assets:Retirement:401K "FIFO"
2024-01-01 open Assets:Taxable:Stock "STRICT"Кращі практики
-
Організація інвентарю: Щоб підтримувати ваш журнал чистим і простим, настійно рекомендується використовувати окремі рахунки для кожного унікального товару, який ви утримуєте, і обмежувати кожен із них цим товаром у його директиві
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Уникайте змішування різних акцій або фондів на одному рахунку, оскільки це ускладнює управління запасами. Список товарів у
openзмушує Beancount відхилити зайвий запис замість того, щоб мовчки змішати два інвентарі. -
Управління лотами:
-
Використовуйте змістовні мітки для лотів, особливо для конкретних транзакцій, як-от збір податкових збитків або надання акцій співробітникам.
Assets:Invest:STOCK 10 STOCK {100.00 USD, "tax-loss-harvest-2024"} -
Документуйте свої угоди коментарями. Це робить ваш журнал легшим для читання та розуміння згодом.
Assets:Invest:STOCK -10 STOCK {100.00 USD} @ 110.00 USD ; Gain: 10%
- Налагодження: Якщо ви зіткнулися з помилками або неочікуваною поведінкою, Beancount надає інструменти для перевірки стану вашого інвентарю.
-
Перегляд стану інвентарю: Використовуйте
bea doctor context main.beancount 42, щоб переглянути транзакцію в рядку 42, включно з її записами та балансами порушених рахунків. Замініть ім'я файлу та номер рядка на транзакцію, яку хочете переглянути.Замініть
<LINENO>на номер рядка одразу після транзакції, щоб побачити її ефект. -
Перевірка відповідності лотів: Інструмент
bea checkперевіряє весь ваш файл. Він виявить будь-які помилки бронювання, як-от неоднозначні відповідності лотів у режиміSTRICT.