Booking Methods¶
Overview¶
Booking determines how lot reductions are matched to existing positions when selling or disposing of commodities that have cost basis tracking.
The Problem¶
When you hold multiple lots of the same commodity purchased at different prices, a reduction (sale) must be matched to specific lots:
; Multiple lots acquired
2024-01-01 * "Buy lot 1"
Assets:Stock 10 AAPL {150 USD, 2024-01-01, "lot1"}
Assets:Cash
2024-02-01 * "Buy lot 2"
Assets:Stock 10 AAPL {160 USD, 2024-02-01, "lot2"}
Assets:Cash
; Which lot does this reduce?
2024-03-01 * "Sell"
Assets:Stock -5 AAPL {} ; ← Booking determines this
Assets:Cash
Booking Methods¶
STRICT (Default)¶
Requires explicit lot specification. Ambiguous reductions are errors.
2024-01-01 open Assets:Stock AAPL "STRICT"
; Must specify which lot
2024-03-01 * "Sell from lot 1"
Assets:Stock -5 AAPL {150 USD, 2024-01-01} ; Explicit
Assets:Cash
; ERROR: Ambiguous - multiple lots match
2024-03-01 * "Ambiguous sell"
Assets:Stock -5 AAPL {} ; Error!
Assets:Cash
FIFO (First-In, First-Out)¶
Reduces oldest lots first, ordered by acquisition date.
2024-01-01 open Assets:Stock AAPL "FIFO"
; Reduces lot1 first (oldest)
2024-03-01 * "Sell FIFO"
Assets:Stock -5 AAPL {}
Assets:Cash
; Equivalent to:
; Assets:Stock -5 AAPL {150 USD, 2024-01-01}
LIFO (Last-In, First-Out)¶
Reduces newest lots first, ordered by acquisition date (descending).
2024-01-01 open Assets:Stock AAPL "LIFO"
; Reduces lot2 first (newest)
2024-03-01 * "Sell LIFO"
Assets:Stock -5 AAPL {}
Assets:Cash
; Equivalent to:
; Assets:Stock -5 AAPL {160 USD, 2024-02-01}
HIFO (Highest-In, First-Out)¶
Reduces highest-cost lots first. Minimizes capital gains.
2024-01-01 open Assets:Stock AAPL "HIFO"
; Reduces lot2 first (highest cost: 160 USD)
2024-03-01 * "Sell HIFO"
Assets:Stock -5 AAPL {}
Assets:Cash
NONE¶
Allows reductions without lot tracking. Creates negative positions if needed.
2024-01-01 open Assets:Stock AAPL "NONE"
; Can sell more than you own
2024-03-01 * "Short sell"
Assets:Stock -100 AAPL {} ; Creates -100 AAPL position
Assets:Cash
AVERAGE¶
Uses average cost basis. All lots are merged conceptually into a single position with average cost.
2024-01-01 open Assets:Stock AAPL "AVERAGE"
; lot1: 10 @ 150 = 1500
; lot2: 10 @ 160 = 1600
; Average: 3100 / 20 = 155 USD
2024-03-01 * "Sell average"
Assets:Stock -5 AAPL {} ; Cost basis: 5 × 155 = 775 USD
Assets:Cash
The average cost is recomputed after each acquisition.
Note: See conformance/python-beancount.md for implementation status.
STRICT_WITH_SIZE¶
Like STRICT, but also requires the reduction size to match exactly.
2024-01-01 open Assets:Stock AAPL "STRICT_WITH_SIZE"
; Must specify exact cost AND size must match lot
2024-03-01 * "Sell"
Assets:Stock -10 AAPL {150 USD} ; Must sell entire lot
Assets:Cash
Lot Matching¶
Cost Specification¶
Reduce by matching cost:
; Match by exact cost
Assets:Stock -5 AAPL {150 USD}
; Match by cost and date
Assets:Stock -5 AAPL {150 USD, 2024-01-01}
; Match by cost, date, and label
Assets:Stock -5 AAPL {150 USD, 2024-01-01, "lot1"}
Date Only¶
Reduce by acquisition date:
Assets:Stock -5 AAPL {2024-01-01}
Label Only¶
Reduce by lot label:
Assets:Stock -5 AAPL {"lot1"}
Empty Cost¶
Let booking method decide:
Assets:Stock -5 AAPL {}
Partial Match¶
If specification matches multiple lots, booking method breaks the tie:
2024-01-01 open Assets:Stock AAPL "FIFO"
; If multiple lots have same cost, FIFO picks oldest
Assets:Stock -5 AAPL {150 USD} ; Oldest 150 USD lot
Merge Cost (*)¶
The merge cost operator explicitly combines all lots into a single average-cost lot:
; Before: lot1 (10 @ 150), lot2 (10 @ 160)
2024-03-01 * "Merge lots"
Assets:Stock 0 AAPL {*}
; After: single lot (20 @ 155)
This is used with AVERAGE booking for explicit lot merging, or to convert from per-lot tracking to average cost.
Note: See conformance/python-beancount.md for implementation status.
Lot Splitting¶
When reducing fewer units than a lot contains, the lot is split:
; Have: 10 AAPL {150 USD}
; Sell: 3 AAPL
; After: 7 AAPL {150 USD} ; Remainder
Cross-Lot Reduction¶
A single reduction may span multiple lots:
; Have: lot1 (10 @ 150), lot2 (10 @ 160)
; FIFO sell 15 shares
2024-03-01 * "Sell 15 FIFO"
Assets:Stock -15 AAPL {}
Assets:Cash
; Reduces: 10 from lot1 (exhausted), 5 from lot2
; Remaining: 5 AAPL {160 USD}
Capital Gains¶
Booking affects capital gains calculations:
; Buy at 150, sell at 180
2024-01-01 * "Buy"
Assets:Stock 10 AAPL {150 USD}
Assets:Cash -1500 USD
2024-06-01 * "Sell"
Assets:Stock -10 AAPL {150 USD} @ 180 USD
Assets:Cash 1800 USD
Income:CapitalGains -300 USD ; Gain: (180-150) × 10
Configuration¶
Per-Account¶
2024-01-01 open Assets:Retirement VTSAX "FIFO"
2024-01-01 open Assets:Trading BTC "LIFO"
2024-01-01 open Assets:LongTerm AAPL "HIFO"
Global Default¶
option "booking_method" "STRICT" ; Default for all accounts
Validation Errors¶
The following conditions produce booking-related validation errors:
| Condition | Description |
|---|---|
| No matching lot | Reduction specification doesn't match any existing lot |
| Insufficient units | Not enough units available in matching lots |
| Ambiguous match | Multiple lots match in STRICT mode |
| Negative inventory | Reduction would create negative position (except NONE) |
Booking errors are reported with descriptive messages explaining why the lot matching failed. See conformance/python-beancount.md for error type details.
Examples¶
FIFO Tax-Lot Accounting¶
2020-01-01 open Assets:Brokerage:AAPL AAPL "FIFO"
2020-03-01 * "Buy" ^apple-2020
Assets:Brokerage:AAPL 100 AAPL {75 USD}
Assets:Cash
2021-06-01 * "Buy" ^apple-2021
Assets:Brokerage:AAPL 50 AAPL {130 USD}
Assets:Cash
2024-01-15 * "Sell (FIFO takes 2020 lot)"
Assets:Brokerage:AAPL -75 AAPL {} @ 185 USD
Assets:Cash
Income:CapitalGains:LongTerm ; Held > 1 year
Specific Lot Selection¶
2020-01-01 open Assets:Brokerage:AAPL AAPL "STRICT"
2024-01-15 * "Sell specific lot"
Assets:Brokerage:AAPL -50 AAPL {130 USD, 2021-06-01} @ 185 USD
Assets:Cash
Income:CapitalGains:ShortTerm ; 2021 lot, held < 1 year
Implementation Notes¶
- Track lots with (cost, date, label, units)
- Index lots for efficient matching
- Implement each booking method's ordering
- Handle partial lot reductions
- Validate against negative inventory (except NONE)
- Preserve lot identity through splits