I hate Kucoin

This commit is contained in:
Nicolás Sánchez 2025-09-04 13:56:25 -03:00
parent 5dde1a1def
commit 27420946cd
3 changed files with 82 additions and 40 deletions

View File

@ -538,7 +538,7 @@ class Broker:
if pairs is None: if pairs is None:
pairs = [] pairs = []
try: try:
if self.get_exchange_name()=="binance": if self.get_exchange_name()in ["binance","kucoin"]:
return self.get_opened_orders_binance(pairs) return self.get_opened_orders_binance(pairs)
return self.get_opened_orders() return self.get_opened_orders()
except Exception as e: except Exception as e:

13
main.py
View File

@ -18,7 +18,7 @@ import exchange_wrapper
import trader import trader
version = "2025.09.03" version = "2025.09.04"
''' '''
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
@ -311,12 +311,16 @@ def main_routine():
futures = [] futures = []
pairs_to_fetch = [] pairs_to_fetch = []
online_pairs = [] online_pairs = []
open_orders = broker.fetch_open_orders(tickers)
for instance in running_traders:
pairs_to_fetch.append(instance.status.get_pair())
open_orders = broker.fetch_open_orders(pairs_to_fetch)
for instance in running_traders: for instance in running_traders:
future = executor.submit(instance.check_status, open_orders) future = executor.submit(instance.check_status, open_orders)
futures.append(future) futures.append(future)
online_pairs.append(f"{instance.base}{instance.quote}") online_pairs.append(f"{instance.base}{instance.quote}")
pairs_to_fetch.append(instance.status.get_pair())
#Fetch prices #Fetch prices
price_list = broker.get_prices(pairs_to_fetch) price_list = broker.get_prices(pairs_to_fetch)
@ -328,9 +332,6 @@ def main_routine():
except Exception as e: except Exception as e:
broker.logger.log_this(f"Error in thread - {e}") broker.logger.log_this(f"Error in thread - {e}")
#Delete no longer used data
del open_orders
curr = 0 curr = 0
top = 0 top = 0
long_traders_status_strings = [] long_traders_status_strings = []

View File

@ -765,12 +765,14 @@ class trader:
self.broker.cancel_order(order["id"],self.status.get_pair()) self.broker.cancel_order(order["id"],self.status.get_pair())
#Check if some safety orders were filled #Check if some safety orders were filled
partial_filled_amount = 0
for order in self.status.get_safety_orders(): for order in self.status.get_safety_orders():
closed_order = self.broker.get_order(order["id"],self.status.get_pair()) closed_order = self.broker.get_order(order["id"],self.status.get_pair())
if closed_order["filled"]==0: if closed_order["filled"]==0:
#If this order wasn't filled, it is safe to assume that no order coming after this one was. #If this order wasn't filled, it is safe to assume that no order coming after this one was.
break break
#Sum the filled amounts #Sum the filled amounts
partial_filled_amount+=closed_order["filled"]
#Better than this, the total filled and total cost can be used to send a sell market order of the partial filled amount, and add that to the profit. #Better than this, the total filled and total cost can be used to send a sell market order of the partial filled amount, and add that to the profit.
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())
self.status.set_base_bought(self.status.get_base_bought() + closed_order["filled"] - self.parse_fees(closed_order)[0]) self.status.set_base_bought(self.status.get_base_bought() + closed_order["filled"] - self.parse_fees(closed_order)[0])
@ -784,6 +786,24 @@ class trader:
#Now we can clear the safety order list #Now we can clear the safety order list
self.status.set_safety_orders([]) self.status.set_safety_orders([])
# if partial_filled_amount!=0 and partial_filled_amount>self.broker.get_min_base_size(self.status.get_pair()):
# #send a sell market order and sum the profits
# market_order = self.broker.new_market_order(self.status.get_pair(),partial_filled_amount,"sell",amount_in_base=True)
# #Wait for it to be filled
# tries = self.broker.get_retries()
# while True:
# time.sleep(self.broker.get_wait_time())
# partial_fill_order = self.broker.get_order(market_order["id"],self.status.get_pair())
# if partial_fill_order["status"]=="closed":
# break
# tries-=1
# if tries==0:
# self.broker.logger.log_this("Partial fill sell order not filling.",1,self.status.get_pair())
# break
# #Sum the profit
if not self.broker.check_for_duplicate_profit_in_db(filled_order): if not self.broker.check_for_duplicate_profit_in_db(filled_order):
self.status.set_pause_reason("calculating profit") self.status.set_pause_reason("calculating profit")
# Calculate the profit # Calculate the profit
@ -1113,8 +1133,11 @@ class trader:
return 1 return 1
#Extract ids from order list #Extract ids from order list
open_orders_ids = [order["id"] for order in open_orders if order["symbol"]==self.status.get_pair()] self.status.set_pause_reason("filtering open orders")
open_orders_list = [order for order in open_orders if order["symbol"]==self.status.get_pair()]
open_orders_ids = [order["id"] for order in open_orders_list]
self.status.set_pause_reason("check for tp_order is valid")
#Checks if the take profit order is valid #Checks if the take profit order is valid
if self.status.get_take_profit_order() is None: if self.status.get_take_profit_order() is None:
self.broker.logger.log_this("Take profit order is None",1,self.status.get_pair()) self.broker.logger.log_this("Take profit order is None",1,self.status.get_pair())
@ -1132,8 +1155,19 @@ class trader:
self.broker.logger.log_this("Take profit order missing. Trader restart disabled.",2,self.status.get_pair()) self.broker.logger.log_this("Take profit order missing. Trader restart disabled.",2,self.status.get_pair())
return 1 return 1
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:
# I hate Kucoin:
# Check if the order has a wrong id. If so, update the order.
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()}")
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:
@ -1162,6 +1196,7 @@ class trader:
self.broker.logger.log_this(f"Take profit order search returned empty order. Order ID: {tp_status['id']}",1,self.status.get_pair()) self.broker.logger.log_this(f"Take profit order search returned empty order. Order ID: {tp_status['id']}",1,self.status.get_pair())
return 1 return 1
self.status.set_pause_reason("check for any so is filled")
# Check if any safety order is filled # Check if any safety order is filled
filled_ids = [] filled_ids = []
for order in self.status.get_safety_orders(): for order in self.status.get_safety_orders():
@ -1169,8 +1204,14 @@ 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()) #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"] #maybe item["status"] in ["closed", "canceled", ""]? #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())
if order["status"]=="closed":
filled_orders.append(order)
if len(filled_orders)>0: #To make sure that the safety orders are actually filled (Kucoin sometimes sends incomplete order lists)
self.status.set_safety_orders_filled(self.status.get_safety_orders_filled()+len(filled_orders)) 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) 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 #0 OK, 1 take profit order is None, 2 not enough funds, 3 can't cancel TP (filled?), 4 can't send new TP