> On Aug 28, 2015, at 8:17 PM, John Ralls <jra...@ceridwen.us> wrote:
> 
> 
>> On Aug 28, 2015, at 6:43 AM, Geert Janssens <geert.gnuc...@kobaltwit.be> 
>> wrote:
>> 
>> On Friday 28 August 2015 08:55:53 John Ralls wrote:
>>> I’ve pushed a feature branch, single-price, to my Github repo
>>> (https://github.com/jralls/gnucash <https://github.com/jralls/gnucash>) 
>>> which covers most of what we’ve
>>> discussed here. I’m still wrestling with the math of how to sensibly
>>> handle rounding itself, so what’s there still uses the hard-coded
>>> 10^6 denom. The branch is from maint because I’d like to put these
>>> changes in 2.6.8.
>>> 
>>> The actual changes are explained in the commit notes. In my limited
>>> testing it appears to work and to provide stability when doing
>>> multiple transactions with the same exchange rate. Please test some
>>> more; I’m sure I didn’t think of every possible variation.
>>> 
>> Hi John,
>> 
>> Thanks for your work on this.
>> 
>> From my first tests and reading the code I have the following observations:
>> 
>> - Let me start with a nit-pick: while reading through the commits I got 
>> confused by the return values of check_account and check_edit. They return 
>> TRUE if the check fails (that is when anything is not ok to continue with a 
>> transfer). From a distance that seems backwards. I usually expect a check 
>> function to return TRUE if all checks pass correctly.
>> 
>> - Next I created a vendor bill, posted it and then paid it in a foreign 
>> currency. This also pops up the transfer dialog. I entered a price and 
>> continued. This added the price to the db (as expected). Next I remove the 
>> payment transaction (from the bank account in the foreign currency) and 
>> issue a new payment via the payment dialog, again in the same foreign 
>> currency. This time however, I enter a to amount directly (ensuring it would 
>> result in a completely different price). Check the price db and note the 
>> existing price hasn't changed.
>> 
>> - The currencies I was playing with are € (from currency) and HKD (to 
>> currency). Before your changes my price db listed a HKD security EUR 
>> currency. On your branch the code now adds a EUR security in HKD currency. 
>> That change is fine in itself. I prefer your normalized way to store 
>> (currency) exchange rates in the db. The issue with this however is that 
>> F::Q won't return an exchange rate for the new price, while it did (and 
>> still does) for the old one.
>> 
>>> As for the math, here’s the conundrum: I proposed earlier to base the
>>> rounding on what would make a 1 scu change in the “to” commodity. The
>>> problems with that idea are that it depends entirely on the amount in
>>> the “from” commodity and that prices are often quoted in fractions of
>>> a scu. For example, the Wall Street Journal website quotes the Yen at
>>> 120.98 to the USD. The Yen’s scu is 1, and the change in the rate to
>>> make a 1¥ change in the value is different if the USD amount is $10
>>> from what it would be if the amount was $1000. Carry that to its
>>> illogical conclusion and we need infinite precision, and that’s
>>> ignoring the fact that we need infinite precision to exactly
>>> represent a lot of rational fractions, but since all the real money
>>> systems use decimal math nowadays that’s not really germane.
>>> 
>>> So I have a new proposal: If the commodities are both currencies,
>>> store exchange rates in the direction where the rate > 1, set the
>>> denominator to 1000, and round-half-up. The price retrieval code
>>> already checks in both directions. If only one of the commodities is
>>> a currency then it’s a price and we store it in the currency with the
>>> denominator = the currency’s scu * 10000.
>>> 
>> See above: the check in both directions is not reliable/borked.
>> 
>>> That leaves commodity-commodity prices. The most common example in
>>> modern life is stock-for-stock exchanges resulting from mergers or
>>> spin-offs. These tend to be one-offs, so no rounding required. Barter
>>> exchange, where one exchanges one commodity for another (e.g. two
>>> bushels of corn for a cow), is similarly fractional rather than
>>> decimal, so again not rounding is appropriate. The third case is the
>>> problem: Bitcoin and similar pseudo-currencies. For maint I think
>>> we’re going to have to leave those prices unrounded as well, but
>>> perhaps for master we should consider creating a separate commodity
>>> category so that users can create commodities that GnuCash treats as
>>> currencies.
>>> 
>> That looks like a very sensible proposal to me.
> 
> Geert,
> 
> Thanks for testing. I agree that the check_foo() semantics are clumsy. I did 
> it that way to avoid negating the return value in the if conditional, but in 
> retrospect that would be clearer, so I’ll flip it.
> 
> Roger that the checks aren’t reliably bidirectional. I’ll dig into that. I 
> hadn’t yet changed anything with regards to which direction prices are 
> recorded, at least not on purpose, so I’ll have to track that down too.
> 
> I coded up the price-rounding algorithm on the flight back today and played 
> with it a little. I think it may need some adjustment.

I’ve pushed more changes to single-price which I think address Geert’s comments 
and some tweaks to maximize significant digit preservation while keeping 
denominators <= 10E6 in most cases. Please test some more!

Regards,
John Ralls
_______________________________________________
gnucash-devel mailing list
gnucash-devel@gnucash.org
https://lists.gnucash.org/mailman/listinfo/gnucash-devel

Reply via email to