2025.09.27
This commit is contained in:
parent
65c406a03d
commit
0576f93477
|
|
@ -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.
|
||||||
|
|
|
||||||
2
main.py
2
main.py
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
52
trader.py
52
trader.py
|
|
@ -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
|
#Cooldown
|
||||||
time.sleep(self.broker.get_wait_time())
|
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())
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue