2025.05.16
This commit is contained in:
parent
68892d2d47
commit
1a62e483ae
|
|
@ -1,5 +1,13 @@
|
||||||
|
2025.05.16:
|
||||||
|
. Added exception handling when removing a trader.
|
||||||
|
. Minor variable renaming.
|
||||||
|
|
||||||
|
2025.05.12:
|
||||||
|
. Improved config file handling when switching to long or short.
|
||||||
|
. If the config file does not exist, it creates it.
|
||||||
|
|
||||||
2025.05.05:
|
2025.05.05:
|
||||||
. Forced Telegram message when a quit flag is raised.
|
. Forced Telegram message when quit flag is raised.
|
||||||
|
|
||||||
2025.05.04:
|
2025.05.04:
|
||||||
. Simplified unwrapped_add_pair.
|
. Simplified unwrapped_add_pair.
|
||||||
|
|
|
||||||
|
|
@ -37,13 +37,18 @@ class ConfigHandler:
|
||||||
self.config_dictionary = self.default_config_dictionary.copy()
|
self.config_dictionary = self.default_config_dictionary.copy()
|
||||||
|
|
||||||
#Loads from disk the config file (if it exists)
|
#Loads from disk the config file (if it exists)
|
||||||
self.load_from_file()
|
if self.load_from_file()==1:
|
||||||
|
#If the config file does not exist, write a new one with the default values
|
||||||
|
self.save_to_file()
|
||||||
if config_dict is not None:
|
if config_dict is not None:
|
||||||
self.config_dictionary = {**self.config_dictionary, **config_dict}
|
self.config_dictionary = {**self.config_dictionary, **config_dict}
|
||||||
self.save_to_file()
|
self.save_to_file()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def reset_to_default(self):
|
||||||
|
self.config_dictionary = self.default_config_dictionary.copy()
|
||||||
|
return 0
|
||||||
|
|
||||||
def get_pair(self):
|
def get_pair(self):
|
||||||
return self.config_dictionary["pair"]
|
return self.config_dictionary["pair"]
|
||||||
|
|
|
||||||
12
main.py
12
main.py
|
|
@ -16,7 +16,7 @@ import exchange_wrapper
|
||||||
import trader
|
import trader
|
||||||
|
|
||||||
|
|
||||||
version = "2025.05.05"
|
version = "2025.05.16"
|
||||||
|
|
||||||
'''
|
'''
|
||||||
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
|
||||||
|
|
@ -244,7 +244,10 @@ def restart_pair_no_json(base: str, quote: str) -> int:
|
||||||
elif order["symbol"]==f"{base}/{quote}" and not x.config.get_is_short() and order["side"]=="buy":
|
elif order["symbol"]==f"{base}/{quote}" and not x.config.get_is_short() and order["side"]=="buy":
|
||||||
broker.logger.log_this(f"Cancelling old buy orders",2,f"{base}/{quote}")
|
broker.logger.log_this(f"Cancelling old buy orders",2,f"{base}/{quote}")
|
||||||
broker.cancel_order(order["id"],order["symbol"])
|
broker.cancel_order(order["id"],order["symbol"])
|
||||||
running_instances.remove(x)
|
try:
|
||||||
|
running_instances.remove(x)
|
||||||
|
except ValueError:
|
||||||
|
broker.logger.log_this(f"Instance {x.config.get_pair()} not found in running_instances.",1,x.config.get_pair())
|
||||||
add_instance(base,quote)
|
add_instance(base,quote)
|
||||||
return 0
|
return 0
|
||||||
return 1
|
return 1
|
||||||
|
|
@ -274,7 +277,10 @@ def main_loop():
|
||||||
broker.rewrite_config_file()
|
broker.rewrite_config_file()
|
||||||
if x.config.get_pair() in worker_status:
|
if x.config.get_pair() in worker_status:
|
||||||
del(worker_status[x.config.get_pair()])
|
del(worker_status[x.config.get_pair()])
|
||||||
running_instances.remove(x)
|
try:
|
||||||
|
running_instances.remove(x)
|
||||||
|
except ValueError:
|
||||||
|
broker.logger.log_this(f"Instance {x.config.get_pair()} not found in running_instances.",1,x.config.get_pair())
|
||||||
|
|
||||||
#Adds pending traders
|
#Adds pending traders
|
||||||
if bool(instances_to_add):
|
if bool(instances_to_add):
|
||||||
|
|
|
||||||
54
trader.py
54
trader.py
|
|
@ -496,19 +496,6 @@ class trader:
|
||||||
self.pause = True
|
self.pause = True
|
||||||
self.status.set_pause_reason("switch_to_short")
|
self.status.set_pause_reason("switch_to_short")
|
||||||
|
|
||||||
#Read the config file
|
|
||||||
self.broker.logger.log_this("Reading config file",2,self.config.get_pair())
|
|
||||||
try:
|
|
||||||
with open(f"configs/{self.base}{self.quote}.json","r") as f:
|
|
||||||
old_config = json.load(f)
|
|
||||||
except Exception as e:
|
|
||||||
self.broker.logger.log_this(f"Error. Can't read the config file. Can't switch mode. Exception: {e}",1,self.config.get_pair())
|
|
||||||
self.pause = False
|
|
||||||
self.status.set_pause_reason("")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
#Calculate if there is enough base and, if so, calculate the optimal order size
|
|
||||||
|
|
||||||
#Fetch the real amount of available base
|
#Fetch the real amount of available base
|
||||||
self.broker.logger.log_this(f"Fetching available {self.base}",2,self.config.get_pair())
|
self.broker.logger.log_this(f"Fetching available {self.base}",2,self.config.get_pair())
|
||||||
free_base = self.fetch_free_base()
|
free_base = self.fetch_free_base()
|
||||||
|
|
@ -566,21 +553,16 @@ class trader:
|
||||||
#Modify config file accordingly
|
#Modify config file accordingly
|
||||||
self.broker.logger.log_this("Modifying config file and saving a backup",2,self.config.get_pair())
|
self.broker.logger.log_this("Modifying config file and saving a backup",2,self.config.get_pair())
|
||||||
try:
|
try:
|
||||||
with open(f"configs/{self.base}{self.quote}.bak","w") as c:
|
self.config.save_to_file(f"configs/{self.base}{self.quote}.bak")
|
||||||
c.write(json.dumps(old_config, indent=4))
|
self.config.set_is_short(True)
|
||||||
old_config["is_short"] = True
|
self.config.save_to_file()
|
||||||
#old_config["order_size"] = optimal_order_size #Now calculated on-the-fly at the start of every deal
|
|
||||||
#old_config["no_of_safety_orders"] = amount_of_so
|
|
||||||
#4. Write the config file
|
|
||||||
with open(f"configs/{self.base}{self.quote}.json","w") as c:
|
|
||||||
c.write(json.dumps(old_config, indent=4))
|
|
||||||
self.broker.logger.log_this("Config file updated",2,self.config.get_pair())
|
self.broker.logger.log_this("Config file updated",2,self.config.get_pair())
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.broker.logger.log_this(f"Error. Can't write the config file. Exception: {e}",1,self.config.get_pair())
|
self.broker.logger.log_this(f"Error. Can't write the config file. Exception: {e}",1,self.config.get_pair())
|
||||||
#self.pause = False
|
#self.pause = False
|
||||||
return 1
|
return 1
|
||||||
self.status.set_stop_when_profit(False)
|
self.status.set_stop_when_profit(False)
|
||||||
self.config.set_is_short(True)
|
#self.config.set_is_short(True)
|
||||||
self.broker.logger.log_this("Done configuring. Starting bot...",2,self.config.get_pair())
|
self.broker.logger.log_this("Done configuring. Starting bot...",2,self.config.get_pair())
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
@ -591,12 +573,12 @@ class trader:
|
||||||
Only does it if the current bot was previously a long one.
|
Only does it if the current bot was previously a long one.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
#Check if it's not already long
|
|
||||||
if not self.config.get_is_short():
|
if not self.config.get_is_short():
|
||||||
self.broker.logger.log_this("Can't switch a long trader to long, there's nothing to do",1,self.config.get_pair())
|
self.broker.logger.log_this("Trader already in long mode, nothing to do",1,self.config.get_pair())
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
self.broker.logger.log_this("Attempting to switch to long bot",0,self.config.get_pair())
|
self.broker.logger.log_this("Attempting to switch to long bot",0,self.config.get_pair())
|
||||||
|
|
||||||
|
#Check old_long data
|
||||||
if not ignore_old_long and self.status.get_old_long()=={}:
|
if not ignore_old_long and self.status.get_old_long()=={}:
|
||||||
self.broker.logger.log_this("Can't find old long info on status_dict, searching for oldlong file",1,self.config.get_pair())
|
self.broker.logger.log_this("Can't find old long info on status_dict, searching for oldlong file",1,self.config.get_pair())
|
||||||
try:
|
try:
|
||||||
|
|
@ -624,21 +606,21 @@ class trader:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.broker.logger.log_this(f"Error in cancel_order while cancelling take profit order. Exception: {e}",1,self.config.get_pair())
|
self.broker.logger.log_this(f"Error in cancel_order while cancelling take profit order. Exception: {e}",1,self.config.get_pair())
|
||||||
|
|
||||||
#Liquidate base
|
#Sell all base currency
|
||||||
self.liquidate_base(ignore_profits=ignore_old_long, already_received_quote=already_received_quote)
|
self.liquidate_base(ignore_profits=ignore_old_long, already_received_quote=already_received_quote)
|
||||||
|
|
||||||
#switch config files and set self.config.get_is_short() to False
|
#Rewrite config file (if it exists)
|
||||||
try:
|
if os.path.isfile(f"configs/{self.base}{self.quote}.bak") and os.path.isfile(f"configs/{self.base}{self.quote}.json"):
|
||||||
with open(f"configs/{self.base}{self.quote}.bak") as c:
|
with open(f"configs/{self.base}{self.quote}.bak") as c:
|
||||||
old_config = json.load(c)
|
old_config = json.load(c)
|
||||||
with open(f"configs/{self.base}{self.quote}.json","w") as c:
|
with open(f"configs/{self.base}{self.quote}.json","w") as c:
|
||||||
c.write(json.dumps(old_config, indent=4))
|
c.write(json.dumps(old_config, indent=4))
|
||||||
self.config.load_from_file()
|
if self.config.load_from_file()==1:
|
||||||
self.config.set_is_short(False) #This probably is not needed
|
self.config.reset_to_default()
|
||||||
except Exception as e:
|
else:
|
||||||
self.broker.logger.log_this(f"Exception in switch_to_long while switching config files: {e}",1,self.config.get_pair())
|
self.broker.logger.log_this("Config/backup file does not exist",1,self.config.get_pair())
|
||||||
self.quit = True
|
self.config.reset_to_default()
|
||||||
return 1
|
self.config.save_to_file()
|
||||||
|
|
||||||
#Remove old_long file (if it exists)
|
#Remove old_long file (if it exists)
|
||||||
if os.path.isfile(f"status/{self.base}{self.quote}.oldlong"):
|
if os.path.isfile(f"status/{self.base}{self.quote}.oldlong"):
|
||||||
|
|
@ -958,13 +940,13 @@ class trader:
|
||||||
amount = (order_size/mid_price)*2 #Extra margin to avoid surprises.
|
amount = (order_size/mid_price)*2 #Extra margin to avoid surprises.
|
||||||
else:
|
else:
|
||||||
amount = order_size*2
|
amount = order_size*2
|
||||||
first_price = order_book["asks"][0][0]
|
top_price = order_book["asks"][0][0]
|
||||||
for x in order_book["asks"]:
|
for x in order_book["asks"]:
|
||||||
suma += x[1]
|
suma += x[1]
|
||||||
if suma>=amount:
|
if suma>=amount:
|
||||||
last_price = x[0]
|
last_price = x[0]
|
||||||
break
|
break
|
||||||
if last_price-first_price>first_price*threshold:
|
if last_price-top_price>top_price*threshold:
|
||||||
#Threshold exceeded
|
#Threshold exceeded
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue