2025.03.03

This commit is contained in:
Nicolás Sánchez 2025-03-03 10:01:05 -03:00
parent ba86c76ad6
commit 7d90b7d833
6 changed files with 318 additions and 260 deletions

View File

@ -1,3 +1,8 @@
2025.03.03:
. Replaced more variables with their respective config handlers.
. Added a new API endpoint: reload_trader_config.
. Removed the config reloading when a trader closes a deal.
2025.03.02: 2025.03.02:
. Fixed an error in restart_pair_no_json() . Fixed an error in restart_pair_no_json()

117
main.py
View File

@ -24,7 +24,7 @@ In case the permissions of the certificate changes, reset them this way:
# ll /etc/letsencrypt/ # ll /etc/letsencrypt/
''' '''
version = "2025.03.02" version = "2025.03.03"
''' '''
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
@ -240,7 +240,7 @@ def restart_pair_no_json(base: str, quote: str) -> int:
try: try:
order_list = broker.fetch_full_orders(tickers) order_list = broker.fetch_full_orders(tickers)
for x in running_instances: for x in running_instances:
if f"{base}/{quote}"==x.pair: if f"{base}/{quote}"==x.config.get_pair():
x.pause = True x.pause = True
#Backing up old status file #Backing up old status file
x.status.save_to_file(is_backup=True) x.status.save_to_file(is_backup=True)
@ -270,17 +270,17 @@ def main_loop():
#Restart traders that have the restart flag raised and remove traders that have the quit flag raised #Restart traders that have the restart flag raised and remove traders that have the quit flag raised
for x in running_instances: for x in running_instances:
if x.restart and x.config.get_attempt_restart(): if x.restart and x.config.get_attempt_restart():
broker.logger.log_this(f"Restarting trader",1,x.pair) broker.logger.log_this(f"Restarting trader",1,x.config.get_pair())
restart_pair_no_json(x.base,x.quote) restart_pair_no_json(x.base,x.quote)
if x.quit: if x.quit:
#Here, check if a duster is needed #Here, check if a duster is needed
broker.logger.log_this(f"Quit flag raised, removing pair.",0,x.pair) broker.logger.log_this(f"Quit flag raised, removing pair.",0,x.config.get_pair())
if f"{x.base}{x.quote}" in tickers: if f"{x.base}{x.quote}" in tickers:
tickers.remove(f"{x.base}{x.quote}") tickers.remove(f"{x.base}{x.quote}")
broker.remove_pair_from_config(f"{x.base}{x.quote}") broker.remove_pair_from_config(f"{x.base}{x.quote}")
broker.rewrite_config_file() broker.rewrite_config_file()
if x.pair in worker_status: if x.config.get_pair() in worker_status:
del(worker_status[x.pair]) del(worker_status[x.config.get_pair()])
running_instances.remove(x) running_instances.remove(x)
#Adds pending traders #Adds pending traders
@ -296,7 +296,7 @@ def main_loop():
for x in running_instances: for x in running_instances:
threads.append(Thread(target=x.check_status,args=(open_orders,))) threads.append(Thread(target=x.check_status,args=(open_orders,)))
online_pairs.append(f"{x.base}{x.quote}") online_pairs.append(f"{x.base}{x.quote}")
pairs_to_fetch.append(x.pair) pairs_to_fetch.append(x.config.get_pair())
#Here, append the dusters' pairs to pairs_to_fetch, if missing. #Here, append the dusters' pairs to pairs_to_fetch, if missing.
# #
@ -333,11 +333,11 @@ def main_loop():
top += int(x.config.get_no_of_safety_orders()) # It shows the percentage of safety orders not filled top += int(x.config.get_no_of_safety_orders()) # It shows the percentage of safety orders not filled
if not x.quit: #Why? Maybe to protect return_status() from weird errors if the trader errored out? if not x.quit: #Why? Maybe to protect return_status() from weird errors if the trader errored out?
try: try:
if x.pair in price_list and price_list[x.pair] is not None: if x.config.get_pair() in price_list and price_list[x.config.get_pair()] is not None:
x.get_status_dict()["price"] = price_list[x.pair] x.get_status_dict()["price"] = price_list[x.config.get_pair()]
except Exception as e: except Exception as e:
broker.logger.log_this(f"Exception while querying for pair price, key not present on price_list dictionary: {e}",1,x.pair) broker.logger.log_this(f"Exception while querying for pair price, key not present on price_list dictionary: {e}",1,x.config.get_pair())
worker_status[x.pair] = x.get_status_dict() worker_status[x.config.get_pair()] = x.get_status_dict()
#Clear the screen buffer #Clear the screen buffer
screen_buffer.clear() screen_buffer.clear()
@ -354,14 +354,14 @@ def main_loop():
global_status["online_workers"] = online_pairs.copy() global_status["online_workers"] = online_pairs.copy()
#Check for paused pairs #Check for paused pairs
global_status["paused_traders"] = [x.pair for x in running_instances if x.pause] global_status["paused_traders"] = [x.config.get_pair() for x in running_instances if x.pause]
if global_status["paused_traders"]: if global_status["paused_traders"]:
screen_buffer.append(f"{cyan}Paused pairs: {list(global_status['paused_traders'])}{white}") screen_buffer.append(f"{cyan}Paused pairs: {list(global_status['paused_traders'])}{white}")
#Check for paused pairs #Check for paused pairs
for x in running_instances: for x in running_instances:
if x.pause: if x.pause:
screen_buffer.append(f"{x.pair} paused: {x.get_status_dict()['pause_reason']}") screen_buffer.append(f"{x.config.get_pair()} paused: {x.get_status_dict()['pause_reason']}")
#Prints general info #Prints general info
instance_uptime = int(time.time()) - instance_start_time instance_uptime = int(time.time()) - instance_start_time
@ -395,7 +395,7 @@ def main_loop():
#Toggle pauses #Toggle pauses
if toggle_pauses: if toggle_pauses:
for instance in running_instances: for instance in running_instances:
if instance.pair in toggle_pauses: if instance.config.get_pair() in toggle_pauses:
instance.pause = not instance.pause instance.pause = not instance.pause
toggle_pauses.clear() toggle_pauses.clear()
@ -1226,6 +1226,30 @@ def reload_safety_order():
return jsonify({'Error': 'API key invalid'}), 401 return jsonify({'Error': 'API key invalid'}), 401
@base_api.route("/reload_trader_config", methods=['POST'])#type:ignore
def reload_trader_config():
'''
POST request
Parameters:
base: str
quote: str
'''
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
try:
if request.json is None:
return jsonify({'Error': 'request.json is None'})
data = request.json
base = data["base"]
quote = data["quote"]
return unwrapped_reload_trader_config(base,quote)
except Exception as e:
print(e)
return jsonify({'Error': 'Halp'})
return jsonify({'Error': 'API key invalid'}), 401
def run_API(): def run_API():
serve(base_api, host="0.0.0.0", port=broker.get_config()["port"], threads=16) serve(base_api, host="0.0.0.0", port=broker.get_config()["port"], threads=16)
#base_api.run(host="0.0.0.0", port=broker.get_config()["port"]) #base_api.run(host="0.0.0.0", port=broker.get_config()["port"])
@ -1294,7 +1318,7 @@ def unwrapped_add_pair(base,quote):
try: try:
#Check if the trader is already running #Check if the trader is already running
for x in running_instances: for x in running_instances:
if f"{base}/{quote}"==x.pair: if f"{base}/{quote}"==x.config.get_pair():
broker.logger.log_this(f"Pair already running",1,f"{base}/{quote}") broker.logger.log_this(f"Pair already running",1,f"{base}/{quote}")
return jsonify({"Error": "Pair already running"}) return jsonify({"Error": "Pair already running"})
@ -1348,7 +1372,7 @@ def unwrapped_remove_pair(base,quote):
try: try:
for x in running_instances: for x in running_instances:
if f"{base}/{quote}"==x.pair: if f"{base}/{quote}"==x.config.get_pair():
x.quit = True x.quit = True
return jsonify({"Success": "Pair to be removed"}) return jsonify({"Success": "Pair to be removed"})
except Exception as e: except Exception as e:
@ -1414,7 +1438,7 @@ def unwrapped_switch_to_long(base,quote,calculate_profits):
if f"{base}{quote}" not in broker.get_pairs(): if f"{base}{quote}" not in broker.get_pairs():
return jsonify({"Error": "Pair not running"}) return jsonify({"Error": "Pair not running"})
for x in running_instances: for x in running_instances:
if f"{base}/{quote}"==x.pair: if f"{base}/{quote}"==x.config.get_pair():
x.pause = True x.pause = True
if x.switch_to_long(ignore_old_long=ignore_old_long)==1: if x.switch_to_long(ignore_old_long=ignore_old_long)==1:
return jsonify({"Error": "Error in switch_to_long()"}) return jsonify({"Error": "Error in switch_to_long()"})
@ -1441,14 +1465,14 @@ def unwrapped_switch_to_short(base,quote):
if f"{base}{quote}" not in broker.get_pairs(): if f"{base}{quote}" not in broker.get_pairs():
return jsonify({"Error": "Pair not running"}) return jsonify({"Error": "Pair not running"})
for x in running_instances: for x in running_instances:
if f"{base}/{quote}"==x.pair and x.switch_to_short()==1: if f"{base}/{quote}"==x.config.get_pair() and x.switch_to_short()==1:
return jsonify({"Error": "Error in switch_to_short()"}) return jsonify({"Error": "Error in switch_to_short()"})
#Restart instance #Restart instance
try: try:
broker.logger.log_this(f"Reinitializing trader",2,f"{base}/{quote}") broker.logger.log_this(f"Reinitializing trader",2,f"{base}/{quote}")
for x in running_instances: for x in running_instances:
if f"{base}/{quote}"==x.pair: if f"{base}/{quote}"==x.config.get_pair():
x.status.set_take_profit_order(x.broker.empty_order) x.status.set_take_profit_order(x.broker.empty_order)
x.so = x.broker.empty_order x.so = x.broker.empty_order
@ -1496,7 +1520,7 @@ def unwrapped_load_old_long(base,quote):
#Creates (or modifies) a key in the status dictionary and assigns the contents of the file to that same key. #Creates (or modifies) a key in the status dictionary and assigns the contents of the file to that same key.
for x in running_instances: for x in running_instances:
if x.pair==f"{base}/{quote}": if x.config.get_pair()==f"{base}/{quote}":
x.get_status_dict()["old_long"]=old_long x.get_status_dict()["old_long"]=old_long
x.update_status(True) x.update_status(True)
return jsonify({"Success": "old_long file loaded to status_dict"}) return jsonify({"Success": "old_long file loaded to status_dict"})
@ -1522,7 +1546,7 @@ def unwrapped_view_old_long(base,quote,from_file):
old_long = json.load(ol) old_long = json.load(ol)
return jsonify(old_long) return jsonify(old_long)
for x in running_instances: for x in running_instances:
if f"{base}/{quote}"==x.pair: if f"{base}/{quote}"==x.config.get_pair():
if "old_long" in x.get_status_dict(): if "old_long" in x.get_status_dict():
return jsonify(x.get_status_dict()["old_long"]) return jsonify(x.get_status_dict()["old_long"])
return jsonify({"Error": "No old_long info found"}) return jsonify({"Error": "No old_long info found"})
@ -1547,7 +1571,7 @@ def unwrapped_switch_to_long_price(base,quote):
try: try:
for x in running_instances: for x in running_instances:
if f"{base}/{quote}"==x.pair: if f"{base}/{quote}"==x.config.get_pair():
if "old_long" in x.get_status_dict(): if "old_long" in x.get_status_dict():
#minimum_switch_price = (old_target - quote_already_in)/base_left #minimum_switch_price = (old_target - quote_already_in)/base_left
old_target = x.get_status_dict()["old_long"]["tp_price"]*x.get_status_dict()["old_long"]["tp_amount"] old_target = x.get_status_dict()["old_long"]["tp_price"]*x.get_status_dict()["old_long"]["tp_amount"]
@ -1577,7 +1601,7 @@ def unwrapped_add_safety_orders(base,quote,amount):
try: try:
for x in running_instances: for x in running_instances:
if f"{base}/{quote}"==x.pair: if f"{base}/{quote}"==x.config.get_pair():
x.pause = True x.pause = True
#x.no_of_safety_orders += int(amount) #x.no_of_safety_orders += int(amount)
x.config.set_no_of_safety_orders(x.config.get_no_of_safety_orders()+int(amount)) x.config.set_no_of_safety_orders(x.config.get_no_of_safety_orders()+int(amount))
@ -1608,7 +1632,7 @@ def unwrapped_mod_tp_level(base,quote,amount):
try: try:
for x in running_instances: for x in running_instances:
if f"{base}/{quote}"==x.pair: if f"{base}/{quote}"==x.config.get_pair():
x.config.set_tp_level(float(amount)) x.config.set_tp_level(float(amount))
broker.logger.log_this("Done. The change will take effect when the next take profit order is placed",2,f"{base}/{quote}") broker.logger.log_this("Done. The change will take effect when the next take profit order is placed",2,f"{base}/{quote}")
return jsonify({"Success": "Success. The change will take effect when the next TP order is placed"}) return jsonify({"Success": "Success. The change will take effect when the next TP order is placed"})
@ -1652,7 +1676,7 @@ def unwrapped_last_call(base,quote):
try: try:
if f"{base}{quote}" in broker.get_pairs(): if f"{base}{quote}" in broker.get_pairs():
for x in running_instances: for x in running_instances:
if f"{base}/{quote}"==x.pair: if f"{base}/{quote}"==x.config.get_pair():
x.stop_when_profit = not x.stop_when_profit x.stop_when_profit = not x.stop_when_profit
x.update_status(True) x.update_status(True)
if x.stop_when_profit: if x.stop_when_profit:
@ -1684,7 +1708,7 @@ def unwrapped_deferred_last_call(base,quote,yyyymmdd):
if limit==0: if limit==0:
return jsonify({"Error": "Can't convert date to unix"}) return jsonify({"Error": "Can't convert date to unix"})
for x in running_instances: for x in running_instances:
if f"{base}{quote}"==x.pair: if f"{base}{quote}"==x.config.get_pair():
x.config.set_programmed_stop_time(limit) x.config.set_programmed_stop_time(limit)
x.config.set_programmed_stop(True) x.config.set_programmed_stop(True)
#save config file to disk #save config file to disk
@ -1710,7 +1734,7 @@ def unwrapped_toggle_pause(base,quote):
try: try:
toggle_pauses.append(f"{base}/{quote}") toggle_pauses.append(f"{base}/{quote}")
for instance in running_instances: for instance in running_instances:
if instance.pair==f"{base}/{quote}": if instance.config.get_pair()==f"{base}/{quote}":
if instance.pause: if instance.pause:
return jsonify({"Success": "Trader will be resumed"}) return jsonify({"Success": "Trader will be resumed"})
return jsonify({"Success": "Trader will be paused"}) return jsonify({"Success": "Trader will be paused"})
@ -1772,21 +1796,21 @@ def unwrapped_add_quote(base,quote,amount):
''' '''
for x in running_instances: for x in running_instances:
if f"{base}/{quote}"==x.pair: if f"{base}/{quote}"==x.config.get_pair():
if x.config.get_is_short(): if x.config.get_is_short():
return jsonify({"Error": "Quote can't be added to short bots"}) return jsonify({"Error": "Quote can't be added to short bots"})
x.pause = True x.pause = True
new_average_price = (x.status.get_quote_spent()+float(amount))/(x.status.get_base_bought()+(float(amount)/x.get_status_dict()["price"])) new_average_price = (x.status.get_quote_spent()+float(amount))/(x.status.get_base_bought()+(float(amount)/x.get_status_dict()["price"]))
broker.logger.log_this(f"Your new average buy price will be {new_average_price} {x.quote}",2,f"{base}/{quote}") broker.logger.log_this(f"Your new average buy price will be {new_average_price} {x.quote}",2,f"{base}/{quote}")
broker.logger.log_this(f"Your new take profit price price will be {new_average_price*x.get_tp_level()} {x.quote}",2,f"{base}/{quote}") broker.logger.log_this(f"Your new take profit price price will be {new_average_price*x.get_tp_level()} {x.quote}",2,f"{base}/{quote}")
new_order = broker.new_market_order(x.pair,float(amount),"buy") new_order = broker.new_market_order(x.config.get_pair(),float(amount),"buy")
if new_order is None: if new_order is None:
broker.logger.log_this("Error: Market order returned None",2,f"{base}/{quote}") broker.logger.log_this("Error: Market order returned None",2,f"{base}/{quote}")
x.pause = False x.pause = False
return jsonify({"Error": "Market order returned None"}) return jsonify({"Error": "Market order returned None"})
while True: while True:
time.sleep(broker.get_wait_time()) time.sleep(broker.get_wait_time())
returned_order = broker.get_order(new_order["id"],x.pair) returned_order = broker.get_order(new_order["id"],x.config.get_pair())
if returned_order==broker.empty_order: if returned_order==broker.empty_order:
broker.logger.log_this("Problems sending the order",2,f"{base}/{quote}") broker.logger.log_this("Problems sending the order",2,f"{base}/{quote}")
x.pause = False x.pause = False
@ -1803,7 +1827,7 @@ def unwrapped_add_quote(base,quote,amount):
x.status.set_quote_spent(x.status.get_quote_spent()+returned_order["cost"]) x.status.set_quote_spent(x.status.get_quote_spent()+returned_order["cost"])
broker.logger.log_this("Cancelling old take profit order and sending a new one",2,f"{base}/{quote}") broker.logger.log_this("Cancelling old take profit order and sending a new one",2,f"{base}/{quote}")
attempts = 5 attempts = 5
while broker.cancel_order(x.status.get_tp_order_id(),x.pair)==1: while broker.cancel_order(x.status.get_tp_order_id(),x.config.get_pair())==1:
broker.logger.log_this("Can't cancel old take profit order, retrying...",2,f"{base}/{quote}") broker.logger.log_this("Can't cancel old take profit order, retrying...",2,f"{base}/{quote}")
time.sleep(broker.get_wait_time()) time.sleep(broker.get_wait_time())
attempts-=1 attempts-=1
@ -1812,7 +1836,7 @@ def unwrapped_add_quote(base,quote,amount):
x.pause = False x.pause = False
return jsonify({"Error": "Can't cancel old take profit order."}) return jsonify({"Error": "Can't cancel old take profit order."})
x.status.set_take_profit_price(x.status.get_quote_spent()/x.status.get_base_bought()*x.get_tp_level()) x.status.set_take_profit_price(x.status.get_quote_spent()/x.status.get_base_bought()*x.get_tp_level())
x.status.set_take_profit_order(broker.new_limit_order(x.pair,x.status.get_base_bought(),"sell",x.status.get_take_profit_price())) x.status.set_take_profit_order(broker.new_limit_order(x.config.get_pair(),x.status.get_base_bought(),"sell",x.status.get_take_profit_price()))
x.update_status(True) x.update_status(True)
break break
else: else:
@ -1858,7 +1882,7 @@ def unwrapped_toggle_cleanup(base,quote):
try: try:
pair_to_toggle = f"{base}/{quote}" pair_to_toggle = f"{base}/{quote}"
for x in running_instances: for x in running_instances:
if pair_to_toggle==x.pair: if pair_to_toggle==x.config.get_pair():
x.config.set_cleanup(not x.config.get_cleanup()) x.config.set_cleanup(not x.config.get_cleanup())
if x.config.get_cleanup(): if x.config.get_cleanup():
return jsonify({"Success": "Cleanup turned ON"}) return jsonify({"Success": "Cleanup turned ON"})
@ -1884,7 +1908,7 @@ def unwrapped_toggle_autoswitch(base,quote):
try: try:
pair_to_toggle = f"{base}/{quote}" pair_to_toggle = f"{base}/{quote}"
for x in running_instances: for x in running_instances:
if pair_to_toggle==x.pair: if pair_to_toggle==x.config.get_pair():
if x.config.get_autoswitch(): if x.config.get_autoswitch():
broker.logger.log_this("Autoswitch turned OFF",1,f"{base}/{quote}") broker.logger.log_this("Autoswitch turned OFF",1,f"{base}/{quote}")
x.config.set_autoswitch(False) x.config.set_autoswitch(False)
@ -1913,7 +1937,7 @@ def unwrapped_toggle_check_old_long_price(base,quote):
try: try:
pair_to_toggle = f"{base}/{quote}" pair_to_toggle = f"{base}/{quote}"
for x in running_instances: for x in running_instances:
if pair_to_toggle==x.pair: if pair_to_toggle==x.config.get_pair():
if x.config.get_check_old_long_price(): if x.config.get_check_old_long_price():
broker.logger.log_this("Check OFF",1,f"{base}/{quote}") broker.logger.log_this("Check OFF",1,f"{base}/{quote}")
x.config.set_check_old_long_price(False) x.config.set_check_old_long_price(False)
@ -1943,7 +1967,7 @@ def unwrapped_switch_quote_currency(base,quote,new_quote):
try: try:
pair_to_switch = f"{base}/{quote}" pair_to_switch = f"{base}/{quote}"
for trader in running_instances: for trader in running_instances:
if pair_to_switch==trader.pair: if pair_to_switch==trader.config.get_pair():
#Pause the trader #Pause the trader
trader.pause = True trader.pause = True
@ -2122,9 +2146,10 @@ def unwrapped_reload_safety_order(base,quote):
''' '''
try: try:
for trader in running_instances: for trader in running_instances:
if trader.pair==f"{base}/{quote}": if trader.config.get_pair()==f"{base}/{quote}":
trader.reload_safety_order() trader.config.load_from_file()
return jsonify({"Success": "Safety order reloaded successfully"}) return jsonify({"Success": "Safety order reloaded successfully"})
return jsonify({"Error": "Trader not found"})
except Exception as e: except Exception as e:
broker.logger.log_this(f"Exception while reloading safety order: {e}",1) broker.logger.log_this(f"Exception while reloading safety order: {e}",1)
return jsonify({"Error": "Safety order couldn't be reloaded"}) return jsonify({"Error": "Safety order couldn't be reloaded"})
@ -2151,6 +2176,22 @@ def unwrapped_get_balance(coin):
return jsonify({"Error": "Balance could not be queried"}) return jsonify({"Error": "Balance could not be queried"})
def unwrapped_reload_trader_config(base,quote):
'''
Reloads the config file of the trader
Parameters:
base (str): The base currency of the pair.
quote (str): The quote currency of the pair.
Returns:
jsonify: A jsonified dictionary detailing the outcome of the operation.
'''
for trader in running_instances:
if trader.config.get_pair() == f"{base}/{quote}":
return jsonify(worker_status[f"{base}/{quote}"])
return jsonify({"Error": "Worker does not exist"})
if __name__=="__main__": if __name__=="__main__":

View File

@ -9,11 +9,10 @@ Mandatory:
6. Multiple safety orders open at the same time (to catch big volatility spikes more effectively) 6. Multiple safety orders open at the same time (to catch big volatility spikes more effectively)
7. Things that should be objects (it's not 1994): 7. Things that should be objects (it's not 1994):
* Orders. * Orders.
* Config object (instead of a config dictionary). * Config (parameter validation remains to be implemented).
* Status object (instead of a status dictionary). * Status (parameter validation remains to be implemented).
8. Implement the ability to add safety orders to a short trader depending on the amount of free funds available, not just any number of orders. 8. Implement the ability to add safety orders to a short trader depending on the amount of free funds available, not just any number of orders.
9. API documentation. 9. API documentation.
10. Do not reload the config file every time a deal is closed and add an API endpoint to do it.
Would be nice to have: Would be nice to have:

429
trader.py

File diff suppressed because it is too large Load Diff

View File

@ -56,6 +56,7 @@ TRADERS
65) toggle_pause 66) toggle_cleanup 67) toggle_autoswitch 65) toggle_pause 66) toggle_cleanup 67) toggle_autoswitch
68) toggle_check_old_long_price 69) switch_quote_currency 68) toggle_check_old_long_price 69) switch_quote_currency
70) reload_safety_order 71) view_old_long 72) switch_price 70) reload_safety_order 71) view_old_long 72) switch_price
73) reload_trader_config
98) Change broker 99) Exit 98) Change broker 99) Exit
''' '''
@ -782,3 +783,16 @@ if __name__=="__main__":
print(json.loads(requests.get(url,headers=headers).content)) print(json.loads(requests.get(url,headers=headers).content))
input("Press ENTER to continue ") input("Press ENTER to continue ")
elif command==73:
print("Reloads from disk the configuration file of a trader")
trading_pair = input("Input trader in the format BASE/QUOTE: ").upper()
if not validate_pair(trading_pair):
print("The input is invalid")
break
if input("Proceed? (Y/n) ") in ["Y","y",""]:
url = f"{base_url}{port}/reload_trader_config"
base,quote = trading_pair.split("/")
parameters = {"base": base,
"quote": quote}
print(json.loads(requests.post(url, headers=headers, json=parameters).content))
input("Press ENTER to continue ")