2025.08.15

This commit is contained in:
Nicolás Sánchez 2025-08-15 23:36:22 -03:00
parent e11be69f00
commit 30d8e84833
5 changed files with 135 additions and 95 deletions

View File

@ -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.

View File

@ -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

10
main.py
View File

@ -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 <Enter> 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 <Enter> to start..."))
input()
#Load exchange config

View File

@ -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):

207
trader.py
View File

@ -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<max_value:
color = green if price>=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_profit<low_percentage:
pct_color = green
if percentage_to_profit>mid_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_price<low_price:
low_boundary_color = bright_green
low_boundary = '{:.20f}'.format(minimum_switch_price)[:decimals].center(decimals)
if mid_price!=0:
multiplier = int(self.status.get_old_long()["tp_price"]/self.status.get_price())
except Exception as e:
print(e)
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 = self.get_color("red")
price_color = self.get_color("white")
target_price_color = self.get_color("green")
pair_color = self.get_color("cyan")
if self.config.get_is_short():
price_color = self.get_color("white")
pair_color = self.get_color("yellow")
if self.status.get_old_long()!={}:
if mid_price>self.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_profit<low_percentage:
pct_color = self.get_color("green")
if percentage_to_profit>mid_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_price<low_price:
low_boundary_color = self.get_color("bright_green")
low_boundary = '{:.20f}'.format(minimum_switch_price)[:decimals].center(decimals)
if mid_price!=0:
multiplier = int(self.status.get_old_long()["tp_price"]/self.status.get_price())
except Exception as e:
print(e)
prices = f"{low_boundary_color}{low_boundary}{white}|{price_color}{mid_boundary}{white}|{target_price_color}{high_boundary}{white}|{pct_color}{pct_to_profit_str}%{white}"
line1 = f"{p}{pair_color}{self.config.get_pair().center(13)}{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 = white
if self.config.get_liquidate_after_switch():
auto_color = red
line1 = f"{line1} | {auto_color}AUTO{white}"
if multiplier>1:
#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: