Управление числовой точностью является краеугольным камнем двойной бухгалтерии. В цифровом учете, особенно при работе с несколькими валютами, ценами акций и дробными долями, небольшие расхождения при округлении могут быстро привести к досадным ошибкам балансировки. Beancount предоставляет сложную, но интуитивно понятную систему для обработки точности и установки допустимых отклонений. Это руководство расскажет вам, как это работает. ⚙️
Основные понятия точности
Основная цель Beancount — гарантировать, что каждая транзакция сбалансирована до нуля. Однако расчеты с участием цен или себестоимости часто дают результаты с большим количеством десятичных знаков, чем практично записывать. Система допусков позволяет учитывать небольшие, приемлемые дисбалансы.
Автоматическое определение допуска
По умолчанию Beancount автоматически определяет требуемый допуск для каждой транзакции. Это определение выполняется индивидуально для каждой транзакции и рассчитывается отдельно для каждой участвующей валюты.
Правило простое: допуск равен половине последней значащей цифры чисел, присутствующих в проводках транзакции.
Например, рассмотрим следующую покупку:
2013-04-03 * "Покупка фонда"
Assets:Fund 10.22626 FUND {37.61 USD}
Assets:Cash -384.61 USDBeancount определяет допуски следующим образом:
- Для актива
FUNDчисло10.22626имеет 5 десятичных знаков. Допуск составляет половину последней цифры, то естьFUND. - Для валюты
USDчисло-384.61имеет 2 десятичных знака. Допуск составляет половину последней цифры, то естьUSD.
Правила веса транзакции
При проверке баланса транзакции Beancount рассчитывает «вес» каждой проводки. Правила для этого расчета следующие:
- Простая сумма: Если проводка содержит только сумму (например,
Assets:Cash -100.00 USD), ее вес равен этой точной сумме. - Проводка с ценой: Если проводка содержит цену за единицу (например,
10 FUND @ 38.46 USD), ее вес равенколичество × цена. - Проводка с себестоимостью: Если проводка содержит общую себестоимость (например,
10 FUND {384.61 USD}), ее вес равен сумме общей себестоимости. - Себестоимость и цена: Если проводка содержит как общую себестоимость, так и цену за единицу (например,
10 FUND {384.61 USD} @ 38.46 USD), для балансировки используется только общая себестоимость. Цена за единицу рассматривается как комментарий или памятка.
Правила определения точности
Система автоматического определения следует нескольким конкретным правилам:
- Формат числа
- Целочисленные суммы (например,
10 USD) не участвуют в определении точности. - Максимальный допуск, который может быть определен автоматически, составляет
0.05единицы (например, из числа10.1 USD). Если вам нужен больший допуск, вы должны указать его вручную. - Себестоимость и цены (например,
{37.61 USD}) исключаются из определения допуска. Используются только основные суммы проводок. - Если проводки для одной и той же валюты имеют разную точность (например,
-10.10 USDи5.123 USD), Beancount использует самый грубый (наибольший) допуск. В этом случае он будет основан на-10.10 USD, что дает допуск вUSD.
-
Обработка по умолчанию Вы можете установить глобальный допуск по умолчанию или допуск по умолчанию для конкретной валюты, если в транзакции нет чисел с десятичными знаками, из которых его можно определить.
; Устанавливает допуск по умолчанию для всех валют без явных правил option "inferred_tolerance_default" "*:0.001" ; Устанавливает конкретный допуск по умолчанию для USD option "inferred_tolerance_default" "USD:0.003" -
Множитель допуска Вы можете глобально увеличить все определенные допуски на фиксированный множитель. Это полезно для ослабления проверок во всем файле без изменения каждой транзакции. Множитель
1.2увеличивает все определенные допуски на 20%.option "inferred_tolerance_multiplier" "1.2" -
Определение на основе себестоимости Обычно себестоимость игнорируется при определении допуска, но вы можете указать 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.271 RGAGX с пользовательским допуском ±0.01 RGAGX
2015-05-08 balance Assets:Fund 4.271 ~ 0.01 RGAGXЗдесь утверждение будет выполнено, если рассчитанный баланс находится между и 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В этой транзакции . Дисбаланс транзакции составляет USD. При включенной опции округления Beancount внутренне обрабатывает ее как:
2013-02-23 * "Покупка"
Assets:Invest 1.245 RGAGX {43.23 USD}
Assets:Cash -53.82 USD
Equity:RoundingError -0.00135 USD ; Добавлено автоматическиОпределенная точность чисел
Beancount также может использовать настройки допуска для автоматического округления чисел еще до их вставки в структуры данных книги.
-
Допуск не указан: Если допуск не определен, числа используются с полной точностью. Округление не происходит.
-
С допуском по умолчанию: Если вы установите допуск по умолчанию, числа будут квантоваться до этого уровня.
option "default_tolerance" "USD:0.001"С этой настройкой число, подобное
53.82135 USD, будет округлено и сохранено как53.821 USD. -
Со счетом округления: Если активны и допуск по умолчанию, и счет округления, Beancount квантует число и фиксирует остаток.
option "default_tolerance" "USD:0.01" option "account_rounding" "Equity:RoundingError"Число, подобное
53.82135 USD, будет сохранено как53.82 USD, а остаток-0.00135 USDбудет проведен по счетуEquity:RoundingError.
Детали реализации
Несколько технических моментов проясняют, как Beancount достигает такой надежности.
-
Представление чисел: Beancount использует модуль
decimalиз Python, а не числа с плавающей точкой. Это позволяет достичь точности до 28 десятичных знаков и избежать ошибок двоичного представления, обычных для чисел с плавающей точкой. -
Класс DisplayContext: Этот внутренний класс обрабатывает все форматирование чисел для отображения. Он учитывает настройки точности для конкретной валюты и может форматировать вывод с выравниванием столбцов и запятыми.
-
Точность против допуска: Важно различать эти два понятия:
- Точность относится к формату отображения числа (сколько десятичных знаков показывается).
- Допуск — это допустимое отклонение от баланса, используемое во время проверок.
Лучшие практики ✨
Вот несколько практических рекомендаций для управления точностью в вашей книге.
Первоначальная настройка
Для большинства новых книг это надежная начальная конфигурация:
; Разумное значение по умолчанию для большинства валют (например, 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 не имеет десятичных знаков).
Стратегия миграции
При применении этих концепций к существующей, запутанной книге:
- Начните с щедрого глобального допуска (например,
*:0.05) и высокого множителя, чтобы файл прошел проверку. - Постепенно ужесточайте допуски и исправляйте возникающие ошибки.
- Добавьте явные цифры к суммам в проблемных транзакциях, чтобы определение могло работать.
- Следите за балансом счета округления. Большой или быстро растущий баланс может указывать на системную проблему, требующую расследования.