Understanding the valuation function and the market function

1,022 views
Skip to first unread message

Jakob Mattsson

unread,
Mar 10, 2016, 8:22:39 AM3/10/16
to Ledger
Hi!

I've read up on the valuation function, but it doesn't seem to behave the way the documentation is describing it.

I have this for example:

P 2016-01-01 £ 1.2 $
P 2016-01-05 £ 1.4 $

2016-01-03
    SomeAsset      £ -100
    SomeExpense    £  100

Now, running ledger balance -X $ gives me 

$ -140  SomeAsset

$  140  SomeExpense


Just as the documentation mentions, I don't want the expense to be re-valuated to $140 on the fifth; I want it to remain $120, which was the price is $ at the time of the purchase. So, to quote the docs: 


Or how about never re-valuating commodities used in Expenses, since they cannot have a different future value:

= /^Expenses:/
    ; VALUE:: market(amount, post.date, exchange)

This says the future valuation is the same as the valuation at the time of posting. post.date equals the posting’s date, while just ’date’ is the value of --now DATE (defaults to today).



Ok, so I try this inline, to make it as simple as possible:

P 2016-01-01 £ 1.2 $
P 2016-01-05 £ 1.4 $

2016-01-03
    SomeAsset      £ -100
    SomeExpense    £  100; VALUE:: market(amount, post.date, exchange)

Now running ledger balance -X $ gives me:

$  -140  SomeAsset

$ 12000  SomeExpense


The expense has clearly been computed using 1.2 rather than 1.4, which is what I wanted, but it's 100 times too large! Why? I've been fiddling with this for quite a while now and can't understand what is going on.

Thanks you all!

John Wiegley

unread,
Mar 10, 2016, 3:44:23 PM3/10/16
to Jakob Mattsson, Ledger
>>>>> Jakob Mattsson <jakob.m...@gmail.com> writes:

> The expense has clearly been computed using 1.2 rather than 1.4, which is
> what I wanted, but it's 100 times too large! Why? I've been fiddling with
> this for quite a while now and can't understand what is going on.

I think what you want is to add --historical (or -H) to your -X report.

--
John Wiegley GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com 60E1 46C4 BD1A 7AC1 4BA2

Jakob Mattsson

unread,
Mar 19, 2016, 3:58:50 PM3/19/16
to John Wiegley, Ledger
Thanks, -H gives me the output I expected in this example!

Now, the problem is that I don't want to value ALL commodities at their acquisition price, only some of them. I'd like to control it per commodity, per transaction or something like that. The docs makes it sound like "VALUE::" should allow me to do it, but I can't seem to get it to work.

Martin Blais

unread,
Mar 19, 2016, 6:13:27 PM3/19/16
to ledger-cli, John Wiegley
Why are you trying to do this?
Can you provide context... what's the use case?



--

---
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 ledger-cli+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

John Wiegley

unread,
Mar 19, 2016, 7:25:25 PM3/19/16
to Jakob Mattsson, Ledger
>>>>> Jakob Mattsson <jakob.m...@gmail.com> writes:

> Thanks, -H gives me the output I expected in this example! Now, the problem
> is that I don't want to value ALL commodities at their acquisition price,
> only some of them. I'd like to control it per commodity, per transaction or
> something like that. The docs makes it sound like "VALUE::" should allow me
> to do it, but I can't seem to get it to work.

Indeed, the intent of VALUE:: is to let you do that, to any degree of
complexity that you like. However, it's also one of C++Ledger's most recent
features, so expect there to be corner cases I hadn't thought of yet.

Jakob Mattsson

unread,
Mar 19, 2016, 8:33:13 PM3/19/16
to ledge...@googlegroups.com
I spend money in two currencies, as I line and work in two places. I don't want expenses in any of these to be revalued over time in terms of the other and I don't want ledger to report a capital gain on transactions between those two currencies. For this, the --historical flag makes perfect sense.

For actual investments, like my stock and my property, I very much want the opposite. These should be revalued over time and there's a clean capital gain/loss on every such transaction.

The section in the docs called "complete control over commodity prices" (or something like that) lists a lot of different ways to work with this, many of which would solve my use case, but I can't get any of them to work as I don't seem to have understood the valuation-function and the market-function properly.

You received this message because you are subscribed to a topic in the Google Groups "Ledger" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ledger-cli/dc6F-HvZOyE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ledger-cli+...@googlegroups.com.

Martin Blais

unread,
Mar 20, 2016, 4:01:13 PM3/20/16
to ledger-cli, Beancount
On Sat, Mar 19, 2016 at 8:33 PM, Jakob Mattsson <jakob.m...@gmail.com> wrote:
I spend money in two currencies, as I line and work in two places. I don't want expenses in any of these to be revalued over time in terms of the other and I don't want ledger to report a capital gain on transactions between those two currencies. For this, the --historical flag makes perfect sense.

Totally agree.
I'm in a similar situation - multiple countries and currencies - and the correct treatment of currencies is as you describe.


For actual investments, like my stock and my property, I very much want the opposite. These should be revalued over time and there's a clean capital gain/loss on every such transaction. 

The section in the docs called "complete control over commodity prices" (or something like that) lists a lot of different ways to work with this, many of which would solve my use case, but I can't get any of them to work as I don't seem to have understood the valuation-function and the market-function properly.

AFAICT the source of the problem here is that Ledger does not treat currency conversions differently than commodities which have a cost basis (e.g. stocks). I think this is an unfortunate design choice, which puts the onus on the user to dispatch between reporting currencies and stocks separately, because currencies retain a kind of cost basis from the time of their conversion.

Beancount distinguishes between currency conversions and stock purchases explicitly, based on whether the units have a cost basis declared on a posting or not. The result of a conversion, after checking that a transaction balances with the given conversion rate, is just a simple deposit in another commodity, without any memory of the converted commodity's rate of conversion. For example, if you convert dollars into Euros, the resulting deposit in the Euro account is....well, just euros. From there on, there's never a need to identify that this particular Euro in that account was one converted at that particular rate. 

The balances in such a system are of two kinds:
- Simple commodities with no cost basis; these are your currencies. By default they can reported as themselves, with no conversion.
- Commodities held with a cost basis value are usually most conveniently reported at their market value by using the current market price x the number of units held.

For example, you might compute balances and obtain a list of balances like this:

Assets:SBS:Checking        430.00 CHF
Assets:DB:Checking         234.30 EUR
Assets:BofA:Checking       600.45 USD
Assets:Schwab:Investments      30 MSFT {93.40 USD}
Assets:Schwab:Investments      20 MSFT {97.10 USD}
Assets:Schwab:Investments      40 AAPL {182.11 USD}

The first three are in simple commodities with no cost basis. The next two, are two lots of the same commodity (MSFT) at different cost basis. The final one is a single lot of another commodity. This is a perfectly fine report in itself. But say the current prices of the assets held at cost are:

2016-03-20 price MSFT   99.87 USD
2016-03-20 price AAPL  210.11 USD

A slightly better report would convert those to their currency value (in this case USD):

Assets:SBS:Checking         430.00 CHF
Assets:DB:Checking          234.30 EUR
Assets:BofA:Checking        600.45 USD
Assets:Schwab:Investments  4993.50 USD
Assets:Schwab:Investments  8404.40 USD

Note that the cost basis is ignored here, and that the market prices were used. Also note that from an implementor's point-of-view it's very clear which balances should be converted or not.

Furthermore, after obtaining the values of each of these in currencies, you might request a report to convert all of them to a single common reporting currency at the current rate to compare them. Say the current exchange rates are:

2016-03-20 price CHF  1.0342 USD
2016-03-20 price EUR  1.1323 USD

You would obtain this result, all in USD:

Assets:SBS:Checking         444.71 USD
Assets:DB:Checking          265.29 USD
Assets:BofA:Checking        600.45 USD
Assets:Schwab:Investments  4744.00 USD
Assets:Schwab:Investments  7284.40 USD

There should never be a need to specify different dates for different commodities. This makes no sense to me. All we have is at a particular point in time, a list of commodities and their corresponding prices, and possible converted values, all rates at the same date. The system should be able to produce such reports automatically. Being able to distinguish between commodities held at cost and ones without a cost makes it possible to produce sensible reports automatically.

Beancount balance reports have a few remaining flaws: (1) they do not currently use the market value to render the value of a lot directly; a plugin is used to insert the unrealized gains as transactions to produce the correct value; it works, and this has the advantage of automatically inserting the unrealized gains portion on the income statement, but I'd prefer to be more explicit about it and leave that to the reporting space (not sure), and (2) the conversion to a single reporting currency is not implemented (and people want it). Those reports stand to get improved a bit.

But the more important issue to me is that the underlying representation si coherent with how these balances are represented in the real world and nothing in the representation prevents us from addressing the reporting shortfalls described in the previous paragraph. Your bank never maintains the rate of conversion of your deposited currency. And unless the gains are significant and the commodities are used for leveraged trading, noone bothers tracking and reporting capital gains on currency conversions on their tax filing. I've suggested in the past that Ledger adopt the same distinction. AFAICT Ledger's currency conversion syntax (@) and cost basis syntax ({}) are undifferentiated, they have the same effect. I don't understand how their semantics differ, and when I've used it, I've found it confusing that cost bases on converted currencies appear in some reports.

I hope this helps clarify this discussion around market value. It doesn't have to be so complicated: there's a date, and a single set of conversion rates at a particular point in time. Then there's a choice about whether lots are converted to their currency value and perhaps further converted to another currency.



(*) If it's needed to deal with gains resulting from currency conversions, the Trading Accounts (search the mailing-list for a link) method can be used; I'm already handling this automatically in Beancount but I'm planning to make this simpler and give the user more control over these by automating the insertion of Trading Accounts postings transaction by transaction. In any case, this is unlikely to be needed much.

Travis Laporte

unread,
Sep 17, 2016, 11:56:29 AM9/17/16
to Ledger
Were you able to find a workaround for this? I am running into the same issues with this use case.

Jakob Mattsson

unread,
Sep 18, 2016, 8:55:09 AM9/18/16
to Ledger
Actually no :(

Reply all
Reply to author
Forward
0 new messages