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

Посібник з точності та допусків у Beancount

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

Основні концепції точності

precision

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

Автоматичне визначення допусків

За замовчуванням Beancount автоматично визначає необхідний допуск для кожної транзакції. Це визначення обробляється індивідуально для кожної транзакції та обчислюється окремо для кожної задіяної валюти.

Правило просте: допуск – це половина останньої значущої цифри чисел, наявних у проведеннях транзакції.

Наприклад, розглянемо цю покупку:

2013-04-03 * "Купівля фонду"
Assets:Fund 10.22626 FUND {37.61 USD}
Assets:Cash -384.61 USD

Beancount визначає допуски наступним чином:

  • Для товару FUND число 10.22626 має 5 знаків після коми. Допуск становить половину останньої цифри, тобто 0.00001div2=0.0000050.00001 \\div 2 = 0.000005 FUND.
  • Для товару USD число -384.61 має 2 знаки після коми. Допуск становить половину останньої цифри, тобто 0.01div2=0.0050.01 \\div 2 = 0.005 USD.

Правила зважування транзакцій

Під час перевірки балансування транзакції Beancount обчислює "вагу" кожного проведення. Правила для цього розрахунку:

  1. Проста сума: Якщо проведення має лише суму (наприклад, Assets:Cash -100.00 USD), його вага є точно цією сумою.
  2. Цінове проведення: Якщо проведення має ціну за одиницю (наприклад, 10 FUND @ 38.46 USD), його вага – це сума × ціна.
  3. Вартісне проведення: Якщо проведення має загальну вартість (наприклад, 10 FUND {384.61 USD}), його вага – це сума загальної вартості.
  4. Вартість і ціна: Якщо проведення має як загальну вартість, так і ціну за одиницю (наприклад, 10 FUND {384.61 USD} @ 38.46 USD), для балансування використовується лише загальна вартість. Ціна за одиницю розглядається як коментар або примітка.

Правила визначення точності

Система автоматичного визначення дотримується кількох конкретних правил:

  1. Формат числа
  • Цілі суми (наприклад, 10 USD) не впливають на визначення точності.
  • Максимальний допуск, який можна автоматично визначити, становить 0.05 одиниць (наприклад, з числа на кшталт 10.1 USD). Якщо вам потрібен більший допуск, ви повинні вказати його вручну.
  • Вартість і ціни (наприклад, {37.61 USD}) виключаються з визначення допуску. Використовуються лише основні суми проведень.
  • Якщо проведення для однієї валюти мають різну точність (наприклад, -10.10 USD і 5.123 USD), Beancount використовує найгрубіший (найбільший) допуск. У цьому випадку він базуватиметься на -10.10 USD, даючи допуск 0.0050.005 USD.
  1. Обробка за замовчуванням Ви можете встановити глобальний або специфічний для валюти допуск за замовчуванням, якщо транзакція не має чисел із знаками після коми, з яких можна було б його визначити.

    ; Встановлює допуск за замовчуванням для всіх валют без явних правил
    option "inferred_tolerance_default" "*:0.001"

    ; Встановлює певний допуск за замовчуванням для USD
    option "inferred_tolerance_default" "USD:0.003"
  2. Множник допуску Ви можете глобально збільшити всі визначені допуски на фіксований множник. Це корисно для послаблення перевірок у всьому файлі без зміни кожної транзакції. Множник 1.2 збільшує всі визначені допуски на 20%.

    option "inferred_tolerance_multiplier" "1.2"
  3. Визначення на основі вартості Хоча вартість зазвичай ігнорується для визначення допуску, ви можете доручити Beancount використовувати її. Це корисно, коли остаточна сума (наприклад, зняття готівки) є найточнішим числом у транзакції.

    option "infer_tolerance_from_cost" "TRUE"

Твердження балансу

Твердження балансу (balance) використовуються для перевірки того, чи збігається баланс вашого рахунку з відомим значенням на певну дату. Вони також мають пов’язаний допуск.

Основний формат

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

; Підтверджує, що баланс становить 4.271 RGAGX з допуском ±0.0005
2015-05-08 balance Assets:Fund 4.271 RGAGX

; Підтверджує, що баланс становить 4.27 RGAGX з допуском ±0.005
2015-05-08 balance Assets:Fund 4.27 RGAGX

Обчислений баланс повинен потрапляти в цей діапазон. Для другого прикладу будь-який баланс між 4.2654.265 і 4.2754.275 пройде перевірку.

Явні допуски

Якщо визначений допуск не підходить, ви можете вказати його явно за допомогою символу тильди (~).

