- 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
cancel_attempts -= 1
time.sleep(self.wait_time) time.sleep(self.wait_time)
tries-=1
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))

64
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,6 +119,7 @@ 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}"
with traders_lock:
for instance in running_traders: for instance in running_traders:
if f"{instance.base}{instance.quote}"==pair: if f"{instance.base}{instance.quote}"==pair:
broker.logger.log_this(f"Pair already running, duplicate traders are not allowed",1,pair) broker.logger.log_this(f"Pair already running, duplicate traders are not allowed",1,pair)
@ -143,6 +144,7 @@ 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}'}")
with traders_lock:
running_traders.append(trader.trader(broker,f'{base}/{quote}')) 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}')
@ -246,6 +248,7 @@ def restart_pair_no_json(base: str, quote: str) -> int:
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair(): if symbol==instance.status.get_pair():
instance.set_pause(True, "Restarting trader") instance.set_pause(True, "Restarting trader")
@ -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,11 +294,18 @@ 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
to_restart = []
to_remove = []
with traders_lock:
for instance in running_traders: for instance in running_traders:
if instance.restart and instance.config.get_attempt_restart(): if instance.restart and instance.config.get_attempt_restart():
to_restart.append(instance)
if instance.quit:
to_remove.append(instance)
for instance in to_restart:
broker.logger.log_this(f"Restarting trader",1,instance.status.get_pair()) broker.logger.log_this(f"Restarting trader",1,instance.status.get_pair())
restart_pair_no_json(instance.base,instance.quote) restart_pair_no_json(instance.base,instance.quote)
if instance.quit: for instance in to_remove:
#Here, check if a duster is needed #Here, check if a duster is needed
broker.logger.log_this(f"{broker.get_exchange_name()} | Quit flag raised, removing trader.",0,instance.status.get_pair()) broker.logger.log_this(f"{broker.get_exchange_name()} | Quit flag raised, removing trader.",0,instance.status.get_pair())
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"{broker.get_exchange_name()} | Quit flag raised, removing trader: {instance.status.get_pair()}",-1) #Forced message to TG
@ -309,6 +320,7 @@ def main_routine():
#Adds pending traders #Adds pending traders
if bool(instances_to_add): if bool(instances_to_add):
with traders_lock:
for instance in instances_to_add: for instance in instances_to_add:
running_traders.append(instance) running_traders.append(instance)
instances_to_add.clear() instances_to_add.clear()
@ -317,11 +329,12 @@ def main_routine():
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)
with traders_lock:
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)
@ -343,6 +356,8 @@ 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()
with traders_lock:
for instance in running_traders: for instance in running_traders:
if not instance.config.get_is_short(): if not instance.config.get_is_short():
curr += int(instance.status.get_so_amount()) # For the safety order occupancy percentage calculation curr += int(instance.status.get_so_amount()) # For the safety order occupancy percentage calculation
@ -374,6 +389,7 @@ 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"]):
with traders_lock:
global_status["online_workers"] = [instance.status.get_pair() for instance in running_traders] global_status["online_workers"] = [instance.status.get_pair() for instance in running_traders]
#Prints general info #Prints general info
@ -409,6 +425,7 @@ def main_routine():
#Toggle pauses #Toggle pauses
if toggle_pauses: if toggle_pauses:
with traders_lock:
for instance in running_traders: for instance in running_traders:
if instance.status.get_pair() in toggle_pauses: if instance.status.get_pair() in toggle_pauses:
instance.pause = not instance.pause instance.pause = not instance.pause
@ -1505,6 +1522,7 @@ 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}"
with traders_lock:
for instance in running_traders: for instance in running_traders:
if instance.status.get_pair() == symbol: if instance.status.get_pair() == symbol:
return jsonify(instance.status.get_status()) return jsonify(instance.status.get_status())
@ -1518,7 +1536,7 @@ 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}
@ -1538,6 +1556,7 @@ 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
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair(): if symbol==instance.status.get_pair():
broker.logger.log_this(f"Pair already running",1,symbol) broker.logger.log_this(f"Pair already running",1,symbol)
@ -1572,6 +1591,7 @@ def unwrapped_remove_pair(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair(): if symbol==instance.status.get_pair():
instance.quit = True instance.quit = True
@ -1639,6 +1659,7 @@ 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"})
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():
instance.set_pause(True, "Switching to long mode") instance.set_pause(True, "Switching to long mode")
@ -1667,6 +1688,7 @@ 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"})
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair() and instance.switch_to_short()==1: if symbol==instance.status.get_pair() and instance.switch_to_short()==1:
return jsonify({"Error": "Error in switch_to_short()"}) return jsonify({"Error": "Error in switch_to_short()"})
@ -1674,6 +1696,7 @@ def unwrapped_switch_to_short(base,quote):
#Restart instance #Restart instance
try: try:
broker.logger.log_this(f"Reinitializing trader",2,symbol) broker.logger.log_this(f"Reinitializing trader",2,symbol)
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair(): if symbol==instance.status.get_pair():
instance.status.set_take_profit_order(instance.broker.empty_order) instance.status.set_take_profit_order(instance.broker.empty_order)
@ -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,6 +1746,7 @@ 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.
with traders_lock:
for instance in running_traders: for instance in running_traders:
if instance.status.get_pair()==symbol: if instance.status.get_pair()==symbol:
instance.get_status_dict()["old_long"]=old_long instance.get_status_dict()["old_long"]=old_long
@ -1747,9 +1771,10 @@ 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)
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair(): if symbol==instance.status.get_pair():
if "old_long" in instance.get_status_dict(): if "old_long" in instance.get_status_dict():
@ -1776,6 +1801,7 @@ def unwrapped_switch_to_long_price(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair(): if symbol==instance.status.get_pair():
if "old_long" in instance.get_status_dict(): if "old_long" in instance.get_status_dict():
@ -1807,6 +1833,7 @@ def unwrapped_add_safety_orders(base,quote,amount):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair(): if symbol==instance.status.get_pair():
instance.set_pause(True, "Adding safety orders") instance.set_pause(True, "Adding safety orders")
@ -1837,6 +1864,7 @@ def unwrapped_base_add_so_calculation(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair(): if symbol==instance.status.get_pair():
free_base = instance.fetch_free_base() free_base = instance.fetch_free_base()
@ -1865,6 +1893,7 @@ def unwrapped_mod_tp_level(base,quote,amount):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair(): if symbol==instance.status.get_pair():
instance.config.set_tp_level(float(amount)) instance.config.set_tp_level(float(amount))
@ -1890,6 +1919,7 @@ def unwrapped_mod_order_size(base,quote,amount):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair(): if symbol==instance.status.get_pair():
instance.config.set_order_size(float(amount)) instance.config.set_order_size(float(amount))
@ -1916,6 +1946,7 @@ def unwrapped_mod_concurrent_safety_orders(base,quote,amount):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair(): if symbol==instance.status.get_pair():
instance.config.set_concurrent_safety_orders(int(amount)) instance.config.set_concurrent_safety_orders(int(amount))
@ -1942,6 +1973,7 @@ def unwrapped_mod_boosted_concurrent_safety_orders(base,quote,amount):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair(): if symbol==instance.status.get_pair():
instance.config.set_boosted_concurrent_safety_orders(int(amount)) instance.config.set_boosted_concurrent_safety_orders(int(amount))
@ -1983,7 +2015,7 @@ 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))
@ -2007,6 +2039,7 @@ def unwrapped_last_call(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair(): if symbol==instance.status.get_pair():
instance.status.set_stop_when_profit(not instance.status.get_stop_when_profit()) instance.status.set_stop_when_profit(not instance.status.get_stop_when_profit())
@ -2041,6 +2074,7 @@ 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"})
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():
instance.config.set_programmed_stop_time(limit) instance.config.set_programmed_stop_time(limit)
@ -2068,6 +2102,7 @@ def unwrapped_toggle_pause(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
toggle_pauses.append(symbol) toggle_pauses.append(symbol)
with traders_lock:
for instance in running_traders: for instance in running_traders:
if instance.status.get_pair()==symbol: if instance.status.get_pair()==symbol:
if instance.pause: if instance.pause:
@ -2088,6 +2123,7 @@ 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:
with traders_lock:
for instance in running_traders: for instance in running_traders:
instance.status.set_stop_when_profit(True) instance.status.set_stop_when_profit(True)
instance.config.set_autoswitch(False) instance.config.set_autoswitch(False)
@ -2105,6 +2141,7 @@ 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:
with traders_lock:
for instance in running_traders: for instance in running_traders:
instance.status.set_stop_when_profit(False) instance.status.set_stop_when_profit(False)
broker.logger.log_this("Modified flag",2,f"{instance.base}/{instance.quote}") broker.logger.log_this("Modified flag",2,f"{instance.base}/{instance.quote}")
@ -2126,7 +2163,7 @@ 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():
@ -2213,6 +2250,7 @@ def unwrapped_toggle_cleanup(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair(): if symbol==instance.status.get_pair():
instance.config.set_cleanup(not instance.config.get_cleanup()) instance.config.set_cleanup(not instance.config.get_cleanup())
@ -2239,6 +2277,7 @@ def unwrapped_force_trader_close(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair(): if symbol==instance.status.get_pair():
outcome = instance.force_close() outcome = instance.force_close()
@ -2265,6 +2304,7 @@ def unwrapped_toggle_autoswitch(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair(): if symbol==instance.status.get_pair():
if instance.config.get_autoswitch(): if instance.config.get_autoswitch():
@ -2295,6 +2335,7 @@ def unwrapped_toggle_liquidate_after_switch(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair(): if symbol==instance.status.get_pair():
if instance.config.get_liquidate_after_switch(): if instance.config.get_liquidate_after_switch():
@ -2325,6 +2366,7 @@ def unwrapped_toggle_check_old_long_price(base,quote):
try: try:
symbol = f"{base}/{quote}" symbol = f"{base}/{quote}"
with traders_lock:
for instance in running_traders: for instance in running_traders:
if symbol==instance.status.get_pair(): if symbol==instance.status.get_pair():
if instance.config.get_check_old_long_price(): if instance.config.get_check_old_long_price():
@ -2439,6 +2481,7 @@ def unwrapped_trader_time():
''' '''
try: try:
with traders_lock:
return jsonify({"Time": max(instance.last_time_seen for instance in running_traders)}) 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)
@ -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,6 +1305,7 @@ 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]
else:
tp_level = self.config.get_tp_level() 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())