Skip to content

Instantly share code, notes, and snippets.

@kevinkassimo
Created July 5, 2021 23:02
Show Gist options
  • Save kevinkassimo/6d8559c00c4bdb6d38faf7297a2bdf66 to your computer and use it in GitHub Desktop.
Save kevinkassimo/6d8559c00c4bdb6d38faf7297a2bdf66 to your computer and use it in GitHub Desktop.
Export Robinhood records to CSV format that can be imported to simplywall.st
# Deps: pandas, grequests
# READ ME BEFORE START!
# Please install: pandas, grequests
# pip3 install pandas grequests
#
# Usage:
# python3 robinhood_to_simplywallst.py [source_json] [optional_custom_ticker_file]
#
# <source_json>: JSON file of your historical transactions downloaded from https://api.robinhood.com/orders/
# <optional_custom_ticker_file>: a JSON file following a simple JSON dictionary format that replaces a ticker symbol with a custom one.
# This might be necessary when there is confusion about the ticker symbol.
# For example, for a ticker symbol "YOU", you might want to replace it with "NYSE:YOU"
# To do such, simply have your <optional_custom_ticker_file> contain {"YOU": "NYSE:YOU"}
# If argument not provided, the default filename to try is "./custom_tickers.json"
#
# The output file will be a CSV file with the same name as <source_json> but with .json replaced with .csv
import json
from sys import argv
import grequests
import pandas as pd
in_filename = argv[1]
out_filename = in_filename.replace(".json", ".csv")
def exception_handler(request, exception):
print(request, exception)
# Use custom
custom_ticker = {}
try:
with open(argv[2] if len(argv) > 2 else "./custom_tickers.json", 'r') as f:
custom_ticker = json.load(f)
except Exception:
print(">>> No custom ticker replacer found")
def patch_custom_ticker(ticker):
return custom_ticker[ticker] if ticker in custom_ticker else ticker
def main():
# Get this JSON from: https://api.robinhood.com/orders/
with open(argv[1], 'r') as f:
j = json.load(f)
j = j["results"]
urls = set()
instrument_to_ticker = {}
# Extract JSON
df = pd.DataFrame(j)
# Translate side into something that simplywall.st can recognize
for i, r in df.iterrows():
# Drop canceled rows
if r["state"] == "cancelled":
df.drop(i, inplace=True)
continue
# buy -> Buy
df.loc[i, "side"] = r["side"].capitalize()
# Date format to YYYY-MM-DD
df.loc[i, "created_at"] = r["created_at"][:r["created_at"].index("T")]
# Prep with instrument_id -> ticker mapping first. Robinhood does not immediately include ticker symbol in the JSON
urls.add(f"https://api.robinhood.com/instruments/{r['instrument_id']}/")
# Get the actual tickers
requests = (grequests.get(u) for u in urls)
for res in grequests.map(requests, exception_handler=exception_handler):
rjson = res.json()
instrument_to_ticker[rjson["id"]] = rjson["symbol"]
for i, r in df.iterrows():
df.loc[i, "instrument_id"] = patch_custom_ticker(instrument_to_ticker[r["instrument_id"]])
df = df.rename(columns={
"instrument_id": "Ticker",
"side": "Type",
"price": "Price",
"quantity": "Shares",
"created_at": "Date"
})
# Output
df[["Ticker", "Type", "Price", "Shares", "Date"]].to_csv(out_filename)
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment