Перейти к основному содержимому

Руководство по точности и допускам в Beancount

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

Основные понятия точности

точность

Основная цель 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. Точность vs. Допуск: Важно различать эти два понятия:

  • Точность относится к формату отображения числа (сколько знаков после запятой показано).
  • Допуск — это допустимое отклонение при проверках во время проверки.

Лучшие практики ✨

Вот несколько практических рекомендаций по управлению точностью в вашей книге.

Начальная настройка

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

; Разумное значение по умолчанию для большинства валют (например, 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. Следите за балансом счета округления. Большой или быстро растущий баланс может сигнализировать о системной проблеме, требующей расследования.