On Tue, Mar 28, 2017 at 8:09 PM Martin Blais <[email protected]> wrote:
> 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. > It totally was me who asked for this change. I hadn't realized how many other problems it would have solved for me! ;) > > 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: > > https://bitbucket.org/blais/beancount/src/b26118a59cf2be4b697893e144ca6319fad009bf/src/python/beancount/query/query_env.py?at=default&fileviewer=file-view-default#query_env.py-619 > > Here are the shell function implementations: > > https://bitbucket.org/blais/beancount/src/b26118a59cf2be4b697893e144ca6319fad009bf/src/python/beancount/query/query_env.py?at=default&fileviewer=file-view-default#query_env.py-366 > > 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: > > https://bitbucket.org/blais/beancount/src/b26118a59cf2be4b697893e144ca6319fad009bf/src/python/beancount/core/convert.py?at=default&fileviewer=file-view-default#convert.py-185 > > > 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 would have made the same decision you did. It simplifies the types of queries that I've been trying to do (take all my assets and convert them into a single currency at market value) without having to make the query too complicated. That being said, I don't have multiple operating currencies without direct currency conversions. > > I hope this helps, > It helps so much! > > > > > > On Mon, Mar 27, 2017 at 10:52 AM, Jason Chu <[email protected]> wrote: > > I learned recently that bean-query has a value() function that returns > market value of a position (contrary to the Beancount - Query Language > <https://docs.google.com/document/d/1s0GOZMcrKKCLlP29MD7kHO4L88evrwWdIO0p4EwRBE0/edit#heading=h.glx9uq8ceis> > docs). > > I'm trying to write a query that sums all the positions of all my > retirement accounts and converts it to one currency. I have CAD, USD, and > commodities that convert to either of those two currencies. > > My previous query was something like this: > > select convert(convert(sum(position), 'CAD'), 'USD') where account ~ > 'Assets:(Awesome|Regexp)' > > Which handled the case where I only had commodity -> CAD and commodity -> > USD prices. Turns out that dropping the inner CAD conversion is no longer > necessary (when did that change?) > > Either way, I assumed that convert used the cost basis and didn't worry at > all about market value. > > If I write a query like this: > > select value(position) where account ~ 'Assets:(Awesome|Regexp)' > > I get what I assume is the market value of all of these inventories. If I > wrap it in a convert(..., 'USD'), I end up with the same result as the > previous queries. Is convert doing a market value conversion? > > If I convert from CAD to USD by hand, the numbers are reasonably close > together, so I think that's what's happening. > > Either way, this seems to have changed from previous times I've run the > queries, so any help would be appreciated. > > -- > You received this message because you are subscribed to the Google Groups > "Beancount" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to [email protected]. > To view this discussion on the web visit > https://groups.google.com/d/msgid/beancount/CAFFHUgtCyRT-bB64e5W-PZgccwJtf8hnvf%2B8ufKnJVoSBhoyAw%40mail.gmail.com > <https://groups.google.com/d/msgid/beancount/CAFFHUgtCyRT-bB64e5W-PZgccwJtf8hnvf%2B8ufKnJVoSBhoyAw%40mail.gmail.com?utm_medium=email&utm_source=footer> > . > For more options, visit https://groups.google.com/d/optout. > > -- > You received this message because you are subscribed to the Google Groups > "Beancount" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to [email protected]. > To view this discussion on the web visit > https://groups.google.com/d/msgid/beancount/CAK21%2BhO03GbtApVregijtqO3KK-HDMve0C_bJkOJ-f8tE%2BshvA%40mail.gmail.com > <https://groups.google.com/d/msgid/beancount/CAK21%2BhO03GbtApVregijtqO3KK-HDMve0C_bJkOJ-f8tE%2BshvA%40mail.gmail.com?utm_medium=email&utm_source=footer> > . > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Beancount" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/beancount/CAFFHUgvDTdHQ0%2BMX2Bnqs3PY4zgJhEEcZ9qtznazjAV9HguRhQ%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
