hoostus / beancount-asset-transfer-plugin

Plugin for beancount, the plaintext accounting software.
Other
11 stars 2 forks source link

You can't sell asset after transfer. #1

Open aduarterengifo opened 2 years ago

aduarterengifo commented 2 years ago

Hello,

There's a bug where you can't sell an asset after transferring if you didn't have enough of that asset before the transfer.

option "operating_currency" "USD"
option "booking_method" "LIFO"
option "insert_pythonpath" "TRUE"

plugin "asset_transfer.transfer"

2021-01-01 open Assets:Bank:USD                 USD
2021-01-01 open Assets:Brokerage:VTI            VTI
2021-01-01 open Assets:Brokerage:VWO            VWO
2021-01-01 open Assets:New-Brokerage:VWO        VWO
2021-01-01 open Assets:New-Brokerage:VTI        VTI

2021-01-02 * "Buy 1 VTI"
    Assets:Brokerage:VTI            1 VTI {100.00 USD}
    Assets:Bank:USD        

2021-01-15 * "Buy 1 VWO"
    Assets:Brokerage:VWO            1 VWO {1.00 USD}
    Assets:Bank:USD

2021-02-02 * "Buy 2 VTI"
    Assets:Brokerage:VTI            2 VTI {200.00 USD}
    Assets:Bank:USD

2021-02-15 * "Buy 2 VWO"
    Assets:Brokerage:VWO            2 VWO {2.00 USD}
    Assets:Bank:USD

2021-03-03 * "Buy 3 VTI"
    Assets:Brokerage:VTI            3 VTI {300.00 USD}
    Assets:Bank:USD

2021-03-15 * "Buy 3 VWO"
    Assets:Brokerage:VWO            3 VWO {3.00 USD}
    Assets:Bank:USD

2021-03-17 * "Buy 2 VTI"
    Assets:New-Brokerage:VTI      1.5 VTI {150.00 USD}
    Assets:Bank:USD

2021-04-03 custom "transfer" 3.2 VTI Assets:Brokerage:VTI Assets:New-Brokerage:VTI

2021-04-04 * "Sell 3 VTI"
    Assets:New-Brokerage:VTI     -2.9 VTI {} @ 100.00 USD
    Assets:Bank:USD           435.000 USD  

The plugin correctly sets the balances but it doesn't work regardless

------------ Balances before transaction

  Assets:Brokerage:VTI                         1 VTI {100.00 USD, 2021-01-02}
  Assets:Brokerage:VTI                         2 VTI {200.00 USD, 2021-02-02}
  Assets:Brokerage:VTI                         3 VTI {300.00 USD, 2021-03-03}

  Assets:New-Brokerage:VTI                   1.5 VTI {150.00 USD, 2021-03-17}

------------ Transaction

2021-04-03 T "Automatically generated by asset transfer plugin" #in-kind-transfer
  Assets:Brokerage:VTI      -3.0 VTI {300.00 USD, 2021-03-03}  ; -900.00 USD
  Assets:New-Brokerage:VTI   3.0 VTI {300.00 USD, 2021-03-03}  ;  900.00 USD
  Assets:Brokerage:VTI      -0.2 VTI {200.00 USD, 2021-02-02}  ; -40.000 USD
  Assets:New-Brokerage:VTI   0.2 VTI {200.00 USD, 2021-02-02}  ;  40.000 USD

Tolerances: VTI=0.05

------------ Balances after transaction

  Assets:Brokerage:VTI                         1 VTI {100.00 USD, 2021-01-02}
* Assets:Brokerage:VTI                       1.8 VTI {200.00 USD, 2021-02-02}

  Assets:New-Brokerage:VTI                   1.5 VTI {150.00 USD, 2021-03-17}
* Assets:New-Brokerage:VTI                     3 VTI {300.00 USD, 2021-03-03}
* Assets:New-Brokerage:VTI                   0.2 VTI {200.00 USD, 2021-02-02}

error:

Not enough lots to reduce "-2.9 VTI {}": 1.5 VTI {150.00 USD, 2021-03-17}
MattCantor commented 1 year ago

Hi, just wanted to check whether this was still a problem or if its been resolved?

hoostus commented 1 year ago

It hasn't been resolved. I don't actually remember if I even looked into it or just forgot about it.

Anyway, having looked into it a bit I'm not sure it can be fixed.

Here's the problem (I think). It is caused by using the {} in the -2.9 VTI {} sell.

In loader.py around lines 506-513 it looks like the loader runs "interpolation" on incomplete booking entries before it runs "transformations" from plugins. So the {} gets triggered (and then fails because it can't find enough matching holdings) before the asset_transfer plugin has a chance to run and actually generate the holdings.

You can workaround this by not using {} and instead specifying the lots explicitly.

That is, instead of

2021-04-04 * "Sell 2.9 VTI" Assets:New-Brokerage:VTI -2.9 VTI {} @ 100.00 USD Assets:Bank:USD

You need to write

`2021-04-04 * "Sell 2.9 VTI"

Assets:New-Brokerage:VTI    -1.5 VTI {150.00 USD, 2021-03-17} @ 100.00 USD  ; -225.000 USD
Assets:New-Brokerage:VTI    -1.4 VTI {300.00 USD, 2021-03-03} @ 100.00 USD  ; -420.000 USD
Assets:Bank:USD      

`

Obviously this isn't great since it means you can never use {} with this plugin, which probably isn't the answer anyone is looking for. (I never use {} which it why it never came up in my usage.)

So I think I need to leave as "Can't Fix", unfortunately. I haven't really followed the 3.0 development so I don't know if this can be fixed over there.

TiFu commented 1 month ago

A solution to this is to not run this as a plugin but as a script to output the relevant transactions & append to the ledger beancount file.

Pre-condition for below quick fix: NO sales post the transfer date. If this is the case, the cost basis gets expanded incorrectly as outlined by hoostus

The script is quite easy to modify for the above purpose:

from beancount.parser import printer

[....]
                    printer.print_entry(new_entry)
                    new_entries.append(new_entry)
                    break

Then just run bean-check to trigger the plugin & copy-paste the output.

If you want FIFO (as some countries require, e.g., Germany), change reverse=True to reverse=False in

            lots = sorted(accounts[source_account], key=lambda a: a.acquisition_date, reverse=False)