Very interesting email, thanks for the discussion Nathan! (comments below)

On Mon, Oct 6, 2014 at 3:31 PM, Nathan Grigg <[email protected]> wrote:

> Sorry to bring up an old topic. I followed this with some interest back
> when we discussed it, but my own thoughts hadn’t yet crystalized, so I was
> silent. Now I have thoughts to share.
>
> Martin Blais:
>
> I think the question should be phrased in terms of what precision you want
> to represent numbers _internally_. Isn't a worthy goal to attempt to
> replicate the same precision as the real-world accounts they represent?
>
>
> I agree. To me, display precision is much less important than the internal
> representation.
>

I beg to differ: to me, internal representation should reflect that is
actually in use by the institution whose accounts we're replicating.


Martin again:
>
> Rounding should occur at the point of calculating the "balance amount",
> that is, the amount that is used to balance against the rest of the
> postings of the transaction.
>
>
> I agree again, but disagree with how this is implemented in both ledger
> and beancount (I am not familiar with hledger). In particular, I think that
> the only way to avoid strange situations is for every transaction to
> balance exactly, as in A+B=0 to the full precision of the internal
> representation.
>
> Let’s ignore the concept of elided values and start by thinking only about
> the whether a transaction balances.
>
> There are two cases.
>
> *Case 1: Single currency. Postings should balance exactly.*
>
> 2014-01-01 * transfer
> Assets:Bank1    $1.00
>         Assets:Bank2   $-1.001
>
> It seems pretty obvious that this should trigger an error. Ledger gets
> this right because it requires all transactions to balance to the maximum
> precision specified in the document (not quite, we’ll get to this later).
> Beancount, with its fixed tolerance, lets this through (Even $-1.01 would
> pass). Even if the tolerance is exposed as an option, you give the user the
> opportunity to screw things up.
>

I like the idea that the tolerance can be inferred automatically from the
smallest digit in the input instead of using a fixed value. I should
implement that in Beancount as well, there's no reason it couldn't do
it.This should be a very easy change to make.

At the moment Beancount uses "0.005" regardless of unit... this is a known
pending issue (I don't have any Japanese users yet I suppose). I've been
thinking that a per-commodity tolerance could be selected instead, i.e., a
map of commodity to tolerance value, but while better, this is also
unsatisfying.

I wonder if inferring like Ledger works in all cases though; consider this
case:

    Assets:Fidelity:Fund        11.27534 FUND {1.2357 USD}
    Assets:Fidelity:Cash       -13.93 USD

The precise cash amount is 13.932937638 USD.
How many digits should this use?

The debited cash is 13.93, this would be the _actual_ amount debited by the
fund manager, so it can't be anything else.
In this example, I would argue that you would want the _minimum_ number of
digits to be used.
(But certainly not the minimum if you're using an integer number of
shares...)

If we can come up with a rule that works well in all cases I'll implement
it.




>
> *Case 2: Multiple currencies.*
>
> 2014-01-01 * buy AAA
> Assets:Investments  2 AAA @ 10.1234 EUR
> Assets:Bank  -20.25 EUR
>
> The 2 AAA and the -20.25 EUR are actual amounts. The quoted rate may have
> been 10.1234, but the truth is, you bought at 10.125 EUR (sucker!)
>
> Note that this need to adjust price due to rounding does not arise solely
> from overprecise pricing, but also when you purchase fractional shares.
>
> 2014-01-01 * buy VPMCX
> Assets:Investments  9.66 VPMCX @ 103.52 USD
> Assets:Bank  1000.00 USD
>
> Again, the $1000 and the 9.66 shares are exact quantities. They do not
> represent something that has been rounded. You do not have an extra,
> invisible 0.0032 USD lying around. It is the $103.52 that is wrong.
>

But is it wrong, really?  Is the cost basis calculated with 103.52 USD or
103.519668737 USD?
Correct or not, I think the bank and govt assume a cost basis calculated
using 103.52 USD, so that's the correct one.

Also, when you calculate your capital gains later, which of the prices
should you use?
Again, I think 103.52 is what you're supposed to use.



So one solution is to simply record the share price you paid instead of the
> share price you were quoted. This is the same as Martin Machlmayr’s
> suggestion to use ‘@@' instead of ‘@'. But as Martin also pointed out,
> there is value in using ‘@‘, namely, your cost basis can match the bank’s
> report, the pricedb gets an accurate market price, and you get an extra
> check that you haven’t mistyped a number.
>
> A different solution is for the program to replace the cost basis that you
> specify with the true cost, as long as it is close enough. But this doesn’t
> solve the problem that you might want to attach the bank-reported cost to
> the posting, or see it in reports.
>

Both of these worry me, as per my other email, because that propagates cost
basis that is unexpectedly exact. I'd rather use the rounded, inexactly
calculated cost basis.


One final solution, and what I have settled on for now, is a rounding
> account. I insert one manually (with elided amount), but the program could
> easily do this for you. It sweeps away whatever is left over, and has
> accumulated 0.12 USD (in expenses) for me so far this year. The alternative
> is that my double-entry accounting ledger is out of balance by 12 cents per
> year. (Maybe not a big deal, but it bugs me.)
>
> The point is, no matter how you decide to round the amounts, you have to
> account for the rounding in some way or accept the fact that your system is
> out of balance.
>
> Note that either of these automated solutions could probably be
> implemented using beancount plugins.
>

Yes, you could.

However, using a plugin you would have to compute each transaction's
balance amounts sum twice, which is somewhat expensive, so if this is a
great solution, I would consider adding it in the interpolation routine
itself to avoid the cost and use the one already computed. I'm not
convinced this should always be done though. (See at the end of this
message.)




*Weird things happening*
>
> If you don’t require each transaction to balance, you easily drift away
> from overall balance. In Ledger:
>
> D 1.00 USD
> 2014-01-01 Test
>     assets  1 CAD @ 1.005 USD
>     liabilities
> 2014-01-02 Test
>     assets  1 CAD @ 1.005 USD
>     liabilities
>
> % ledger bal liabilities
> 2014-01-01 Test                 liabilities               -1.00 USD
>  -1.00 USD
> 2014-01-02 Test                 liabilities               -1.00 USD
>  -2.01 USD
>
> Here is another:
> 2014-01-01 Test
>     assets  1 CAD @ 1.005 USD
>     liabilities  -1.00 USD
> 2014-01-02 Test
>     assets  1 CAD @ 1.005 USD
>     liabilities  -1.00 USD
> 2014-01-03 Test
>     assets  1 CAD @ 1.005 USD
>     liabilities  -1.005 USD
>
> % ledger bal -B
>            3.015 USD  assets
>           -3.005 USD  liabilities
> --------------------
>            0.010 USD
>
> This second example is curious because if you put the third transaction at
> the beginning, the other two now fail to balance, because the precision
> becomes 3 decimal points before they are read, whereas before the precision
> switched from 2 to 3 partway through.
>

Now that... is something that would really bother me. If anything should be
inferred from the precision of the numbers in the input, its effects should
always be only _local_ IMO.



*Eliding postings*
>
> Once you have what it means to balance figured out, it is easy to complete
> a transaction with an elided posting. Simply choose the value that
> minimizes the error. (And then either roll the error into an adjusted price
> or add a rounding transaction.) Obviously, to do this, you would need rules
> about precision, per currency and possibly per account. If you really want
> to, you can have custom rounding rules.
>
> In my experience, though, you will often still get the number wrong,
> because at the end of the day, the bank will do what it does for its own
> reasons. (In my 401k, for example, I contribute a fixed $X to buy Y
> fractional shares at price Z, but X - Y*Z has been as big as 2.5 cents
> because strictly speaking the bank is setting Y = round(X/Z, 3), even
> though I would never think of it that way, or record it that way in my
> ledger.)
>
>
Alright, so here's what I propose:

- I could add an option for the user to insert the name of a rounding
account.
- This option would be empty by default, and the current behaviour would
not change.
- However, if you set an account for it, all transactions with an inexact
balance will receive the balance amount (and perhaps have a new leg
inserted on them automatically).

Would that be a reasonable compromise?
With no account, you get 0.005 looseness (or whatever this becomes if
inference is implemented).
With an account, you get precise balances throughout, but no manual input
is required.

Thoughts?


Thanks for an illuminating discussion! :)





> Nathan
>
>  --
>
> ---
> 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.
>

-- 

--- 
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