For a while this was really messy and IIRC you (or someone else?) requested a cleanup of those functions so that they could be reused somewhere else. I don't recall changing the semantics but I did go through the entire codebase and refactored the very many instances of homegrown and slightly varying conversions to a single "beancount.core.convert" module, which is now the canonical place these things occur. This really was getting out of hand and frankly driving me nuts as well, I had never properly spent time to clean this up. Now it's clean. So that's the history.
The current (and hopefully neverchanging) status of this is that the shell's VALUE() functions map to convert.get_value(), while the shell's CONVERT() functions map to convert.convert_*().
Here are the mappings:
Here are the shell function implementations:
The conversion functions are here:
https://bitbucket.org/blais/beancount/src/b26118a59cf2be4b697893e144ca6319fad009bf/src/python/beancount/core/convert.py?at=default&fileviewer=file-view-default#convert.py-100
The main different between VALUE and CONVERT is that VALUE makes a conversion into the known cost currency (of a position with a non-null cost field), while CONVERT accepts any destination currency. For CONVERT, if the destination currency != its cost currency and no direct conversion can be found in the price database, it attempts to convert to cost first, then to convert that cost value to the destination currency. See logic here:
Maybe this is easier to follow with an example.
Say, you have a position of 100 IMO {40.00 CAD} and the current price of IMO is 41.00 USD.
The value of the position should be 4000.00 CAD.
The conversion of the position to CAD should also be 4000.00 CAD.
The conversion of the position to USD should fail.
Say the price database contains a price for IMO in USD, that is IMO = 30.76 USD.
The conversion would succeed, calculating 100 IMO * 30.76 USD = 3076 USD
Say the price database INSTEAD contained only an exchange rate, that is a price for USD = 1.3 CAD
The conversion would make the attempt above, fail, then convert to CAD = 4000.00 CAD, and finally convert CAD to USD calculating 4000 / 1.3 = 3076 USD.
If both the rates are present, the direct conversion would be preferred.
(I hesitated when I made that decision. Should I keep it as simple as possible and fail many times a conversion would seem to be naturally possible, or make it a little bit smarter and attempt to convert through the cost for convenience? I went for the latter. Somebody else suggested going even further and attempting all the implied rates through any other currency in the price database but I decided against that, because it adds ambiguity and an implementation isn't straightforward. It's nice to keep things simple. One normally would maintain price conversions between their operating currencies so this works well IMO.)
I hope this helps,