diff --git a/main.py b/main.py index e524087..9e97d00 100644 --- a/main.py +++ b/main.py @@ -18,7 +18,7 @@ import exchange_wrapper import trader -version = "2025.08.19" +version = "2025.08.23" ''' Color definitions. If you want to change them, check the reference at https://en.wikipedia.org/wiki/ANSI_escape_code#Colors diff --git a/status_handler.py b/status_handler.py index a192bd3..afb4a49 100644 --- a/status_handler.py +++ b/status_handler.py @@ -13,6 +13,7 @@ class StatusHandler: "take_profit_order": broker.get_empty_order(), "take_profit_price": 0.0, "safety_orders": [], + "safety_orders_filled": 0, "next_so_price": 0.0, "order_size": 0.0, "partial_profit": 0.0, @@ -64,6 +65,9 @@ class StatusHandler: """ return self.status_dictionary["safety_orders"] + def get_safety_orders_filled(self): + return self.status_dictionary["safety_orders_filled"] + def get_next_so_price(self): return self.status_dictionary["next_so_price"] @@ -191,6 +195,10 @@ class StatusHandler: self.status_dictionary["safety_orders"] = orders return 0 + def set_safety_orders_filled(self, amount: int): + self.status_dictionary["safety_orders_filled"] = amount + return 0 + def set_next_so_price(self, price: float): # if not isinstance(price, float): # self.broker.logger.log_this(f"Price provided is not a float",1,self.get_pair()) diff --git a/trader.py b/trader.py index ec836d0..4cdbe6e 100755 --- a/trader.py +++ b/trader.py @@ -5,7 +5,7 @@ from config_handler import ConfigHandler from status_handler import StatusHandler class trader: - def __init__(self, broker, pair: str, is_import: bool = False, forced_tp_id = None, forced_so_id = None): + def __init__(self, broker, pair: str, is_import: bool = False): #Flags self.pause = True @@ -75,7 +75,7 @@ class trader: def __str__(self): return self.status.get_status_string() - + def get_color(self, color): ''' Returns white if color does not exist @@ -91,7 +91,6 @@ class trader: return colors[color] if color in colors else "\033[0;37;40m" - def get_status_dict(self): return self.status.get_status() @@ -116,6 +115,7 @@ class trader: self.status.clear_deal_order_history() self.status.set_take_profit_order(self.broker.get_empty_order()) self.status.set_safety_orders([]) + self.status.set_safety_orders_filled(0) #Reloads the market new_market_data = self.broker.fetch_market(self.config.get_pair()) @@ -437,7 +437,7 @@ class trader: return 1 #balance_to_clean /= 2 #Maybe it's a good idea, sort of DCAing the dust. min_base_size = self.broker.get_min_base_size(self.config.get_pair()) - minimum_cleanup_size = self.status.get_safety_order()["amount"]*2 # type: ignore + minimum_cleanup_size = self.status.get_safety_orders()[0]["amount"]*2 if balance_to_clean-minimum_cleanup_size >= min_base_size: self.broker.logger.log_this(f"Balance to clean: {balance_to_clean-minimum_cleanup_size} {self.base}",2,self.config.get_pair()) @@ -724,7 +724,7 @@ class trader: #Cancel all the safety orders ASAP for order in self.status.get_safety_orders(): - self.broker.cancel_order(order["id"]) + self.broker.cancel_order(order["id"],self.config.get_pair()) #Check if some safety orders were filled for order in self.status.get_safety_orders(): closed_order = self.broker.get_order(order["id"],self.config.get_pair()) @@ -831,7 +831,8 @@ class trader: if orders_to_place<1: return 0 orders_placed = 0 - for _ in range(orders_to_place): + for i in range(orders_to_place): + self.broker.logger.log_this(f"Sending a new safety order ({i+1}/{orders_to_place})",2,self.config.get_pair()) so_size = self.gib_so_size(self.status.get_order_size(),self.status.get_so_amount()+1,self.config.get_safety_order_scale()) if self.config.get_is_short(): new_order = self.broker.new_limit_order(self.config.get_pair(),so_size,"sell",self.status.get_safety_price_table()[self.status.get_so_amount()+1]) @@ -901,8 +902,6 @@ class trader: return 2 #Check if old TP order was partially filled - # TODO: This should also be taken into account for the profit calculation - # Do the partial profit calculation and save it for later old_tp_order = self.broker.get_order(self.status.get_take_profit_order()["id"],self.config.get_pair()) if old_tp_order["filled"]>0: self.broker.logger.log_this(f"Old take profit order is partially filled, id {old_tp_order['id']}",1,self.config.get_pair()) @@ -910,11 +909,10 @@ class trader: self.status.update_deal_order_history(old_tp_order) #self.status.set_base_bought(old_tp_order["remaining"]) # Partial profit calculation - #if not self.config.get_is_short(): - # current_deal_price = self.status.get_base_bought()/self.status.get_quote_spent() - # self.status.set_partial_profit(self.status.get_partial_profit()+old_tp_order["cost"]-(old_tp_order["filled"]*current_deal_price)-self.parse.fees(old_tp_order)[1]) - # self.update_status(True) - # + if not self.config.get_is_short(): + current_deal_price = self.status.get_base_bought()/self.status.get_quote_spent() + self.status.set_partial_profit(self.status.get_partial_profit()+old_tp_order["cost"]-(old_tp_order["filled"]*current_deal_price)-self.parse_fees(old_tp_order)[1]) + self.update_status(True) self.status.set_base_bought(self.status.get_base_bought() - old_tp_order["filled"] - self.parse_fees(old_tp_order)[0]) self.status.set_quote_spent(self.status.get_quote_spent() - old_tp_order["cost"]) self.status.set_fees_paid_in_quote(self.status.get_fees_paid_in_quote() + self.parse_fees(old_tp_order)[1]) @@ -1094,6 +1092,7 @@ class trader: if filled_ids!=[]: closed_orders = self.broker.get_closed_orders(self.config.get_pair()) filled_orders = [item for item in closed_orders if item["id"] in filled_ids and item["status"]=="closed"] #maybe item["status"] in ["closed", "canceled", ""]? + self.status.set_safety_orders_filled(self.status.get_safety_orders_filled()+len(filled_orders)) renew_outcome = self.renew_tp_and_so_routine(filled_orders) #0 OK, 1 take profit order is None, 2 not enough funds, 3 can't cancel TP (filled?), 4 can't send new TP if renew_outcome==1: @@ -1553,7 +1552,7 @@ class trader: except Exception as e: print(e) - safety_order_string = f"{self.status.get_so_amount()-1}/{self.config.get_no_of_safety_orders()}".rjust(5) + safety_order_string = f"{self.status.get_safety_orders_filled()}/{self.config.get_no_of_safety_orders()}{self.get_color('cyan')} {len(self.status.get_safety_orders())}{self.get_color('white')}".rjust(6) 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(): diff --git a/utils/commander.py b/utils/commander.py index b3ec7a8..09d0400 100644 --- a/utils/commander.py +++ b/utils/commander.py @@ -11,6 +11,12 @@ try: api_key = credentials.get_credentials("testnet_api_key")["key"] base_url = credentials.get_url("testnet") #type: ignore exchanges = {"Binance":"/binance"} + if sys.argv[1]=="--local_testnet": + is_testnet = True + string_to_add = "LOCAL TESTNET " + api_key = credentials.get_credentials("local_testnet_api_key")["key"] + base_url = credentials.get_url("local_testnet") #type: ignore + exchanges = {"Binance":":5001"} elif sys.argv[1]=="--mainnet": is_testnet = False string_to_add = "MAINNET "