- 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:
parent
12999a2189
commit
ffe58e2c0d
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
64
main.py
|
|
@ -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 = []
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue