BTW, David: as you can see, transfers work fine when fully specified, so this is a matter of convenience. I personally have a vim plugin that uses bean-doctor context to insert the lots.
Curious: is there anything specific to crypto that makes these transfers common? On Tuesday, December 29, 2020 at 9:55:53 PM UTC-8 redst...@gmail.com wrote: > That makes sense. I was thinking of a system where > plugin/booking/interpolation iterate over the same entries until no more > modifications occur. This would involve some thought to prove (a) > commutativity (order doesn't matter), and (b) convergence (no infinite > iterations). > > Reg. the other approach -- i.e., supporting this in core booking algos: > even outside crypto, isn't the philosophy you've put forth "works on > unambiguous source"? Given that, is there a syntax that removes ambiguity? > For example: > *2020-01-01 * "Transfer"* > * Asset:BrokerageA -10 HOOLI {}* > * Asset:BrokerageB: 10 HOOLI {}* > > might be unambiguous for FIFO, LIFO, and STRICT, and arguably for NONE > (and AVG in the future). I.e., identical CostSpec after inverting the sign > of one. I haven't thought deeply about all cases, and anyway, not the most > important thing for v3. > > > > On Tuesday, December 29, 2020 at 9:29:55 PM UTC-8 bl...@furius.ca wrote: > >> Ahh yes, indeed. That's a bit of a problem. I don't have a good solution >> for this yet. >> Simply providing parser-level plugin functionality wouldn't work here, >> because the information for the postings to be transferred is filled in by >> the interpolation code. This is a feature that would need to be applied in >> the booking code, e.g., apply the inventory updates based on the result of >> the transfers. >> >> If this is the defining/key feature that enables working with crypto >> currencies, we could consider supporting this explicitly in the core >> booking algos (in v3, not touching v2 much anymore). >> >> Another idea would be to create a new kind of hook, one that is >> registered from a plugin, e.g. a callback of yours invoked by the booking >> code itself, and whose results applied to a transaction are immediately >> reflected on the state of the affected inventories. Maybe this is the right >> place to do this (I've never had this idea before.) Now, imagine >> generalizing this further to provide and implement all opf the current >> booking mechanisms that are currently built in the core. Call this >> "customizable booking." >> >> >> >> >> On Tue, Dec 29, 2020 at 7:34 PM redst...@gmail.com <redst...@gmail.com> >> wrote: >> >>> This is interesting. From what I can tell: >>> >>> - Beancount's loader proceeds thus: parse -> booking+interpolation >>> -> plugins -> validate. >>> - Therefore, when booking+interpolation is run on your parsed >>> source, the transfer plugin has not had a chance to transform the >>> entries >>> and transfer the lots. >>> - This means, that the reduction in your source (-120 XYZ {}) can't >>> be done because there are no lots to reduce at booking+interpolation. >>> Therefore, it's interpreted as an augmentation (aka buying a short >>> position). (Side note: your "sell" transaction should look like "-120 >>> XYZ >>> {} @@ 480 EUR", or " -120 XYZ {} @ 4 EUR", so it's a reduction, and not >>> an >>> augmentation, and should include an "Income:" posting to capture >>> gain/loss, which you'll need to do anyway once this problem is fixed) >>> >>> AFAICT, this means that the transfer lots plugin won't work without some >>> rethinking of the loader, perhaps allowing for pre-booking plugins. Martin >>> may have other ideas or workarounds though. >>> >>> >>> On Tuesday, December 29, 2020 at 12:23:38 PM UTC-8 David Terry wrote: >>> >>>> Hey, >>>> >>>> Just getting started with beancount and I ran into this problem when >>>> entering some crypto trades. I tried out the transfer_lots plugin in the >>>> beanlabs repo, and I ran into some issues that I don't really understand. >>>> I >>>> can attach cost basis and buy and sell lots within one account without >>>> issue (see here >>>> <https://gist.github.com/xwvvvvwx/75acb4c05dd9b061e8eb46636dbcbc18#file-works-bean>), >>>> >>>> however when I transfer some assets to a new account and then attempt to >>>> see them, I'm running into problems (example file >>>> <https://gist.github.com/xwvvvvwx/75acb4c05dd9b061e8eb46636dbcbc18#file-broken-bean> >>>> ). >>>> >>>> Once there is a transfer involved, beancount no longer seems to reduce >>>> lots according to FIFO, and instead seems to attach a new cost basis to >>>> the >>>> removed lots based on the price at the time of the sale. The output from >>>> running `bean-doctor context` against the last trade in the problematic >>>> file is below. You can see that the sale has resulted in an extra 120 lots >>>> @ 4EUR being deducted from the inventory. Is this a bug, or am I using the >>>> plugin wrong? >>>> >>>> ------------ Balances before transaction >>>> >>>> Assets:Binance:XYZ 100 XYZ {2 EUR, 2020-12-25} >>>> Assets:Binance:XYZ 50 XYZ {3 EUR, 2020-12-25} >>>> >>>> Assets:Binance:EUR >>>> >>>> >>>> ------------ Transaction >>>> >>>> 2020-12-25 * "Binance" "Sell 120 XYZ" >>>> Assets:Binance:XYZ -120 XYZ {4 EUR, 2020-12-25} ; -480 EUR >>>> Assets:Binance:EUR 480 EUR ; 480 EUR >>>> >>>> >>>> Basis: (-480 EUR) >>>> >>>> ------------ Balances after transaction >>>> >>>> Assets:Binance:XYZ 100 XYZ {2 EUR, 2020-12-25} >>>> Assets:Binance:XYZ 50 XYZ {3 EUR, 2020-12-25} >>>> * Assets:Binance:XYZ -120 XYZ {4 EUR, 2020-12-25} >>>> >>>> * Assets:Binance:EUR 480 EUR >>>> >>>> >>>> On Saturday, December 26, 2020 at 5:17:08 PM UTC+1 bl...@furius.ca >>>> wrote: >>>> >>>>> Here, refined further to show how it's leveraging the reduction spec: >>>>> >>>>> https://github.com/beancount/beancount/blob/master/experiments/plugins/transfer_lots_test.py >>>>> >>>>> Maybe this should be part of the builtin plugins. >>>>> Love my little plugin system >>>>> >>>>> >>>>> >>>>> >>>>> On Sat, Dec 26, 2020 at 11:14 AM Martin Blais <bl...@furius.ca> wrote: >>>>> >>>>>> Here, that's what I meant: >>>>>> >>>>>> https://github.com/beancount/beancount/commit/9e6e8f8c3793982a6de5af5321e3026d326f8170 >>>>>> This plugin does what you want (I think). >>>>>> >>>>>> On Sat, Dec 26, 2020 at 10:29 AM Martin Blais <bl...@furius.ca> >>>>>> wrote: >>>>>> >>>>>>> On Wed, Dec 23, 2020 at 11:11 PM Justus Pendleton < >>>>>>> jus...@ryoohki.net> wrote: >>>>>>> >>>>>>>> On Wednesday, December 23, 2020 at 11:03:44 AM UTC+7 >>>>>>>> bl...@furius.ca wrote: >>>>>>>> >>>>>>>>> Short answer is: no, but that's quickly becoming a FAQ from crypto >>>>>>>>> users. >>>>>>>>> It could be designed, but that would be a new feature. >>>>>>>>> >>>>>>>> >>>>>>>> I only use Spec ID booking so I might be missing something but >>>>>>>> isn't moving lots just a small 5 or 6 line python script iterating >>>>>>>> over >>>>>>>> beancount.ops.holdings.get_final_holdings? Would this work or is it >>>>>>>> more >>>>>>>> complicated? I'm not sure that a plugin is simpler/clearer than just >>>>>>>> generating the transaction externally and then inserting it into the >>>>>>>> beancount file. >>>>>>>> >>>>>>> >>>>>>> There's that. OTOH if this is super common for crypto, I'm thinking >>>>>>> we should design it in and make it convenient in the input syntax to >>>>>>> make >>>>>>> such transfers. >>>>>>> >>>>>>> In theory it *could* be done with a plugin today as Ben suggest: I >>>>>>> imagined it more like this though: >>>>>>> >>>>>>> 2020-12-19 T "Binance" "Transfer BTC Coinbase-Pro => Binance" >>>>>>> Assets:Crypto:BTC:Binance 0.2 BTC {} >>>>>>> Assets:Crypto:BTC:Coinbase-Pro >>>>>>> >>>>>>> whereby the plugin would know to select transactions with flag 'T' >>>>>>> (or perhaps a tag given in its config, whatever) and convert the >>>>>>> posting on >>>>>>> Assets:Crypto:BTC:Coinbase-Pro to include all the original matched >>>>>>> reductions. I think this should be doable today actually. >>>>>>> >>>>>>> >>>>>>> >>>>>>> holdings = beancount.ops.holdings.get_final_holdings(entries, >>>>>>>> included_account_types=('Assets',)) >>>>>>>> print(f'{datetime.date.today()} * "ACATS" "Autogenerated lot >>>>>>>> transfer to new account"') >>>>>>>> for h in filter(match, holdings): >>>>>>>> cost_date = None >>>>>>>> print(f' {h.account} -{h.number} {h.currency} {{ {cost_date}, >>>>>>>> {h.cost_number} {h.cost_currency} }}') >>>>>>>> print(f' {args.destination} {h.number} {h.currency} {{ >>>>>>>> {cost_date}, {h.cost_number} {h.cost_currency} }}') >>>>>>>> >>>>>>>> The only problem I see is that get_final_holdings returns a Holding >>>>>>>> tuple that doesn't include the acquisition date. But there's a note in >>>>>>>> the >>>>>>>> code saying the Holding tuple should go away and just be replaced by a >>>>>>>> Position, which would hold the acquisition date. >>>>>>>> >>>>>>> >>>>>>> beancount.ops.holdings is gone in v3. It was superfluous anyway >>>>>>> (well when I started it I wasn't sure if it would start acquiring more >>>>>>> features than just an inventory). Now you can simply aggregate over an >>>>>>> inventory and enumerate its contents (positions). >>>>>>> >>>>>>> -- >>> 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 beancount+...@googlegroups.com. >>> >> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/beancount/58b12132-c3cd-401b-98e5-3035d034846dn%40googlegroups.com >>> >>> <https://groups.google.com/d/msgid/beancount/58b12132-c3cd-401b-98e5-3035d034846dn%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- 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 beancount+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/beancount/2431d4ee-e998-4260-b98e-a8f801d71cd4n%40googlegroups.com.