メインコンテンツまでスキップ

Beancount における精度と許容誤差のガイド

数値精度を管理することは、複式簿記の基礎です。 デジタル簿記では、特に複数の通貨、株価、端株を扱う場合、小さな丸め誤差がすぐに、フラストレーションのたまるバランスエラーにつながる可能性があります。 Beancount は、精度を処理し、許容できる許容誤差を設定するための、洗練されていながら直感的なシステムを提供します。 このガイドでは、その仕組みについて説明します。 ⚙️

精度に関する主な概念

precision

Beancount の主な目標は、すべての取引がゼロになるようにバランスさせることです。 ただし、価格やコストを含む計算では、記録するのに実用的ではない小数点以下の桁数で結果が生成されることがよくあります。 許容誤差システムを使用すると、小さくて許容できる不均衡を許容できます。

自動許容誤差推論

デフォルトでは、Beancount は各トランザクションに必要な許容誤差を自動的に推論します。 この推論はトランザクションごとに個別に処理され、関係する通貨ごとに個別に計算されます。

ルールは簡単です。 許容誤差は、トランザクションの転記に存在する数値の最後の有効桁の半分です。

たとえば、次の購入を検討してください。

2013-04-03 * "Buy Fund"
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 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 アサーションの許容誤差は、金額の小数点以下の桁数から推論されます。

; 残高が 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

計算された残高は、この範囲内にある必要があります。 2 番目の例では、4.2654.2654.2754.275 の範囲の残高であれば、チェックに合格します。

明示的な許容誤差

推論された許容誤差が適切でない場合は、チルダ (~) 文字を使用して明示的に指定できます。

; 残高が 4.271 RGAGX で、カスタム許容誤差が ±0.01 RGAGX であることをアサートします
2015-05-08 balance Assets:Fund 4.271 ~ 0.01 RGAGX

ここでは、計算された残高が 4.2614.2614.2814.281 RGAGX の範囲内であれば、アサーションは合格します。

丸め管理

計算からの小さな残余が予想され、許容される場合のために、Beancount はそれらを体系的に管理するためのツールを提供します。

丸め誤差の追跡

丸め誤差を自動的に収集するために、特別なアカウントを指定できます。 これにより、ごくわずかな残りの金額を 1 か所にまとめて、トランザクションのバランスを完全に保ちます。

まず、オプションを有効にしてアカウントを開きます。

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

これで、Beancount は、許容誤差の範囲内でバランスが取れていないトランザクションに 3 番目のレグを自動的に追加し、差額を Equity:RoundingError に転記します。

2013-02-23 * "Purchase"
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 * "Purchase"
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. 精度と許容誤差: これら 2 つの概念を区別することが重要です。

  • 精度は、数値の表示形式 (表示される小数点以下の桁数) に関連します。
  • 許容誤差は、検証チェック中に使用される不均衡に対する許容範囲です。

ベストプラクティス ✨

台帳で精度を管理するための実用的な推奨事項をいくつか示します。

初期設定

ほとんどの新しい台帳の場合、これは堅牢な開始構成です。

; ほとんどの通貨 (例: 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. 丸めアカウントの残高を監視します。 大きな残高または急速に増加する残高は、調査が必要なシステム上の問題を示している可能性があります。