; Підтверджує, що баланс становить 4.271 RGAGX з користувацьким допуском ±0.01 RGAGX
2015-05-08 balance Assets:Fund 4.271 ~ 0.01 RGAGX

Тут твердження пройде, якщо обчислений баланс знаходиться між 4.2614.261 і 4.2814.281 RGAGX.

Управління заокругленням

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

Відстеження помилок заокруглення

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

Спочатку ввімкніть параметр і відкрийте рахунок:

option "account_rounding" "Equity:RoundingError"
2000-01-01 open Equity:RoundingError

Тепер Beancount автоматично додасть третій компонент до будь-якої транзакції, яка не балансується в межах її допуску, переносячи різницю на Equity:RoundingError.

2013-02-23 * "Купівля"
Assets:Invest 1.245 RGAGX {43.23 USD}
Assets:Cash -53.82 USD

У цій транзакції 1.245times43.23=53.821351.245 \\times 43.23 = 53.82135. Транзакція незбалансована на 0.00135-0.00135 USD. Якщо ввімкнено опцію заокруглення, Beancount внутрішньо обробляє її як:

2013-02-23 * "Купівля"
Assets:Invest 1.245 RGAGX {43.23 USD}
Assets:Cash -53.82 USD
Equity:RoundingError -0.00135 USD ; Автоматично додано

Визначена точність числа

Beancount також може використовувати налаштування допуску для автоматичного заокруглення чисел ще до того, як вони будуть вставлені в структури даних книги.

  1. Не вказано допуск: Якщо допуск не визначено, числа використовуються з їхньою повною точністю. Заокруглення не відбувається.

  2. З допуском за замовчуванням: Якщо ви встановите допуск за замовчуванням, числа будуть квантовані до цього рівня.

    option "default_tolerance" "USD:0.001"

    З цим налаштуванням число, наприклад, 53.82135 USD, буде заокруглено та збережено як 53.821 USD.

  3. З рахунком заокруглення: Якщо одночасно активовано допуск за замовчуванням і рахунок заокруглення, Beancount квантує число та фіксує залишок.

    option "default_tolerance" "USD:0.01"
    option "account_rounding" "Equity:RoundingError"

    Число, наприклад, 53.82135 USD, буде збережено як 53.82 USD, а залишок -0.00135 USD буде перенесено на Equity:RoundingError.

Деталі реалізації

Кілька технічних моментів пояснюють, як Beancount досягає цієї надійності.

  1. Представлення чисел: Beancount використовує модуль decimal Python, а не числа з плаваючою комою. Це дозволяє використовувати до 28 знаків після коми та уникає помилок бінарного представлення, поширених для чисел з плаваючою комою.

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

  3. Точність проти допуску: Важливо розрізняти ці дві концепції:

  • Точність стосується формату відображення числа (скільки знаків після коми відображається).
  • Допуск – це дозволений дисбаланс, який використовується під час перевірок.

Найкращі практики ✨

Ось кілька практичних рекомендацій щодо керування точністю у вашій книзі.

Початкове налаштування

Для більшості нових книг це надійна початкова конфігурація:

; Розумне значення за замовчуванням для більшості валют (наприклад, USD, EUR)
option "inferred_tolerance_default" "*:0.005"

; 10% буфер для всіх визначених допусків
option "inferred_tolerance_multiplier" "1.1"

; Рахунок для збору всього пилу заокруглення
option "account_rounding" "Equity:RoundingError"
2000-01-01 open Equity:RoundingError

Поради щодо усунення несправностей

Якщо ви зіткнулися з помилками балансування:

  • Додайте знаки після коми до суми проведення, щоб створити більш жорстке, більш точне визначення локального допуску.
  • Використовуйте явні допуски (~) у твердженнях balance, які не вдаються через передбачувані розбіжності.
  • Відстежуйте помилки заокруглення на спеціальному рахунку, щоб побачити, де і як часто вони виникають.
  • Розгляньте можливість встановлення специфічних для валюти значень за замовчуванням, якщо ви часто маєте справу з валютами, які мають різні правила (наприклад, JPY не має десяткових знаків).

Стратегія міграції

Під час застосування цих концепцій до існуючої, брудної книги:

  1. Почніть із щедрого глобального допуску (наприклад, *:0.05) і високого множника, щоб файл було перевірено.
  2. Поступово затягуйте допуски та виправляйте помилки, які з’являються.
  3. Додайте явні цифри до сум у проблемних транзакціях, щоб визначення могло виконати свою роботу.
  4. Слідкуйте за балансом рахунку заокруглення. Великий або швидко зростаючий баланс може сигналізувати про системну проблему, яку потрібно дослідити.