From 452bddbe3e06e54f498f03842f81c42f5b492188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20S=C3=A1nchez?= Date: Tue, 29 Oct 2024 11:24:01 -0300 Subject: [PATCH] Changes in slippage detection --- changelog.txt | 3 +++ exchange_wrapper.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ main.py | 2 +- trader.py | 35 ++++++++++++++--------------------- 4 files changed, 62 insertions(+), 22 deletions(-) diff --git a/changelog.txt b/changelog.txt index 829b811..4598c27 100755 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +2024.10.29: +. New functions to get top ask and top bid prices. + 2024.10.28: . Docstrings and comments improvements. . New endpoint: /edit_cooldown_multiplier. diff --git a/exchange_wrapper.py b/exchange_wrapper.py index 1f921ba..2ac9127 100755 --- a/exchange_wrapper.py +++ b/exchange_wrapper.py @@ -337,6 +337,50 @@ class broker: return self.last_price + def get_top_ask_price(self,symbol): + ''' + Returns the top ask price for the given symbol + + Parameters: + symbol: the symbol to get the top ask price for + + Returns: + the top ask price for the given symbol + ''' + + orderbook = self.get_order_book(symbol) + if orderbook=={}: + self.logger.log_this("Can't fetch orderbook (from get_top_ask_price)",1,symbol) + return self.get_ticker_price(symbol) + try: + return orderbook["asks"][0][0] + except Exception as e: + self.logger.log_this(f"Exception getting top ask price: {e}",1,symbol) + return self.get_ticker_price(symbol) + + + def get_top_bid_price(self,symbol): + ''' + Returns the top bid price for the given symbol + + Parameters: + symbol: the symbol to get the top bid price for + + Returns: + the top bid price for the given symbol + ''' + + orderbook = self.get_order_book(symbol) + if orderbook=={}: + self.logger.log_this("Can't fetch orderbook (from get_top_bid_price)",1,symbol) + return self.get_ticker_price(symbol) + try: + return orderbook["bids"][0][0] + except Exception as e: + self.logger.log_this(f"Exception getting top mid price: {e}",1,symbol) + return self.get_ticker_price(symbol) + + def get_mid_price(self,symbol): ''' Retrieves the orderbook and returns the average price [(top bid + top ask)/2] diff --git a/main.py b/main.py index dd484f3..a8367fd 100644 --- a/main.py +++ b/main.py @@ -22,7 +22,7 @@ In case the permissions of the certificate changes, reset them this way: # ll /etc/letsencrypt/ ''' -version = "2024.10.28" +version = "2024.10.29" ''' Color definitions. If you want to change them, check the reference at https://en.wikipedia.org/wiki/ANSI_escape_code#Colors diff --git a/trader.py b/trader.py index 21dd5d2..066c5f2 100755 --- a/trader.py +++ b/trader.py @@ -890,7 +890,7 @@ class trader: self.stop_when_profit = True self.status_dict["pause_reason"] = "take_profit_routine - if stop_when_profit" - if self.stop_when_profit: #Signal to stop when profit + if self.stop_when_profit: #Signal to stop when trade is closed self.broker.logger.log_this("Pair shutting down. So long and thanks for all the fish",0,self.pair) self.quit = True return 1 @@ -906,23 +906,16 @@ class trader: #self.safety_order_index = 0 self.config_dict = self.reload_config_dict() - self.status_dict["pause_reason"] = "take_profit_routine - Cooldown" - self.broker.logger.log_this(f"Cooldown period...",2,self.pair) - time.sleep(self.broker.get_wait_time()*self.broker.get_cooldown_multiplier()) - - try: - percentage_difference = abs(filled_order['price']-self.broker.get_mid_price(self.pair))/filled_order["price"] - if percentage_difference>self.broker.get_slippage_default_threshold(): - #self.broker.logger.log_this(f"Slippage threshold exceeded, {self.broker.get_wait_time()*self.broker.get_cooldown_multiplier()}s cooldown.",1,self.pair) - self.broker.logger.log_this(f"Slippage threshold exceeded, waiting for cooldown and restarting pair",1,self.pair) - time.sleep(self.broker.get_wait_time()*self.broker.get_cooldown_multiplier()) - self.pause = False - self.restart = True - #self.write_status_file(True) - return 1 - except Exception as e: - self.broker.logger.log_this(f"Exception while calculating percentage difference: {e}",1,self.pair) - self.broker.logger.log_this(f"Resuming...",2,self.pair) + self.broker.logger.log_this("Checking slippage...",2,self.pair) + price_to_compare = self.broker.get_top_bid_price(self.pair) if self.is_short else self.broker.get_top_ask_price(self.pair) + if abs(filled_order["price"]-price_to_compare)/filled_order["price"]>self.broker.get_slippage_default_threshold(): + self.broker.logger.log_this(f"Slippage threshold exceeded, waiting for cooldown and restarting pair",1,self.pair) + time.sleep(self.broker.get_wait_time()*self.broker.get_cooldown_multiplier()) + #The trader is restarted by the instance instead of by itself to allow a couple of more seconds for the price to return to normal. + #This could also be the default behavior. + self.pause = False + self.restart = True + return 1 #Restarting the trader self.status_dict["pause_reason"] = "take_profit_routine - restart_bot call" @@ -1083,7 +1076,7 @@ class trader: return 0 - def check_slippage(self, threshold: float, order_size: float) -> bool: + def check_slippage(self, threshold: float, order_size: float, old_price: float = 0) -> bool: ''' Checks that the slippage is between range. Returns True if threshold is exceeded, False otherwise. ''' @@ -1093,9 +1086,9 @@ class trader: return False suma = 0 try: - mid_price = (order_book["asks"][0][0]+order_book["bids"][0][0])/2 + mid_price = old_price if old_price!=0 else (order_book["asks"][0][0]+order_book["bids"][0][0])/2 amount = (order_size/mid_price)*2 #Extra margin to avoid surprises. - first_price = order_book["asks"][0][0] + first_price = order_book["asks"][0][0] #This could be first_price = old_price if old_price!=0 else order_book["asks"][0][0] for x in order_book["asks"]: suma += x[1] if suma>=amount: