On Mon, Jun 23, 2014 at 02:02:57AM -0400, Martin Blais wrote:I've finished going through it only now. I'm affected by one of the
> I've been doing some thinking about improving the booking method used
> in Beancount. In the following document, I summarize the issues with
> inventory booking and list some unsatisfied use cases, identify
> current shortcomings in both Beancount and Ledger (with specific
> examples), list a set of requirements for a better inventory booking
> method and outline a design proposal for an improved method:
>
> https://docs.google.com/document/d/1F8IJ_7fMHZ75XFPocMokLxVZczAhrBRBVN9uMhQFCZ4/
problems you describe, namely the inability to book against the average
cost lot (your "{*}" syntax), and I've found the solution you propose
quite elegant. Ditto for the mechanisms of specifying lots and
resolving incomplete (or "ambiguous", if you wish) lot specifications.
[ In passing: the only way I've found with Ledger to actually find out
the average lot price is to first do
"ledger bal Stocks -l 'commodity == XXX'", then redo the same adding
"-B", and finally do the division myself. If there is a better way,
I'd be glad to learn about it. ]
I'm left wondering whether average cost basis should be a per account
property, rather than (or maybe: in addition to) something that
auto-magically happen the first time you post using "{*}".
Your main example for average cost basis are tax sheltered accounts. By
definition that is an example of an account-specific property. If that
is a common use case for average cost basis, then it'd make sense to
allow user to declare accounts (or account/commodity pairs, as we
discussed in the customizable rounding thread) as average cost basis.
Those accounts will have the property that they always contain a single
lot, whose cost is updated every time you post something to it,
computing the new average cost.
I wouldn't mind having both the ability to declare accounts as average
cost basis and, for other accounts, automatic fusion at the first
occurrence of "{*}".
I've also added other (minor/editorial) comments to the document itself.
I'm left wondering whether average cost basis should be a per account
property, rather than (or maybe: in addition to) something that
auto-magically happen the first time you post using "{*}".Yes, and I like that too. I think I mentioned adding an attribute to the Open directive somewhere in order to let the user specify the default booking method. I'll add a more explicit section in the proposal about this, with an example.
On Sun, Jul 13, 2014 at 01:27:30PM -0400, Martin Blais wrote:> history of lot additions and So if you have some past history of lot
> That might even be incorrect, I'm not sure. I believe Ledger does not
> reduce lots, it seems to be matching positive and negative lots by
> "grouping" only at the reporting level (I'm not entirely sure about
> this, Zach make a comment on the doc this morning pointing out the
> --lot-prices and --lot-date options, and the behavior seems to point
> that way, e.g., you can "reduce" a lot that does not exist. I should
> go dig in the source code to find out). So if you have some past
> additions and reductions, they might affect the average cost you endI've already witnessed first hand that Ledger does allow you to reduce
> up with using your method, whereas the current inventory may not
> include all the lots that are being used.
lots that do not exist (going negative). So I'm still not seeing the
risk of incorrect calculation that you hinted at; if you think it's
real, can you try to build one? (or give me some extra hints so that I
can try building it).
2014/06/01 Deposit some cash Equity:OpeningBalances Assets:Investing:Cash $20000 P MSFT $520 2014/07/02 Buy one lot Assets:Investing:Stocks 5 MSFT @ $530 Assets:Investing:Cash 2014/07/02 Buy one lot Assets:Investing:Stocks 5 MSFT @ $540 Assets:Investing:Cash P MSFT $550
mandarine [default]:~/p/beancount$ ledger -f /home/blais/p/ledger-experiments/avgcost1.lgr --no-color bal Stocks 10 MSFT Assets:Investing:Stocks mandarine [default]:~/p/beancount$ ledger -f /home/blais/p/ledger-experiments/avgcost1.lgr --no-color bal Stocks -B $5350 Assets:Investing:Stocks
2014/06/01 Deposit some cash Equity:OpeningBalances Assets:Investing:Cash $20000 2014/06/02 Buy one lot Assets:Investing:Stocks 10 MSFT @ $500 Assets:Investing:Cash 2014/06/03 Sell the lot Assets:Investing:Stocks -10 MSFT @ $510 Assets:Investing:Cash P MSFT $520 2014/07/02 Buy one lot Assets:Investing:Stocks 5 MSFT @ $530 Assets:Investing:Cash 2014/07/02 Buy one lot Assets:Investing:Stocks 5 MSFT @ $540 Assets:Investing:Cash P MSFT $550
mandarine [default]:~/p/beancount$ ledger -f /home/blais/p/ledger-experiments/avgcost2.lgr --no-color bal Stocks 10 MSFT Assets:Investing:Stocks mandarine [default]:~/p/beancount$ ledger -f /home/blais/p/ledger-experiments/avgcost2.lgr --no-color bal Stocks -B $5250 Assets:Investing:Stocks
> > I'm left wondering whether average cost basis should be a per account
> > property, rather than (or maybe: in addition to) something that
> > auto-magically happen the first time you post using "{*}".
On Sun, Jul 13, 2014 at 01:29:10PM -0400, Martin Blais wrote:Your comments made me realize two things:
> Actually, there already is one, right here:
> https://docs.google.com/document/d/1F8IJ_7fMHZ75XFPocMokLxVZczAhrBRBVN9uMhQFCZ4/edit#heading=h.k18hdhviv191
1) what I actually had in mind was the ability to declare *mandatory*
average cost posting for a given account, inhibiting usage of other
booking methods on it. That was not entirely clear to me when I wrote
my previous message, so thanks for making me realize that :)
What it is currently supported by your proposal is only setting the
*default* booking method, but that does not stop others methods from
being used. The invariant I've mentioned in the previous post
(ensuring that only one lot exists) can be guaranteed only by
mandatory booking method.
[ Aside: upon re-reading the above section, the AVERAGE option is
kinda confusing. My understanding of the FIFO and LIFO options is
that they are limited to disambiguating among the lots that have
been selected by your matching algorithms, i.e., they are not
LIFO/FIFO across all lots. OTOH AVERAGE makes sense only when
computed across all lots. So discussing FIFO/LIFO together with
AVERAGE is puzzling. If that is really what you want, this "detail"
should be communicated more clearly, IMHO. ]
2) in terms of design, it'd probably be better to enforce the constraint
of having a single lot as some sort of post-booking check, rather
than overloading even more the expressivity of account declaration
options. (Note: I'm not a Beancounter user, so it's not clear to me
if you've enough expressivity in your checks to encode this. But that
sounds like a better place where to put this.)
On Sun, Jul 13, 2014 at 7:12 PM, Stefano Zacchiroli <za...@upsilon.cc> wrote:
On Sun, Jul 13, 2014 at 01:27:30PM -0400, Martin Blais wrote:2) in terms of design, it'd probably be better to enforce the constraint
of having a single lot as some sort of post-booking check, rather
than overloading even more the expressivity of account declaration
options. (Note: I'm not a Beancounter user, so it's not clear to me
if you've enough expressivity in your checks to encode this. But that
sounds like a better place where to put this.)Yes, this is a good idea. In general I like to perform checks in separate stages, it makes the code a lot nicer and opens up the possibility to shove this check into a plugin that you could enable only if you want it. An easy way to do this without a syntax extension would be to specify a AVERAGE_ONLY booking type, that would barf if the user attempts to use a non-average method and that might trigger the aggregation on additions as well.I'll update the proposal doc.
On Sun, Jul 13, 2014 at 08:08:04PM -0400, Martin Blais wrote:> 2014/06/03 Sell the lotSo, this looks incorrect to me --- or, better, I've learned from
> Assets:Investing:Stocks -10 MSFT @ $510
> Assets:Investing:Cash
folklore and first hand experience that with ledger-cli you should never
reduce without specifying the lot price (or, even better, I should
probably state that the semantics of what happens if you do *not*
specify lot price is unclear to me).
So I've changed this part of your example in:
2014/06/03 Sell the lot
Assets:Investing:Stocks -10 MSFT {$500} @ $510
Assets:Investing:Cash
see attached avgcost3.lgr
* Stefano Zacchiroli <za...@upsilon.cc> [2014-07-14 22:34]:
> So, this looks incorrect to me --- or, better, I've learned fromI'm behind email and haven't read the thread yet, but what happens is
> folklore and first hand experience that with ledger-cli you should never
> reduce without specifying the lot price (or, even better, I should
> probably state that the semantics of what happens if you do *not*
> specify lot price is unclear to me).
that you end up with negative lots. You can see what's going on
behind the scenes by adding --lot-prices:
10 MSFT {$500}
-10 MSFT {$510} Assets:Investing:Stocks
> I'm not so sure I understand your concern. Please be specific (this isIf there is a way to enforce the invariant that there is always only one
> subtle).
> If you use {} to specify the cost, e.g.,
>
> ... -10 MSFT {}
>
> this is only unambiguous in the case the inventory has a single lot for
> that commodity, so that degenerates to the same as the average cost (the
> average cost of one lot is ... just the cost of that lot).
> Otherwise, you'd have to use {*} everywhere there might be ambiguity:
>
> ... -10 MSFT {*}
>
> In which case every lot reduction triggers an aggregation.
lot, then I'd be fine with the {} version. But AFAICT there is no such
way, as when I buy, it will create lots at different prices, right?
So, unless there is a way to automatically trigger lot merge also when
*increasing* a position, it looks like one will have to invariably use
the {*} version because, AFAIU the current state of your spec, lot
merges are performed only when reducing. (Or maybe they also happen upon
increases if you've chosen AVERAGE as the default posting method, but
that was not entirely clear to me upon first read.)