diff --git a/changelog.txt b/changelog.txt index c1d2262..f827861 100755 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,13 @@ +2025.05.16: +. Added exception handling when removing a trader. +. Minor variable renaming. + +2025.05.12: +. Improved config file handling when switching to long or short. +. If the config file does not exist, it creates it. + 2025.05.05: -. Forced Telegram message when a quit flag is raised. +. Forced Telegram message when quit flag is raised. 2025.05.04: . Simplified unwrapped_add_pair. diff --git a/config_handler.py b/config_handler.py index 77897ad..057c28a 100644 --- a/config_handler.py +++ b/config_handler.py @@ -37,13 +37,18 @@ class ConfigHandler: self.config_dictionary = self.default_config_dictionary.copy() #Loads from disk the config file (if it exists) - self.load_from_file() + if self.load_from_file()==1: + #If the config file does not exist, write a new one with the default values + self.save_to_file() if config_dict is not None: self.config_dictionary = {**self.config_dictionary, **config_dict} self.save_to_file() + def reset_to_default(self): + self.config_dictionary = self.default_config_dictionary.copy() + return 0 def get_pair(self): return self.config_dictionary["pair"] diff --git a/main.py b/main.py index 485d551..aff3b0f 100644 --- a/main.py +++ b/main.py @@ -16,7 +16,7 @@ import exchange_wrapper import trader -version = "2025.05.05" +version = "2025.05.16" ''' Color definitions. If you want to change them, check the reference at https://en.wikipedia.org/wiki/ANSI_escape_code#Colors @@ -244,7 +244,10 @@ def restart_pair_no_json(base: str, quote: str) -> int: elif order["symbol"]==f"{base}/{quote}" and not x.config.get_is_short() and order["side"]=="buy": broker.logger.log_this(f"Cancelling old buy orders",2,f"{base}/{quote}") broker.cancel_order(order["id"],order["symbol"]) - running_instances.remove(x) + try: + running_instances.remove(x) + except ValueError: + broker.logger.log_this(f"Instance {x.config.get_pair()} not found in running_instances.",1,x.config.get_pair()) add_instance(base,quote) return 0 return 1 @@ -274,7 +277,10 @@ def main_loop(): broker.rewrite_config_file() if x.config.get_pair() in worker_status: del(worker_status[x.config.get_pair()]) - running_instances.remove(x) + try: + running_instances.remove(x) + except ValueError: + broker.logger.log_this(f"Instance {x.config.get_pair()} not found in running_instances.",1,x.config.get_pair()) #Adds pending traders if bool(instances_to_add): diff --git a/trader.py b/trader.py index 8741cd5..4de13b8 100755 --- a/trader.py +++ b/trader.py @@ -496,19 +496,6 @@ class trader: self.pause = True self.status.set_pause_reason("switch_to_short") - #Read the config file - self.broker.logger.log_this("Reading config file",2,self.config.get_pair()) - try: - with open(f"configs/{self.base}{self.quote}.json","r") as f: - old_config = json.load(f) - except Exception as e: - self.broker.logger.log_this(f"Error. Can't read the config file. Can't switch mode. Exception: {e}",1,self.config.get_pair()) - self.pause = False - self.status.set_pause_reason("") - return 1 - - #Calculate if there is enough base and, if so, calculate the optimal order size - #Fetch the real amount of available base self.broker.logger.log_this(f"Fetching available {self.base}",2,self.config.get_pair()) free_base = self.fetch_free_base() @@ -566,21 +553,16 @@ class trader: #Modify config file accordingly self.broker.logger.log_this("Modifying config file and saving a backup",2,self.config.get_pair()) try: - with open(f"configs/{self.base}{self.quote}.bak","w") as c: - c.write(json.dumps(old_config, indent=4)) - old_config["is_short"] = True - #old_config["order_size"] = optimal_order_size #Now calculated on-the-fly at the start of every deal - #old_config["no_of_safety_orders"] = amount_of_so - #4. Write the config file - with open(f"configs/{self.base}{self.quote}.json","w") as c: - c.write(json.dumps(old_config, indent=4)) + self.config.save_to_file(f"configs/{self.base}{self.quote}.bak") + self.config.set_is_short(True) + self.config.save_to_file() self.broker.logger.log_this("Config file updated",2,self.config.get_pair()) except Exception as e: self.broker.logger.log_this(f"Error. Can't write the config file. Exception: {e}",1,self.config.get_pair()) #self.pause = False return 1 self.status.set_stop_when_profit(False) - self.config.set_is_short(True) + #self.config.set_is_short(True) self.broker.logger.log_this("Done configuring. Starting bot...",2,self.config.get_pair()) return 0 @@ -590,13 +572,13 @@ class trader: Takes a short bot and changes the mode to long. Only does it if the current bot was previously a long one. ''' - - #Check if it's not already long - if not self.config.get_is_short(): - self.broker.logger.log_this("Can't switch a long trader to long, there's nothing to do",1,self.config.get_pair()) - return 1 + if not self.config.get_is_short(): + self.broker.logger.log_this("Trader already in long mode, nothing to do",1,self.config.get_pair()) + return 1 self.broker.logger.log_this("Attempting to switch to long bot",0,self.config.get_pair()) + + #Check old_long data if not ignore_old_long and self.status.get_old_long()=={}: self.broker.logger.log_this("Can't find old long info on status_dict, searching for oldlong file",1,self.config.get_pair()) try: @@ -624,21 +606,21 @@ class trader: except Exception as e: self.broker.logger.log_this(f"Error in cancel_order while cancelling take profit order. Exception: {e}",1,self.config.get_pair()) - #Liquidate base + #Sell all base currency self.liquidate_base(ignore_profits=ignore_old_long, already_received_quote=already_received_quote) - #switch config files and set self.config.get_is_short() to False - try: + #Rewrite config file (if it exists) + if os.path.isfile(f"configs/{self.base}{self.quote}.bak") and os.path.isfile(f"configs/{self.base}{self.quote}.json"): with open(f"configs/{self.base}{self.quote}.bak") as c: - old_config = json.load(c) + old_config = json.load(c) with open(f"configs/{self.base}{self.quote}.json","w") as c: c.write(json.dumps(old_config, indent=4)) - self.config.load_from_file() - self.config.set_is_short(False) #This probably is not needed - except Exception as e: - self.broker.logger.log_this(f"Exception in switch_to_long while switching config files: {e}",1,self.config.get_pair()) - self.quit = True - return 1 + if self.config.load_from_file()==1: + self.config.reset_to_default() + else: + self.broker.logger.log_this("Config/backup file does not exist",1,self.config.get_pair()) + self.config.reset_to_default() + self.config.save_to_file() #Remove old_long file (if it exists) if os.path.isfile(f"status/{self.base}{self.quote}.oldlong"): @@ -958,13 +940,13 @@ class trader: amount = (order_size/mid_price)*2 #Extra margin to avoid surprises. else: amount = order_size*2 - first_price = order_book["asks"][0][0] + top_price = order_book["asks"][0][0] for x in order_book["asks"]: suma += x[1] if suma>=amount: last_price = x[0] break - if last_price-first_price>first_price*threshold: + if last_price-top_price>top_price*threshold: #Threshold exceeded return True return False