Created
January 15, 2021 12:18
-
-
Save erlingpaulsen/3813d26d3d025b66c816ff9c2c6120c2 to your computer and use it in GitHub Desktop.
Python script for connecting to your Coinbase account through the API. Used to compute and plot the balance and cost per wallet and in total, in addition to calculate the total profit/loss. Will calculate to your native currency.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json, hmac, hashlib, time, requests | |
import numpy as np | |
from requests.auth import AuthBase | |
import matplotlib.pyplot as plt | |
# Name of account holder (only for displaying) | |
USER = 'My name' | |
# API key and secret. Create these in your Coinbase account with all read permissions selected for all accounts | |
API_KEY = 'xxx' | |
API_SECRET = 'xxx' | |
# API version time should match the API version displayed in your account page | |
API_VERSION_TIME = '2021-01-14' | |
# API base URL | |
API_URL = 'https://api.coinbase.com/v2/' | |
# Native currency | |
NATIVE_CURRENCY = 'NOK' | |
# Create custom authentication for Coinbase API | |
class CoinbaseWalletAuth(AuthBase): | |
def __init__(self, api_key, secret_key): | |
self.api_key = api_key | |
self.secret_key = secret_key.encode('utf8') | |
def __call__(self, request): | |
timestamp = str(int(time.time())) | |
message = timestamp + request.method + request.path_url + (request.body or '') | |
message = message.encode('utf8') | |
signature = hmac.new(self.secret_key, message, hashlib.sha256).hexdigest() | |
request.headers.update({ | |
'CB-ACCESS-SIGN': signature, | |
'CB-ACCESS-TIMESTAMP': timestamp, | |
'CB-ACCESS-KEY': self.api_key, | |
'CB-VERSION': API_VERSION_TIME, | |
}) | |
return request | |
auth = CoinbaseWalletAuth(API_KEY, API_SECRET) | |
# Total balance and total cost in native currency | |
total_balance_native = 0 | |
total_cost_native = 0 | |
# Dictionary for storing balance and cost per account/wallet | |
account_balances = {} | |
account_costs = {} | |
# Get all accounts | |
r_account = requests.get(API_URL + 'accounts?limit=100', auth=auth) | |
for account in r_account.json()['data']: | |
account_id = account['id'] | |
account_name = account['currency']['name'] | |
account_balance = account['balance']['amount'] | |
account_currency = account['currency']['code'] | |
account_cost_native = 0 | |
account_balance_native = 0 | |
# If account balance greater than zero, compute the balance in native currency | |
if (float(account_balance) > 0): | |
exchange_rates = requests.get(API_URL + 'exchange-rates?currency={0}'.format(account_currency)).json()['data']['rates'] | |
account_balance_native = np.multiply(float(account_balance), float(exchange_rates[NATIVE_CURRENCY])) | |
total_balance_native += account_balance_native | |
# Get all buys in account | |
r_buy = requests.get(API_URL + 'accounts/{0}/buys?limit=100'.format(account_id), auth=auth) | |
transactions = [] | |
for buy in r_buy.json()['data']: | |
buy_id = buy['id'] | |
transaction_date = buy['payout_at'].split('T')[0] | |
transaction_amount = buy['amount']['amount'] | |
transaction_amount_currency = buy['amount']['currency'] | |
transaction_fee_amount = buy['fee']['amount'] | |
transaction_fee_currency = buy['fee']['currency'] | |
transaction_cost_amount = buy['total']['amount'] | |
transaction_cost_currency = buy['total']['currency'] | |
# If transaction is completed, print details, compute cost in native currency and add to total account cost | |
if buy['status'] == 'completed': | |
transactions.append('{0:.4f} {1} for {2:.1f} {3} on {4}'.format(float(transaction_amount), transaction_amount_currency, float(transaction_cost_amount), transaction_cost_currency, transaction_date)) | |
exchange_rates = requests.get(API_URL + 'exchange-rates?currency={0}'.format(transaction_cost_currency)).json()['data']['rates'] | |
transaction_cost_native = np.multiply(float(transaction_cost_amount), float(exchange_rates[NATIVE_CURRENCY])) | |
account_cost_native += float(transaction_cost_native) | |
# Add total account cost to total cost | |
total_cost_native += account_cost_native | |
# If total account balance or cost is greater than zero, add to dict for plotting and print details | |
if (float(account_balance) > 0) or (account_cost_native > 0): | |
account_balances[account_currency] = account_balance_native | |
account_costs[account_currency] = account_cost_native | |
print('{0}:\n\tBalance: {1:.4f} {2} = {3:.1f} {4}'.format(account_name, float(account_balance), account_currency, account_balance_native, NATIVE_CURRENCY)) | |
print('\tTotal Cost: {0:.1f} {1}'.format(account_cost_native, NATIVE_CURRENCY)) | |
if len(transactions) > 0: | |
print('\tTransactions:') | |
for t in transactions: | |
print('\t\t{0}'.format(t)) | |
print('') | |
# Total profit/loss | |
profit_loss_native = total_balance_native - total_cost_native | |
profit_loss_percent = np.multiply(np.divide(profit_loss_native, total_balance_native), 100) | |
print('Total:\n\tBalance: {0:.1f} {1}'.format(total_balance_native, NATIVE_CURRENCY)) | |
print('\tCost: {0:.1f} {1}'.format(total_cost_native, NATIVE_CURRENCY)) | |
print('\tProfit/Loss: {0:.1f} {1}, {2:.2f} %'.format(profit_loss_native, NATIVE_CURRENCY, profit_loss_percent)) | |
# Plotting balance and cost per account in native currency | |
labels = list(account_balances.keys()) | |
x = np.arange(len(labels)) | |
width = 0.35 | |
fig, ax = plt.subplots(figsize=(12,6)) | |
rects1 = ax.bar(x - width/2, account_balances.values(), width, label='Balance') | |
rects2 = ax.bar(x + width/2, account_costs.values(), width, label='Cost') | |
ax.set_ylabel(NATIVE_CURRENCY) | |
ax.set_title('{0} - Balance and Cost per Wallet - Total Profit/Loss is {1:.2f} %'.format(USER, profit_loss_percent)) | |
ax.set_xticks(x) | |
ax.set_xticklabels(labels) | |
ax.legend() | |
plt.grid(True) | |
plt.show() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment