Skip to content

Instantly share code, notes, and snippets.

@unrelentingfox
Last active July 4, 2024 07:58
Show Gist options
  • Save unrelentingfox/66e586fb2d397bf45d5291bea9adcaf7 to your computer and use it in GitHub Desktop.
Save unrelentingfox/66e586fb2d397bf45d5291bea9adcaf7 to your computer and use it in GitHub Desktop.
A python script that queries all of your historic trades and calculates the average price you purchased coins at. This was a quick script based on the examples found here: https://docs.kraken.com/rest/. I am open to feedback!!
#!/usr/local/bin/python3
import base64
import hashlib
import hmac
import json
import os
import requests
import time
import urllib.parse
# SAMPLE OUTPUT
# TICKER AVG COST LAST PRICE GAIN/LOSS
# XETHZUSD 4187.51 3911.61 -6.59%
# KAVAUSD 5.90 5.38 -8.88%
# DOTUSD 40.06 36.15 -9.78%
# XXBTZUSD 56039.83 49928.40 -10.91%
# XDGUSD 0.48 0.43 -9.75%
# Read Kraken API key and secret stored in environment variables
api_url = "https://api.kraken.com"
api_key = os.environ['api_key_KRAKEN']
api_sec = os.environ['api_sec_KRAKEN']
def get_kraken_signature(urlpath, data, secret):
postdata = urllib.parse.urlencode(data)
encoded = (str(data['nonce']) + postdata).encode()
message = urlpath.encode() + hashlib.sha256(encoded).digest()
mac = hmac.new(base64.b64decode(secret), message, hashlib.sha512)
sigdigest = base64.b64encode(mac.digest())
return sigdigest.decode()
# Attaches auth headers and returns results of a POST request
def kraken_request(uri_path, data, api_key, api_sec):
headers = {}
headers['API-Key'] = api_key
# get_kraken_signature() as defined in the 'Authentication' section
headers['API-Sign'] = get_kraken_signature(uri_path, data, api_sec)
req = requests.post((api_url + uri_path), headers=headers, data=data)
return req
def check_errors(resp):
if resp["error"]:
print("There were errors with the request:")
print(resp["error"])
exit(1)
def get_average_cost():
resp = kraken_request('/0/private/TradesHistory', {
"nonce": str(int(1000*time.time())),
"trades": True
}, api_key, api_sec).json()
check_errors(resp)
trade_history = resp["result"]["trades"]
average_cost = {}
total_vol = {}
total_cost = {}
for trade_key in trade_history:
trade = trade_history[trade_key]
ttype = trade["type"]
currency_pair = trade["pair"]
volume = float(trade["vol"])
cost = float(trade["cost"])
fee = float(trade["fee"])
if ttype == "buy":
total_vol[currency_pair] = total_vol.get(currency_pair, 0.0) + volume
total_cost[currency_pair] = total_cost.get(currency_pair, 0.0) + (cost + fee)
elif ttype == "sell":
total_vol[currency_pair] = total_vol.get(currency_pair, 0.0) - volume
total_cost[currency_pair] = total_cost.get(currency_pair, 0.0) - (cost - fee)
for currency_pair in total_vol:
if total_vol[currency_pair] > 0.0:
average_cost[currency_pair] = total_cost[currency_pair] / total_vol[currency_pair]
return average_cost
def get_last_price(currency_pairs):
last_price = {}
for currency_pair in currency_pairs:
resp = requests.get('https://api.kraken.com/0/public/Trades?pair=%s' % currency_pair).json()
check_errors(resp)
last_price[currency_pair] = float(resp["result"][currency_pair][-1][0])
return last_price
def calc_gain_loss_percent(average_cost, last_price):
gain_loss_percent = {}
for currency_pair in average_cost:
gain_loss_percent[currency_pair] = (last_price[currency_pair] - average_cost[currency_pair]) / average_cost[currency_pair] * 100
return gain_loss_percent
def display_info(average_cost, last_price, gain_loss_percent):
fcolumns = "{0:<12} {1:<12} {2:<12} {3:<12}"
ffloat = "{:.2f}"
fpercent = ffloat+"%"
print(fcolumns.format("TICKER", "AVG COST", "LAST PRICE", "GAIN/LOSS"))
for currency_pair in average_cost:
print(fcolumns.format(
currency_pair,
ffloat.format(average_cost[currency_pair]),
ffloat.format(last_price[currency_pair]),
fpercent.format(gain_loss_percent[currency_pair])
))
average_cost = get_average_cost()
last_price = get_last_price(average_cost.keys())
gain_loss_percent = calc_gain_loss_percent(average_cost, last_price)
display_info(average_cost, last_price, gain_loss_percent)
@seralouk
Copy link

seralouk commented Nov 8, 2021

I use my fiat currency to invest into some coins and thus, the trade tab is empty. Any way to adapt this for the information under the kraken.com/u/history/ledger section? This looks like this: https://pasteboard.co/zXG7FEhc0WXL.png

@TheCamFreak
Copy link

Hello Dustin,
I am wondering if you can give me a tip how to fix this error:
Error: Invalid base64-encoded string: number of data characters (85) cannot be 1 more than a multiple of 4

It's happening when I try to execute the code.

@DVN237294
Copy link

Thanks Dustin for the good work!

I have added a few extra features (sorry for the sloppy code. Python is not my native language) here: https://gist.github.com/DVN237294/4f40133b79926dd598333580a9f5d82f

  • Original script only fetched the previous 50 trades at most. This now loops through all trades in history (that kraken exposes)
  • Added some basic api limiting to adhere to krakens limits (seemed like it was actually not necessary in my case. Not sure why)
  • Prints the received trades and total trade count
  • Changed from floats to decimals to avoid monetary rounding errors
  • Added a few more columns to output: TOTAL VOL, TOTAL COST, TOTAL FEES, MIN PRICE and MAX PRICE

@unrelentingfox
Copy link
Author

@DVN237294 Thanks for the collaboration!

I want to note that I no longer use this script since there are services online that do this for free. I'm using Koinly currently, but there are other options too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment