diff --git a/changelog.txt b/changelog.txt index 9bbc7b2..7dc5338 100755 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,7 @@ +2025.08.15: +. "deal order history" is now disabled by default. +. CPU optimizations in status string generation. + 2025.08.14: . Refactored gib_so_size. . Refactored seconds_to_time. diff --git a/exchange_wrapper.py b/exchange_wrapper.py index f0d203c..503fe48 100755 --- a/exchange_wrapper.py +++ b/exchange_wrapper.py @@ -23,7 +23,8 @@ class Broker: self.retries = self.broker_config["retries"] if "retries" in self.broker_config else 5 self.slippage_default_threshold = self.broker_config["slippage_default_threshold"] if "slippage_default_threshold" in self.broker_config else .03 self.logger = Logger(self.broker_config) - self.write_order_history = True #This should be a toggle in config_file + self.follow_order_history = False #This should be a toggle in config_file + self.write_order_history = False #This should be a toggle in config_file #Initialize database self.profits_database_filename = "profits/profits_database.db" @@ -198,6 +199,9 @@ class Broker: def get_write_order_history(self): return self.write_order_history + def get_follow_order_history(self): + return self.follow_order_history + def get_cooldown_multiplier(self): return self.cooldown_multiplier diff --git a/main.py b/main.py index b341504..a1418ed 100644 --- a/main.py +++ b/main.py @@ -16,7 +16,7 @@ import exchange_wrapper import trader -version = "2025.08.14" +version = "2025.08.15" ''' Color definitions. If you want to change them, check the reference at https://en.wikipedia.org/wiki/ANSI_escape_code#Colors @@ -345,7 +345,9 @@ def main_loop(): screen_buffer.append(str(instance)) #Updates some global status variables prior to deletion of those - global_status["online_workers"] = online_pairs.copy() + #global_status["online_workers"] = online_pairs.copy() + if len(running_traders)!=len(global_status["online_workers"]): + global_status["online_workers"] = [instance.config.get_pair() for instance in running_traders] #Check for paused pairs global_status["paused_traders"] = [instance.config.get_pair() for instance in running_traders if instance.pause] @@ -2413,9 +2415,9 @@ if __name__=="__main__": import_mode = True if "--first_start" in argv: import_mode = False - print(time.strftime("[%Y/%m/%d %H:%M:%S] | Initializing in FIRST START MODE, press enter to start...")) + print(time.strftime("[%Y/%m/%d %H:%M:%S] | Initializing in FIRST START MODE, press to start...")) else: - print(time.strftime("[%Y/%m/%d %H:%M:%S] | Initializing in IMPORT MODE, press enter to start...")) + print(time.strftime("[%Y/%m/%d %H:%M:%S] | Initializing in IMPORT MODE, press to start...")) input() #Load exchange config diff --git a/status_handler.py b/status_handler.py index 6b1f6ee..c17b5ec 100644 --- a/status_handler.py +++ b/status_handler.py @@ -389,7 +389,8 @@ class StatusHandler: def update_deal_order_history(self, new_deal: dict): # if not isinstance(new_deal, dict): # self.broker.logger.log_this(f"value provided is not a dict",1,self.get_pair()) - self.status_dictionary["deal_order_history"].append(self.strip_order(new_deal)) + if not self.broker.get_follow_order_history(): + self.status_dictionary["deal_order_history"].append(self.strip_order(new_deal)) return 0 def strip_order(self, order): diff --git a/trader.py b/trader.py index 0f13353..3bd1aa6 100755 --- a/trader.py +++ b/trader.py @@ -29,6 +29,12 @@ class trader: self.market_reload_period = 86400 #Market reload period in seconds self.status.set_start_time(int(time.time())) self.last_time_seen = time.time() + + #Status string caches + self.status_string_cache = "" + self.low_price_cache = None + self.mid_price_cache = None + self.high_price_cache = None if self.config.get_is_short(): #Check if there is an old_long file. If so, load it. @@ -71,6 +77,22 @@ class trader: return self.status.get_status_string() + def get_color(self, color): + ''' + Returns white if color does not exist + ''' + colors = {"yellow": "\033[0;33;40m", + "green": "\033[0;32;40m", + "red": "\033[0;31;40m", + "blue": "\033[0;34;40m", + "cyan": "\033[0;36;40m", + "bright_white": "\033[0;97;40m", + "bright_green": "\033[0;92;40m", + "white": "\033[0;37;40m"} + return colors[color] if color in colors else "\033[0;37;40m" + + + def get_status_dict(self): return self.status.get_status() @@ -1429,14 +1451,11 @@ class trader: ''' Returns the status string properly formatted for screen output ''' - yellow = "\033[0;33;40m" - green = "\033[0;32;40m" - red = "\033[0;31;40m" - blue = "\033[0;34;40m" - cyan = "\033[0;36;40m" - bright_white = "\033[0;97;40m" - bright_green = "\033[0;92;40m" - white = "\033[0;37;40m" + + decimals = 11 + low_percentage = 1 + mid_percentage = 10 + high_percentage = 20 def draw_line(price,min_value,max_value,break_even): ''' @@ -1452,98 +1471,108 @@ class trader: self.broker.logger.log_this(f"{e}") value = 1 if min_value=break_even else red + color = self.get_color("green") if price>=break_even else self.get_color("red") else: - color = red if price>=break_even else green - return f"{color}{'='*value}{white}{'='*max(0,(80-value))}"[:100] + color = self.get_color("red") if price>=break_even else self.get_color("green") + return f"{color}{'='*value}{self.get_color('white')}{'='*max(0,(80-value))}"[:100] - decimals = 11 - low_percentage = 1 - mid_percentage = 10 - high_percentage = 20 - - safety_order_string = f"{self.status.get_so_amount()-1}/{self.config.get_no_of_safety_orders()}".rjust(5) - low_price = self.status.get_next_so_price() if self.status.get_next_so_price() is not None else 0 mid_price = self.status.get_price() if self.status.get_price() is not None else 0 high_price = self.status.get_take_profit_price() if self.status.get_take_profit_price() is not None else 0 - low_boundary = '{:.20f}'.format(low_price)[:decimals].center(decimals) - mid_boundary = '{:.20f}'.format(mid_price)[:decimals].center(decimals) - high_boundary = '{:.20f}'.format(high_price)[:decimals].center(decimals) + if low_price==self.low_price_cache and mid_price==self.mid_price_cache and high_price==self.high_price_cache: + #status_string = self.status_string_cache + #Edit uptime + position = self.status_string_cache.find("Uptime") + new_uptime = self.seconds_to_time(self.status.get_deal_uptime()) + status_string = self.status_string_cache[:position+8] + new_uptime + self.status_string_cache[position+8+len(new_uptime):] + else: + #Update caches + self.low_price_cache = low_price + self.mid_price_cache = mid_price + self.high_price_cache = high_price - percentage_to_profit = 100 - pct_to_profit_str = "XX.XX" - if mid_price!=0: - diff = abs(high_price-mid_price) - percentage_to_profit = diff/mid_price*100 + #Formatting + low_boundary = '{:.20f}'.format(low_price)[:decimals].center(decimals) + mid_boundary = '{:.20f}'.format(mid_price)[:decimals].center(decimals) + high_boundary = '{:.20f}'.format(high_price)[:decimals].center(decimals) + + percentage_to_profit = 100 + pct_to_profit_str = "XX.XX" + if mid_price!=0: + diff = abs(high_price-mid_price) + percentage_to_profit = diff/mid_price*100 - #Formatting (on-screen percentage not longer than 4 digits) - pct_to_profit_str = "{:.2f}".format(percentage_to_profit) - if len(pct_to_profit_str)==4: - pct_to_profit_str = f" {pct_to_profit_str}" - elif len(pct_to_profit_str)==6: - pct_to_profit_str = pct_to_profit_str[:5] + #Formatting (on-screen percentage not longer than 4 digits) + pct_to_profit_str = "{:.2f}".format(percentage_to_profit) + if len(pct_to_profit_str)==4: + pct_to_profit_str = f" {pct_to_profit_str}" + elif len(pct_to_profit_str)==6: + pct_to_profit_str = pct_to_profit_str[:5] - line3 = "" - if self.status.get_base_bought()!=0: - line3 = draw_line(mid_price,low_price,high_price,self.status.get_quote_spent()/self.status.get_base_bought()) - p = "*PAUSED*" if self.pause==True else "" - low_boundary_color = red - price_color = white - target_price_color = green - pair_color = cyan - if self.config.get_is_short(): - price_color = white - pair_color = yellow - if self.status.get_old_long()!={}: - if mid_price>self.status.get_old_long()["tp_price"]: - price_color = bright_green - if high_price>self.status.get_old_long()["tp_price"]: - target_price_color = bright_green - - #Set percentage's color - pct_color = white - if percentage_to_profitmid_percentage: - pct_color = yellow - if percentage_to_profit>high_percentage: - pct_color = red - - multiplier = 0 - if self.config.get_is_short() and self.status.get_old_long()!={}: - try: - #Logic to display switch price - old_target = self.status.get_old_long()["tp_price"]*self.status.get_old_long()["tp_amount"] - base_left = self.status.get_old_long()["tp_amount"]-self.status.get_base_bought() - minimum_switch_price = (old_target - self.status.get_quote_spent())/base_left - if old_target-self.status.get_quote_spent()>0 and base_left>0 and minimum_switch_priceself.status.get_old_long()["tp_price"]: + price_color = self.get_color("bright_green") + if high_price>self.status.get_old_long()["tp_price"]: + target_price_color = self.get_color("bright_green") + + #Set percentage's color + pct_color = self.get_color("white") + if percentage_to_profitmid_percentage: + pct_color = self.get_color("yellow") + if percentage_to_profit>high_percentage: + pct_color = self.get_color("red") + + multiplier = 0 + if self.config.get_is_short() and self.status.get_old_long()!={}: + try: + #Logic to display switch price + old_target = self.status.get_old_long()["tp_price"]*self.status.get_old_long()["tp_amount"] + base_left = self.status.get_old_long()["tp_amount"]-self.status.get_base_bought() + minimum_switch_price = (old_target - self.status.get_quote_spent())/base_left + if old_target-self.status.get_quote_spent()>0 and base_left>0 and minimum_switch_price1: - #Only displays the multiplier if autoswitch is enabled. - line1 = f"{line1}{auto_color}x{multiplier}{white}" - if self.config.get_programmed_stop() and time.time()<=self.config.get_programmed_stop_time(): - line1 = f"{line1} | PROGRAMMED LAST DEAL" - if self.status.get_stop_when_profit(): - line1 = f"{line1} | LAST DEAL" + safety_order_string = f"{self.status.get_so_amount()-1}/{self.config.get_no_of_safety_orders()}".rjust(5) + prices = f"{low_boundary_color}{low_boundary}{self.get_color('white')}|{price_color}{mid_boundary}{self.get_color('white')}|{target_price_color}{high_boundary}{self.get_color('white')}|{pct_color}{pct_to_profit_str}%{self.get_color('white')}" + line1 = f"{p}{pair_color}{self.config.get_pair().center(13)}{self.get_color('white')}| {safety_order_string} |{prices}| Uptime: {self.seconds_to_time(self.status.get_deal_uptime())}" + if self.status.get_is_boosted(): + line1 = f"{line1} | BOOSTED" + if self.config.get_autoswitch(): + auto_color = self.get_color("white") + if self.config.get_liquidate_after_switch(): + auto_color = self.get_color("red") + line1 = f"{line1} | {auto_color}AUTO{self.get_color('white')}" + if multiplier>1: + #Only displays the multiplier if autoswitch is enabled. + line1 = f"{line1}{auto_color}x{multiplier}{self.get_color('white')}" + if self.config.get_programmed_stop() and time.time()<=self.config.get_programmed_stop_time(): + line1 = f"{line1} | PROGRAMMED LAST DEAL" + if self.status.get_stop_when_profit(): + line1 = f"{line1} | LAST DEAL" + + status_string = f"{self.get_color('white')}{line1}\n{line3}{self.get_color('white')}" + self.status_string_cache = status_string - return f"{white}{line1}\n{line3}{white}" + return status_string def load_imported_trader(self, forced_tp_order_id = None, forced_safety_order_id = None) -> int: