From 9114322191c95d1944ea22341d9f1e09fc10fdc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20S=C3=A1nchez?= Date: Wed, 6 Nov 2024 18:55:18 -0300 Subject: [PATCH] optimized switch_to_long --- changelog.txt | 3 +++ main.py | 2 +- trader.py | 47 +++++++++++++++++++++++++++--------------- utils/generate_keys.py | 2 +- 4 files changed, 35 insertions(+), 19 deletions(-) diff --git a/changelog.txt b/changelog.txt index f48377b..91f365c 100755 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +2024.11.06: +. Optimized the conditionals that lead to switch_to_long. + 2024.10.31: . Added an option to set the wait time before sending a new safety order. . Added a per-trader option to enable or disable slippage checks. diff --git a/main.py b/main.py index d0d3e9b..2bf4236 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.31" +version = "2024.11.06" ''' 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 664b56d..13d3d4e 100755 --- a/trader.py +++ b/trader.py @@ -664,7 +664,7 @@ class trader: return 0 - def switch_to_long(self, from_take_profit: bool = False, ignore_old_long: bool = False) -> int: + def switch_to_long(self, ignore_old_long: bool = False, already_received_quote: float = 0) -> int: ''' Takes a short bot and changes the mode to long. Only does it if the current bot was previously a long one. @@ -697,20 +697,17 @@ class trader: return 1 #Cancel open orders - if not from_take_profit: - #I think this exception handler is al pedo. - try: - self.broker.cancel_order(self.so["id"],self.pair) - except Exception as e: - self.broker.logger.log_this(f"Error in cancel_order while cancelling safety order. Exception: {e}",1,self.pair) - #Also this one. - try: - self.broker.cancel_order(self.tp_order["id"],self.pair) - except Exception as e: - self.broker.logger.log_this(f"Error in cancel_order while cancelling take profit order. Exception: {e}",1,self.pair) + try: + self.broker.cancel_order(self.so["id"],self.pair) + except Exception as e: + self.broker.logger.log_this(f"Error in cancel_order while cancelling safety order. Exception: {e}",1,self.pair) + try: + self.broker.cancel_order(self.tp_order["id"],self.pair) + except Exception as e: + self.broker.logger.log_this(f"Error in cancel_order while cancelling take profit order. Exception: {e}",1,self.pair) #Liquidate base - self.liquidate_base(ignore_profits=ignore_old_long) + self.liquidate_base(ignore_profits=ignore_old_long, already_received_quote=already_received_quote) #switch config files and set self.is_short to False try: @@ -743,7 +740,7 @@ class trader: return 0 - def liquidate_base(self, ignore_profits: bool = True) -> int: + def liquidate_base(self, ignore_profits: bool = True, already_received_quote: float = 0) -> int: ''' Fetches the amount of free base on the exchange, sells the entirety of the amount and calculates profits Sends the Telegram message and writes the profits to disk @@ -770,7 +767,7 @@ class trader: #calculate profits if not ignore_profits: - profit = market_tp_order["cost"] - self.status_dict["old_long"]["quote_spent"] - self.status_dict["old_long"]["fees_paid_in_quote"] - fees_paid + profit = already_received_quote + market_tp_order["cost"] - self.status_dict["old_long"]["quote_spent"] - self.status_dict["old_long"]["fees_paid_in_quote"] - fees_paid #self.status_dict["acc_profit"] += profit #Add profits to file and send telegram notifying profits @@ -879,6 +876,8 @@ class trader: self.broker.logger.log_this(f"Fill price: {filled_order['price']} {self.quote}",2,self.pair) self.broker.logger.log_this(f"Safety orders triggered: {self.safety_order_index-1}",2,self.pair) + ''' + RENDERED OBSOLETE BY THE NEW SWITCH TO LONG OPTIMIZATION #Check if it needs to switch the trader mode self.status_dict["pause_reason"] = "check for autoswitch" #If it's a short bot that used to be long AND autoswitch is enabled @@ -894,7 +893,7 @@ class trader: self.restart = True self.broker.logger.log_this("Error, switch_to_long returned 1, pair will be restarted",0,self.pair) return 1 - + ''' self.status_dict["pause_reason"] = "take_profit_routine - check time limit" #Checks if there is a time limit for the trader @@ -1240,8 +1239,22 @@ class trader: return 1 #Check if short price exceeds old long price. If so, send a Telegram message - if self.is_short and self.config_dict["check_old_long_price"]: + if self.is_short and "old_long" in self.status_dict and self.config_dict["check_old_long_price"]: self.check_old_long_price() + + self.status_dict["pause_reason"] = "check for autoswitch" + #If it's a short bot that used to be long AND autoswitch is enabled + if self.is_short and "autoswitch" in self.config_dict and self.config_dict["autoswitch"] and "old_long" in self.status_dict: + #If selling the base currency left at the current market price plus the quote already received turns out to be more than the amount of the old_long, + # it means that we already are in profit territory, switch back to long. + old_target = self.status_dict["old_long"]["tp_price"]*self.status_dict["old_long"]["tp_amount"] + base_left = self.status_dict["old_long"]["tp_amount"]-self.status_dict["base_bought"] + if (base_left*self.status_dict["price"])+self.status_dict["quote_spent"]>=old_target: + #Sell all base (market), report the profits and restart the trader + self.status_dict["pause_reason"] = "automatic_switch" + self.switch_to_long(already_received_quote=self.status_dict["quote_spent"]) + self.restart = True + return 1 #Render status line(s) self.status_dict["status_string"] = self.generate_status_strings() diff --git a/utils/generate_keys.py b/utils/generate_keys.py index f251249..622fd59 100644 --- a/utils/generate_keys.py +++ b/utils/generate_keys.py @@ -9,7 +9,7 @@ for user in users: keys.append([user,str(uuid.uuid4())]) -database_connection = sqlite3.connect("../api_credentials.db") +database_connection = sqlite3.connect("api_credentials.db") database_cursor = database_connection.cursor() database_cursor.execute("CREATE TABLE IF NOT EXISTS credentials_table (user TEXT, key TEXT)")