-
Notifications
You must be signed in to change notification settings - Fork 109
/
csv-export.py
238 lines (197 loc) · 7.18 KB
/
csv-export.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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
from __future__ import print_function
from Robinhood import Robinhood
from login_data import collect_login_data
from profit_extractor import profit_extractor
import getpass
import collections
import argparse
import ast
from dotenv import load_dotenv, find_dotenv
import os
logged_in = False
parser = argparse.ArgumentParser(
description='Export Robinhood trades to a CSV file')
parser.add_argument(
'--debug', action='store_true', help='store raw JSON output to debug.json')
parser.add_argument(
'--username', default='', help='your Robinhood username')
parser.add_argument(
'--password', default='', help='your Robinhood password')
parser.add_argument(
'--mfa_code', help='your Robinhood mfa_code')
parser.add_argument(
'--device_token', help='your device token')
parser.add_argument(
'--profit', action='store_true', help='calculate profit for each sale')
parser.add_argument(
'--dividends', action='store_true', help='export dividend payments')
args = parser.parse_args()
username = args.username
password = args.password
mfa_code = args.mfa_code
device_token = args.device_token
load_dotenv(find_dotenv())
robinhood = Robinhood()
# login to Robinhood
logged_in = collect_login_data(robinhood_obj=robinhood, username=username, password=password, device_token=device_token, mfa_code=mfa_code)
print("Pulling trades. Please wait...")
fields = collections.defaultdict(dict)
trade_count = 0
queued_count = 0
#holds instrument['symbols'] to reduce API ovehead {instrument_url:symbol}
cached_instruments = {}
# fetch order history and related metadata from the Robinhood API
orders = robinhood.get_endpoint('orders')
# load a debug file
# raw_json = open('debug.txt','rU').read()
# orders = ast.literal_eval(raw_json)
# store debug
if args.debug:
# save the CSV
try:
with open("debug.txt", "w+") as outfile:
outfile.write(str(orders))
print("Debug infomation written to debug.txt")
except IOError:
print('Oops. Unable to write file to debug.txt')
# do/while for pagination
paginated = True
page = 0
while paginated:
for i, order in enumerate(orders['results']):
executions = order['executions']
symbol = cached_instruments.get(order['instrument'], False)
if not symbol:
symbol = robinhood.get_custom_endpoint(order['instrument'])['symbol']
cached_instruments[order['instrument']] = symbol
fields[i + (page * 100)]['symbol'] = symbol
for key, value in enumerate(order):
if value != "executions":
fields[i + (page * 100)][value] = order[value]
fields[i + (page * 100)]['num_of_executions'] = len(executions)
fields[i + (page * 100)]['execution_state'] = order['state']
if len(executions) > 0:
trade_count += 1
fields[i + (page * 100)]['execution_state'] = ("completed", "partially filled")[order['cumulative_quantity'] < order['quantity']]
fields[i + (page * 100)]['first_execution_at'] = executions[0]['timestamp']
fields[i + (page * 100)]['settlement_date'] = executions[0]['settlement_date']
elif order['state'] == "queued":
queued_count += 1
# paginate
if orders['next'] is not None:
page = page + 1
orders = robinhood.get_custom_endpoint(str(orders['next']))
else:
paginated = False
# for i in fields:
# print fields[i]
# print "-------"
# check we have trade data to export
if trade_count > 0 or queued_count > 0:
print("%d queued trade%s and %d executed trade%s found in your account." %
(queued_count, "s" [queued_count == 1:], trade_count,
"s" [trade_count == 1:]))
# print str(queued_count) + " queded trade(s) and " + str(trade_count) + " executed trade(s) found in your account."
else:
print("No trade history found in your account.")
quit()
# CSV headers
keys = fields[0].keys()
keys = sorted(keys)
csv = ','.join(keys) + "\n"
# CSV rows
for row in fields:
for idx, key in enumerate(keys):
if (idx > 0):
csv += ","
try:
csv += str(fields[row][key])
except:
csv += ""
csv += "\n"
# choose a filename to save to
print("Choose a filename or press enter to save to `robinhood.csv`:")
try:
input = raw_input
except NameError:
pass
filename = input().strip()
if filename == '':
filename = "robinhood.csv"
try:
with open(filename, "w+") as outfile:
outfile.write(csv)
except IOError:
print("Oops. Unable to write file to ", filename)
if args.dividends:
fields=collections.defaultdict(dict)
dividend_count = 0
queued_dividends = 0
# fetch order history and related metadata from the Robinhood API
dividends = robinhood.get_endpoint('dividends')
paginated = True
page = 0
while paginated:
for i, dividend in enumerate(dividends['results']):
symbol = cached_instruments.get(dividend['instrument'], False)
if not symbol:
symbol = robinhood.get_custom_endpoint(dividend['instrument'])['symbol']
cached_instruments[dividend['instrument']] = symbol
fields[i + (page * 100)]['symbol'] = symbol
for key, value in enumerate(dividend):
if value != "executions":
fields[i + (page * 100)][value] = dividend[value]
fields[i + (page * 100)]['execution_state'] = order['state']
if dividend['state'] == "pending":
queued_dividends += 1
elif dividend['state'] == "paid":
dividend_count += 1
# paginate
if dividends['next'] is not None:
page = page + 1
orders = robinhood.get_custom_endpoint(str(dividends['next']))
else:
paginated = False
# for i in fields:
# print fields[i]
# print "-------"
# check we have trade data to export
if dividend_count > 0 or queued_dividends > 0:
print("%d queued dividend%s and %d executed dividend%s found in your account." %
(queued_dividends, "s" [queued_count == 1:], dividend_count,
"s" [trade_count == 1:]))
# print str(queued_count) + " queded trade(s) and " + str(trade_count) + " executed trade(s) found in your account."
else:
print("No dividend history found in your account.")
quit()
# CSV headers
keys = fields[0].keys()
keys = sorted(keys)
csv = ','.join(keys) + "\n"
# CSV rows
for row in fields:
for idx, key in enumerate(keys):
if (idx > 0):
csv += ","
try:
csv += str(fields[row][key])
except:
csv += ""
csv += "\n"
# choose a filename to save to
print("Choose a filename or press enter to save to `dividends.csv`:")
try:
input = raw_input
except NameError:
pass
filename = input().strip()
if filename == '':
filename = "dividends.csv"
# save the CSV
try:
with open(filename, "w+") as outfile:
outfile.write(csv)
except IOError:
print("Oops. Unable to write file to ", filename)
if args.profit:
profit_csv = profit_extractor(csv, filename)