diff --git a/.gitignore b/.gitignore index b743145..a9cd81b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *__pycache__* venv/* .env +kraken.key diff --git a/app.py b/app.py index a59319f..0aee405 100644 --- a/app.py +++ b/app.py @@ -1,81 +1,28 @@ -import numpy +import krakenex +import pandas from dotenv import load_dotenv -from Kraken import Kraken -from scipy import stats +from pykrakenapi import KrakenAPI +from scipy.stats import linregress +from time import sleep -load_dotenv() +k = krakenex.API() +k.load_key('kraken.key') +kraken = KrakenAPI(k, tier='Pro') -kraken = Kraken() -raw = { - asset: { - asset_pair: kraken.ohlc(asset_pair) for asset_pair in kraken.ASSET_PAIRS[asset] - } for asset in kraken.ASSETS - } -processed = { - asset: { - asset_pair: { - 'time': numpy.array( - [int(each[0]) for each in raw[asset][asset_pair]['result'][kraken.ASSET_PAIRS[asset][asset_pair]]] - ), - 'open': numpy.array( - [float(each[1]) for each in raw[asset][asset_pair]['result'][kraken.ASSET_PAIRS[asset][asset_pair]]] - ), - 'high': numpy.array( - [float(each[2]) for each in raw[asset][asset_pair]['result'][kraken.ASSET_PAIRS[asset][asset_pair]]] - ), - 'low': numpy.array( - [float(each[3]) for each in raw[asset][asset_pair]['result'][kraken.ASSET_PAIRS[asset][asset_pair]]] - ), - 'close': numpy.array( - [float(each[4]) for each in raw[asset][asset_pair]['result'][kraken.ASSET_PAIRS[asset][asset_pair]]] - ), - 'volume': numpy.array( - [float(each[5]) for each in raw[asset][asset_pair]['result'][kraken.ASSET_PAIRS[asset][asset_pair]]] - ), - 'count': numpy.array( - [float(each[6]) for each in raw[asset][asset_pair]['result'][kraken.ASSET_PAIRS[asset][asset_pair]]] - ) - } for asset_pair in kraken.ASSET_PAIRS[asset] - } for asset in kraken.ASSETS - } -linregresses = { - asset: { - asset_pair: { - 'open': stats.linregress( - processed[asset][asset_pair]['time'], - processed[asset][asset_pair]['open'] - ), - 'high': stats.linregress( - processed[asset][asset_pair]['time'], - processed[asset][asset_pair]['high'] - ), - 'low': stats.linregress( - processed[asset][asset_pair]['time'], - processed[asset][asset_pair]['low'] - ), - 'close': stats.linregress( - processed[asset][asset_pair]['time'], - processed[asset][asset_pair]['close'] - ) - } for asset_pair in kraken.ASSET_PAIRS[asset] - } for asset in kraken.ASSETS - } -slopes = { - asset: { - asset_pair: { - 'open': linregresses[asset][asset_pair]['open'].slope, - 'high': linregresses[asset][asset_pair]['high'].slope, - 'low': linregresses[asset][asset_pair]['low'].slope, - 'close': linregresses[asset][asset_pair]['close'].slope - } for asset_pair in kraken.ASSET_PAIRS[asset] - } for asset in kraken.ASSETS - } -averages = { - asset: { - asset_pair: sum( - [slopes[asset][asset_pair][each] for each in slopes[asset][asset_pair]] - )/4 for asset_pair in kraken.ASSET_PAIRS[asset] - } for asset in kraken.ASSETS - } -print(averages) +def get_markets_by_asset(asset): + tradable_asset_pairs = kraken.get_tradable_asset_pairs() + return tradable_asset_pairs[ + ((tradable_asset_pairs['base'] == asset | tradable_asset_pairs['quote'] == asset) + & (tradable_asset_pairs['status'] == 'online')) + ] + +def get_ohlc_linear_regression(ohlc): + regressions = pandas.DataFrame({ + 'open': linregress(ohlc['time'].astype(float), ohlc['open'].astype(float)), + 'high': linregress(ohlc['time'].astype(float), ohlc['high'].astype(float)), + 'low': linregress(ohlc['time'].astype(float), ohlc['low'].astype(float)), + 'close': linregress(ohlc['time'].astype(float), ohlc['close'].astype(float)) + }).transpose() + regressions.columns = ['slope', 'intercept', 'r_value', 'p_value', 'stderr'] + return regressions diff --git a/Kraken.py b/pykraken.py similarity index 58% rename from Kraken.py rename to pykraken.py index 01af915..e8f22ec 100644 --- a/Kraken.py +++ b/pykraken.py @@ -7,26 +7,6 @@ import time import urllib.parse class Kraken(): - ASSETS = [ - 'ZUSD', - 'XETH', - 'XXBT' - ] - - ASSET_PAIRS = { - 'ZUSD': { - 'ETHUSD': 'XETHZUSD', - 'XBTUSD': 'XXBTZUSD' - }, - 'XETH': { - 'ETHUSD': 'XETHZUSD', - 'ETHXBT': 'XETHXXBT' - }, - 'XXBT': { - 'ETHXBT': 'XETHXXBT', - 'XBTUSD': 'XXBTZUSD' - } - } class Order(): @@ -76,12 +56,21 @@ class Kraken(): data['userref'] = self.userref return data + class KrakenError(Exception): + def __init__(self, message): + self.message = message + + def __str__(self): + return f'Kraken API Error: {self.message}' + + # Core def __init__(self): self.api_url = 'https://api.kraken.com/' self.api_token = os.getenv('KRAKEN_API_TOKEN') self.api_sec = os.getenv('KRAKEN_API_SEC') + self.asset_pairs = self.get_asset_pairs()['result'] - def _get_kraken_signature(self, urlpath, data, secret): + def _kraken_signature(self, urlpath, data, secret): return base64.b64encode( hmac.new( base64.b64decode(secret), @@ -91,21 +80,52 @@ class Kraken(): hashlib.sha512 ).digest()).decode() - def _kraken_request(self, uri_path, data): - return requests.post( - (self.api_url + uri_path), + def _kraken_post(self, uri_path, data): + resp = requests.post( + f'{self.api_url}{uri_path}', headers = { 'API-Key': self.api_sec, - 'API-Sign': self._get_kraken_signature(uri_path, data, self.api_sec) + 'API-Sign': self._kraken_signature(uri_path, data, self.api_sec) }, data=data ).json() + for error in resp['error']: + raise self.KrakenError(error) + def _kraken_get(self, uri_path): + resp = requests.get(f'{self.api_url}{uri_path}').json() + for error in resp['error']: + raise self.KrakenError(err) + return resp + + # Misc. + def get_asset_markets(self, asset): + return [ + each for each in self.asset_pairs if + self.asset_pairs[each]['base'] == asset or + self.asset_pairs[each]['quote'] == asset + ] + + # Spot market data + def get_asset_pairs(self): + return _kraken_get('/0/public/AssetPairs') + + def get_ohlc(self, asset_pair): + return _kraken_get('/0/public/OHLC?pair={asset_pair}') + + def get_depth(self, asset_pair): + return _kraken_get('/0/public/Depth?pair={asset_pair}') + + def get_trades(self, asset_pair): + return _kraken_get('/0/public/Trades?pair={asset_pair}') + + def get_spread(self, asset_pair): + return _kraken_get('/0/public/Spread?pair={asset_pair}') + + # Account data def get_account_balance(self): - return self._kraken_request('/0/private/Balance', {'nonce': str(int(1000*time.time()))}) + return self._kraken_post('/0/private/Balance', {'nonce': str(int(1000*time.time()))}) + # Spot trading def add_order(self, order): - return self._kraken_request('/0/private/AddOrder', dict(order)) - - def ohlc(self, asset_pair): - return requests.get(f'{self.api_url}/0/public/OHLC?pair={asset_pair}').json() + return self._kraken_post('/0/private/AddOrder', dict(order)) diff --git a/requirements.txt b/requirements.txt index 80ab45a..1e41a8c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -numpy +krakenex +pykrakenapi python-dotenv -requests scipy