eprbell / rp2

Privacy-focused, free, open-source cryptocurrency tax calculator for multiple countries: it handles multiple coins/exchanges and computes long/short-term capital gains, cost bases, in/out lot relationships/fractioning, and account balances. It supports FIFO, LIFO, HIFO and it outputs in form 8949 format. It has a programmable plugin architecture
https://pypi.org/project/rp2/
Apache License 2.0
256 stars 42 forks source link

Spending from Exchange with zero balance #106

Closed gbtorrance closed 3 months ago

gbtorrance commented 4 months ago

While working on my taxes I found something that is kind of concerning.

Example:

Say you have 1 BTC and two Exchanges defined in RP2: E1 and E2. Your 1 BTC was purchased and resides on E1 (according to the RP2 spreadsheets). But then record a transaction to SELL 1 BTC from E2. (Remember, E2 should have no BTC.)

A few problems are encountered when you run RP2:

  1. There is no error/warning of "overspending" for E2.
  2. In open_positions.ods the "Asset" tab will list that you still have 1 BTC, even though you actually have zero BTC.
  3. In open_positions.ods the "Asset - Exchange" tab will list that you have 1 BTC on E1, and will not list E2 at all. (But E2 should have a balance of negative 1 BTC, right?)
  4. In both of these tabs cost basis is shown as zero because it has all been "spent".

This is quite confusing and concerning. One could have bad data in the input spreadsheet and never notice it because there are no errors/warnings and open_positions.ods does not reflect what should be a negative balance on "over-spent" exchanges.

Please understand I don't mean this to be critical. This is open-source, free software, and I'm well aware that I have not paid anything for it or directly contributed to writing it. I am very grateful to have it, but felt it was still important to report the issue.

Thanks!

eprbell commented 4 months ago

For issue 1, can you provide a simple ods and config file reproducing the issue?

For the other issues, CC: @mdavid217, who worked on the open position plugin.

gbtorrance commented 4 months ago

Sure!

First of all, I made a small change to my original post to change "warning" to "error/warning" as, in retrospect, I think an error may be more appropriate. (Warnings can easily be missed, but there is no getting past an error.)

I have created an ODS and config file to reproduce the issue, however, I did realize in doing so that what I wrote above is not totally correct. A few points.

Regarding #1, there are no errors/warnings (as mentioned above):

INFO: Country: us
INFO: Generation Language: en
INFO: Accounting method: fifo
INFO: Configuration file: Config_Test.ini
INFO: Input file: RP2_Input_Test.ods
INFO: Processing BTC
INFO: Generating output for plugin 'rp2.plugin.report.open_positions'
INFO: Plugin 'rp2.plugin.report.open_positions' output: /mnt/h1/_Data/Financial/Crypto/RP2_CryptoTax/Config_Test/output/fifo_open_positions.ods
INFO: Generating output for plugin 'rp2.plugin.report.rp2_full_report'
INFO: Plugin 'rp2.plugin.report.rp2_full_report' output: /mnt/h1/_Data/Financial/Crypto/RP2_CryptoTax/Config_Test/output/fifo_rp2_full_report.ods
INFO: Generating output for plugin 'rp2.plugin.report.us.tax_report_us'
INFO: Plugin 'rp2.plugin.report.us.tax_report_us' output: /mnt/h1/_Data/Financial/Crypto/RP2_CryptoTax/Config_Test/output/fifo_tax_report_us.ods
INFO: Log file: ./log/rp2_2024_03_02_17_01_17_447657.log
INFO: Generated output directory: output/
INFO: Done

But regarding the other issues, it makes a difference whether the coin is fully spent or only partially spent.

In the former case, if the coin (in the sample: BTC) is fully spent, it will not show up at all in open_positions.ods. To test this set crypto_out_no_fee to 1 to fully spend the BTC.

image

In this case "Asset - Exchange" looks like this:

image

And "Asset" looks similar:

image

This could be considered correct behavior for open_positions.ods.

But in the latter case, if the coin is only partially spent, it will show up in open_positions.ods, but with very confusing results. (The results seem to indicate that you have not spent anything, though the cost basis will show that you have.) To test this set crypto_out_no_fee to 0.99999 to partially spend the BTC.

image

In this case "Asset - Exchange" looks like this:

image

And "Asset" looks like this:

image

Since overall there should only be 0.00001 BTC remaining, I'm sure you can see how this is confusing. In the absence of any error when generating the output (which I think would be the ideal behavior), is it possible to show a balance of -0.99999 for E2 in "Asset - Exchange" and a balance of 0.0000 for total BTC in "Asset"?

Hopefully this makes sense. Thanks for looking into this!

Config_Test.zip

eprbell commented 4 months ago

Thanks for reporting the bug and providing the repro files! It does look like a missing check. The Account Balances table in rp2_full_report shows a balance for E2 of -0.99999.

gbtorrance commented 4 months ago

No problem!

Ah, good to know that rp2_full_report.ods includes that info. I have typically not looked at that sheet, but will do so going forward to make sure I don't have any negative balances.

Thanks!

eprbell commented 3 months ago

The negative balance issue has been fixed with commit aa39258. Now at balance creation time there are new checks to ensure the balance never goes negative (these checks can be disabled with the new -n switch).

@gbtorrance could you verify the fix? Thanks.

gbtorrance commented 3 months ago

Thanks @eprbell! I will give it a try.

But to be clear, is there a new build to install or do I need to build from source?

eprbell commented 3 months ago

There is no new release yet, so you need to use top of tree.

gbtorrance commented 3 months ago

OK, thanks @eprbell. It may take me a bit to get around to testing this, but I will do so. (Hopefully this week.)

eprbell commented 3 months ago

No worries, take your time!

gbtorrance commented 3 months ago

@eprbell I'm looking into testing this now. Following the Development README I've cloned the source, installed all the dependencies, and successfully executed the unit tests. But I'm not a Python guy, and I'm not sure how to actually execute rp2_us from the source. Can you assist? Thanks. (BTW, I'm on Linux.)

eprbell commented 3 months ago

Sure:

gbtorrance commented 3 months ago

Thanks @eprbell!

OK, I've tested and it seems good to me. I've tested both with and without the -n flag, on input that has negative exchange balances and input that does not have negative exchange balances ... and it operates as expected in all cases.

To be thorough, the open_positions.ods sheets will still present potentially confusing results when the -n flag is provided and exchanges hold negative balances (as described in points 2 - 4 of the original post). But given that rp2_us now defaults to providing an error in the case of negative exchange balances, I'd say this is very minor.

Thank you so much for making the change. Much appreciated!

eprbell commented 3 months ago

Thanks for reporting and testing! With -n the balance can go negative (as you say, it's not the default): I added the flag because there were a few unit tests that were going negative and I didn't want to have to rewrite them (because they were thoroughly checked by hand and they offered a strong baseline for CI).

Is it OK to close the issue?

gbtorrance commented 3 months ago

I added the flag because there were a few unit tests...

Makes sense.

Is it OK to close the issue?

Yes, please go ahead ! Thanks again.