Перейти до основного вмісту

Керовані цінові включення тепер розв'язуються в розміщених журналах

Опубліковано 9 хв. читанняMike ThriftMike Thrift
Керовані цінові включення тепер розв'язуються в розміщених журналах
Зміст цієї сторінки

Ваші активи вже в журналі. Ціни на них — це те, що ви продовжуєте вводити знову й знову.

Ця асиметрія — найстаріша рутина в обліку звичайним текстом. Покупка записується один раз і залишається істинною назавжди: 120 NWRB {41.80 USD, 2024-03-12} фіксує кількість, вартість і дату, і ніщо з того, що станеться потім, не змінює жодного з цих трьох. Ціна — навпаки: правильна на один день, а потім тихо стає неправильною, причому неправильною в такий спосіб, який жодна перевірка балансу ніколи не виявить, бо застаріла ціна все одно балансується ідеально. Власна відповідь Beancount завжди полягала в тому, щоб отримувати їх інструментом і комітити результат, що працює і що багато хто вже автоматизував. Але це все ще скрипт, яким ви володієте, cron-запис, який ви підтримуєте, і файл, який ви зливаєте.

Тепер рушій журналу beancount.io робить це розв'язання сам, для журналів, розміщених у нас. Цей допис про те, що насправді вийшло, чого він свідомо не торкається і — так само важливо — що ще не побудовано.

Що вийшло

Розміщений журнал beancount.io може містити включення, ціль якого — URL, а не ім'я файлу:

; main.bean, in a hosted beancount.io ledger.
;
; The managed line is shown commented out on purpose: upstream `include` takes a
; file glob, so this file still loads if you copy it to your own machine. Only
; the hosted engine resolves the URL form.
 
option "title" "Taxable brokerage"
option "operating_currency" "USD"
 
include "accounts.bean"
; include "https://beancount.io/prices/ACME-USD"
 
include "transactions/purchases.bean"
include "transactions/sales.bean"

include у вихідному Beancount приймає ім'я файлу — «вказаний шлях може бути абсолютним або відносним ім'ям файлу» — це все, що є у специфікації, — тож цінове включення за URL не є чистим Beancount і ніколи не вдає, що ним є. Це поведінка розміщеного рушія, і ось що саме рушій з ним робить:

  • Він матеріалізує потік як віртуальний файл лише для читання. URL розв'язується через власний шлях розв'язання включень рушія, саме там, де опинився б локальний файл, тож кожна директива зберігає реальне розташування джерела. Ваші байти ніколи не перезаписуються. Файл, який ви написали, залишається файлом, який ви написали.
  • Отримане тіло перевіряється як таке, що містить лише ціни. Директиви price, коментарі та чотири дозволені ключі метаданих — price-source, price-kind, observed-at і provisional — і нічого більше. Будь-що поза цим відхиляє все тіло. Часткового приймання немає, тож потік ніколи не може пронести транзакцію у ваші книги.
  • Потоки кешуються як незмінна ревізія плюс рухомий вказівник. Оновлення керується позначкою часу, а не завершенням терміну кешу, що означає, що збій у джерела не може забрати з собою вашу останню добру ревізію. Невдале оновлення ніколи не замінює добру ревізію нічим.
  • Свіжість обчислюється під час читання журналу, а не зберігається: recent, stale або unavailable, поряд із часом спостереження, який повідомив сам потік. Ціна, яку ви не можете датувати, — це ціна, яку ви не можете перевірити.
  • Керовані записи доступні лише для читання. Редагування чи видалення такого запису відхиляється з помилкою, що називає кероване джерело, і вони не враховуються в лімітах директив — потокові не дозволено споживати бюджет вашого журналу.

Усе з цього списку виконується всередині служби розміщеного журналу. Ніщо з цього не змінює того, що означає директива price: вона все ще встановлює курс обміну між базовим товаром і товаром котирування, саме так, як це визначає довідник мови. Завдання рушія — лише підставити правильні, датовані, атрибутовані ціни перед завантажувачем.

Ваша власна ціна завжди перемагає

Це та частина, яка вирішує, чи придатний потік для того, хто ставиться до свого журналу серйозно, тож вона формулюється точно.

