From cab571f549eb462c5e6efc383b4fa8dc4bc21f09 Mon Sep 17 00:00:00 2001 From: eric o meehan Date: Sat, 14 Sep 2024 12:45:19 -0400 Subject: [PATCH] v0.0.7 --- Dockerfile | 4 ++ app.py | 108 ---------------------------------------- kraken-bot/KrakenBot.py | 98 ++++++++++++++++++++++++++++++++++++ kraken-bot/__init__.py | 0 kraken-bot/app.py | 17 +++++++ 5 files changed, 119 insertions(+), 108 deletions(-) create mode 100644 Dockerfile delete mode 100644 app.py create mode 100644 kraken-bot/KrakenBot.py create mode 100644 kraken-bot/__init__.py create mode 100644 kraken-bot/app.py diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..14a6c8d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,4 @@ +FROM debian +RUN apt-get update && apt-get install -y python3-pip +RUN pip3 install --break-system-packages krakenex pykrakenapi python-dotenv scipy +COPY kraken-bot /usr/local/src/kraken-bot diff --git a/app.py b/app.py deleted file mode 100644 index b16c3ce..0000000 --- a/app.py +++ /dev/null @@ -1,108 +0,0 @@ -import krakenex -import os -import pandas -import time - -from dotenv import load_dotenv -from pykrakenapi import KrakenAPI -from scipy.stats import linregress -from time import sleep - -load_dotenv() - -R_VALUE_TARGET = float(os.getenv('R_VALUE_TARGET')) -INVESTMENT_COUNT = int(os.getenv('INVESTMENT_COUNT')) -INVESTMENT_VOLUME = float(os.getenv('INVESTMENT_VOLUME')) - -k = krakenex.API( - os.getenv('KRAKEN_API_TOKEN'), - os.getenv('KRAKEN_API_SEC') - ) -kraken = KrakenAPI(k, tier='Pro') - -def filter_asset_pairs(tradable_asset_pairs): - return tradable_asset_pairs[ - (tradable_asset_pairs['quote'] == 'ZUSD') & - (tradable_asset_pairs['status'] == 'online') - ] - -def model_asset_pair(asset_pair): - ohlc = kraken.get_ohlc_data(asset_pair)[0] - sleep(kraken.factor) - model = 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() - model.columns = ['slope', 'intercept', 'r_value', 'p_value', 'stderr'] - return model - -def grade_models(models): - model_averages = pandas.DataFrame({ - model: { - 'slope': models[model].slope.mean(), - 'intercept': models[model].intercept.mean(), - 'r_value': models[model].r_value.mean(), - 'p_value': models[model].p_value.mean(), - 'stderr': models[model].stderr.mean() - } for model in models - }).transpose() - filtered_models = model_averages[ - (model_averages['r_value'] >= R_VALUE_TARGET) & - (model_averages['slope'] > 0) - ] - return filtered_models.sort_values(by='slope', ascending=False) - -def sell_asset(market, volume): - kraken.add_standard_order( - ordertype = 'market', - type = 'sell', - pair = market, - volume = volume, - validate = False - ) - sleep(kraken.factor) - print(f"Sold {volume} on {market}") - -def buy_asset(market, volume): - kraken.add_standard_order( - ordertype = 'market', - type = 'buy', - pair = market, - volume = volume, - validate = False - ) - print(f"Purchased {volume} on {market}") - sleep(kraken.factor) - -def main(): - asset_pairs = filter_asset_pairs(kraken.get_tradable_asset_pairs()) - sleep(kraken.factor) - graded_models = grade_models( - {asset_pair: model_asset_pair(asset_pair) for asset_pair in asset_pairs.index} - ) - - account_balance = kraken.get_account_balance() - for asset in account_balance[(account_balance.index != 'ZUSD') & (account_balance.vol > 0)]: - for market in asset_pairs[asset_pairs['base'] == asset].index: - if market not in graded_models[:INVESTMENT_COUNT].index: - sell_asset(market, account_balance.loc[asset].vol) - - account_balance = kraken.get_account_balance() - while ((len(account_balance[account_balance.vol > 0]) - 1 < INVESTMENT_COUNT) & - (account_balance.loc['ZUSD'].vol > INVESTMENT_VOLUME)): - for market in graded_models.index: - if asset_pairs.loc[market].base not in account_balance[account_balance.vol > 0].index: - ohlc, last = kraken.get_ohlc_data(market) - volume = INVESTMENT_VOLUME/ohlc.iloc[-1].close - buy_asset(market, volume) - account_balance = kraken.get_account_balance() - sleep(kraken.factor) - break - - print(kraken.get_account_balance()) - print(kraken.get_trade_balance(asset='ZUSD')) - -if __name__ == '__main__': - main() diff --git a/kraken-bot/KrakenBot.py b/kraken-bot/KrakenBot.py new file mode 100644 index 0000000..61e52be --- /dev/null +++ b/kraken-bot/KrakenBot.py @@ -0,0 +1,98 @@ +import krakenex +import pandas +import time + +from pykrakenapi import KrakenAPI +from scipy.stats import linregress + +class KrakenBot(): + def __init__(self, kraken_api_token, kraken_api_sec, tier, r_value_target, investment_count, investment_volume): + self.r_value_target = r_value_target + self.investment_count = investment_count + self.investment_volume = investment_volume + k = krakenex.API(kraken_api_token, kraken_api_sec) + self.kraken = KrakenAPI(k, tier=tier) + + def filter_asset_pairs(self, tradable_asset_pairs): + return tradable_asset_pairs[ + (tradable_asset_pairs['quote'] == 'ZUSD') & + (tradable_asset_pairs['status'] == 'online') + ] + + def model_asset_pair(self, asset_pair): + ohlc = self.kraken.get_ohlc_data(asset_pair)[0] + time.sleep(self.kraken.factor) + model = 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() + model.columns = ['slope', 'intercept', 'r_value', 'p_value', 'stderr'] + return model + + def grade_models(self, models): + model_averages = pandas.DataFrame({ + model: { + 'slope': models[model].slope.mean(), + 'intercept': models[model].intercept.mean(), + 'r_value': models[model].r_value.mean(), + 'p_value': models[model].p_value.mean(), + 'stderr': models[model].stderr.mean() + } for model in models + }).transpose() + filtered_models = model_averages[ + (model_averages['r_value'] >= self.r_value_target) & + (model_averages['slope'] > 0) + ] + return filtered_models.sort_values(by='slope', ascending=False) + + def sell_asset(self, market, volume): + self.kraken.add_standard_order( + ordertype = 'market', + type = 'sell', + pair = market, + volume = volume, + validate = False + ) + time.sleep(self.kraken.factor) + print(f"Sold {volume} on {market}") + + def buy_asset(self, market, volume): + self.kraken.add_standard_order( + ordertype = 'market', + type = 'buy', + pair = market, + volume = volume, + validate = False + ) + print(f"Purchased {volume} on {market}") + time.sleep(self.kraken.factor) + + def update(self): + asset_pairs = self.filter_asset_pairs(self.kraken.get_tradable_asset_pairs()) + time.sleep(self.kraken.factor) + graded_models = self.grade_models( + {asset_pair: self.model_asset_pair(asset_pair) for asset_pair in asset_pairs.index} + ) + + account_balance = self.kraken.get_account_balance() + for asset in account_balance[(account_balance.index != 'ZUSD') & (account_balance.vol > 0)]: + for market in asset_pairs[asset_pairs['base'] == asset].index: + if market not in graded_models[:self.investment_count].index: + self.sell_asset(market, account_balance.loc[asset].vol) + + account_balance = self.kraken.get_account_balance() + while ((len(account_balance[account_balance.vol > 0]) - 1 < self.investment_count) & + (account_balance.loc['ZUSD'].vol > self.investment_volume)): + for market in graded_models.index: + if asset_pairs.loc[market].base not in account_balance[account_balance.vol > 0].index: + ohlc, last = self.kraken.get_ohlc_data(market) + volume = self.investment_volume/ohlc.iloc[-1].close + self.buy_asset(market, volume) + account_balance = self.kraken.get_account_balance() + time.sleep(self.kraken.factor) + break + + print(self.kraken.get_account_balance()) + print(self.kraken.get_trade_balance(asset='ZUSD')) diff --git a/kraken-bot/__init__.py b/kraken-bot/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/kraken-bot/app.py b/kraken-bot/app.py new file mode 100644 index 0000000..d6fa8a4 --- /dev/null +++ b/kraken-bot/app.py @@ -0,0 +1,17 @@ +import os + +from KrakenBot import KrakenBot +from dotenv import load_dotenv + +load_dotenv() +bot = KrakenBot( + kraken_api_token = os.getenv('KRAKEN_API_TOKEN'), + kraken_api_sec = os.getenv('KRAKEN_API_SEC'), + tier = 'Pro', + r_value_target = float(os.getenv('R_VALUE_TARGET')), + investment_count = int(os.getenv('INVESTMENT_COUNT')), + investment_volume = float(os.getenv('INVESTMENT_VOLUME')) + ) + +if __name__ == '__main__': + bot.update()