- Fixed tp mode 2 non-functional

- Fixed duster binance fee estimation
- Fixed executor variable shadowing breaking graceful shutdown
- Fixed infinite loop in cancel_order
- Fixed modifying running_traders during iteration
- Fixed missing "status/" prefix in old_long file paths
- Removed double TP order cancellation while switching to short.
- Added locks to prevent race conditions on running_traders.
This commit is contained in:
Nicolás Sánchez 2026-06-03 18:43:40 -03:00
parent 12999a2189
commit ffe58e2c0d
5 changed files with 389 additions and 317 deletions

View File

@ -1,3 +1,13 @@
2026.06.03:
. Fixed tp mode 2 non-functional
. Fixed duster binance fee estimation
. Fixed executor variable shadowing breaking graceful shutdown
. Fixed infinite loop in cancel_order
. Fixed modifying running_traders during iteration
. Fixed missing "status/" prefix in old_long file paths
. Removed double TP order cancellation while switching to short.
. Added locks to prevent race conditions on running_traders.
2025.12.01: 2025.12.01:
. Modified log output of new_market_order. . Modified log output of new_market_order.
. Modified Kucoin's case in min_amount_of_base. . Modified Kucoin's case in min_amount_of_base.

View File

@ -189,7 +189,8 @@ class duster:
if self.broker.get_exchange_name()=="binance": #CCXT still to this day does not take Binance fees into account. if self.broker.get_exchange_name()=="binance": #CCXT still to this day does not take Binance fees into account.
try: try:
fee_rate = self.broker.fetch_market["maker"] if order["type"]=="limit" else self.broker.fetch_market["taker"] market = self.broker.fetch_maker(self.duster_status["pair"])
fee_rate = market["maker"] if order["type"]=="limit" else market["taker"]
except Exception as e: except Exception as e:
self.broker.logger.log_this(f"Exception fetching market information: {e}. Using default fee rate of 0.1%",1,f"{base}{quote}") self.broker.logger.log_this(f"Exception fetching market information: {e}. Using default fee rate of 0.1%",1,f"{base}{quote}")
fee_rate = 0.001 fee_rate = 0.001

View File

@ -622,24 +622,42 @@ class Broker:
:return: 0 if order was succesfully canceled, 1 if not :return: 0 if order was succesfully canceled, 1 if not
''' '''
tries = self.retries//2 cancel_attempts = self.retries//2
while tries>0: while cancel_attempts > 0:
try: try:
while self.get_order(id,symbol)["status"]=="open": self.exchange.cancel_order(id, symbol)
self.exchange.cancel_order(id,symbol) time.sleep(self.wait_time)
time.sleep(self.wait_time) if self.get_order(id, symbol)["status"] != "open":
return 0 return 0
except Exception as e: except Exception as e:
if self.get_order(id,symbol)["status"]=="canceled": if self.get_order(id, symbol)["status"] == "canceled":
return 0 return 0
self.logger.log_this(f"Exception in cancel_order: id {id} - exception: {e}",1) self.logger.log_this(f"Exception in cancel_order: id {id} - exception: {e}",1)
if no_retries: if no_retries:
break break
time.sleep(self.wait_time) cancel_attempts -= 1
tries-=1 time.sleep(self.wait_time)
return 1 return 1
# tries = self.retries//2
# while tries>0:
# try:
# while self.get_order(id,symbol)["status"]=="open":
# self.exchange.cancel_order(id,symbol)
# time.sleep(self.wait_time)
# return 0
# except Exception as e:
# if self.get_order(id,symbol)["status"]=="canceled":
# return 0
# self.logger.log_this(f"Exception in cancel_order: id {id} - exception: {e}",1)
# if no_retries:
# break
# time.sleep(self.wait_time)
# tries-=1
# return 1
def amount_to_precision(self,pair,amount): def amount_to_precision(self,pair,amount):
try: try:
return float(self.exchange.amount_to_precision(pair,amount)) return float(self.exchange.amount_to_precision(pair,amount))

644
main.py
View File

@ -5,7 +5,7 @@ from sys import argv
from os import _exit as os_exit from os import _exit as os_exit
from json import load from json import load
from datetime import date from datetime import date
from threading import Thread from threading import Thread, Lock
from waitress import serve from waitress import serve
from concurrent.futures import ThreadPoolExecutor, as_completed from concurrent.futures import ThreadPoolExecutor, as_completed
@ -18,7 +18,7 @@ import exchange_wrapper
import trader import trader
version = "2025.12.01" version = "2026.06.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
@ -43,7 +43,7 @@ executor = None
def shutdown_handler(signum, _): def shutdown_handler(signum, _):
broker.logger.log_this(f"Received signal {signum}, shutting down.", 2) broker.logger.log_this(f"Received signal {signum}, shutting down.", 2)
if executor: if executor:
executor.shutdown(wait=True, timeout=5) executor.shutdown(wait=True)
os_exit(0) os_exit(0)
# Register signals for shutdown handler # Register signals for shutdown handler
@ -119,10 +119,11 @@ def add_instance(base: str, quote: str) -> int:
#Check if the pair is already running #Check if the pair is already running
pair = f"{base}{quote}" pair = f"{base}{quote}"
for instance in running_traders: with traders_lock:
if f"{instance.base}{instance.quote}"==pair: for instance in running_traders:
broker.logger.log_this(f"Pair already running, duplicate traders are not allowed",1,pair) if f"{instance.base}{instance.quote}"==pair:
return 1 broker.logger.log_this(f"Pair already running, duplicate traders are not allowed",1,pair)
return 1
#Initialize the trader object and add the pair to the tickers list #Initialize the trader object and add the pair to the tickers list
instances_to_add.append(trader.trader(broker,f"{base}/{quote}")) instances_to_add.append(trader.trader(broker,f"{base}/{quote}"))
@ -143,7 +144,8 @@ def initialize_instance(base: str, quote: str) -> int:
int: 0 if successful int: 0 if successful
''' '''
broker.logger.log_this(f"Initializing {f'{base}/{quote}'}") broker.logger.log_this(f"Initializing {f'{base}/{quote}'}")
running_traders.append(trader.trader(broker,f'{base}/{quote}')) with traders_lock:
running_traders.append(trader.trader(broker,f'{base}/{quote}'))
if f'{base}{quote}' not in tickers: if f'{base}{quote}' not in tickers:
tickers.append(f'{base}{quote}') tickers.append(f'{base}{quote}')
return 0 return 0
@ -246,33 +248,34 @@ def restart_pair_no_json(base: str, quote: str) -> int:
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
for instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair(): for instance in running_traders:
instance.set_pause(True, "Restarting trader") if symbol==instance.status.get_pair():
#Backing up old status file instance.set_pause(True, "Restarting trader")
instance.status.save_to_file(is_backup=True) #Backing up old status file
instance.status.save_to_file(is_backup=True)
broker.logger.log_this(f"Cancelling old take profit order",2,symbol) broker.logger.log_this(f"Cancelling old take profit order",2,symbol)
try:
old_tp_order = instance.status.get_take_profit_order()
broker.cancel_order(old_tp_order["id"],old_tp_order["symbol"])
except Exception as e:
broker.logger.log_this(f"Error canceling old take profit order: {e}",2,symbol)
broker.logger.log_this(f"Cancelling old take safety orders",2,symbol)
for item in instance.status.get_safety_orders():
try: try:
broker.cancel_order(item["id"],item["symbol"]) old_tp_order = instance.status.get_take_profit_order()
broker.cancel_order(old_tp_order["id"],old_tp_order["symbol"])
except Exception as e: except Exception as e:
broker.logger.log_this(f"Error canceling old safety order: {e}",2,symbol) broker.logger.log_this(f"Error canceling old take profit order: {e}",2,symbol)
try: broker.logger.log_this(f"Cancelling old take safety orders",2,symbol)
running_traders.remove(instance) for item in instance.status.get_safety_orders():
except ValueError: try:
broker.logger.log_this(f"Instance {instance.status.get_pair()} not found in running_traders.",1,instance.status.get_pair()) broker.cancel_order(item["id"],item["symbol"])
add_instance(base,quote) except Exception as e:
return 0 broker.logger.log_this(f"Error canceling old safety order: {e}",2,symbol)
return 1
try:
running_traders.remove(instance)
except ValueError:
broker.logger.log_this(f"Instance {instance.status.get_pair()} not found in running_traders.",1,instance.status.get_pair())
add_instance(base,quote)
return 0
return 1
except Exception as e: except Exception as e:
broker.logger.log_this(f"Exception in restart_pair_no_json: {e}",1,symbol) broker.logger.log_this(f"Exception in restart_pair_no_json: {e}",1,symbol)
return 1 return 1
@ -282,6 +285,7 @@ def main_routine():
global last_market_reload global last_market_reload
global reload_interval global reload_interval
global screen_buffer global screen_buffer
global executor
executor = ThreadPoolExecutor(max_workers=len(broker.get_config()["pairs"])+worker_threads_overprovisioning) executor = ThreadPoolExecutor(max_workers=len(broker.get_config()["pairs"])+worker_threads_overprovisioning)
is_testnet = "TESTNET " if broker.get_config()["is_sandbox"] else "" is_testnet = "TESTNET " if broker.get_config()["is_sandbox"] else ""
@ -290,42 +294,51 @@ def main_routine():
while True: while True:
#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 instance in running_traders: to_restart = []
if instance.restart and instance.config.get_attempt_restart(): to_remove = []
broker.logger.log_this(f"Restarting trader",1,instance.status.get_pair()) with traders_lock:
restart_pair_no_json(instance.base,instance.quote) for instance in running_traders:
if instance.quit: if instance.restart and instance.config.get_attempt_restart():
#Here, check if a duster is needed to_restart.append(instance)
broker.logger.log_this(f"{broker.get_exchange_name()} | Quit flag raised, removing trader.",0,instance.status.get_pair()) if instance.quit:
broker.logger.log_this(f"{broker.get_exchange_name()} | Quit flag raised, removing trader: {instance.status.get_pair()}",-1) #Forced message to TG to_remove.append(instance)
if f"{instance.base}{instance.quote}" in tickers: for instance in to_restart:
tickers.remove(f"{instance.base}{instance.quote}") broker.logger.log_this(f"Restarting trader",1,instance.status.get_pair())
broker.remove_pair_from_config(f"{instance.base}{instance.quote}") restart_pair_no_json(instance.base,instance.quote)
broker.rewrite_config_file() for instance in to_remove:
try: #Here, check if a duster is needed
running_traders.remove(instance) broker.logger.log_this(f"{broker.get_exchange_name()} | Quit flag raised, removing trader.",0,instance.status.get_pair())
except ValueError: broker.logger.log_this(f"{broker.get_exchange_name()} | Quit flag raised, removing trader: {instance.status.get_pair()}",-1) #Forced message to TG
broker.logger.log_this(f"Instance {instance.status.get_pair()} not found in running_traders.",1,instance.status.get_pair()) if f"{instance.base}{instance.quote}" in tickers:
tickers.remove(f"{instance.base}{instance.quote}")
broker.remove_pair_from_config(f"{instance.base}{instance.quote}")
broker.rewrite_config_file()
try:
running_traders.remove(instance)
except ValueError:
broker.logger.log_this(f"Instance {instance.status.get_pair()} not found in running_traders.",1,instance.status.get_pair())
#Adds pending traders #Adds pending traders
if bool(instances_to_add): if bool(instances_to_add):
for instance in instances_to_add: with traders_lock:
running_traders.append(instance) for instance in instances_to_add:
instances_to_add.clear() running_traders.append(instance)
instances_to_add.clear()
#Prepares the trader threads #Prepares the trader threads
futures = [] futures = []
pairs_to_fetch = [] pairs_to_fetch = []
online_pairs = [] online_pairs = []
with traders_lock:
for instance in running_traders: for instance in running_traders:
pairs_to_fetch.append(instance.status.get_pair()) pairs_to_fetch.append(instance.status.get_pair())
open_orders = broker.fetch_open_orders(pairs_to_fetch) open_orders = broker.fetch_open_orders(pairs_to_fetch)
for instance in running_traders: with traders_lock:
future = executor.submit(instance.check_status, open_orders) for instance in running_traders:
futures.append(future) future = executor.submit(instance.check_status, open_orders)
online_pairs.append(f"{instance.base}{instance.quote}") futures.append(future)
online_pairs.append(f"{instance.base}{instance.quote}")
#Fetch prices #Fetch prices
price_list = broker.get_prices(pairs_to_fetch) price_list = broker.get_prices(pairs_to_fetch)
@ -343,24 +356,26 @@ def main_routine():
short_traders_status_strings = [] short_traders_status_strings = []
paused_traders_status_strings = [] paused_traders_status_strings = []
global_status["paused_traders"].clear() global_status["paused_traders"].clear()
for instance in running_traders:
if not instance.config.get_is_short():
curr += int(instance.status.get_so_amount()) # For the safety order occupancy percentage calculation
top += int(instance.config.get_no_of_safety_orders())
if "status_string" in instance.get_status_dict():
long_traders_status_strings.append(str(instance))
elif "status_string" in instance.get_status_dict():
short_traders_status_strings.append(str(instance))
try:
if instance.status.get_pair() in price_list and price_list[instance.status.get_pair()] is not None:
instance.get_status_dict()["price"] = price_list[instance.status.get_pair()]
except Exception as e:
broker.logger.log_this(f"Exception while querying for pair price, key not present on price_list dictionary: {e}",1,instance.status.get_pair())
#Add paused traders to the paused trader list with traders_lock:
if instance.pause: for instance in running_traders:
global_status["paused_traders"].append(instance.status.get_pair()) if not instance.config.get_is_short():
paused_traders_status_strings.append(f"{cyan}Paused pairs: {list(global_status['paused_traders'])}{white}") curr += int(instance.status.get_so_amount()) # For the safety order occupancy percentage calculation
top += int(instance.config.get_no_of_safety_orders())
if "status_string" in instance.get_status_dict():
long_traders_status_strings.append(str(instance))
elif "status_string" in instance.get_status_dict():
short_traders_status_strings.append(str(instance))
try:
if instance.status.get_pair() in price_list and price_list[instance.status.get_pair()] is not None:
instance.get_status_dict()["price"] = price_list[instance.status.get_pair()]
except Exception as e:
broker.logger.log_this(f"Exception while querying for pair price, key not present on price_list dictionary: {e}",1,instance.status.get_pair())
#Add paused traders to the paused trader list
if instance.pause:
global_status["paused_traders"].append(instance.status.get_pair())
paused_traders_status_strings.append(f"{cyan}Paused pairs: {list(global_status['paused_traders'])}{white}")
#Delete no longer used data #Delete no longer used data
del price_list del price_list
@ -374,7 +389,8 @@ def main_routine():
#Updates some global status variables prior to deletion of those #Updates some global status variables prior to deletion of those
if len(running_traders)!=len(global_status["online_workers"]): if len(running_traders)!=len(global_status["online_workers"]):
global_status["online_workers"] = [instance.status.get_pair() for instance in running_traders] with traders_lock:
global_status["online_workers"] = [instance.status.get_pair() for instance in running_traders]
#Prints general info #Prints general info
instance_uptime = int(time.time()) - instance_start_time instance_uptime = int(time.time()) - instance_start_time
@ -409,9 +425,10 @@ def main_routine():
#Toggle pauses #Toggle pauses
if toggle_pauses: if toggle_pauses:
for instance in running_traders: with traders_lock:
if instance.status.get_pair() in toggle_pauses: for instance in running_traders:
instance.pause = not instance.pause if instance.status.get_pair() in toggle_pauses:
instance.pause = not instance.pause
toggle_pauses.clear() toggle_pauses.clear()
#Checks if market reload is due #Checks if market reload is due
@ -1505,9 +1522,10 @@ def unwrapped_return_worker_status(base,quote):
dict: The status dictionary of the trader. dict: The status dictionary of the trader.
''' '''
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
for instance in running_traders: with traders_lock:
if instance.status.get_pair() == symbol: for instance in running_traders:
return jsonify(instance.status.get_status()) if instance.status.get_pair() == symbol:
return jsonify(instance.status.get_status())
return jsonify({"Error": "Worker does not exist"}) return jsonify({"Error": "Worker does not exist"})
@ -1518,8 +1536,8 @@ def unwrapped_return_all_worker_status():
Returns: Returns:
dict: The status dictionary of all traders. dict: The status dictionary of all traders.
''' '''
with traders_lock:
return {instance.status.get_pair(): instance.status.get_status() for instance in running_traders} return {instance.status.get_pair(): instance.status.get_status() for instance in running_traders}
def unwrapped_add_pair(base,quote): def unwrapped_add_pair(base,quote):
@ -1538,10 +1556,11 @@ def unwrapped_add_pair(base,quote):
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
#Check if the trader is already running #Check if the trader is already running
for instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair(): for instance in running_traders:
broker.logger.log_this(f"Pair already running",1,symbol) if symbol==instance.status.get_pair():
return jsonify({"Error": "Pair already running"}) broker.logger.log_this(f"Pair already running",1,symbol)
return jsonify({"Error": "Pair already running"})
#Check if the market exists and it's open #Check if the market exists and it's open
if not broker.validate_market(symbol): if not broker.validate_market(symbol):
@ -1572,9 +1591,10 @@ def unwrapped_remove_pair(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
for instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair(): for instance in running_traders:
instance.quit = True if symbol==instance.status.get_pair():
instance.quit = True
return jsonify({"Success": "Pair to be removed"}) return jsonify({"Success": "Pair to be removed"})
except Exception as e: except Exception as e:
broker.logger.log_this(f"Exception while removing instance: {e}",1,symbol) broker.logger.log_this(f"Exception while removing instance: {e}",1,symbol)
@ -1639,15 +1659,16 @@ def unwrapped_switch_to_long(base,quote,calculate_profits):
#Close trader and orders and pull info our of the orders #Close trader and orders and pull info our of the orders
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 instance in running_traders: with traders_lock:
if f"{base}/{quote}"==instance.status.get_pair(): for instance in running_traders:
instance.set_pause(True, "Switching to long mode") if f"{base}/{quote}"==instance.status.get_pair():
if instance.switch_to_long(ignore_old_long=ignore_old_long,double_check_price=False)==1: instance.set_pause(True, "Switching to long mode")
return jsonify({"Error": "Error in switch_to_long()"}) if instance.switch_to_long(ignore_old_long=ignore_old_long,double_check_price=False)==1:
if instance.start_trader()==1: return jsonify({"Error": "Error in switch_to_long()"})
instance.quit = True if instance.start_trader()==1:
return jsonify({"Error": "Error switching to long mode (wAPI)"}) instance.quit = True
return jsonify({"Success": "Pair switched to long mode"}) return jsonify({"Error": "Error switching to long mode (wAPI)"})
return jsonify({"Success": "Pair switched to long mode"})
return jsonify({"Error": "Pair not found"}) return jsonify({"Error": "Pair not found"})
@ -1667,27 +1688,29 @@ def unwrapped_switch_to_short(base,quote):
symbol = f"{base}/{quote}" symbol = f"{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 instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair() and instance.switch_to_short()==1: for instance in running_traders:
return jsonify({"Error": "Error in switch_to_short()"}) if symbol==instance.status.get_pair() and instance.switch_to_short()==1:
return jsonify({"Error": "Error in switch_to_short()"})
#Restart instance #Restart instance
try: try:
broker.logger.log_this(f"Reinitializing trader",2,symbol) broker.logger.log_this(f"Reinitializing trader",2,symbol)
for instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair(): for instance in running_traders:
instance.status.set_take_profit_order(instance.broker.empty_order) if symbol==instance.status.get_pair():
instance.so = instance.broker.empty_order instance.status.set_take_profit_order(instance.broker.empty_order)
instance.so = instance.broker.empty_order
#Reloading config file #Reloading config file
instance.config.load_from_file() instance.config.load_from_file()
#Enabling autoswitch #Enabling autoswitch
instance.config.set_autoswitch(True) instance.config.set_autoswitch(True)
if instance.start_trader()==1: if instance.start_trader()==1:
instance.quit = True instance.quit = True
return jsonify({"Error": "Error switching to short mode (wAPI)"}) return jsonify({"Error": "Error switching to short mode (wAPI)"})
return jsonify({"Success": "Pair switched to short mode"}) return jsonify({"Success": "Pair switched to short mode"})
except Exception as e: except Exception as e:
broker.logger.log_this(f"Exception while reinitializing instance: {e}",1,symbol) broker.logger.log_this(f"Exception while reinitializing instance: {e}",1,symbol)
return jsonify({"Error": "Can't initialize trader"}) return jsonify({"Error": "Can't initialize trader"})
@ -1709,7 +1732,7 @@ def unwrapped_load_old_long(base,quote):
#Load the file #Load the file
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
with open(f"{base}{quote}.oldlong") as ol: with open(f"status/{base}{quote}.oldlong") as ol:
old_long = load(ol) old_long = load(ol)
except Exception as e: except Exception as e:
broker.logger.log_this(f"Exception while loading old_long file: {e}",1,symbol) broker.logger.log_this(f"Exception while loading old_long file: {e}",1,symbol)
@ -1723,11 +1746,12 @@ def unwrapped_load_old_long(base,quote):
#Maybe here we could also check that the keys have the proper values #Maybe here we could also check that the keys have the proper values
#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 instance in running_traders: with traders_lock:
if instance.status.get_pair()==symbol: for instance in running_traders:
instance.get_status_dict()["old_long"]=old_long if instance.status.get_pair()==symbol:
instance.update_status(True) instance.get_status_dict()["old_long"]=old_long
return jsonify({"Success": "old_long file loaded to status_dict"}) instance.update_status(True)
return jsonify({"Success": "old_long file loaded to status_dict"})
return jsonify({"Error": "Pair not found"}) return jsonify({"Error": "Pair not found"})
@ -1747,14 +1771,15 @@ def unwrapped_view_old_long(base,quote,from_file):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
if int(from_file)==1: if int(from_file)==1:
with open(f"{base}{quote}.oldlong") as ol: with open(f"status/{base}{quote}.oldlong") as ol:
old_long = load(ol) old_long = load(ol)
return jsonify(old_long) return jsonify(old_long)
for instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair(): for instance in running_traders:
if "old_long" in instance.get_status_dict(): if symbol==instance.status.get_pair():
return jsonify(instance.get_status_dict()["old_long"]) if "old_long" in instance.get_status_dict():
return jsonify({"Error": "No old_long info found"}) return jsonify(instance.get_status_dict()["old_long"])
return jsonify({"Error": "No old_long info found"})
return jsonify({"Error": "Pair not found"}) return jsonify({"Error": "Pair not found"})
except Exception as e: except Exception as e:
broker.logger.log_this(f"Exception while viewing old_long info: {e}",1,symbol) broker.logger.log_this(f"Exception while viewing old_long info: {e}",1,symbol)
@ -1776,16 +1801,17 @@ def unwrapped_switch_to_long_price(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
for instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair(): for instance in running_traders:
if "old_long" in instance.get_status_dict(): if symbol==instance.status.get_pair():
#minimum_switch_price = (old_target - quote_already_in)/base_left if "old_long" in instance.get_status_dict():
old_target = instance.get_status_dict()["old_long"]["tp_price"]*instance.get_status_dict()["old_long"]["tp_amount"] #minimum_switch_price = (old_target - quote_already_in)/base_left
base_left = instance.get_status_dict()["old_long"]["tp_amount"]-instance.get_status_dict()["base_bought"] old_target = instance.get_status_dict()["old_long"]["tp_price"]*instance.get_status_dict()["old_long"]["tp_amount"]
minimum_switch_price = (old_target - instance.get_status_dict()["quote_spent"])/base_left base_left = instance.get_status_dict()["old_long"]["tp_amount"]-instance.get_status_dict()["base_bought"]
return jsonify({"switch_price": minimum_switch_price}) minimum_switch_price = (old_target - instance.get_status_dict()["quote_spent"])/base_left
return jsonify({"Error": "No old_long info found"}) return jsonify({"switch_price": minimum_switch_price})
return jsonify({"Error": "Pair not found"}) return jsonify({"Error": "No old_long info found"})
return jsonify({"Error": "Pair not found"})
except Exception as e: except Exception as e:
broker.logger.log_this(f"Exception while viewing old_long info: {e}",1,symbol) broker.logger.log_this(f"Exception while viewing old_long info: {e}",1,symbol)
return jsonify({"Error": f"{e}"}) return jsonify({"Error": f"{e}"})
@ -1807,17 +1833,18 @@ def unwrapped_add_safety_orders(base,quote,amount):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
for instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair(): for instance in running_traders:
instance.set_pause(True, "Adding safety orders") if symbol==instance.status.get_pair():
instance.status.set_no_of_safety_orders(instance.status.get_no_of_safety_orders()+int(amount)) instance.set_pause(True, "Adding safety orders")
broker.logger.log_this("Recalculating safety price table...",1,symbol) instance.status.set_no_of_safety_orders(instance.status.get_no_of_safety_orders()+int(amount))
instance.status.set_safety_price_table(instance.calculate_safety_prices(instance.status.get_start_price(),instance.config.get_no_of_safety_orders(),instance.config.get_safety_order_deviance())) broker.logger.log_this("Recalculating safety price table...",1,symbol)
broker.logger.log_this(f"Done. Added {amount} safety orders",1,symbol) instance.status.set_safety_price_table(instance.calculate_safety_prices(instance.status.get_start_price(),instance.config.get_no_of_safety_orders(),instance.config.get_safety_order_deviance()))
instance.update_status(True) broker.logger.log_this(f"Done. Added {amount} safety orders",1,symbol)
instance.set_pause(False) instance.update_status(True)
return jsonify({"Success": f"Done. Added {amount} safety orders"}) instance.set_pause(False)
return jsonify({"Error": "Pair not found"}) return jsonify({"Success": f"Done. Added {amount} safety orders"})
return jsonify({"Error": "Pair not found"})
except Exception as e: except Exception as e:
broker.logger.log_this(f"{e}",2,symbol) broker.logger.log_this(f"{e}",2,symbol)
return jsonify({"Error": "Error adding safety orders"}) return jsonify({"Error": "Error adding safety orders"})
@ -1837,14 +1864,15 @@ def unwrapped_base_add_so_calculation(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
for instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair(): for instance in running_traders:
free_base = instance.fetch_free_base() if symbol==instance.status.get_pair():
if free_base is None: free_base = instance.fetch_free_base()
return jsonify({"Error": "Can't fetch amount of free base on the exchange"}) if free_base is None:
amount_of_orders = instance.base_add_calculation(free_base) return jsonify({"Error": "Can't fetch amount of free base on the exchange"})
return jsonify({"Amount": amount_of_orders, "Free base on exchange": free_base}) amount_of_orders = instance.base_add_calculation(free_base)
return jsonify({"Error": "Can't find the pair in the running instances"}) return jsonify({"Amount": amount_of_orders, "Free base on exchange": free_base})
return jsonify({"Error": "Can't find the pair in the running instances"})
except Exception as e: except Exception as e:
broker.logger.log_this(f"{e}",2,symbol) broker.logger.log_this(f"{e}",2,symbol)
return jsonify({"Error": "Error in unwrapped_base_add_so_calculation"}) return jsonify({"Error": "Error in unwrapped_base_add_so_calculation"})
@ -1865,9 +1893,10 @@ def unwrapped_mod_tp_level(base,quote,amount):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
for instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair(): for instance in running_traders:
instance.config.set_tp_level(float(amount)) if symbol==instance.status.get_pair():
instance.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,symbol) broker.logger.log_this("Done. The change will take effect when the next take profit order is placed",2,symbol)
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"})
except Exception: except Exception:
@ -1890,10 +1919,11 @@ def unwrapped_mod_order_size(base,quote,amount):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
for instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair(): for instance in running_traders:
instance.config.set_order_size(float(amount)) if symbol==instance.status.get_pair():
instance.config.save_to_file() instance.config.set_order_size(float(amount))
instance.config.save_to_file()
broker.logger.log_this("Done. The change will take effect when the next deal is started",2,symbol) broker.logger.log_this("Done. The change will take effect when the next deal is started",2,symbol)
return jsonify({"Success": "Success. The change will take effect when the next deal is started"}) return jsonify({"Success": "Success. The change will take effect when the next deal is started"})
except Exception: except Exception:
@ -1916,10 +1946,11 @@ def unwrapped_mod_concurrent_safety_orders(base,quote,amount):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
for instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair(): for instance in running_traders:
instance.config.set_concurrent_safety_orders(int(amount)) if symbol==instance.status.get_pair():
instance.config.save_to_file() instance.config.set_concurrent_safety_orders(int(amount))
instance.config.save_to_file()
broker.logger.log_this("Done. The change will take effect as new safety orders are sent or filled",2,symbol) broker.logger.log_this("Done. The change will take effect as new safety orders are sent or filled",2,symbol)
return jsonify({"Success": "Success. The change will take effect as new safety orders are sent or filled"}) return jsonify({"Success": "Success. The change will take effect as new safety orders are sent or filled"})
except Exception: except Exception:
@ -1942,10 +1973,11 @@ def unwrapped_mod_boosted_concurrent_safety_orders(base,quote,amount):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
for instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair(): for instance in running_traders:
instance.config.set_boosted_concurrent_safety_orders(int(amount)) if symbol==instance.status.get_pair():
instance.config.save_to_file() instance.config.set_boosted_concurrent_safety_orders(int(amount))
instance.config.save_to_file()
broker.logger.log_this("Done. The change will take effect as new safety orders are sent or filled",2,symbol) broker.logger.log_this("Done. The change will take effect as new safety orders are sent or filled",2,symbol)
return jsonify({"Success": "Success. The change will take effect as new safety orders are sent or filled"}) return jsonify({"Success": "Success. The change will take effect as new safety orders are sent or filled"})
except Exception: except Exception:
@ -1983,13 +2015,13 @@ def unwrapped_mod_global_tp_level(amount):
Returns: Returns:
jsonify: A jsonified dictionary detailing the outcome of the operation jsonify: A jsonified dictionary detailing the outcome of the operation
''' '''
with traders_lock:
for instance in running_traders: for instance in running_traders:
try: try:
instance.config.set_tp_level(float(amount)) instance.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) broker.logger.log_this("Done. The change will take effect when the next take profit order is placed",2)
except Exception: except Exception:
broker.logger.log_this("Error changing percentage. Ignoring.",2) broker.logger.log_this("Error changing percentage. Ignoring.",2)
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"})
@ -2007,16 +2039,17 @@ def unwrapped_last_call(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
for instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair(): for instance in running_traders:
instance.status.set_stop_when_profit(not instance.status.get_stop_when_profit()) if symbol==instance.status.get_pair():
instance.update_status(True) instance.status.set_stop_when_profit(not instance.status.get_stop_when_profit())
if instance.status.get_stop_when_profit():
instance.config.set_autoswitch(False)
instance.update_status(True) instance.update_status(True)
return jsonify({"Success": "Trader scheduled to go offline when profit is reached"}) if instance.status.get_stop_when_profit():
return jsonify({"Success": "Last call cancelled"}) instance.config.set_autoswitch(False)
return jsonify({"Error": "Trader does not exist"}) instance.update_status(True)
return jsonify({"Success": "Trader scheduled to go offline when profit is reached"})
return jsonify({"Success": "Last call cancelled"})
return jsonify({"Error": "Trader does not exist"})
except Exception: except Exception:
return jsonify({"Error": "Halp"}) return jsonify({"Error": "Halp"})
@ -2041,12 +2074,13 @@ def unwrapped_deferred_last_call(base,quote,yyyymmdd):
limit = time_to_unix(year,month,day) limit = time_to_unix(year,month,day)
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 instance in running_traders: with traders_lock:
if f"{base}{quote}"==instance.status.get_pair(): for instance in running_traders:
instance.config.set_programmed_stop_time(limit) if f"{base}{quote}"==instance.status.get_pair():
instance.config.set_programmed_stop(True) instance.config.set_programmed_stop_time(limit)
#save config file to disk instance.config.set_programmed_stop(True)
instance.broker.rewrite_config_file() #save config file to disk
instance.broker.rewrite_config_file()
return jsonify({"Success": f"Trader scheduled to go offline when profit is reached after {limit}"}) return jsonify({"Success": f"Trader scheduled to go offline when profit is reached after {limit}"})
except Exception: except Exception:
return jsonify({"Error": "Halp"}) return jsonify({"Error": "Halp"})
@ -2068,13 +2102,14 @@ def unwrapped_toggle_pause(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
toggle_pauses.append(symbol) toggle_pauses.append(symbol)
for instance in running_traders: with traders_lock:
if instance.status.get_pair()==symbol: for instance in running_traders:
if instance.pause: if instance.status.get_pair()==symbol:
instance.status.set_pause_reason("") if instance.pause:
return jsonify({"Success": "Trader will be resumed"}) instance.status.set_pause_reason("")
instance.status.set_pause_reason("User requested pause") return jsonify({"Success": "Trader will be resumed"})
return jsonify({"Success": "Trader will be paused"}) instance.status.set_pause_reason("User requested pause")
return jsonify({"Success": "Trader will be paused"})
return jsonify({"Error": "Trader does not exist"}) return jsonify({"Error": "Trader does not exist"})
except Exception: except Exception:
return jsonify({"Error": "Halp"}) return jsonify({"Error": "Halp"})
@ -2088,10 +2123,11 @@ def unwrapped_global_last_call():
jsonify: A jsonified dictionary detailing the outcome of the operation. jsonify: A jsonified dictionary detailing the outcome of the operation.
''' '''
try: try:
for instance in running_traders: with traders_lock:
instance.status.set_stop_when_profit(True) for instance in running_traders:
instance.config.set_autoswitch(False) instance.status.set_stop_when_profit(True)
broker.logger.log_this("Modified flag",2,f"{instance.base}/{instance.quote}") instance.config.set_autoswitch(False)
broker.logger.log_this("Modified flag",2,f"{instance.base}/{instance.quote}")
return jsonify({"Success": "All traders scheduled to go offline when profit is reached"}) return jsonify({"Success": "All traders scheduled to go offline when profit is reached"})
except Exception: except Exception:
return jsonify({"Error": "Halp"}) return jsonify({"Error": "Halp"})
@ -2105,9 +2141,10 @@ def unwrapped_cancel_global_last_call():
jsonify: A jsonified dictionary detailing the outcome of the operation. jsonify: A jsonified dictionary detailing the outcome of the operation.
''' '''
try: try:
for instance in running_traders: with traders_lock:
instance.status.set_stop_when_profit(False) for instance in running_traders:
broker.logger.log_this("Modified flag",2,f"{instance.base}/{instance.quote}") instance.status.set_stop_when_profit(False)
broker.logger.log_this("Modified flag",2,f"{instance.base}/{instance.quote}")
return jsonify({"Success": "Last call canceled"}) return jsonify({"Success": "Last call canceled"})
except Exception: except Exception:
return jsonify({"Error": "Halp"}) return jsonify({"Error": "Halp"})
@ -2126,58 +2163,58 @@ def unwrapped_add_quote(base,quote,amount):
Returns: Returns:
json: A jsonified dictionary detailing the outcome of the operation. json: A jsonified dictionary detailing the outcome of the operation.
''' '''
with traders_lock:
for instance in running_traders: for instance in running_traders:
if f"{base}/{quote}"==instance.status.get_pair(): if f"{base}/{quote}"==instance.status.get_pair():
if instance.config.get_is_short(): if instance.config.get_is_short():
return jsonify({"Error": "Quote can't be added to short traders"}) return jsonify({"Error": "Quote can't be added to short traders"})
instance.set_pause(True, "Adding quote") instance.set_pause(True, "Adding quote")
new_average_price = (instance.status.get_quote_spent()+float(amount))/(instance.status.get_base_bought()+(float(amount)/instance.status.get_price())) new_average_price = (instance.status.get_quote_spent()+float(amount))/(instance.status.get_base_bought()+(float(amount)/instance.status.get_price()))
broker.logger.log_this(f"Your new average buy price will be {new_average_price} {quote}",2,instance.status.get_pair()) broker.logger.log_this(f"Your new average buy price will be {new_average_price} {quote}",2,instance.status.get_pair())
broker.logger.log_this(f"Your new take profit price price will be {new_average_price*instance.get_tp_level()} {quote}",2,instance.status.get_pair()) broker.logger.log_this(f"Your new take profit price price will be {new_average_price*instance.get_tp_level()} {quote}",2,instance.status.get_pair())
new_order = broker.new_market_order(instance.status.get_pair(),float(amount),"buy") new_order = broker.new_market_order(instance.status.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,instance.status.get_pair()) broker.logger.log_this("Error: Market order returned None",2,instance.status.get_pair())
instance.set_pause(False)
return jsonify({"Error": "Market order returned None"})
while True:
time.sleep(broker.get_wait_time())
returned_order = broker.get_order(new_order["id"],instance.status.get_pair())
if returned_order==broker.empty_order:
broker.logger.log_this("Problems sending the order",2,instance.status.get_pair())
instance.set_pause(False) instance.set_pause(False)
return jsonify({"Error": "Problems sending the order"}) return jsonify({"Error": "Market order returned None"})
elif returned_order["status"]=="expired": while True:
instance.set_pause(False)
return jsonify({"Error": "New order expired"})
elif returned_order["status"]=="closed":
broker.logger.log_this("Order sent",2,instance.status.get_pair())
new_fees_in_base, new_fees_in_quote = instance.parse_fees(returned_order)
instance.status.set_fees_paid_in_base(instance.status.get_fees_paid_in_base() + new_fees_in_base)
instance.status.set_fees_paid_in_quote(instance.status.get_fees_paid_in_quote() + new_fees_in_quote)
instance.status.set_base_bought(instance.status.get_base_bought() + returned_order["filled"] - new_fees_in_base)
instance.status.set_quote_spent(instance.status.get_quote_spent()+returned_order["cost"])
broker.logger.log_this("Cancelling old take profit order and sending a new one",2,instance.status.get_pair())
attempts = 5
while broker.cancel_order(instance.status.get_take_profit_order()["id"],instance.status.get_pair())==1:
broker.logger.log_this("Can't cancel old take profit order, retrying...",2,instance.status.get_pair())
time.sleep(broker.get_wait_time())
attempts-=1
if attempts==0:
broker.logger.log_this("Can't cancel old take profit order, cancelling...",2,instance.status.get_pair())
instance.set_pause(False)
return jsonify({"Error": "Can't cancel old take profit order."})
instance.status.set_take_profit_price(instance.status.get_quote_spent()/instance.status.get_base_bought()*instance.get_tp_level())
instance.status.set_take_profit_order(broker.new_limit_order(instance.status.get_pair(),instance.status.get_base_bought(),"sell",instance.status.get_take_profit_price()))
instance.update_status(True)
break
else:
broker.logger.log_this("Waiting for initial order to get filled",2,instance.status.get_pair())
broker.logger.log_this(f"{returned_order}",2,instance.status.get_pair())
time.sleep(broker.get_wait_time()) time.sleep(broker.get_wait_time())
instance.set_pause(False) returned_order = broker.get_order(new_order["id"],instance.status.get_pair())
broker.logger.log_this("Done",2,instance.status.get_pair()) if returned_order==broker.empty_order:
return jsonify({"Success": "Quote added successfully"}) broker.logger.log_this("Problems sending the order",2,instance.status.get_pair())
instance.set_pause(False)
return jsonify({"Error": "Problems sending the order"})
elif returned_order["status"]=="expired":
instance.set_pause(False)
return jsonify({"Error": "New order expired"})
elif returned_order["status"]=="closed":
broker.logger.log_this("Order sent",2,instance.status.get_pair())
new_fees_in_base, new_fees_in_quote = instance.parse_fees(returned_order)
instance.status.set_fees_paid_in_base(instance.status.get_fees_paid_in_base() + new_fees_in_base)
instance.status.set_fees_paid_in_quote(instance.status.get_fees_paid_in_quote() + new_fees_in_quote)
instance.status.set_base_bought(instance.status.get_base_bought() + returned_order["filled"] - new_fees_in_base)
instance.status.set_quote_spent(instance.status.get_quote_spent()+returned_order["cost"])
broker.logger.log_this("Cancelling old take profit order and sending a new one",2,instance.status.get_pair())
attempts = 5
while broker.cancel_order(instance.status.get_take_profit_order()["id"],instance.status.get_pair())==1:
broker.logger.log_this("Can't cancel old take profit order, retrying...",2,instance.status.get_pair())
time.sleep(broker.get_wait_time())
attempts-=1
if attempts==0:
broker.logger.log_this("Can't cancel old take profit order, cancelling...",2,instance.status.get_pair())
instance.set_pause(False)
return jsonify({"Error": "Can't cancel old take profit order."})
instance.status.set_take_profit_price(instance.status.get_quote_spent()/instance.status.get_base_bought()*instance.get_tp_level())
instance.status.set_take_profit_order(broker.new_limit_order(instance.status.get_pair(),instance.status.get_base_bought(),"sell",instance.status.get_take_profit_price()))
instance.update_status(True)
break
else:
broker.logger.log_this("Waiting for initial order to get filled",2,instance.status.get_pair())
broker.logger.log_this(f"{returned_order}",2,instance.status.get_pair())
time.sleep(broker.get_wait_time())
instance.set_pause(False)
broker.logger.log_this("Done",2,instance.status.get_pair())
return jsonify({"Success": "Quote added successfully"})
return jsonify({"Error": "Something horrible happened :S"}) return jsonify({"Error": "Something horrible happened :S"})
@ -2213,12 +2250,13 @@ def unwrapped_toggle_cleanup(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
for instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair(): for instance in running_traders:
instance.config.set_cleanup(not instance.config.get_cleanup()) if symbol==instance.status.get_pair():
if instance.config.get_cleanup(): instance.config.set_cleanup(not instance.config.get_cleanup())
return jsonify({"Success": "Cleanup turned ON"}) if instance.config.get_cleanup():
return jsonify({"Success": "Cleanup turned OFF"}) return jsonify({"Success": "Cleanup turned ON"})
return jsonify({"Success": "Cleanup turned OFF"})
except Exception as e: except Exception as e:
broker.logger.log_this(f"Exception while toggling cleanup: {e}",1,symbol) broker.logger.log_this(f"Exception while toggling cleanup: {e}",1,symbol)
return jsonify({"Error": "Halp"}) return jsonify({"Error": "Halp"})
@ -2239,13 +2277,14 @@ def unwrapped_force_trader_close(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
for instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair(): for instance in running_traders:
outcome = instance.force_close() if symbol==instance.status.get_pair():
if outcome==0: outcome = instance.force_close()
return jsonify({"Success": "Trader closed position successfully"}) if outcome==0:
return jsonify({"Error": "Error while forcing trader to close position"}) return jsonify({"Success": "Trader closed position successfully"})
return jsonify({"Error": "Trader not found"}) return jsonify({"Error": "Error while forcing trader to close position"})
return jsonify({"Error": "Trader not found"})
except Exception as e: except Exception as e:
broker.logger.log_this(f"Exception while forcing trader to close position: {e}",1,symbol) broker.logger.log_this(f"Exception while forcing trader to close position: {e}",1,symbol)
return jsonify({"Error": "Halp"}) return jsonify({"Error": "Halp"})
@ -2265,16 +2304,17 @@ def unwrapped_toggle_autoswitch(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
for instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair(): for instance in running_traders:
if instance.config.get_autoswitch(): if symbol==instance.status.get_pair():
broker.logger.log_this("Autoswitch turned OFF",1,symbol) if instance.config.get_autoswitch():
instance.config.set_autoswitch(False) broker.logger.log_this("Autoswitch turned OFF",1,symbol)
return jsonify({"Success": "Autoswitch is now OFF"}) instance.config.set_autoswitch(False)
else: return jsonify({"Success": "Autoswitch is now OFF"})
broker.logger.log_this("Autoswitch turned ON",1,symbol) else:
instance.config.set_autoswitch(True) broker.logger.log_this("Autoswitch turned ON",1,symbol)
return jsonify({"Success": "Autoswitch is now ON"}) instance.config.set_autoswitch(True)
return jsonify({"Success": "Autoswitch is now ON"})
return jsonify({"Error": "Trader not running"}) return jsonify({"Error": "Trader not running"})
except Exception as e: except Exception as e:
broker.logger.log_this(f"Exception while toggling autoswitch: {e}",1,symbol) broker.logger.log_this(f"Exception while toggling autoswitch: {e}",1,symbol)
@ -2295,16 +2335,17 @@ def unwrapped_toggle_liquidate_after_switch(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
for instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair(): for instance in running_traders:
if instance.config.get_liquidate_after_switch(): if symbol==instance.status.get_pair():
broker.logger.log_this("Liquidate after switch turned OFF",1,symbol) if instance.config.get_liquidate_after_switch():
instance.config.set_liquidate_after_switch(False) broker.logger.log_this("Liquidate after switch turned OFF",1,symbol)
return jsonify({"Success": "Liquidate after switch is now OFF"}) instance.config.set_liquidate_after_switch(False)
else: return jsonify({"Success": "Liquidate after switch is now OFF"})
broker.logger.log_this("Liquidate after switch turned ON",1,symbol) else:
instance.config.set_liquidate_after_switch(True) broker.logger.log_this("Liquidate after switch turned ON",1,symbol)
return jsonify({"Success": "Liquidate after switch is now ON"}) instance.config.set_liquidate_after_switch(True)
return jsonify({"Success": "Liquidate after switch is now ON"})
return jsonify({"Error": "Trader not running"}) return jsonify({"Error": "Trader not running"})
except Exception as e: except Exception as e:
broker.logger.log_this(f"Exception while toggling liquidate after switch: {e}",1,symbol) broker.logger.log_this(f"Exception while toggling liquidate after switch: {e}",1,symbol)
@ -2325,16 +2366,17 @@ def unwrapped_toggle_check_old_long_price(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
for instance in running_traders: with traders_lock:
if symbol==instance.status.get_pair(): for instance in running_traders:
if instance.config.get_check_old_long_price(): if symbol==instance.status.get_pair():
broker.logger.log_this("Check OFF",1,symbol) if instance.config.get_check_old_long_price():
instance.config.set_check_old_long_price(False) broker.logger.log_this("Check OFF",1,symbol)
return jsonify({"Success": "Old long price check turned OFF"}) instance.config.set_check_old_long_price(False)
else: return jsonify({"Success": "Old long price check turned OFF"})
broker.logger.log_this("Check ON",1,symbol) else:
instance.config.set_check_old_long_price(True) broker.logger.log_this("Check ON",1,symbol)
return jsonify({"Success": "Old long price check turned ON"}) instance.config.set_check_old_long_price(True)
return jsonify({"Success": "Old long price check turned ON"})
return jsonify({"Error": "Trader not running"}) return jsonify({"Error": "Trader not running"})
except Exception as e: except Exception as e:
broker.logger.log_this(f"Exception while toggling check_old_long_price: {e}",1,symbol) broker.logger.log_this(f"Exception while toggling check_old_long_price: {e}",1,symbol)
@ -2439,7 +2481,8 @@ def unwrapped_trader_time():
''' '''
try: try:
return jsonify({"Time": max(instance.last_time_seen for instance in running_traders)}) with traders_lock:
return jsonify({"Time": max(instance.last_time_seen for instance in running_traders)})
except Exception as e: except Exception as e:
broker.logger.log_this(f"Exception while retrieving trader_time: {e}",1) broker.logger.log_this(f"Exception while retrieving trader_time: {e}",1)
return jsonify({"Error": str(e)}) return jsonify({"Error": str(e)})
@ -2634,6 +2677,7 @@ if __name__=="__main__":
broker = exchange_wrapper.Broker(exchange,read_config,argv[1]) #Also passes the config filename broker = exchange_wrapper.Broker(exchange,read_config,argv[1]) #Also passes the config filename
#Declaring some variables #Declaring some variables
traders_lock = Lock()
running_traders = [] running_traders = []
instances_to_add = [] instances_to_add = []
online_pairs = [] online_pairs = []

View File

@ -560,8 +560,6 @@ class trader:
self.broker.logger.log_this("Can't cancel the take profit order. Can't switch mode",1,self.status.get_pair()) self.broker.logger.log_this("Can't cancel the take profit order. Can't switch mode",1,self.status.get_pair())
self.set_pause(False) self.set_pause(False)
return 1 return 1
if self.status.get_take_profit_order()["id"]!="":
self.broker.cancel_order(self.status.get_take_profit_order()["id"],self.status.get_pair())
#Save the old take profit order info for later use #Save the old take profit order info for later use
self.broker.logger.log_this("Saving state in status_dict",2,self.status.get_pair()) self.broker.logger.log_this("Saving state in status_dict",2,self.status.get_pair())
@ -1307,7 +1305,8 @@ class trader:
if len(self.config.get_tp_table())>=order_index: if len(self.config.get_tp_table())>=order_index:
tp_level = self.config.get_tp_table()[order_index] #Custom percentage table tp_level = self.config.get_tp_table()[order_index] #Custom percentage table
tp_level = self.config.get_tp_table()[-1] tp_level = self.config.get_tp_table()[-1]
tp_level = self.config.get_tp_level() else:
tp_level = self.config.get_tp_level()
elif self.config.get_tp_mode()==3: #Linear percentage table elif self.config.get_tp_mode()==3: #Linear percentage table
profit_table = self.linear_space(self.config.get_tp_level()+0.005,self.config.get_tp_level()-0.005,self.status.get_no_of_safety_orders()) profit_table = self.linear_space(self.config.get_tp_level()+0.005,self.config.get_tp_level()-0.005,self.status.get_no_of_safety_orders())
tp_level = profit_table[-1] tp_level = profit_table[-1]