Для тієї самої дати й тієї самої пари товарів — а також для оберненої пари — ціна, яку ви написали самі, перемагає над керованим потоком, незалежно від порядку включень.

Не «зазвичай» і не «якщо ви поставите своє включення останнім». Рішення про затінення ухвалюється до побудови карти цін, тож воно не залежить від того, де включення стоїть у файлі. Перемістіть його на початок, перемістіть його в кінець, розділіть його на три файли: відповідь та сама.

; include "https://beancount.io/prices/ACME-USD"   ; hosted-engine form, again shown commented
 
; A price you wrote yourself, for the same date and pair.
; This one wins — above the include or below it, it makes no difference.
2026-09-16 price ACME 93.40 USD

(ACME — це вигаданий емітент із прикладного журналу далі; число вигадане, а не ринкове спостереження.)

Чому саме таке правило, а не протилежне: ціна у вашому власному файлі — це рішення. Це може бути ціна закриття, яку ваш брокер надрукував у виписці, з якою ви звіряєтеся, котирування на ту саму мить для позиції, що мало торгується, або цифра, яку ваш бухгалтер попросив використати. Потік нічого з цього не знає, а система, яка тихо перекриває цифру, створену людиною, перестала бути журналом і стала думкою. Потік заповнює прогалини; він вас не виправляє.

Ціни змінюють оцінку і нічого більше

Друге запевнення є структурним, а не вибором політики, і його варто показати на реальних цифрах, а не просто ствердити. Ось прикладний журнал для криптовалют — датовані лоти, стейкінг, майнінг, позиції DeFi, аірдропи:

Відкрити Приклад обліку криптовалют — партії з датами, стейкінг, DeFi та ейрдропи у новій вкладці

Візьміть один запис із нього. Аірдроп токена управління надходить і записується як дохід за справедливою ринковою вартістю на день, коли він прибуває:

2024-03-20 * "Uniswap" "Receive UNI governance token airdrop"
  Assets:Crypto:Wallet:MetaMask:UNI          50.00 UNI {12.50 USD, 2024-03-20}
  Income:Crypto:Airdrops                      -625.00 USD

Ці $625.00 доходу та базова вартість $12.50 за одиницю, прикріплена до лота, тепер є фактами про 2024-03-20. Кожна цінова директива в журналі — керована, написана від руки чи взагалі відсутня — не торкається ні того, ні того. Ціни змінюють ринкову вартість; вони ніколи не змінюють кількості, базову вартість, грошові потоки, комісії чи реалізовані прибутки. Саме тому ціновий потік — це безпечна річ, яку можна прийняти як допомогу: найгірше, що може зробити неправильна ціна, — це неправильно показати, скільки позиція варта сьогодні, і вона ніколи не може зіпсувати число, яке ви поставите в податковій декларації.

Де неправильна модель цін насправді вводить вас в оману

Прикладний журнал для акцій та ETF демонструє гострішу версію тієї самої думки:

Відкрити Приклад собівартості акцій та ETF — ідентифіковані партії, спліт 4 до 1, продажі конкретних партій у новій вкладці

Він містить дроблення акцій 4-до-1, і дроблення записано правильно — як зміну кількості, що зберігає загальну базову вартість, не торкаючись жодного рахунку доходів:

2025-07-15 * "Broker" "NWRB 4-for-1 share split — quantity change, not income"
  Assets:Brokerage:NWRB                   -120 NWRB {41.80 USD, 2024-03-12}
  Assets:Brokerage:NWRB                    480 NWRB {10.45 USD, 2024-03-12}

Обидві сторони — $5,016.00. Ринкова вартість не змінюється внаслідок дроблення — 120 акцій по $62.00 напередодні, 480 акцій по $15.50 наступного дня, $7,440.00 в обох випадках — і дата придбання у фігурних дужках зберігається, що й робить продаж цих акцій у 2026 році довгостроковим.

