duelinggalois / crypto-tax-calculator Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
Pandas is pinned to 1.0.3 as many tests fail when upgrading to newer pandas package. The failure is due to the assertion not recognizing NaN == NaN
as true when using pandas assert_almost_equal
.
Failure
Traceback (most recent call last):
File "/usr/lib/python3.7/unittest/case.py", line 59, in testPartExecutor
yield
File "/usr/lib/python3.7/unittest/case.py", line 615, in run
testMethod()
File "/usr/lib/python3.7/unittest/mock.py", line 1204, in patched
return func(*args, **keywargs)
File "/home/rev3ks/Documents/tax-basis-calculation/test/csv/test_read_csv.py", line 106, in test_read_negative_values
check_exact=True
File "/home/rev3ks/.local/share/virtualenvs/tax-basis-calculation-PHoVZTgs/lib/python3.7/site-packages/pandas/_testing.py", line 1716, in assert_frame_equal
atol=atol,
File "/home/rev3ks/.local/share/virtualenvs/tax-basis-calculation-PHoVZTgs/lib/python3.7/site-packages/pandas/_testing.py", line 1484, in assert_series_equal
index_values=np.asarray(left.index),
File "pandas/_libs/testing.pyx", line 46, in pandas._libs.testing.assert_almost_equal
File "pandas/_libs/testing.pyx", line 161, in pandas._libs.testing.assert_almost_equal
File "/home/rev3ks/.local/share/virtualenvs/tax-basis-calculation-PHoVZTgs/lib/python3.7/site-packages/pandas/_testing.py", line 1073, in raise_assert_detail
raise AssertionError(msg)
AssertionError: DataFrame.iloc[:, 10] (column name="usd per btc") are different
DataFrame.iloc[:, 10] (column name="usd per btc") values are different (33.33333 %)
[index]: [0, 1, 2]
[left]: [NaN, 1100, 1200]
[right]: [NaN, 1100, 1200]
Goal is to unpin version and figure out a better way to test datafame equivalence so that NaN == NaN
is not a failure
When processing BTC trades, their are some mismatched sizes, different by a negligible amount that should be rounded. This was occurring for all assets, but was remedied by calling quantize on the decimals that get scaled when splitting up a trade. My guess is this is still occurring for BTC due to trades where BTC is the quote pair, extra magic goes into figuring out what the size of BTC is when it is the quote and not the base.
Depositing funds into an crypto wallet or into the eth2 deposit contract should exclude them from being considered in the LIFO process for exchange trades, and also exchange funds should not be considered in the LIFO of assets on the Ethereum network. Thus the task is to create the ability to support multiple accounts or buckets for each asset, ie eth on exchange, eth on network, eth in deposit contract. This will also require some import of transfers from one bucket to the next, maybe from the exchange or an etherscan.
Basis should be a positive number. It was helpful to think of it as a negative because total value fro a buy from the exchange is a negative value. Basis in accounting is really the positive that cancels the negative to leave zero (-8000 USD + 1 BTC * 8000 USD / BTC = 0 thus the 1 BTC has a basis of 8000 USD).
All the data to calculate basis, years profit and loss, are created, but those values need to be added together to get your taxable profit and loss. There should be a summary page where all of this is already done that get created.
The tax calculator is what is left of the original untested code that was written, it can be broken up into a few classes to make testing easier. One of these classes should be the code that loads the DataFrames
from the file paths provided. This would be a nice to have, the import logic is working as expected currently.
Given a list of Ethereum wallet addresses, pull in all transactions for each wallet for a range of dates, specifically the current tax year. Data should be stored in a data frame. The data frame should be compatible with the basis and fills data frames loaded from imported files.
The adjusted value column should be rounded as it will always be in terms of USD, no need to keep track of fractions of cents. Also it probably should be renamed, this is the column that represents the taxable basis or proceeds amount.
Washes should be checked in the next 30 days of the next year. This introduces the concept of a year into logic. Currently code is agnostic to what times it runs for. Not sure the best way to determine this, but I my first thought is to use the time stamp of the basis trades coming to determine what tax year is being processed.
If a basis trade is passed to the TradeProcessor
with a timestamp between the end of the current tax year being processed and 30 days after the current tax year, check to see if it washes a loss from the current tax year and count it as a loss if it does.
Validating the output for wash trade adjustments is super tedious right now. It would be ideal to have a sheet that showed loss id's, loss timestamp (for proceeds trade), loss prior to wash, adjusted loss for wash, wash basis trade id, trade timestamp, basis, adjusted basis, the total of the adjustment that is getting moved from one to the other, and the number of days between the loss and the wash buy back which would be negative or positive based on the buy back being before or after the loss.
The difference between the two is that the BucketHandler works with the Trade object and the TradeProcessor uses a Series which is nested within the Trade object. Ideally the use of all fields in the trade series would be replaced by getters in the Trade object. The main difficulty would be refactoring the tests. This would also require transforming series objects resulting from iterating over a dataframe to the Trade object and transforming the Trade object into a row in a dataframe for export.
Deposits of assets are tricky as they need to include the basis for those assets. That basis needs to be available to support the deposit, otherwise it should be ignored.
In prior tax years, all of my trading was short term, in 2020, there was much less activity and many of the assets sold were held for longer than a year. These trades need to be separated from the short term trades as they have a lower tax rate on them.
Talked to my tax advisor about a basis reporting question related to issue #14 and he advised me that there was no need to track wash trading because the IRS has said that crypto is not a security and is instead property, so wash logic is not needed. Create a flag to pass into the command line to enable wash trading logic. Default will be not to enable it. Operate logic to calculate wash trading from code based on flag presence.
Input is all basis trades, output is separated by asset. Additionally, the import code checks for a specific suffix "_with_usd.csv" to see if exchange rate at time of trade is needed for non USD trades. This check should also check for values in the "usd per btc" column instead or in addition. This would be good to do in addition to refactoring the input code #16.
Once #32 is completed, there will be an ability to track transfers of assets on chain, then, transactions on chain consuming gas can be considered in taxes as 0 value proceeds transactions and the basis for those assets can be deducted.
Once transactions have been loaded into a dataframe, they should be combined with fills dataframe and sorted. Testing will need to be expanded for new concepts that were not previously considered:
These tasks may need to be broken up into smaller tasks.
It would be ideal to concatenate the basis and proceeds matched trades into one sheet before writing it to a csv. Problem is that the columns match and pandas does not like that. If you could add another column to each series that had the other columns as children, name each parent column separately, and concatenate that bad boy, that would be ideal.
| idx | Basis Trades | Proceeds Trades |
| idx | trade id | side | ... | trade id | side | ... |
| 1 | data... |
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.