Last active
May 29, 2017 18:39
-
-
Save pvacey/841f2337931f91ba3322b67dc27a5a3d to your computer and use it in GitHub Desktop.
This file contains 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
#!venv/bin/python | |
import json, hmac, hashlib, time, requests, base64, locale | |
from requests.auth import AuthBase | |
# Create custom authentication for Exchange | |
class CoinbaseExchangeAuth(AuthBase): | |
def __init__(self, api_key, secret_key, passphrase): | |
self.api_key = api_key | |
self.secret_key = secret_key | |
self.passphrase = passphrase | |
def __call__(self, request): | |
timestamp = str(time.time()) | |
message = timestamp + request.method + request.path_url + (request.body or '') | |
hmac_key = base64.b64decode(self.secret_key) | |
signature = hmac.new(hmac_key, message, hashlib.sha256) | |
signature_b64 = signature.digest().encode('base64').rstrip('\n') | |
request.headers.update({ | |
'CB-ACCESS-SIGN': signature_b64, | |
'CB-ACCESS-TIMESTAMP': timestamp, | |
'CB-ACCESS-KEY': self.api_key, | |
'CB-ACCESS-PASSPHRASE': self.passphrase, | |
'Content-Type': 'application/json' | |
}) | |
return request | |
api_url = 'https://api.gdax.com/' | |
API_KEY = '' | |
API_SECRET = '' | |
API_PASS = '' | |
auth = CoinbaseExchangeAuth(API_KEY, API_SECRET, API_PASS) | |
def pprint(str): | |
print json.dumps(str, indent=2) | |
def getNetGain(product_type): | |
'''adds up all trade fills for a particular product type''' | |
r = requests.get(api_url + 'fills', auth=auth) | |
fills = r.json() | |
tmp_fills = [] | |
for f in fills: | |
if f['product_id'] == product_type: | |
tmp_fills.append(f) | |
total = 0 | |
for f in tmp_fills: | |
price = float(f['price']) | |
size = float(f['size']) | |
if f['side'] == 'sell': | |
total = total + (size * price) | |
elif f['side'] == 'buy': | |
total = total - (size * price) | |
total = total - float(f['fee']) | |
return total | |
def get_position(product_type): | |
'''calculate standing since the last time we had 0 balance''' | |
fills = requests.get(api_url + 'fills?product_id={}'.format(product_type), auth=auth).json() | |
i = 0 | |
total = get_transfer_balance(product_type) | |
tmp = 0 | |
for f in reversed(fills): | |
if f['side'] == 'buy': | |
total = total + float(f['size']) | |
elif f['side'] == 'sell': | |
total = total - float(f['size']) | |
#print '{}. {} - {}'.format(i, f['side'], total) | |
if round(total,8) == 0: | |
tmp = i | |
i +=1 | |
# find the position that we last hit 0 (in non reversed list) | |
pos = i - 1 - tmp | |
tmp_fills = fills[:pos] | |
cost = 0 | |
fees = 0 | |
price = 0 | |
#print 'total {} '.format(total) | |
for t in tmp_fills: | |
fraction_of_total = float(t['size'])/total | |
price = price + (fraction_of_total * float(t['price'])) | |
cost = cost + (float(t['size']) * float(t['price'])) | |
#print '{} | {} | {}'.format(f['side'], float(t['size']), cost) | |
fees = fees + (float(t['fee'])) | |
return {'cost':cost, 'fees':fees, 'price':price} | |
def getPrice(product_type): | |
'''get the current market price''' | |
uri = 'products/{}/ticker'.format(product_type) | |
r = requests.get(api_url + uri) | |
return round(float(r.json()['price']),2) | |
def get_account_balance(product_type): | |
'''get an account balance for a particular product type''' | |
product_type = product_type.split('-')[0] | |
accts = requests.get(api_url + 'accounts', auth=auth).json() | |
for a in accts: | |
if a['currency'] == product_type: | |
return float(a['balance']) | |
def get_transfer_balance(product_type): | |
'''sum up the deposits and withdrawals for an account''' | |
product_type = product_type.split('-')[0] | |
accts = requests.get(api_url + 'accounts', auth=auth).json() | |
#pprint(accts) | |
# find the right account | |
for i, a in enumerate(accts): | |
if a['currency'] == product_type: | |
index = i | |
# find the transfers in this account and add them up | |
total = 0.0 | |
history = requests.get(api_url + 'accounts/{}/ledger'.format(accts[index]['id']), auth=auth).json() | |
transfers = [] | |
for t in history: | |
if t['type'] == 'transfer': | |
transfers.append(t) | |
total = total + float(t['amount']) | |
#pprint(transfers) | |
return total | |
def account_statement(product_type): | |
balance = get_account_balance(product_type) | |
if product_type == 'BTC-USD': | |
currency_name = "Bitcoin" | |
elif product_type == 'ETH-USD': | |
currency_name = "Ether" | |
else: | |
print 'unhandled currency: {}'.format(product_type) | |
return | |
if balance == 0: | |
tmp={'fees':0, 'cost':0, 'price':0} | |
else: | |
tmp = get_position(product_type) | |
fees = tmp['fees'] | |
cost = tmp['cost'] + fees | |
purchase_price = tmp['price'] | |
gain = getNetGain(product_type) | |
market_price = getPrice(product_type) | |
balance_value = market_price * balance | |
sell_fees = balance_value*.0025 | |
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') | |
dollars = locale.currency | |
s = '-------------------------' | |
s += '\n# {}'.format(currency_name) | |
s += '\n-------------------------' | |
s += '\nmarket price: {}'.format(dollars(market_price)) | |
s += '\npurchase price: {}'.format(dollars(purchase_price)) | |
s += '\nbalance: {}'.format(balance) | |
s += '\nmarket value: {}'.format(dollars(balance_value)) | |
s += '\npurchase value: {}'.format(dollars(cost)) | |
s += '\n-------------------------' | |
s += '\nunrealized pnl: {}'.format(dollars(balance_value - cost)) | |
if balance_value > cost: s += '\nsell fees: {}'.format(dollars(sell_fees)) | |
#if balance_value > cost: | |
# print 'unrealized pnl w/ fees: {}'.format(dollars(balance_value - cost - sell_fees)) | |
return s | |
if __name__ == '__main__': | |
print account_statement('BTC-USD') | |
print '' | |
print account_statement('ETH-USD') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment