On Wed, May 14, 2014 at 6:15 PM, Martin Michlmayr <[email protected]> wrote:

> John and I had a long discussion on IRC a few days ago which resulted
> in a patch that changes the definition of cost in ledger (-B).
>
> The background of the discussion was bugs #712 and #713.
>
> Bug #712 is about Equity:Capital Gains and Equity:Capital Loss
> entries ledger automatically generates that are in my opinion
> incorrect. (<http://bugs.ledger-cli.org/show_bug.cgi?id=712>)
>
> Bug #713 is about strange behaviour with -B after a capital gain or
> loss is made (<http://bugs.ledger-cli.org/show_bug.cgi?id=713>).
>
> As it turns out, both of these issues can be addressed by changing the
> definition of cost in ledger.  In the past, if you bought 1 AAA for
> $10 and then sold it for $12, ledger would take $12 as the cost.  With
> the patch, the cost is $10.  In my opinion, this brings ledger in line
> with accounting expectations.
>

That's how I do it too and it works for me.

I believe I nailed that model right in the v2 rewrite:
Beancount uses "Inventory" objects which contain lots, modified by
postings, by account.
An inventory is a MAPPING of "Lot" to a number of units.
A Lot is a triplet of (currency, cost, lot-date).
(The cost is itself a tuple of (amount, cost-currency)).
Both the cost and lot-date are optional and may be null (None in Python).
If both are null, that's the degenerate case of "just a currency."
That is elegant: operations on currencies and units held at cost work the
same way!
For example, a possible inventory for an account could be this map:

    (USD, None, None) -> 12000
    (GOOG, (512.30, USD), None) -> 50

This would be an inventory with $12,000 in USD and 50 units of GOOG bought
at $512.30 USD each.
(Typically I keep those in separate accounts, but to make this example
demonstrative I put them in the same.)
Selling with a transaction like this:

2014-05-01 * "Selling some Googs"
  Assets:Investments   -10 GOOG {512.30 USD} @ 523.20 USD
  Assets:Investments          5222.00 USD
  Expenses:Commissions   10.00 USD
  Income:CapitalGains

does the following:
- Balancing computes the cost of each posting. For the first leg, this is
-10 x 512.30 = -5123.00 USD. The fourth posting is automatically computed
from the residual of the sum of costs, that is, -5123.00 + 5232.00
- The 523.20 USD price on the first posting is NOT USED in the calculation;
however, it is used in that it creates a data point in the price database
for the rate of "GOOG in USD".

Inventory operations are only allowed to modify IDENTICAL LOTS.
That's the key constraint.
The resulting inventory for the Investments account would be:

    (USD, None, None) -> 6778
    (GOOG, (512.30, USD), None) -> 40

One drawback of this is that the capital gains automatically calculated
that way will include the commissions amount. One way to get around this is
that you can subtract the commissions account when you do use the amounts
to e.g. declare your taxes.

Splits are handled by a transaction that empties all the lots and recreates
them:

2014-05-01 * "Example split"
  Assets:Investments         -40 GOOG {512.30 USD}
  Assets:Investments         80 GOOG {256.15 USD}

Would result in this:

    (USD, None, None) -> 6778
    (GOOG, (256.15, USD), None) -> 80

Another constraint is that if a lot has a cost, booking against a lot may
not result in a negative number (that raises an error). Relaxing that
constraint would allow one to trade in instruments with negative prices,
e.g., spread futures.

Dealing with average cost trading or cost basis readjustments (not
implemented yet) involves joining together multiple lots and recreating new
ones in a way that preserves the total cost in the inventory; with this
data structure / model it's quite obvious how to implement them as basic
operations on an inventory.

I really like the simplicity of this and am wondering if we could make it
even simpler.

Automatic booking against an inventory, e.g. adding automatic FIFO or LIFO,
would require having the date of each lot always inserted in the key of the
inventory items (from the transaction, not from the lot-date field), along
with special rules for selecting which lots a posting is allowed to modify,
essentially ignoring the lot-date from the inventory if the posting does
not specify it. This is partly why I'm considering making the "lot-date"
compulsory and adding a "lot identifier" used to disambiguate booking
against an inventory with multiple matching lots of the same cost with just
differing dates, which would only be required if the posting constrains it
to. One can imagine relaxing the matching rules between a posting and
inventory further to allow one to just specify "-40 GOOG" above, without a
cost, and if unambiguous, to allow it to just select the only lot that is
available.

-- 

--- 
You received this message because you are subscribed to the Google Groups 
"Ledger" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to