forked from gsugar87/CryptoTaxes
/
CryptoTaxes.py
173 lines (162 loc) · 8.5 KB
/
CryptoTaxes.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# This will calculate cryptocurrency taxes based off coinbase, gdax, and bittrex logs
import gdax_reader
import bittrex_reader
import coinbase_reader
import fill_8949
import cPickle as pickle
import os
import turbo_tax
import argparse
import cost_basis
import dateutil.parser
import sys
import copy
def fix_orders(orders):
buys_fixed = []
sells_fixed = []
for order in orders:
# See if the exchange currency is BTC
if order[6] == 'BTC':
# This is a coin-coin transaction
# We need to get the btc value in $$ and create another trade (a sell order)
bitcoin_price_usd = gdax_reader.get_btc_price(order[0])
cost_btc = order[3]
cost_usd = cost_btc * bitcoin_price_usd
cost_per_coin_usd = cost_usd/order[4]
# get the coin name
product = order[1]
# Fix any coin discrepancies (right now call all bitcoin cash BCH, sometimes it is called BCC)
if product == 'BCC':
product = 'BCH'
if order[2] == 'buy':
buys_fixed.append([order[0], product, 'buy', cost_usd, order[4], cost_per_coin_usd, 'USD'])
sells_fixed.append([order[0], 'BTC', 'sell', cost_usd, order[3], bitcoin_price_usd, 'USD'])
elif order[2] == 'sell':
sells_fixed.append([order[0], product, 'sell', cost_usd, order[4], cost_per_coin_usd, 'USD'])
buys_fixed.append([order[0], 'BTC', 'buy', cost_usd, order[3], bitcoin_price_usd, 'USD'])
else:
print("WEIRD! Unknown order buy sell type!")
print(order)
else:
# This order was already paid/received with USD
if order[2] == 'buy':
buys_fixed.append(order)
elif order[2] == 'sell':
sells_fixed.append(order)
else:
print("WEIRD! Unknown order buy/sell type!")
print(order)
return buys_fixed, sells_fixed
if __name__ == '__main__':
# Get the user's name and social security number
# Parse potential inputs
parser = argparse.ArgumentParser()
parser.add_argument('-name', default='Full Name', help='Your full name for filling out form 8949.')
parser.add_argument('-social', default='123456789', help='Your social security number for filling out form 8949.')
parser.add_argument('-year', type=int, default=2017, help='The tax year you want to fill out.')
parser.add_argument('-startyear', type=int, default=0, help='The year to start looking for buy orders. ' +
'Use this if you have the cost basis for previous ' +
'years (pass the filename with -costbasis)')
parser.add_argument('-costbasis', default='', help='An optional file containing the cost basis of coins not ' +
'included in your GDAX, Coinbase, or Bittrex history.')
parser.add_argument('--download', action='store_true', help='Use this flag to download the transaction history. ' +
'Otherwise the data will be loaded from save.p')
parser.add_argument('--turbotax', action='store_true', help='Use this flag to make a Turbo Tax txf import file.')
parser.add_argument('--form8949', action='store_true', help='Use this flag to make the IRS form 8949 pdfs.')
parser.add_argument('--saveorders', action='store_true', help='Use this flag to save the orders in a Python ' +
'pickle file.')
# Use a preset argument list if using pycharm console
if 'pydevconsole' in sys.argv[0]:
args = parser.parse_args([
'-name', "Glenn Sugar",
'-year', '2017',
'-startyear', '2017'])
else:
args = parser.parse_args()
if args.download:
# Read in the GDAX buys and sells
gdax_buys, gdax_sells = gdax_reader.get_buys_sells()
# Read in the Coinbase buys and sells
coinbase_buys, coinbase_sells = coinbase_reader.get_buys_sells()
# Read in the Bittrex buys and sells
bittrex_buys, bittrex_sells = bittrex_reader.get_buys_sells()
# Go through the buys and sells and see if they are coin-coin transactions
# Fixed means that coin-coin transactions are now coin-usd, usd-coin
print('Fixing coin-coin transactions...')
buys_fixed = []
sells_fixed = []
for orders in [coinbase_buys, coinbase_sells, gdax_buys, gdax_sells, bittrex_buys, bittrex_sells]:
b, s = fix_orders(orders)
buys_fixed += b
sells_fixed += s
# See if any buy orders should be removed due to startyear input argument
if args.startyear > 0:
# Loop through the buys and remove any that are before the startyear
buys_fixed_startyear = []
startyear_buys = dateutil.parser.parse('%d/1/2 00:00:00Z' % args.startyear)
for b in buys_fixed:
if b[0] >= startyear_buys:
buys_fixed_startyear.append(b)
buys_fixed = buys_fixed_startyear
# Add cost basis file buys if needed
if len(args.costbasis) > 0:
# parse the costbasis file
other_buys = cost_basis.parse_cost_basis_file(args.costbasis)
buys_fixed += other_buys
# sort the buys and sells by date
print('Sorting the buy and sell orders by time')
buys_sorted = sorted(buys_fixed, key=lambda buy_order: buy_order[0])
sells_sorted = sorted(sells_fixed, key=lambda buy_order: buy_order[0])
# Get the full order information to be used on form 8949 (use list to prevent overwriting buys/sells)
full_orders = cost_basis.get_cost_basis(copy.deepcopy(sells_sorted), copy.deepcopy(buys_sorted),
basis_type='highest', tax_year=args.year)
# Save the files in a pickle
if args.saveorders:
pickle.dump([buys_sorted, sells_sorted, full_orders], open("save.p", "wb"))
pickle.dump([buys_sorted, sells_sorted, full_orders, coinbase_buys, coinbase_sells, gdax_buys, gdax_sells,
bittrex_buys, bittrex_sells], open("save_everything.p", "wb"))
print('Orders saved into save.p and save_everything.p')
else:
# Load the transaction data
[buys_sorted, sells_sorted, full_orders] = pickle.load(open("save.p", "rb"))
print('Buy and sell orders are loaded.')
# See if any buy orders should be removed due to startyear input argument
if args.startyear > 0:
# Loop through the buys and remove any that are before the startyear
buys_fixed_startyear = []
startyear_buys = dateutil.parser.parse('%d/1/2 00:00:00Z' % args.startyear)
for b in buys_sorted:
if b[0] >= startyear_buys:
buys_fixed_startyear.append(b)
buys_sorted = buys_fixed_startyear
# See if we should add more buys via a costbasis file
if len(args.costbasis) > 0:
# parse the costbasis file
other_buys = cost_basis.parse_cost_basis_file(args.costbasis)
buys_sorted += other_buys
buys_sorted = sorted(list(buys_sorted), key=lambda buy_order: buy_order[0])
full_orders = cost_basis.get_cost_basis(copy.deepcopy(sells_sorted), copy.deepcopy(buys_sorted),
basis_type='highest', tax_year=args.year)
# Make the Turbo Tax import file
if args.turbotax:
print('Creating the Turbo Tax import file.')
turbo_tax.make_txf(full_orders)
# Make the 8949 forms
if args.form8949:
print('Creating the 8949 forms.')
fill_8949.makePDF(full_orders, "test", args.name, args.social)
# Get the net data (net cost basis, net revenue, net gain/loss
net_cost = 0
net_rev = 0
net_gain = 0
for o in full_orders:
net_cost += o[4]
net_rev += o[3]
net_gain += o[5]
# make a cumulative gain array for debugging purposes
# cumulative_gains = []
# running_gain = 0
# for i in range(len(full_orders)):
# cumulative_gains.append(full_orders[i][5] + running_gain)
# running_gain += full_orders[i][5]
print('Done! Net Gain: %1.2f, Net Revenue: %1.2f, Net Cost: %1.2f' % (net_gain, net_rev, net_cost))