2025.09.27

This commit is contained in:
Nicolás Sánchez 2025-09-27 20:12:29 -03:00
parent 65c406a03d
commit 0576f93477
4 changed files with 36 additions and 32 deletions

View File

@ -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: 2025.09.25:
. Added a pause after getting filled orders in check_status. . Added a pause after getting filled orders in check_status.
. Added an extra logging line in take_profit_routine. . Added an extra logging line in take_profit_routine.

View File

@ -18,7 +18,7 @@ import exchange_wrapper
import trader 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 Color definitions. If you want to change them, check the reference at https://en.wikipedia.org/wiki/ANSI_escape_code#Colors

View File

@ -418,11 +418,11 @@ class StatusHandler:
self.status_dictionary["deal_order_history"] = [] self.status_dictionary["deal_order_history"] = []
return 0 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): # if not isinstance(new_deal, dict):
# self.broker.logger.log_this(f"value provided is not a dict",1,self.get_pair()) # 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 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 return 0
def save_to_file(self, file_path = None, is_backup = False): def save_to_file(self, file_path = None, is_backup = False):

View File

@ -242,7 +242,7 @@ class trader:
#Save the order #Save the order
if self.broker.follow_order_history: if self.broker.follow_order_history:
self.status.set_pause_reason("start_trader - saving the order in deal_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 # Reset the fee count and sum fees from the first order
self.status.set_fees_paid_in_base(self.parse_fees(returned_order)[0]) 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: if balance_to_clean is None:
self.broker.logger.log_this("Can't fetch free base",1,self.status.get_pair()) self.broker.logger.log_this("Can't fetch free base",1,self.status.get_pair())
return 1 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()): #If the balance is greater than the size of the first safety order, sell the difference.
self.broker.logger.log_this(f"Balance to clean: {balance_to_clean} {self.base}",2,self.status.get_pair()) # 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()) 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: 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()) self.broker.logger.log_this("Problems with the cleanup order, new_limit_order returned None",1,self.status.get_pair())
return 1 return 1
@ -755,7 +758,7 @@ class trader:
#Save the order in history. #Save the order in history.
if self.broker.get_follow_order_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 #Cancel all the safety orders ASAP
for order in self.status.get_safety_orders(): for order in self.status.get_safety_orders():
@ -772,7 +775,7 @@ class trader:
partial_filled_price.append(closed_order["average"]) 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()) 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(): 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. 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 break
#Now we can clear the safety order list #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) #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()): 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 #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) 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) time.sleep(self.broker.get_wait_time()*2)
tries = self.broker.get_retries() tries = self.broker.get_retries()
@ -956,15 +960,21 @@ class trader:
#Save the order #Save the order
if self.broker.get_follow_order_history(): if self.broker.get_follow_order_history():
for item in filled_safety_orders: 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 #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: for order in filled_safety_orders:
safety_orders_to_remove_by_id.append(order["id"]) safety_orders_to_remove_by_id.append(order["id"])
new_fees_base,new_fees_quote = self.parse_fees(order) 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) previous_fees_paid_in_quote += new_fees_quote
self.status.set_base_bought(self.status.get_base_bought() + order["filled"] - new_fees_base) previous_base += order["filled"]
self.status.set_quote_spent(self.status.get_quote_spent() + order["cost"]) 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 #Remove the filled safety orders from the list
if safety_orders_to_remove_by_id!=[]: if safety_orders_to_remove_by_id!=[]:
@ -987,7 +997,7 @@ class trader:
if old_tp_order["filled"]>0: 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()) 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(): 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"]) #self.status.set_base_bought(old_tp_order["remaining"])
# Partial profit calculation # Partial profit calculation
if not self.config.get_is_short(): 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() 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())<max_orders: if len(self.status.get_safety_orders())<max_orders:
self.send_new_safety_order_batch(max_orders-len(self.status.get_safety_orders())) self.send_new_safety_order_batch(max_orders-len(self.status.get_safety_orders()))
#Cooldown
time.sleep(self.broker.get_wait_time()) #Cooldown
time.sleep(self.broker.get_wait_before_new_safety_order())
#Send new TP order #Send new TP order
if self.send_new_tp_order()==1: if self.send_new_tp_order()==1:
@ -1139,17 +1150,6 @@ class trader:
self.status.set_pause_reason("check if tp_order is filled") self.status.set_pause_reason("check if tp_order is filled")
#Checks if the take profit order is filled #Checks if the take profit order is filled
if self.status.get_take_profit_order()["id"] not in open_orders_ids: if self.status.get_take_profit_order()["id"] not in open_orders_ids:
# Check if the order has a wrong id. If so, update the order.
# To cover a very rare case that happens if the trader sends a new take profit order but is interrupted before saving the status.
# Not sure if it is worth to keep this code.
for order in open_orders_list:
if order["amount"]==self.status.get_take_profit_order()["amount"] and order["price"]==self.status.get_take_profit_order()["price"] and order["side"]==self.status.get_take_profit_order()["side"]:
#Right order, wrong id. Update order
self.broker.logger.log_this(f"Updating take profit order for {self.status.get_pair()}",1,self.status.get_pair())
self.status.set_take_profit_order(order)
self.update_status(True)
return 0
tp_status = self.broker.get_order(self.status.get_take_profit_order()["id"],self.status.get_pair()) tp_status = self.broker.get_order(self.status.get_take_profit_order()["id"],self.status.get_pair())
if tp_status["status"]=="closed": if tp_status["status"]=="closed":
if tp_status["filled"]>0: if tp_status["filled"]>0:
@ -1186,8 +1186,6 @@ class trader:
filled_ids.append(order["id"]) filled_ids.append(order["id"])
if filled_ids!=[]: 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 = [] filled_orders = []
for id in filled_ids: for id in filled_ids:
order = self.broker.get_order(id, self.status.get_pair()) order = self.broker.get_order(id, self.status.get_pair())