Поширена помилка — записати дроблення як подію ціни й покластися на «скоригований на дроблення» ряд, щоб оцінка вийшла правильною. Це працює лише доти, доки кожна ціна, яку ви коли-небудь побачите, скоригована так само. Щойно з'явиться некоригована цифра — старе підтвердження, скриншот, сторонній ряд, який нічого не перераховує, — позиція оцінюється вчетверо дорожче, ніж варта, а кількість акцій у журналі вже не збігається з випискою брокера, тож перевірка на кінець року, яка могла б це виявити, не може спрацювати.

Це справжній аргумент на користь цінового потоку з оголошеним джерелом, оголошеним видом і видимим часом спостереження: не зручність, а знання того, за якою конвенцією обчислено число, яке ви щойно імпортували. Власний ціновий файл прикладного журналу свідомо некоригований і прямо це зазначає, а його дві директиви, що охоплюють дроблення, написані як перевірка, яку можна підтвердити на око.

Одне чесне зауваження щодо переходу в будь-який з цих вбудувань: розміщений переглядач журналу показує залишки рахунків за собівартістю і не пропонує на сторінці жодного керування оцінкою. Журнали вище там, щоб показати вам журнали — лоти, дроблення, продажі конкретних лотів, — а не ринкову оцінку, яку переглядач наразі не відображає. Обидва публічні, і обидва можна клонувати та запускати локально.

Чого тут ще немає

Запис у журналі змін вартий менше ніж нічого, якщо він дозволяє вам повірити в те, що не є правдою, тож ось друга половина, прямо і без жодної дати, прив'язаної до чогось із цього.

  • Цінова кінцева точка не публічна. Анонімний запит до https://beancount.io/prices/<ALIAS> перенаправляється на сторінку входу. Публічного каталогу псевдонімів немає.
  • Тож це не те, що ви можете вставити у свій власний файл сьогодні. Рушій розв'язує включення; маршрут, який він розв'язує, ще не відкритий. Коли він відкриється, це буде окремий запис у журналі змін.
  • Локальний CLI bea не розв'язує URL-включення. Він читає файли з диска, тож URL-включення локально провалюється як файловий шаблон, що не відповідає жодному файлу. Підтримка завантажувача в CLI — це окремо названий наступний крок.
  • Немає поверхні API. Жодного поля REST, GraphQL чи MCP для керованих цін.
  • Немає поверхні панелі керування. Жодного екрана під'єднання потоку і жодної позначки свіжості в інтерфейсі; свіжості, яку обчислює рушій, поки ніде відобразитися.
  • Знімки й експорт не побудовані, як і каталог інструментів чи кінцева точка ручного оновлення.

Що вийшло — це рівень рушія: розв'язання включень, перевірка, кеш ревізій, правило пріоритету та обчислення свіжості. Це та частина, на якій має стояти все інше, і це та частина, яку найважче змінити згодом, тож саме вона пішла першою.

Куди дивитися далі

Обидва журнали вище є частиною галереї прикладів — шести опрацьованих шаблонів, які ви можете клонувати та запускати локально; обидва ці два свідомо постачаються зі статичними, зафіксованими у сховищі ціновими файлами, тож клон, зроблений через два роки, все одно видасть той самий звіт, що й сьогодні. Усе інше, що ми випускаємо, потрапляє до журналу змін.

Якщо ви й досі підтримуєте ціни в актуальному стані власним завантажувачем — це залишається правильною відповіддю для локального журналу, і документація Beancount щодо отримання цін разом із підтримуваним інструментом beanprice — це те, з чого почати.

Залишайте нудну частину нудною

Причина, чому ціни варто автоматизувати, полягає в тому, що вони — єдина частина журналу звичайним текстом, яка занепадає сама по собі. Beancount.io дає вам облік звичайним текстом, який залишається вашим — придатним для аудиту, під контролем версій і ніколи не перезаписуваним за вашою спиною, — і це саме той стандарт, якому керований потік мав відповідати, перш ніж ми випустили хоч один. Почніть безкоштовно і тримайте свої книги у файлах, які ви можете читати.

Поділитися цією статтею

Стежити за цією темою

  • RSS
  • Atom

Джерело: https://beancount.io/uk/blog/2026/09/17/managed-price-includes-hosted-ledgers

Опубліковано: 17 вересня 2026 р.