From 82c26a79a362dbcd5beb0d9f27fa64f1d4141dd4 Mon Sep 17 00:00:00 2001 From: Azulinho Date: Tue, 27 Jun 2023 22:01:22 +0100 Subject: [PATCH] return default ticker values if symbol not in config This change will allow to always process lines for each coin, so that in prove-backtesting we will have full coin state between backtesting runs. --- lib/bot.py | 182 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 147 insertions(+), 35 deletions(-) diff --git a/lib/bot.py b/lib/bot.py index 28fced5..54ff569 100644 --- a/lib/bot.py +++ b/lib/bot.py @@ -33,6 +33,33 @@ limiter = Limiter(rate) +def get_ticker_with_default(tickers, symbol, key) -> str: + """returns ticker values with default if symbol doesn't exist""" + + if symbol not in tickers: + if key == "BUY_AT_PERCENTAGE": + return "-99999999" + if key == "SELL_AT_PERCENTAGE": + return "+99999999" + if key == "STOP_LOSS_AT_PERCENTAGE": + return "-99999999" + if key == "TRAIL_TARGET_SELL_PERCENTAGE": + return "-1" + if key == "TRAIL_RECOVERY_PERCENTAGE": + return "-1" + if key == "SOFT_LIMIT_HOLDING_TIME": + return "99999999999999" + if key == "HARD_LIMIT_HOLDING_TIME": + return "999999999999999999999" + if key == "NAUGHTY_TIMEOUT": + return "999999999999999999" + if key == "KLINES_TREND_PERIOD": + return "3d" + if key == "KLINES_SLICE_PERCENTAGE_CHANGE": + return "+99999999" + return str(tickers[symbol][key]) + + class Bot: """Bot Class""" @@ -1127,19 +1154,39 @@ def clear_coin_stats(self, coin: Coin) -> None: coin.holding_time = 1 coin.buy_at_percentage = add_100( - float(self.tickers[coin.symbol]["BUY_AT_PERCENTAGE"]) + float( + get_ticker_with_default( + self.tickers, coin.symbol, "BUY_AT_PERCENTAGE" + ) + ) ) coin.sell_at_percentage = add_100( - float(self.tickers[coin.symbol]["SELL_AT_PERCENTAGE"]) + float( + get_ticker_with_default( + self.tickers, coin.symbol, "SELL_AT_PERCENTAGE" + ) + ) ) coin.stop_loss_at_percentage = add_100( - float(self.tickers[coin.symbol]["STOP_LOSS_AT_PERCENTAGE"]) + float( + get_ticker_with_default( + self.tickers, coin.symbol, "STOP_LOSS_AT_PERCENTAGE" + ) + ) ) coin.trail_target_sell_percentage = add_100( - float(self.tickers[coin.symbol]["TRAIL_TARGET_SELL_PERCENTAGE"]) + float( + get_ticker_with_default( + self.tickers, coin.symbol, "TRAIL_TARGET_SELL_PERCENTAGE" + ) + ) ) coin.trail_recovery_percentage = add_100( - float(self.tickers[coin.symbol]["TRAIL_RECOVERY_PERCENTAGE"]) + float( + get_ticker_with_default( + self.tickers, coin.symbol, "TRAIL_RECOVERY_PERCENTAGE" + ) + ) ) coin.bought_at = float(0) coin.dip = float(0) @@ -1284,17 +1331,13 @@ def load_coins(self) -> None: with open(coins_state_file, "rt") as f: objects: dict[str, Any] = dict(json.loads(f.read())) for symbol in objects.keys(): # pylint: disable=C0206 - # discard any coins for which we don't have tickers info - # if we don't, init_or_update_coin() would raise and error - # as we would be missing the BUY/SELL percentages - if symbol in self.tickers: - self.init_or_update_coin( - objects[symbol], load_klines=load_klines - ) + self.init_or_update_coin( + objects[symbol], load_klines=load_klines + ) - # pylint: disable=consider-using-dict-items - for k, v in objects[symbol].items(): - setattr(self.coins[symbol], k, v) + # pylint: disable=consider-using-dict-items + for k, v in objects[symbol].items(): + setattr(self.coins[symbol], k, v) logging.warning(f"coins contains {str(self.coins.keys())}") @@ -1319,35 +1362,63 @@ def load_coins(self) -> None: logging.warning(f"overriding values from config for: {symbols}") for symbol in self.coins: # pylint: disable=C0206 self.coins[symbol].buy_at_percentage = add_100( - self.tickers[symbol]["BUY_AT_PERCENTAGE"] + get_ticker_with_default( + self.tickers, symbol, "BUY_AT_PERCENTAGE" + ) ) + self.coins[symbol].sell_at_percentage = add_100( - self.tickers[symbol]["SELL_AT_PERCENTAGE"] + get_ticker_with_default( + self.tickers, symbol, "SELL_AT_PERCENTAGE" + ) ) + self.coins[symbol].stop_loss_at_percentage = add_100( - self.tickers[symbol]["STOP_LOSS_AT_PERCENTAGE"] + get_ticker_with_default( + self.tickers, symbol, "STOP_LOSS_AT_PERCENTAGE" + ) ) + self.coins[symbol].soft_limit_holding_time = int( - self.tickers[symbol]["SOFT_LIMIT_HOLDING_TIME"] + get_ticker_with_default( + self.tickers, symbol, "SOFT_LIMIT_HOLDING_TIME" + ) ) + self.coins[symbol].hard_limit_holding_time = int( - self.tickers[symbol]["HARD_LIMIT_HOLDING_TIME"] + get_ticker_with_default( + self.tickers, symbol, "HARD_LIMIT_HOLDING_TIME" + ) ) + self.coins[symbol].trail_target_sell_percentage = add_100( - self.tickers[symbol]["TRAIL_TARGET_SELL_PERCENTAGE"] + get_ticker_with_default( + self.tickers, symbol, "TRAIL_TARGET_SELL_PERCENTAGE" + ) ) + self.coins[symbol].trail_recovery_percentage = add_100( - self.tickers[symbol]["TRAIL_RECOVERY_PERCENTAGE"] + get_ticker_with_default( + self.tickers, symbol, "TRAIL_RECOVERY_PERCENTAGE" + ) ) + self.coins[symbol].klines_trend_period = str( - self.tickers[symbol]["KLINES_TREND_PERIOD"] + get_ticker_with_default( + self.tickers, symbol, "KLINES_TREND_PERIOD" + ) ) + self.coins[symbol].klines_slice_percentage_change = float( - self.tickers[symbol]["KLINES_SLICE_PERCENTAGE_CHANGE"] + get_ticker_with_default( + self.tickers, symbol, "KLINES_SLICE_PERCENTAGE_CHANGE" + ) ) self.coins[symbol].naughty_timeout = int( - self.tickers[symbol]["NAUGHTY_TIMEOUT"] + get_ticker_with_default( + self.tickers, symbol, "NAUGHTY_TIMEOUT" + ) ) # log some info on the coins in our wallet at boot @@ -1527,17 +1598,58 @@ def process_line( symbol, float(date), float(market_price), - float(self.tickers[symbol]["BUY_AT_PERCENTAGE"]), - float(self.tickers[symbol]["SELL_AT_PERCENTAGE"]), - float(self.tickers[symbol]["STOP_LOSS_AT_PERCENTAGE"]), - float(self.tickers[symbol]["TRAIL_TARGET_SELL_PERCENTAGE"]), - float(self.tickers[symbol]["TRAIL_RECOVERY_PERCENTAGE"]), - int(self.tickers[symbol]["SOFT_LIMIT_HOLDING_TIME"]), - int(self.tickers[symbol]["HARD_LIMIT_HOLDING_TIME"]), - int(self.tickers[symbol]["NAUGHTY_TIMEOUT"]), - str(self.tickers[symbol]["KLINES_TREND_PERIOD"]), - float(self.tickers[symbol]["KLINES_SLICE_PERCENTAGE_CHANGE"]), + float( + get_ticker_with_default( + self.tickers, symbol, "BUY_AT_PERCENTAGE" + ) + ), + float( + get_ticker_with_default( + self.tickers, symbol, "SELL_AT_PERCENTAGE" + ) + ), + float( + get_ticker_with_default( + self.tickers, symbol, "STOP_LOSS_AT_PERCENTAGE" + ) + ), + float( + get_ticker_with_default( + self.tickers, symbol, "TRAIL_TARGET_SELL_PERCENTAGE" + ) + ), + float( + get_ticker_with_default( + self.tickers, symbol, "TRAIL_RECOVERY_PERCENTAGE" + ) + ), + int( + get_ticker_with_default( + self.tickers, symbol, "SOFT_LIMIT_HOLDING_TIME" + ) + ), + int( + get_ticker_with_default( + self.tickers, symbol, "HARD_LIMIT_HOLDING_TIME" + ) + ), + int( + get_ticker_with_default( + self.tickers, symbol, "NAUGHTY_TIMEOUT" + ) + ), + str( + get_ticker_with_default( + self.tickers, symbol, "KLINES_TREND_PERIOD" + ) + ), + float( + get_ticker_with_default( + self.tickers, symbol, "KLINES_SLICE_PERCENTAGE_CHANGE" + ) + ), ) + if self.check_for_delisted_coin(symbol): return else: