본문으로 건너뛰기

Beancount의 정밀도 및 허용 오차 안내

수치 정밀도 관리는 복식 부기의 초석입니다. 디지털 부기에서 특히 여러 통화, 주가 및 소수 주식을 처리할 때 작은 반올림 불일치가 발생하면 잔액 오류가 발생하여 좌절감을 느낄 수 있습니다. Beancount는 정밀도를 처리하고 허용 가능한 오차를 설정하기 위한 정교하면서도 직관적인 시스템을 제공합니다. 이 가이드에서는 작동 방식을 안내합니다. ⚙️

핵심 정밀도 개념

정밀도

Beancount의 주요 목표는 모든 거래의 잔액이 0이 되도록 하는 것입니다. 그러나 가격 또는 비용과 관련된 계산은 실제로 기록하기에 실용적인 것보다 더 많은 소수 자릿수를 가진 결과를 생성하는 경우가 많습니다. 허용 오차 시스템은 작고 허용 가능한 불균형을 허용합니다.

자동 허용 오차 추론

기본적으로 Beancount는 각 거래에 필요한 허용 오차를 자동으로 추론합니다. 이 추론은 모든 거래에 대해 개별적으로 처리되고 관련된 각 통화에 대해 별도로 계산됩니다.

규칙은 간단합니다. 허용 오차는 거래 게시물에 있는 숫자의 마지막 유효 자릿수의 절반입니다.

예를 들어 다음 구매를 고려해 보겠습니다.

2013-04-03 * "펀드 구매"
Assets:Fund 10.22626 FUND {37.61 USD}
Assets:Cash -384.61 USD

Beancount는 다음과 같이 허용 오차를 추론합니다.

  • FUND 상품의 경우 숫자 10.22626은 소수점 5자리를 가집니다. 허용 오차는 마지막 자릿수의 절반이므로 0.00001÷2=0.0000050.00001 \div 2 = 0.000005 FUND입니다.
  • USD 상품의 경우 숫자 -384.61은 소수점 2자리를 가집니다. 허용 오차는 마지막 자릿수의 절반이므로 0.01÷2=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 USD5.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 어설션에 대한 허용 오차는 금액의 소수 자릿수에서 추론됩니다.

; 잔액이 ±0.0005의 허용 오차로 4.271 RGAGX인지 어설션
2015-05-08 balance Assets:Fund 4.271 RGAGX

; 잔액이 ±0.005의 허용 오차로 4.27 RGAGX인지 어설션
2015-05-08 balance Assets:Fund 4.27 RGAGX

계산된 잔액은 이 범위 내에 있어야 합니다. 두 번째 예제의 경우 4.2654.2654.2754.275 사이의 모든 잔액은 검사를 통과합니다.

명시적 허용 오차

추론된 허용 오차가 적합하지 않은 경우 물결표(~) 문자를 사용하여 명시적으로 지정할 수 있습니다.

; 잔액이 ±0.01 RGAGX의 사용자 지정 허용 오차로 4.271 RGAGX인지 어설션
2015-05-08 balance Assets:Fund 4.271 ~ 0.01 RGAGX

여기서 계산된 잔액이 4.2614.2614.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.245×43.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는 Python의 decimal 모듈을 사용하며 부동 소수점 숫자를 사용하지 않습니다. 이를 통해 최대 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. 반올림 계정의 잔액을 모니터링합니다. 크거나 빠르게 증가하는 잔액은 조사가 필요한 시스템 문제를 나타낼 수 있습니다.