ConfigHandler almost ready (without parameter validation)
This commit is contained in:
parent
487115c15e
commit
72c8773263
|
|
@ -1,9 +1,12 @@
|
||||||
|
import json
|
||||||
|
|
||||||
class ConfigHandler:
|
class ConfigHandler:
|
||||||
'''
|
'''
|
||||||
Handles the configuration of the trader and the validation of the parameters
|
Handles the configuration of the trader and the validation of the parameters
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, pair, config_dict = None):
|
def __init__(self, pair, broker, config_dict = None):
|
||||||
|
self.broker = broker
|
||||||
self.default_config_dictionary = {
|
self.default_config_dictionary = {
|
||||||
"pair": pair,
|
"pair": pair,
|
||||||
"is_short": False,
|
"is_short": False,
|
||||||
|
|
@ -19,6 +22,7 @@ class ConfigHandler:
|
||||||
"autoswitch": False,
|
"autoswitch": False,
|
||||||
"attempt_restart": True,
|
"attempt_restart": True,
|
||||||
"tp_mode": 3,
|
"tp_mode": 3,
|
||||||
|
"tp_level": 1.02,
|
||||||
"tp_table": [],
|
"tp_table": [],
|
||||||
"check_slippage": True,
|
"check_slippage": True,
|
||||||
"programmed_stop": False,
|
"programmed_stop": False,
|
||||||
|
|
@ -34,13 +38,10 @@ class ConfigHandler:
|
||||||
self.config_dictionary = self.default_config_dictionary.copy()
|
self.config_dictionary = self.default_config_dictionary.copy()
|
||||||
else:
|
else:
|
||||||
self.config_dictionary = {**self.default_config_dictionary, **config_dict}
|
self.config_dictionary = {**self.default_config_dictionary, **config_dict}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_config(self):
|
|
||||||
return self.config_dictionary
|
|
||||||
|
|
||||||
def get_pair(self):
|
def get_pair(self):
|
||||||
return self.config_dictionary["pair"]
|
return self.config_dictionary["pair"]
|
||||||
|
|
||||||
|
|
@ -83,6 +84,9 @@ class ConfigHandler:
|
||||||
def get_tp_mode(self):
|
def get_tp_mode(self):
|
||||||
return self.config_dictionary["tp_mode"]
|
return self.config_dictionary["tp_mode"]
|
||||||
|
|
||||||
|
def get_tp_level(self):
|
||||||
|
return self.config_dictionary["tp_level"]
|
||||||
|
|
||||||
def get_tp_table(self):
|
def get_tp_table(self):
|
||||||
return self.config_dictionary["tp_table"]
|
return self.config_dictionary["tp_table"]
|
||||||
|
|
||||||
|
|
@ -166,6 +170,10 @@ class ConfigHandler:
|
||||||
self.config_dictionary["tp_mode"] = tp_mode
|
self.config_dictionary["tp_mode"] = tp_mode
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
def set_tp_level(self, tp_level: float):
|
||||||
|
self.config_dictionary["tp_level"] = tp_level
|
||||||
|
return 0
|
||||||
|
|
||||||
def set_tp_table(self, tp_table: list):
|
def set_tp_table(self, tp_table: list):
|
||||||
self.config_dictionary["tp_table"] = tp_table
|
self.config_dictionary["tp_table"] = tp_table
|
||||||
return 0
|
return 0
|
||||||
|
|
@ -202,4 +210,33 @@ class ConfigHandler:
|
||||||
|
|
||||||
def set_check_old_long_price(self, check_old_long_price: bool):
|
def set_check_old_long_price(self, check_old_long_price: bool):
|
||||||
self.config_dictionary["check_old_long_price"] = check_old_long_price
|
self.config_dictionary["check_old_long_price"] = check_old_long_price
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def save_to_file(self, file_path: str):
|
||||||
|
try:
|
||||||
|
with open(file_path, "w") as f:
|
||||||
|
json.dump(self.config_dictionary, f)
|
||||||
|
return 0
|
||||||
|
except Exception as e:
|
||||||
|
self.broker.logger.log_this(f"Error saving config to file: {file_path}: {e}",1,self.get_pair())
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def load_from_file(self, file_path: str):
|
||||||
|
try:
|
||||||
|
with open(file_path, "r") as f:
|
||||||
|
self.set_config(json.load(f))
|
||||||
|
return 0
|
||||||
|
except Exception as e:
|
||||||
|
self.broker.logger.log_this(f"Error loading config to file: {file_path}: {e}",1,self.get_pair())
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def get_config(self):
|
||||||
|
return self.config_dictionary
|
||||||
|
|
||||||
|
def set_config(self, config_dictionary: dict):
|
||||||
|
'''
|
||||||
|
Validates every key in the config dictionary and sets the config dictionary
|
||||||
|
'''
|
||||||
|
self.config_dictionary = config_dictionary
|
||||||
return 0
|
return 0
|
||||||
|
|
@ -25,6 +25,7 @@ class Broker:
|
||||||
self.logger = Logger(self.read_config)
|
self.logger = Logger(self.read_config)
|
||||||
self.write_order_history = True #This should be a toggle in config_file
|
self.write_order_history = True #This should be a toggle in config_file
|
||||||
|
|
||||||
|
#Initialize database
|
||||||
self.profits_database_filename = "profits/profits_database.db"
|
self.profits_database_filename = "profits/profits_database.db"
|
||||||
self.database_connection = sqlite3.connect(self.profits_database_filename)
|
self.database_connection = sqlite3.connect(self.profits_database_filename)
|
||||||
self.database_cursor = self.database_connection.cursor()
|
self.database_cursor = self.database_connection.cursor()
|
||||||
|
|
@ -41,6 +42,7 @@ class Broker:
|
||||||
self.database_connection.commit()
|
self.database_connection.commit()
|
||||||
self.database_connection.close()
|
self.database_connection.close()
|
||||||
|
|
||||||
|
#Load markets
|
||||||
self.exchange.load_markets()
|
self.exchange.load_markets()
|
||||||
|
|
||||||
#Populates deals cache
|
#Populates deals cache
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
|
import json
|
||||||
|
|
||||||
class StatusHandler:
|
class StatusHandler:
|
||||||
'''
|
'''
|
||||||
Handles the status of the trader and the validation of the parameters
|
Handles the status of the trader and the validation of the parameters
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, status_dict = None):
|
def __init__(self, broker, status_dict = None):
|
||||||
|
self.broker = broker
|
||||||
self.default_status_dictionary = {
|
self.default_status_dictionary = {
|
||||||
"tp_order_id": "",
|
"tp_order_id": "",
|
||||||
"take_profit_order": {},
|
"take_profit_order": {},
|
||||||
|
|
@ -274,10 +277,38 @@ class StatusHandler:
|
||||||
self.status_dictionary["deal_order_history"] = deal_history
|
self.status_dictionary["deal_order_history"] = deal_history
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def update_deal_order_history(self, new_deal: dict):
|
def update_deal_order_history(self, new_deal: dict):
|
||||||
self.status_dictionary["deal_order_history"].append(new_deal)
|
self.status_dictionary["deal_order_history"].append(new_deal)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def save_to_file(self, file_path: str):
|
||||||
|
try:
|
||||||
|
with open(file_path, "w") as f:
|
||||||
|
json.dump(self.status_dictionary, f)
|
||||||
|
return 0
|
||||||
|
except Exception as e:
|
||||||
|
self.broker.logger.log_this(f"Error saving status to file: {file_path}: {e}",1)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def load_from_file(self, file_path: str):
|
||||||
|
try:
|
||||||
|
with open(file_path, "r") as f:
|
||||||
|
self.set_status(json.load(f))
|
||||||
|
return 0
|
||||||
|
except Exception as e:
|
||||||
|
self.broker.logger.log_this(f"Error loading status from file: {file_path}: {e}",1)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
def get_status(self):
|
def get_status(self):
|
||||||
return self.status_dictionary
|
return self.status_dictionary
|
||||||
|
|
||||||
|
def set_status(self, dictionary: dict):
|
||||||
|
'''
|
||||||
|
Validates every key in the dictionary and then sets the status dictionary
|
||||||
|
'''
|
||||||
|
|
||||||
|
self.status_dictionary = dictionary
|
||||||
|
return 0
|
||||||
164
trader.py
164
trader.py
|
|
@ -2,6 +2,8 @@ import csv
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
|
from config_handler import ConfigHandler
|
||||||
|
from status_handler import StatusHandler
|
||||||
|
|
||||||
class trader:
|
class trader:
|
||||||
def __init__(self, broker, config_dict: dict, is_import: bool = False):
|
def __init__(self, broker, config_dict: dict, is_import: bool = False):
|
||||||
|
|
@ -12,20 +14,16 @@ class trader:
|
||||||
self.broker = broker
|
self.broker = broker
|
||||||
self.tp_order = self.broker.get_empty_order()
|
self.tp_order = self.broker.get_empty_order()
|
||||||
self.so = self.broker.get_empty_order()
|
self.so = self.broker.get_empty_order()
|
||||||
self.config_dict = config_dict
|
self.config = ConfigHandler(config_dict["pair"],broker,config_dict)
|
||||||
self.pair = self.config_dict["pair"]
|
self.pair = self.config.get_pair()
|
||||||
self.market = self.broker.fetch_market(self.pair)
|
self.market = self.broker.fetch_market(self.pair)
|
||||||
self.market_load_time = int(time.time())
|
self.market_load_time = int(time.time())
|
||||||
self.market_reload_period = 86400 #Market reload period in seconds
|
self.market_reload_period = 86400 #Market reload period in seconds
|
||||||
self.base,self.quote = self.pair.split("/")
|
self.base,self.quote = self.pair.split("/")
|
||||||
self.is_short = self.config_dict["is_short"]
|
self.is_short = self.config.get_is_short()
|
||||||
self.profit_table = self.config_dict["tp_table"]
|
self.profit_table = self.config.get_tp_table()
|
||||||
self.max_short_safety_orders = 45
|
self.max_short_safety_orders = self.config.get_max_short_safety_orders()
|
||||||
if "max_short_safety_orders" in config_dict:
|
self.check_slippage = self.config.get_check_slippage()
|
||||||
self.max_short_safety_orders = config_dict["max_short_safety_orders"]
|
|
||||||
self.check_slippage = True
|
|
||||||
if "check_slippage" in self.config_dict:
|
|
||||||
self.check_slippage = self.config_dict["check_slippage"]
|
|
||||||
self.is_boosted = False
|
self.is_boosted = False
|
||||||
self.start_time = int(time.time())
|
self.start_time = int(time.time())
|
||||||
self.total_amount_of_quote=0
|
self.total_amount_of_quote=0
|
||||||
|
|
@ -42,10 +40,8 @@ class trader:
|
||||||
"quote_spent": 0,
|
"quote_spent": 0,
|
||||||
"base_bought": 0,
|
"base_bought": 0,
|
||||||
"so_amount": 0,
|
"so_amount": 0,
|
||||||
#"max_so_amount": config_dict["no_of_safety_orders"],
|
|
||||||
"take_profit_price": 1,
|
"take_profit_price": 1,
|
||||||
"next_so_price": 1,
|
"next_so_price": 1,
|
||||||
#"acc_profit": 0,
|
|
||||||
"tp_order_id": "",
|
"tp_order_id": "",
|
||||||
"take_profit_order": {},
|
"take_profit_order": {},
|
||||||
"so_order_id": "",
|
"so_order_id": "",
|
||||||
|
|
@ -61,10 +57,12 @@ class trader:
|
||||||
"short_price_exceeds_old_long": False,
|
"short_price_exceeds_old_long": False,
|
||||||
"speol_notified": False
|
"speol_notified": False
|
||||||
}
|
}
|
||||||
if "stop_time" in self.config_dict and int(self.config_dict["stop_time"])<int(time.time()):
|
#What is this? Why?
|
||||||
|
if self.config.get_programmed_stop() and int(self.config.get_programmed_stop_time())<int(time.time()):
|
||||||
self.config_dict.pop("stop_time",None)
|
self.config_dict.pop("stop_time",None)
|
||||||
#Write config file changes
|
#Write config file changes
|
||||||
self.broker.rewrite_config_file()
|
self.broker.rewrite_config_file()
|
||||||
|
|
||||||
if self.is_short:
|
if self.is_short:
|
||||||
#Check if there is an old_long file. If so, load it.
|
#Check if there is an old_long file. If so, load it.
|
||||||
try:
|
try:
|
||||||
|
|
@ -75,15 +73,10 @@ class trader:
|
||||||
self.profit_filename = f"profits/{self.base}{self.quote}.profits"
|
self.profit_filename = f"profits/{self.base}{self.quote}.profits"
|
||||||
self.log_filename = f"logs/{self.base}{self.quote}.log"
|
self.log_filename = f"logs/{self.base}{self.quote}.log"
|
||||||
|
|
||||||
self.boosted_deals_range = 4
|
self.boosted_deals_range = self.config.get_boosted_deals_range()
|
||||||
self.boosted_time_range = 3600
|
self.boosted_time_range = self.config.get_boosted_time_range()
|
||||||
self.boosted_amount = .01
|
self.boosted_amount = self.config.get_boosted_amount()
|
||||||
if "boosted_deals_range" in self.config_dict:
|
|
||||||
self.boosted_deals_range = self.config_dict["boosted_deals_range"]
|
|
||||||
if "boosted_time_range" in self.config_dict:
|
|
||||||
self.boosted_time_range = self.config_dict["boosted_time_range"]
|
|
||||||
if "boosted_amount" in self.config_dict:
|
|
||||||
self.boosted_amount = self.config_dict["boosted_amount"]
|
|
||||||
self.deals_timestamps = self.broker.get_trades_timestamps(self.pair,self.boosted_time_range)
|
self.deals_timestamps = self.broker.get_trades_timestamps(self.pair,self.boosted_time_range)
|
||||||
|
|
||||||
self.stop_when_profit = False
|
self.stop_when_profit = False
|
||||||
|
|
@ -101,7 +94,7 @@ class trader:
|
||||||
elif start_result==1: #If initialization fails
|
elif start_result==1: #If initialization fails
|
||||||
self.quit = True
|
self.quit = True
|
||||||
elif start_result==2: #Retries exceeded
|
elif start_result==2: #Retries exceeded
|
||||||
if "force_restart_if_retries_exhausted" in self.config_dict and self.config_dict["force_restart_if_retries_exhausted"]:
|
if self.config.get_force_restart_if_retries_exhausted():
|
||||||
self.pause = False
|
self.pause = False
|
||||||
self.restart = True
|
self.restart = True
|
||||||
else:
|
else:
|
||||||
|
|
@ -194,8 +187,8 @@ class trader:
|
||||||
if order_size is None or no_of_safety_orders is None:
|
if order_size is None or no_of_safety_orders is None:
|
||||||
self.broker.logger.log_this("Can't calculate optimal size",1,self.pair)
|
self.broker.logger.log_this("Can't calculate optimal size",1,self.pair)
|
||||||
return 1
|
return 1
|
||||||
self.config_dict["order_size"] = order_size
|
self.config.set_order_size(order_size)
|
||||||
self.config_dict["no_of_safety_orders"] = no_of_safety_orders
|
self.config.set_no_of_safety_orders(no_of_safety_orders)
|
||||||
self.broker.logger.log_this(f"Order size: {self.broker.amount_to_precision(self.pair,order_size)}. Amount of safety orders: {no_of_safety_orders}",2,self.pair)
|
self.broker.logger.log_this(f"Order size: {self.broker.amount_to_precision(self.pair,order_size)}. Amount of safety orders: {no_of_safety_orders}",2,self.pair)
|
||||||
|
|
||||||
#Write the changes to the config file
|
#Write the changes to the config file
|
||||||
|
|
@ -207,12 +200,12 @@ class trader:
|
||||||
self.status_dict["pause_reason"] = "start_trader - checking order size"
|
self.status_dict["pause_reason"] = "start_trader - checking order size"
|
||||||
self.broker.logger.log_this("Checking for order size",2,self.pair)
|
self.broker.logger.log_this("Checking for order size",2,self.pair)
|
||||||
minimum_order_size_allowed = self.broker.get_min_quote_size(self.pair)
|
minimum_order_size_allowed = self.broker.get_min_quote_size(self.pair)
|
||||||
if minimum_order_size_allowed is not None and minimum_order_size_allowed>self.config_dict["order_size"]:
|
if minimum_order_size_allowed is not None and minimum_order_size_allowed>self.config.get_order_size():
|
||||||
self.broker.logger.log_this(f"Order size too small. Minimum order size is {minimum_order_size_allowed} {self.quote}",1,self.pair)
|
self.broker.logger.log_this(f"Order size too small. Minimum order size is {minimum_order_size_allowed} {self.quote}",1,self.pair)
|
||||||
if minimum_order_size_allowed<self.config_dict["order_size"]*2:
|
if minimum_order_size_allowed<self.config.get_order_size()*2:
|
||||||
#int(n)+1 is treated here as a simplified ceil function, since minimum_order_size_allowed will always be positive.
|
#int(n)+1 is treated here as a simplified ceil function, since minimum_order_size_allowed will always be positive.
|
||||||
self.broker.logger.log_this(f"Due to exchange limits, trader initial order size will be {float(int(minimum_order_size_allowed)+1)} {self.quote}",1,self.pair)
|
self.broker.logger.log_this(f"Due to exchange limits, trader initial order size will be {float(int(minimum_order_size_allowed)+1)} {self.quote}",1,self.pair)
|
||||||
self.config_dict["order_size"] = float(int(minimum_order_size_allowed)+1)
|
self.config.set_order_size(float(int(minimum_order_size_allowed)+1))
|
||||||
else:
|
else:
|
||||||
self.broker.logger.log_this("Limit difference is more than 2x the configured order size. Please adjust the order size in the trader config file and restart the trader.",1,self.pair)
|
self.broker.logger.log_this("Limit difference is more than 2x the configured order size. Please adjust the order size in the trader config file and restart the trader.",1,self.pair)
|
||||||
return 1
|
return 1
|
||||||
|
|
@ -221,19 +214,19 @@ class trader:
|
||||||
if self.check_slippage:
|
if self.check_slippage:
|
||||||
self.broker.logger.log_this("Checking slippage...",2,self.pair)
|
self.broker.logger.log_this("Checking slippage...",2,self.pair)
|
||||||
self.status_dict["pause_reason"] = "start_trader - checking slippage"
|
self.status_dict["pause_reason"] = "start_trader - checking slippage"
|
||||||
if self.check_orderbook_depth(self.broker.get_slippage_default_threshold(),self.config_dict["order_size"]):
|
if self.check_orderbook_depth(self.broker.get_slippage_default_threshold(),self.config.get_order_size()):
|
||||||
#Slippage threshold exceeded
|
#Slippage threshold exceeded
|
||||||
self.broker.logger.log_this("Slippage threshold exceeded",1,self.pair)
|
self.broker.logger.log_this("Slippage threshold exceeded",1,self.pair)
|
||||||
return 3
|
return 3
|
||||||
|
|
||||||
self.status_dict["pause_reason"] = "start_trader - after slippage"
|
self.status_dict["pause_reason"] = "start_trader - after slippage"
|
||||||
self.status_dict["order_size"] = self.config_dict["order_size"]
|
self.status_dict["order_size"] = self.config.get_order_size()
|
||||||
|
|
||||||
#Sending initial order
|
#Sending initial order
|
||||||
self.status_dict["pause_reason"] = "start_trader - sending first order"
|
self.status_dict["pause_reason"] = "start_trader - sending first order"
|
||||||
self.broker.logger.log_this("Sending first order...",2,self.pair)
|
self.broker.logger.log_this("Sending first order...",2,self.pair)
|
||||||
action = "sell" if self.is_short else "buy"
|
action = "sell" if self.is_short else "buy"
|
||||||
first_order = self.broker.new_market_order(self.pair,self.config_dict["order_size"],action)
|
first_order = self.broker.new_market_order(self.pair,self.config.get_order_size(),action)
|
||||||
#self.broker.logger.log_this(f"First order id: {first_order}",1,self.pair)
|
#self.broker.logger.log_this(f"First order id: {first_order}",1,self.pair)
|
||||||
if first_order in [None,self.broker.get_empty_order()]:
|
if first_order in [None,self.broker.get_empty_order()]:
|
||||||
self.broker.logger.log_this(f"Error sending the first order. Market order returned {first_order}",1,self.pair)
|
self.broker.logger.log_this(f"Error sending the first order. Market order returned {first_order}",1,self.pair)
|
||||||
|
|
@ -300,9 +293,8 @@ class trader:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# Generate the safety prices table
|
# Generate the safety prices table
|
||||||
#self.start_price = returned_order["average"]
|
|
||||||
self.start_price = self.broker.price_to_precision(self.pair,self.total_amount_of_quote/self.total_amount_of_base)
|
self.start_price = self.broker.price_to_precision(self.pair,self.total_amount_of_quote/self.total_amount_of_base)
|
||||||
self.safety_price_table = self.calculate_safety_prices(self.start_price,self.config_dict["no_of_safety_orders"],self.config_dict["safety_order_deviance"])
|
self.safety_price_table = self.calculate_safety_prices(self.start_price,self.config.get_no_of_safety_orders(),self.config.get_safety_order_deviance())
|
||||||
|
|
||||||
# Send the first safety order
|
# Send the first safety order
|
||||||
self.status_dict["pause_reason"] = "start_trader - sending safety order"
|
self.status_dict["pause_reason"] = "start_trader - sending safety order"
|
||||||
|
|
@ -316,7 +308,7 @@ class trader:
|
||||||
|
|
||||||
# Send cleanup order (if cleanup)
|
# Send cleanup order (if cleanup)
|
||||||
self.status_dict["pause_reason"] = "start_trader - doing cleanup (if needed)"
|
self.status_dict["pause_reason"] = "start_trader - doing cleanup (if needed)"
|
||||||
if self.config_dict["cleanup"] and not self.is_short: #Short traders do not need cleanup.
|
if self.config.get_cleanup() and not self.is_short: #Short traders do not need cleanup.
|
||||||
self.do_cleanup()
|
self.do_cleanup()
|
||||||
|
|
||||||
# Write variables to status_dict and reset deal_uptime
|
# Write variables to status_dict and reset deal_uptime
|
||||||
|
|
@ -337,7 +329,7 @@ class trader:
|
||||||
config_filename = f"configs/{self.base}{self.quote}.json"
|
config_filename = f"configs/{self.base}{self.quote}.json"
|
||||||
with open(config_filename,"r") as y:
|
with open(config_filename,"r") as y:
|
||||||
config_dict = json.load(y)
|
config_dict = json.load(y)
|
||||||
if self.config_dict["autoswitch"]: # In what context was this useful?
|
if self.config.get_autoswitch(): # In what context was this useful?
|
||||||
config_dict["autoswitch"] = True #
|
config_dict["autoswitch"] = True #
|
||||||
return config_dict
|
return config_dict
|
||||||
|
|
||||||
|
|
@ -373,7 +365,7 @@ class trader:
|
||||||
self.status_dict["quote_spent"]=self.total_amount_of_quote
|
self.status_dict["quote_spent"]=self.total_amount_of_quote
|
||||||
self.status_dict["base_bought"]=self.total_amount_of_base
|
self.status_dict["base_bought"]=self.total_amount_of_base
|
||||||
self.status_dict["so_amount"]=self.safety_order_index
|
self.status_dict["so_amount"]=self.safety_order_index
|
||||||
self.status_dict["no_of_safety_orders"]=self.config_dict["no_of_safety_orders"]
|
self.status_dict["no_of_safety_orders"]=self.config.get_no_of_safety_orders()
|
||||||
self.status_dict["take_profit_price"]=self.take_profit_price
|
self.status_dict["take_profit_price"]=self.take_profit_price
|
||||||
self.status_dict["safety_price_table"]=self.safety_price_table
|
self.status_dict["safety_price_table"]=self.safety_price_table
|
||||||
self.status_dict["deal_uptime"]=int(time.time()) - self.deal_start_time
|
self.status_dict["deal_uptime"]=int(time.time()) - self.deal_start_time
|
||||||
|
|
@ -381,14 +373,14 @@ class trader:
|
||||||
self.status_dict["fees_paid_in_base"]=self.fees_paid_in_base
|
self.status_dict["fees_paid_in_base"]=self.fees_paid_in_base
|
||||||
self.status_dict["fees_paid_in_quote"]=self.fees_paid_in_quote
|
self.status_dict["fees_paid_in_quote"]=self.fees_paid_in_quote
|
||||||
self.status_dict["start_price"]=self.start_price
|
self.status_dict["start_price"]=self.start_price
|
||||||
self.status_dict["tp_mode"]=self.config_dict["tp_mode"]
|
self.status_dict["tp_mode"]=self.config.get_tp_mode()
|
||||||
self.status_dict["profit_table"]=self.config_dict["tp_table"]
|
self.status_dict["profit_table"]=self.config.get_tp_table()
|
||||||
self.status_dict["start_time"]=self.start_time
|
self.status_dict["start_time"]=self.start_time
|
||||||
self.status_dict["deal_start_time"]=self.deal_start_time
|
self.status_dict["deal_start_time"]=self.deal_start_time
|
||||||
self.status_dict["stop_when_profit"]=self.stop_when_profit
|
self.status_dict["stop_when_profit"]=self.stop_when_profit
|
||||||
self.status_dict["autoswitch"]=False
|
self.status_dict["autoswitch"]=False
|
||||||
if "autoswitch" in self.config_dict:
|
if "autoswitch" in self.config_dict:
|
||||||
self.status_dict["autoswitch"]=self.config_dict["autoswitch"]
|
self.status_dict["autoswitch"]=self.config.get_autoswitch()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.broker.logger.log_this(f"Can't update status dictionary. Exception: {e}",1,self.pair)
|
self.broker.logger.log_this(f"Can't update status dictionary. Exception: {e}",1,self.pair)
|
||||||
|
|
||||||
|
|
@ -546,7 +538,7 @@ class trader:
|
||||||
optimal_order_size = 0
|
optimal_order_size = 0
|
||||||
minimum_amount_of_safety_orders = 1 #This variable could be a config knob
|
minimum_amount_of_safety_orders = 1 #This variable could be a config knob
|
||||||
while amount_of_so>minimum_amount_of_safety_orders:
|
while amount_of_so>minimum_amount_of_safety_orders:
|
||||||
optimal_order_size = self.return_optimal_order_size(free_base,min_base_size,amount_of_so,self.config_dict["safety_order_scale"]) #safety_order_scale: safety order growth factor
|
optimal_order_size = self.return_optimal_order_size(free_base,min_base_size,amount_of_so,self.config.get_safety_order_scale()) #safety_order_scale: safety order growth factor
|
||||||
if optimal_order_size!=0:
|
if optimal_order_size!=0:
|
||||||
self.broker.logger.log_this(f"Optimal order size is {optimal_order_size}",2,self.pair)
|
self.broker.logger.log_this(f"Optimal order size is {optimal_order_size}",2,self.pair)
|
||||||
break
|
break
|
||||||
|
|
@ -770,7 +762,7 @@ class trader:
|
||||||
self.safety_order_index = 0
|
self.safety_order_index = 0
|
||||||
|
|
||||||
#Disabling autoswitch
|
#Disabling autoswitch
|
||||||
#self.config_dict["autoswitch"] = False
|
#self.config.set_autoswitch(False)
|
||||||
|
|
||||||
#Done. Ready for start_trader
|
#Done. Ready for start_trader
|
||||||
return 0
|
return 0
|
||||||
|
|
@ -894,7 +886,7 @@ class trader:
|
||||||
|
|
||||||
self.status_dict["pause_reason"] = "take_profit_routine - check time limit"
|
self.status_dict["pause_reason"] = "take_profit_routine - check time limit"
|
||||||
#Checks if there is a time limit for the trader
|
#Checks if there is a time limit for the trader
|
||||||
if "stop_time" in self.config_dict and time.time()>int(self.config_dict["stop_time"]):
|
if self.config.get_programmed_stop() and time.time()>int(self.config.get_programmed_stop_time()):
|
||||||
self.stop_when_profit = True
|
self.stop_when_profit = True
|
||||||
|
|
||||||
self.status_dict["pause_reason"] = "take_profit_routine - if stop_when_profit"
|
self.status_dict["pause_reason"] = "take_profit_routine - if stop_when_profit"
|
||||||
|
|
@ -918,7 +910,7 @@ class trader:
|
||||||
self.pause = False
|
self.pause = False
|
||||||
self.restart = True
|
self.restart = True
|
||||||
return 1
|
return 1
|
||||||
elif self.check_orderbook_depth(self.broker.get_slippage_default_threshold(),self.config_dict["order_size"],filled_order["price"]):
|
elif self.check_orderbook_depth(self.broker.get_slippage_default_threshold(),self.config.get_order_size(),filled_order["price"]):
|
||||||
self.broker.logger.log_this(f"Orderbook depth not sufficient, waiting for cooldown and restarting trader",1,self.pair)
|
self.broker.logger.log_this(f"Orderbook depth not sufficient, waiting for cooldown and restarting trader",1,self.pair)
|
||||||
time.sleep(self.broker.get_wait_time()*self.broker.get_cooldown_multiplier())
|
time.sleep(self.broker.get_wait_time()*self.broker.get_cooldown_multiplier())
|
||||||
self.pause = False
|
self.pause = False
|
||||||
|
|
@ -1046,7 +1038,7 @@ class trader:
|
||||||
if not self.warnings["speol_notified"] and price_exceeds:
|
if not self.warnings["speol_notified"] and price_exceeds:
|
||||||
#Only notify one time AND if autoswitch is off
|
#Only notify one time AND if autoswitch is off
|
||||||
self.warnings["speol_notified"] = True
|
self.warnings["speol_notified"] = True
|
||||||
if not self.config_dict["autoswitch"]:
|
if not self.config.get_autoswitch():
|
||||||
message = f"{self.base}@{self.status_dict['price']} ({str(self.broker.exchange)}), exceeds old long price of {self.status_dict['old_long']['tp_price']}"
|
message = f"{self.base}@{self.status_dict['price']} ({str(self.broker.exchange)}), exceeds old long price of {self.status_dict['old_long']['tp_price']}"
|
||||||
self.broker.logger.log_this(message,0,self.pair)
|
self.broker.logger.log_this(message,0,self.pair)
|
||||||
return 0
|
return 0
|
||||||
|
|
@ -1120,7 +1112,7 @@ class trader:
|
||||||
if self.tp_order["id"]=="":
|
if self.tp_order["id"]=="":
|
||||||
self.broker.logger.log_this(f"Take profit order missing. Stopping bot. Order ID: {self.tp_order['id']}",1,self.pair)
|
self.broker.logger.log_this(f"Take profit order missing. Stopping bot. Order ID: {self.tp_order['id']}",1,self.pair)
|
||||||
self.broker.cancel_order(self.so["id"],self.pair)
|
self.broker.cancel_order(self.so["id"],self.pair)
|
||||||
if self.config_dict["attempt_restart"]:
|
if self.config.get_attempt_restart():
|
||||||
self.write_status_file(is_backup=True)
|
self.write_status_file(is_backup=True)
|
||||||
self.restart = True
|
self.restart = True
|
||||||
self.broker.logger.log_this("Raising restart flag: take profit order missing, trader will be restarted",0,self.pair)
|
self.broker.logger.log_this("Raising restart flag: take profit order missing, trader will be restarted",0,self.pair)
|
||||||
|
|
@ -1137,7 +1129,7 @@ class trader:
|
||||||
self.broker.logger.log_this(f"Take profit order closed but not filled, 0 filled. Stopping bot. Order ID: {self.tp_order['id']}",1,self.pair)
|
self.broker.logger.log_this(f"Take profit order closed but not filled, 0 filled. Stopping bot. Order ID: {self.tp_order['id']}",1,self.pair)
|
||||||
#Cancelling safety order and stopping bot
|
#Cancelling safety order and stopping bot
|
||||||
self.broker.cancel_order(self.so["id"],self.pair)
|
self.broker.cancel_order(self.so["id"],self.pair)
|
||||||
if self.config_dict["attempt_restart"]:
|
if self.config.get_attempt_restart():
|
||||||
self.write_status_file(is_backup=True)
|
self.write_status_file(is_backup=True)
|
||||||
self.restart = True
|
self.restart = True
|
||||||
self.broker.logger.log_this("Take profit order closed but not filled, trader will be restarted.",0,self.pair)
|
self.broker.logger.log_this("Take profit order closed but not filled, trader will be restarted.",0,self.pair)
|
||||||
|
|
@ -1146,7 +1138,7 @@ class trader:
|
||||||
return 1
|
return 1
|
||||||
elif tp_status["status"]=="canceled":
|
elif tp_status["status"]=="canceled":
|
||||||
#TODO: Here, if the safety order is still open, we could resend the tp order.
|
#TODO: Here, if the safety order is still open, we could resend the tp order.
|
||||||
if self.config_dict["attempt_restart"]:
|
if self.config.get_attempt_restart():
|
||||||
self.broker.logger.log_this("Take profit order canceled. Restarting the bot.",1,self.pair)
|
self.broker.logger.log_this("Take profit order canceled. Restarting the bot.",1,self.pair)
|
||||||
self.write_status_file(is_backup=True)
|
self.write_status_file(is_backup=True)
|
||||||
self.restart = True
|
self.restart = True
|
||||||
|
|
@ -1158,7 +1150,7 @@ class trader:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# Check if safety order is filled
|
# Check if safety order is filled
|
||||||
if self.so["id"] not in open_orders_ids and self.safety_order_index<=self.config_dict["no_of_safety_orders"]:
|
if self.so["id"] not in open_orders_ids and self.safety_order_index<=self.config.get_no_of_safety_orders():
|
||||||
#so_status = self.so
|
#so_status = self.so
|
||||||
#if self.so["id"]!="":
|
#if self.so["id"]!="":
|
||||||
so_status = self.broker.get_order(self.so["id"],self.pair)
|
so_status = self.broker.get_order(self.so["id"],self.pair)
|
||||||
|
|
@ -1170,42 +1162,42 @@ class trader:
|
||||||
if so_status["status"] in ["closed", "canceled", ""] and tp_order_status["status"]=="open":
|
if so_status["status"] in ["closed", "canceled", ""] and tp_order_status["status"]=="open":
|
||||||
#Switch to short if all safety orders are sent and autoswitch is enabled.
|
#Switch to short if all safety orders are sent and autoswitch is enabled.
|
||||||
#May get into trouble if the trader is short of funds
|
#May get into trouble if the trader is short of funds
|
||||||
if not self.is_short and self.safety_order_index==self.config_dict["no_of_safety_orders"] and self.config_dict["autoswitch"]:
|
if not self.is_short and self.safety_order_index==self.config.get_no_of_safety_orders() and self.config.get_autoswitch():
|
||||||
self.switch_to_short()
|
self.switch_to_short()
|
||||||
self.write_status_file(is_backup=True)
|
self.write_status_file(is_backup=True)
|
||||||
self.restart = True
|
self.restart = True
|
||||||
return 0
|
return 0
|
||||||
a = self.new_so_routine(so_status,self.safety_order_index<self.config_dict["no_of_safety_orders"])
|
a = self.new_so_routine(so_status,self.safety_order_index<self.config.get_no_of_safety_orders())
|
||||||
#0 OK, 1 not enough funds, 2 can't cancel old TP, 3 can't send new TP
|
#0 OK, 1 not enough funds, 2 can't cancel old TP, 3 can't send new TP
|
||||||
if a==1:
|
if a==1:
|
||||||
self.broker.logger.log_this(f"Can't send new safety order. Not enough funds? new_so_routine returned {a}",1,self.pair)
|
self.broker.logger.log_this(f"Can't send new safety order. Not enough funds? new_so_routine returned {a}",1,self.pair)
|
||||||
#If there are not enough funds do not even try to send more safety orders
|
#If there are not enough funds do not even try to send more safety orders
|
||||||
#This way of doing it seems more practical than setting up yet another flag
|
#This way of doing it seems more practical than setting up yet another flag
|
||||||
self.config_dict["no_of_safety_orders"] = self.safety_order_index
|
self.config.set_no_of_safety_orders(self.safety_order_index)
|
||||||
return 1
|
return 1
|
||||||
elif a==2:
|
elif a==2:
|
||||||
self.broker.logger.log_this(f"Can't cancel old take profit order. new_so_routine returned {a}",1,self.pair)
|
self.broker.logger.log_this(f"Can't cancel old take profit order. new_so_routine returned {a}",1,self.pair)
|
||||||
self.pause = False
|
self.pause = False
|
||||||
self.status_dict["pause_reason"] = ""
|
self.status_dict["pause_reason"] = ""
|
||||||
if self.config_dict["attempt_restart"]:
|
if self.config.get_attempt_restart():
|
||||||
self.write_status_file(is_backup=True)
|
self.write_status_file(is_backup=True)
|
||||||
self.restart = True
|
self.restart = True
|
||||||
return 1
|
return 1
|
||||||
elif a==3:
|
elif a==3:
|
||||||
#self.pause = False
|
#self.pause = False
|
||||||
self.broker.logger.log_this(f"Error in trader: Can't send new take profit order. Restart will be attempted. new_so_routine returned {a}",0,self.pair)
|
self.broker.logger.log_this(f"Error in trader: Can't send new take profit order. Restart will be attempted. new_so_routine returned {a}",0,self.pair)
|
||||||
if self.config_dict["attempt_restart"]:
|
if self.config.get_attempt_restart():
|
||||||
self.write_status_file(is_backup=True)
|
self.write_status_file(is_backup=True)
|
||||||
self.restart = True
|
self.restart = True
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
#Check if short price exceeds old long price. If so, send a Telegram message
|
#Check if short price exceeds old long price. If so, send a Telegram message
|
||||||
if self.is_short and "old_long" in self.status_dict and self.config_dict["check_old_long_price"]:
|
if self.is_short and "old_long" in self.status_dict and self.config.get_check_old_long_price():
|
||||||
self.check_old_long_price()
|
self.check_old_long_price()
|
||||||
|
|
||||||
self.status_dict["pause_reason"] = "check for autoswitch"
|
self.status_dict["pause_reason"] = "check for autoswitch"
|
||||||
#If it's a short bot that used to be long AND autoswitch is enabled
|
#If it's a short bot that used to be long AND autoswitch is enabled
|
||||||
if self.is_short and "autoswitch" in self.config_dict and self.config_dict["autoswitch"] and "old_long" in self.status_dict:
|
if self.is_short and "autoswitch" in self.config_dict and self.config.get_autoswitch() and "old_long" in self.status_dict:
|
||||||
#If selling the base currency left at the current market price plus the quote already received turns out to be more than the old long deal target,
|
#If selling the base currency left at the current market price plus the quote already received turns out to be more than the old long deal target,
|
||||||
# it means that we already are in profit territory, switch back to long.
|
# it means that we already are in profit territory, switch back to long.
|
||||||
#A more conservative approach would be old_target = self.status_dict["old_long"]["quote_spent"], just breaking even.
|
#A more conservative approach would be old_target = self.status_dict["old_long"]["quote_spent"], just breaking even.
|
||||||
|
|
@ -1241,7 +1233,7 @@ class trader:
|
||||||
|
|
||||||
def get_tp_level(self, order_index: int = 0) -> float:
|
def get_tp_level(self, order_index: int = 0) -> float:
|
||||||
'''
|
'''
|
||||||
Returns the correct take profit percentage, according to the strategy (config_dict["tp_mode"]):
|
Returns the correct take profit percentage, according to the strategy (config.get_tp_mode()):
|
||||||
0. Fixed percentage
|
0. Fixed percentage
|
||||||
1. Variable percentage (+0.5% to -0.5% of the fixed percentage)
|
1. Variable percentage (+0.5% to -0.5% of the fixed percentage)
|
||||||
2. Custom percentage table
|
2. Custom percentage table
|
||||||
|
|
@ -1257,26 +1249,26 @@ class trader:
|
||||||
self.is_boosted = True
|
self.is_boosted = True
|
||||||
boost_percentage = self.boosted_amount
|
boost_percentage = self.boosted_amount
|
||||||
|
|
||||||
if self.is_short or self.config_dict["tp_mode"]==0: #Fixed take profit percentage
|
if self.is_short or self.config.get_tp_mode()==0: #Fixed take profit percentage
|
||||||
tp_level = self.config_dict["tp_level"]
|
tp_level = self.config.get_tp_level()
|
||||||
elif self.config_dict["tp_mode"]==1: #Variable percentage
|
elif self.config.get_tp_mode()==1: #Variable percentage
|
||||||
limit = self.config_dict["no_of_safety_orders"]/3
|
limit = self.config.get_no_of_safety_orders()/3
|
||||||
if order_index<=1:
|
if order_index<=1:
|
||||||
tp_level = self.config_dict["tp_level"]+0.005
|
tp_level = self.config.get_tp_level()+0.005
|
||||||
elif order_index<=limit:
|
elif order_index<=limit:
|
||||||
tp_level = self.config_dict["tp_level"]
|
tp_level = self.config.get_tp_level()
|
||||||
elif limit<=order_index<=limit*2:
|
elif limit<=order_index<=limit*2:
|
||||||
tp_level = self.config_dict["tp_level"]-0.0025
|
tp_level = self.config.get_tp_level()-0.0025
|
||||||
else:
|
else:
|
||||||
tp_level = self.config_dict["tp_level"]-0.005
|
tp_level = self.config.get_tp_level()-0.005
|
||||||
elif self.config_dict["tp_mode"]==2:
|
elif self.config.get_tp_mode()==2:
|
||||||
if ["tp_table"] in self.config_dict:
|
if ["tp_table"] in self.config_dict:
|
||||||
if len(self.config_dict["tp_table"])>=order_index:
|
if len(self.config.get_tp_table())>=order_index:
|
||||||
tp_level = self.config_dict["tp_table"][order_index] #Custom percentage table
|
tp_level = self.config.get_tp_table()[order_index] #Custom percentage table
|
||||||
tp_level = self.config_dict["tp_table"][-1]
|
tp_level = self.config.get_tp_table()[-1]
|
||||||
tp_level = self.config_dict["tp_level"]
|
tp_level = self.config.get_tp_level()
|
||||||
elif self.config_dict["tp_mode"]==3: #Linear percentage table
|
elif self.config.get_tp_mode()==3: #Linear percentage table
|
||||||
profit_table = self.linear_space(self.config_dict["tp_level"]+0.005,self.config_dict["tp_level"]-0.005,self.config_dict["no_of_safety_orders"])
|
profit_table = self.linear_space(self.config.get_tp_level()+0.005,self.config.get_tp_level()-0.005,self.config.get_no_of_safety_orders())
|
||||||
tp_level = profit_table[-1]
|
tp_level = profit_table[-1]
|
||||||
if order_index<len(profit_table): #If more safety orders were added, instead of recalculating the whole table
|
if order_index<len(profit_table): #If more safety orders were added, instead of recalculating the whole table
|
||||||
tp_level = profit_table[order_index] #it just returns the last value. Otherwise, the percentage gets very small.
|
tp_level = profit_table[order_index] #it just returns the last value. Otherwise, the percentage gets very small.
|
||||||
|
|
@ -1366,7 +1358,7 @@ class trader:
|
||||||
'''
|
'''
|
||||||
Sends a new safety order to the exchange
|
Sends a new safety order to the exchange
|
||||||
'''
|
'''
|
||||||
so_size = self.gib_so_size(size,self.safety_order_index+1,self.config_dict["safety_order_scale"]) #safety_order_scale: safety order growth factor
|
so_size = self.gib_so_size(size,self.safety_order_index+1,self.config.get_safety_order_scale()) #safety_order_scale: safety order growth factor
|
||||||
if self.is_short:
|
if self.is_short:
|
||||||
new_order = self.broker.new_limit_order(self.pair,so_size,"sell",self.safety_price_table[self.safety_order_index+1])
|
new_order = self.broker.new_limit_order(self.pair,so_size,"sell",self.safety_price_table[self.safety_order_index+1])
|
||||||
else:
|
else:
|
||||||
|
|
@ -1428,16 +1420,16 @@ class trader:
|
||||||
Generates a table of safety order's prices
|
Generates a table of safety order's prices
|
||||||
'''
|
'''
|
||||||
safety_price_table = [start_price]
|
safety_price_table = [start_price]
|
||||||
if self.config_dict["dynamic_so_deviance"]:# and no_of_safety_orders>=30:
|
if self.config.get_dynamic_so_deviance():# and no_of_safety_orders>=30:
|
||||||
#if self.config_dict["dynamic_so_deviance"] and not self.is_short:
|
#if self.config.get_dynamic_so_deviance() and not self.is_short:
|
||||||
#bias should be a real number between -1 and 1 (1>n>-1, NOT 1=>n>=-1)
|
#bias should be a real number between -1 and 1 (1>n>-1, NOT 1=>n>=-1)
|
||||||
#If bias -> 1, more space between the first orders, if -> -1, more space between the last orders, if 0, no change..
|
#If bias -> 1, more space between the first orders, if -> -1, more space between the last orders, if 0, no change..
|
||||||
if "bias" in self.config_dict:
|
if "bias" in self.config_dict:
|
||||||
deviance_factor = safety_order_deviance*self.clip_value(self.config_dict["bias"],-.99,.99)
|
deviance_factor = safety_order_deviance*self.clip_value(self.config.get_bias(),-.99,.99)
|
||||||
so_deviance_table = self.linear_space(safety_order_deviance+deviance_factor,safety_order_deviance-deviance_factor,no_of_safety_orders)
|
so_deviance_table = self.linear_space(safety_order_deviance+deviance_factor,safety_order_deviance-deviance_factor,no_of_safety_orders)
|
||||||
else:
|
else:
|
||||||
#Old way of calculating deviance
|
#Old way of calculating deviance
|
||||||
so_deviance_table = self.linear_space(safety_order_deviance-self.config_dict["dsd_range"],safety_order_deviance+self.config_dict["dsd_range"],no_of_safety_orders)
|
so_deviance_table = self.linear_space(safety_order_deviance-self.config.get_dsd_range(),safety_order_deviance+self.config.get_dsd_range(),no_of_safety_orders)
|
||||||
so_deviance_table.extend([so_deviance_table[-1]]*2) #This extra entries are needed in the next for loop
|
so_deviance_table.extend([so_deviance_table[-1]]*2) #This extra entries are needed in the next for loop
|
||||||
else:
|
else:
|
||||||
so_deviance_table = [safety_order_deviance]*(no_of_safety_orders+2)
|
so_deviance_table = [safety_order_deviance]*(no_of_safety_orders+2)
|
||||||
|
|
@ -1540,10 +1532,10 @@ class trader:
|
||||||
#Change pair-related variables
|
#Change pair-related variables
|
||||||
old_quote = self.quote
|
old_quote = self.quote
|
||||||
self.quote = new_quote
|
self.quote = new_quote
|
||||||
self.config_dict["pair"] = f"{self.base}/{self.quote}"
|
self.config.set_pair(f"{self.base}/{self.quote}")
|
||||||
self.profit_filename = f"profits/{self.base}{self.quote}.profits"
|
self.profit_filename = f"profits/{self.base}{self.quote}.profits"
|
||||||
self.log_filename = f"logs/{self.base}{self.quote}.log"
|
self.log_filename = f"logs/{self.base}{self.quote}.log"
|
||||||
self.pair = self.config_dict["pair"]
|
self.pair = self.config.get_pair()
|
||||||
|
|
||||||
#If there is an old_long file, also copy it
|
#If there is an old_long file, also copy it
|
||||||
if self.is_short and "old_long" in self.status_dict:
|
if self.is_short and "old_long" in self.status_dict:
|
||||||
|
|
@ -1576,10 +1568,10 @@ class trader:
|
||||||
self.broker.remove_pair_from_config(f"{self.base}{new_quote}")
|
self.broker.remove_pair_from_config(f"{self.base}{new_quote}")
|
||||||
self.broker.add_pair_to_config(f"{self.base}{self.quote}")
|
self.broker.add_pair_to_config(f"{self.base}{self.quote}")
|
||||||
|
|
||||||
self.config_dict["pair"] = f"{self.base}/{self.quote}"
|
self.config.set_pair(f"{self.base}/{self.quote}")
|
||||||
self.profit_filename = f"profits/{self.base}{self.quote}.profits"
|
self.profit_filename = f"profits/{self.base}{self.quote}.profits"
|
||||||
self.log_filename = f"logs/{self.base}{self.quote}.log"
|
self.log_filename = f"logs/{self.base}{self.quote}.log"
|
||||||
self.pair = self.config_dict["pair"]
|
self.pair = self.config.get_pair()
|
||||||
|
|
||||||
#Writing config file
|
#Writing config file
|
||||||
if write_broker_file and self.broker.rewrite_config_file()==1:
|
if write_broker_file and self.broker.rewrite_config_file()==1:
|
||||||
|
|
@ -1626,7 +1618,7 @@ class trader:
|
||||||
mid_percentage = 10
|
mid_percentage = 10
|
||||||
high_percentage = 20
|
high_percentage = 20
|
||||||
|
|
||||||
safety_order_string = f"{self.status_dict['so_amount']-1}/{self.config_dict['no_of_safety_orders']}".rjust(5)
|
safety_order_string = f"{self.status_dict['so_amount']-1}/{self.config.get_no_of_safety_orders()}".rjust(5)
|
||||||
|
|
||||||
#Check if necessary
|
#Check if necessary
|
||||||
low_price = 0
|
low_price = 0
|
||||||
|
|
@ -1701,12 +1693,12 @@ class trader:
|
||||||
line1 = f"{p}{pair_color}{self.pair.center(13)}{white}| {safety_order_string} |{prices}| Uptime: {self.seconds_to_time(self.status_dict['deal_uptime'])}"
|
line1 = f"{p}{pair_color}{self.pair.center(13)}{white}| {safety_order_string} |{prices}| Uptime: {self.seconds_to_time(self.status_dict['deal_uptime'])}"
|
||||||
if self.is_boosted:
|
if self.is_boosted:
|
||||||
line1 = f"{line1} | BOOSTED"
|
line1 = f"{line1} | BOOSTED"
|
||||||
if self.config_dict["autoswitch"]:
|
if self.config.get_autoswitch():
|
||||||
line1 = f"{line1} | AUTO"
|
line1 = f"{line1} | AUTO"
|
||||||
if multiplier>1:
|
if multiplier>1:
|
||||||
#Only displays the multiplier if autoswitch is enabled.
|
#Only displays the multiplier if autoswitch is enabled.
|
||||||
line1 = f"{line1}x{multiplier}"
|
line1 = f"{line1}x{multiplier}"
|
||||||
if "stop_time" in self.config_dict and time.time()<=int(self.config_dict["stop_time"]):
|
if self.config.get_programmed_stop() and time.time()<=self.config.get_programmed_stop_time():
|
||||||
line1 = f"{line1} | PROGRAMMED LAST DEAL"
|
line1 = f"{line1} | PROGRAMMED LAST DEAL"
|
||||||
if self.stop_when_profit==True:
|
if self.stop_when_profit==True:
|
||||||
line1 = f"{line1} | LAST DEAL"
|
line1 = f"{line1} | LAST DEAL"
|
||||||
|
|
@ -1733,7 +1725,7 @@ class trader:
|
||||||
self.total_amount_of_quote = self.status_dict["quote_spent"]
|
self.total_amount_of_quote = self.status_dict["quote_spent"]
|
||||||
self.total_amount_of_base = self.status_dict["base_bought"]
|
self.total_amount_of_base = self.status_dict["base_bought"]
|
||||||
self.safety_order_index = self.status_dict["so_amount"]
|
self.safety_order_index = self.status_dict["so_amount"]
|
||||||
self.config_dict["no_of_safety_orders"] = self.status_dict["no_of_safety_orders"] #If this is not loaded from status_dict, it will ignore if safety orders were added at runtime
|
self.config.set_no_of_safety_orders(self.status_dict["no_of_safety_orders"]) #If this is not loaded from status_dict, it will ignore if safety orders were added at runtime
|
||||||
self.take_profit_price = self.status_dict["take_profit_price"]
|
self.take_profit_price = self.status_dict["take_profit_price"]
|
||||||
self.safety_price_table = self.status_dict["safety_price_table"]
|
self.safety_price_table = self.status_dict["safety_price_table"]
|
||||||
self.fees_paid_in_base = self.status_dict["fees_paid_in_base"]
|
self.fees_paid_in_base = self.status_dict["fees_paid_in_base"]
|
||||||
|
|
@ -1756,9 +1748,9 @@ class trader:
|
||||||
|
|
||||||
#Load safety order
|
#Load safety order
|
||||||
self.so = self.broker.get_order(self.status_dict["so_order_id"],self.pair)
|
self.so = self.broker.get_order(self.status_dict["so_order_id"],self.pair)
|
||||||
if self.so==self.broker.get_empty_order() and self.safety_order_index<self.config_dict["no_of_safety_orders"]:
|
if self.so==self.broker.get_empty_order() and self.safety_order_index<self.config.get_no_of_safety_orders():
|
||||||
#The second condition is important: it signals that the empty order returned was because of an error, not because the trader ran out of funds in the past.
|
#The second condition is important: it signals that the empty order returned was because of an error, not because the trader ran out of funds in the past.
|
||||||
#When the trader runs out of funds, safety_order_index=config_dict["no_of_safety_orders"]
|
#When the trader runs out of funds, safety_order_index=config.get_no_of_safety_orders()
|
||||||
self.broker.logger.log_this("Couldn't load safety order. Aborting.",2,self.pair)
|
self.broker.logger.log_this("Couldn't load safety order. Aborting.",2,self.pair)
|
||||||
self.quit = True
|
self.quit = True
|
||||||
return 1
|
return 1
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue