diff --git a/changelog.txt b/changelog.txt index 587adc1..e77552b 100755 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,9 @@ +2025.09.27: +. Added notes in every entry of deal_order_history. +. Minor refactor in renew_tp_and_so_routine. +. Added another cooldown before sending a take profit order (To give the exchange a bit more time to reflect correctly the amount of base present in the account) +. Updated cleanup routine to leave some change in the account. + 2025.09.25: . Added a pause after getting filled orders in check_status. . Added an extra logging line in take_profit_routine. diff --git a/main.py b/main.py index 911eba8..a063bf0 100644 --- a/main.py +++ b/main.py @@ -18,7 +18,7 @@ import exchange_wrapper import trader -version = "2025.09.25" +version = "2025.09.27" ''' 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 1baddec..13c704e 100644 --- a/status_handler.py +++ b/status_handler.py @@ -418,11 +418,11 @@ class StatusHandler: self.status_dictionary["deal_order_history"] = [] return 0 - def update_deal_order_history(self, new_deal: dict): + def update_deal_order_history(self, new_deal: dict, note: str = ""): # if not isinstance(new_deal, dict): # self.broker.logger.log_this(f"value provided is not a dict",1,self.get_pair()) id = new_deal["id"] if "id" in new_deal else None - self.status_dictionary["deal_order_history"].append(id) + self.status_dictionary["deal_order_history"].append(f"{note} - {id}") return 0 def save_to_file(self, file_path = None, is_backup = False): diff --git a/trader.py b/trader.py index 3dc1e1a..4b37fe5 100755 --- a/trader.py +++ b/trader.py @@ -242,7 +242,7 @@ class trader: #Save the order if self.broker.follow_order_history: self.status.set_pause_reason("start_trader - saving the order in deal_order_history") - self.status.update_deal_order_history(returned_order) + self.status.update_deal_order_history(returned_order, "init") # Reset the fee count and sum fees from the first order self.status.set_fees_paid_in_base(self.parse_fees(returned_order)[0]) @@ -441,12 +441,15 @@ class trader: if balance_to_clean is None: self.broker.logger.log_this("Can't fetch free base",1,self.status.get_pair()) return 1 - balance_to_clean /= 2 #Maybe it's a good idea, sort of DCAing the dust. - - if balance_to_clean*self.status.get_start_price()>self.broker.get_min_quote_size(self.status.get_pair()): - self.broker.logger.log_this(f"Balance to clean: {balance_to_clean} {self.base}",2,self.status.get_pair()) + + #If the balance is greater than the size of the first safety order, sell the difference. + # Sometimes when an order is filled the balance is not updated immediately, so having a bit of a buffer irons out a couple of issues. + min_size = self.status.get_safety_orders()[0]["amount"] + + if (balance_to_clean-min_size)*self.status.get_start_price()>self.broker.get_min_quote_size(self.status.get_pair()): + self.broker.logger.log_this(f"Balance to clean: {balance_to_clean-min_size} {self.base}",2,self.status.get_pair()) self.broker.logger.log_this("Sending cleanup order...",2,self.status.get_pair()) - cleanup_order = self.broker.new_limit_order(self.status.get_pair(),balance_to_clean,"sell",self.status.get_take_profit_price(),no_retries=True) + cleanup_order = self.broker.new_limit_order(self.status.get_pair(),balance_to_clean-min_size,"sell",self.status.get_take_profit_price(),no_retries=True) if cleanup_order is None: self.broker.logger.log_this("Problems with the cleanup order, new_limit_order returned None",1,self.status.get_pair()) return 1 @@ -755,7 +758,7 @@ class trader: #Save the order in history. if self.broker.get_follow_order_history(): - self.status.update_deal_order_history(filled_order) + self.status.update_deal_order_history(filled_order, "tp") #Cancel all the safety orders ASAP for order in self.status.get_safety_orders(): @@ -772,7 +775,7 @@ class trader: partial_filled_price.append(closed_order["average"]) self.broker.logger.log_this(f"Old safety order is partially filled, ID: {closed_order['id']}, {closed_order['filled']}/{closed_order['amount']} {self.base} filled",1,self.status.get_pair()) if self.broker.get_follow_order_history(): - self.status.update_deal_order_history(closed_order) + self.status.update_deal_order_history(closed_order, "partial_fill") if closed_order["remaining"]!=0: #If this order is not completely filled, it is safe to assume that no order coming after this one was partially filled. break #Now we can clear the safety order list @@ -783,6 +786,7 @@ class trader: #With short traders is just an accounting issue, since when the trader restarts it will be buying cheaper what it sold more expensive in the partially filled safety order(s) if partial_filled_amount!=0 and len(partial_filled_price)>0 and partial_filled_amount>self.broker.get_min_base_size(self.status.get_pair()): #send a market order and sum the profits and wait for it to be filled + self.broker.logger.log_this("Sending partial fill sell order...",1,self.status.get_pair()) market_order = self.broker.new_market_order(self.status.get_pair(),partial_filled_amount,"sell",amount_in_base=True) time.sleep(self.broker.get_wait_time()*2) tries = self.broker.get_retries() @@ -956,15 +960,21 @@ class trader: #Save the order if self.broker.get_follow_order_history(): for item in filled_safety_orders: - self.status.update_deal_order_history(item) + self.status.update_deal_order_history(item, "so") #Add the amount filled in the last safety orders to the totals + previous_base = self.status.get_base_bought() + previous_quote = self.status.get_quote_spent() + previous_fees_paid_in_quote = self.status.get_fees_paid_in_quote() for order in filled_safety_orders: safety_orders_to_remove_by_id.append(order["id"]) - new_fees_base,new_fees_quote = self.parse_fees(order) - self.status.set_fees_paid_in_quote(self.status.get_fees_paid_in_quote() + new_fees_quote) - self.status.set_base_bought(self.status.get_base_bought() + order["filled"] - new_fees_base) - self.status.set_quote_spent(self.status.get_quote_spent() + order["cost"]) + new_fees_base, new_fees_quote = self.parse_fees(order) + previous_fees_paid_in_quote += new_fees_quote + previous_base += order["filled"] + previous_quote += order["cost"] + self.status.set_base_bought(previous_base) + self.status.set_quote_spent(previous_quote) + self.status.set_fees_paid_in_quote(previous_fees_paid_in_quote) #Remove the filled safety orders from the list if safety_orders_to_remove_by_id!=[]: @@ -987,7 +997,7 @@ class trader: 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.status.get_pair()) if self.broker.get_follow_order_history(): - self.status.update_deal_order_history(old_tp_order) + self.status.update_deal_order_history(old_tp_order, "old_tp") #self.status.set_base_bought(old_tp_order["remaining"]) # Partial profit calculation if not self.config.get_is_short(): @@ -1008,8 +1018,9 @@ class trader: max_orders = self.config.get_concurrent_safety_orders() if not self.status.get_is_boosted() else self.config.get_boosted_concurrent_safety_orders() if len(self.status.get_safety_orders())0: @@ -1186,8 +1186,6 @@ class trader: filled_ids.append(order["id"]) if filled_ids!=[]: - #closed_orders = self.broker.get_closed_orders(self.status.get_pair()) - #filled_orders = [item for item in closed_orders if item["id"] in filled_ids and item["status"]=="closed"] filled_orders = [] for id in filled_ids: order = self.broker.get_order(id, self.status.get_pair())