diff --git a/config_handler.py b/config_handler.py index 057c28a..09d8611 100644 --- a/config_handler.py +++ b/config_handler.py @@ -1,4 +1,5 @@ import json +import os class ConfigHandler: ''' @@ -125,105 +126,171 @@ class ConfigHandler: def get_config_file_path(self): return self.config_file_path - def set_config_file_path(self, new_file_path): + def set_config_file_path(self, new_file_path: str): + if not isinstance(new_file_path, str): + self.broker.logger.log_this(f"File path provided is not a string",1,self.get_pair()) + return 1 self.config_file_path = new_file_path return 0 def set_pair(self, pair: str): + if not isinstance(pair, str): + self.broker.logger.log_this(f"Pair provided is not a string",1,self.get_pair()) + return 1 self.config_dictionary["pair"] = pair return 0 def set_is_short(self, is_short: bool): + if not isinstance(is_short, bool): + self.broker.logger.log_this(f"Is short provided is not a boolean",1,self.get_pair()) + return 1 self.config_dictionary["is_short"] = is_short return 0 def set_order_size(self, order_size): - #if not isinstance(order_size, (int, float)): - # raise ValueError("order_size must be an integer or a float") + if not isinstance(order_size, (int, float)): + self.broker.logger.log_this(f"Order size provided is not a number",1,self.get_pair()) + return 1 self.config_dictionary["order_size"] = order_size return 0 def set_no_of_safety_orders(self, no_of_safety_orders: int): + if not isinstance(no_of_safety_orders, int): + self.broker.logger.log_this(f"No of safety orders provided is not an integer",1,self.get_pair()) + return 1 self.config_dictionary["no_of_safety_orders"] = no_of_safety_orders return 0 def set_max_short_safety_orders(self, max_short_safety_orders: int): + if not isinstance(max_short_safety_orders, int): + self.broker.logger.log_this(f"Max short safety orders provided is not an integer",1,self.get_pair()) + return 1 self.config_dictionary["max_short_safety_orders"] = max_short_safety_orders return 0 def set_safety_order_deviance(self, safety_order_deviance: int): + if not isinstance(safety_order_deviance, int): + self.broker.logger.log_this(f"Safety order deviance provided is not an integer",1,self.get_pair()) + return 1 self.config_dictionary["safety_order_deviance"] = safety_order_deviance return 0 def set_safety_order_scale(self, safety_order_scale: float): + if not isinstance(safety_order_scale, float): + self.broker.logger.log_this(f"Safety order scale provided is not a float",1,self.get_pair()) + return 1 self.config_dictionary["safety_order_scale"] = safety_order_scale return 0 def set_dynamic_so_deviance(self, dynamic_so_deviance: bool): + if not isinstance(dynamic_so_deviance, bool): + self.broker.logger.log_this(f"Dynamic safety order deviance provided is not a boolean",1,self.get_pair()) + return 1 self.config_dictionary["dynamic_so_deviance"] = dynamic_so_deviance return 0 def set_bias(self, bias: float): + if not isinstance(bias, float): + self.broker.logger.log_this(f"Bias provided is not a float",1,self.get_pair()) + return 1 self.config_dictionary["bias"] = bias return 0 def set_dsd_range(self, dsd_range): - #if not isinstance(dsd_range, (int, float)): - # raise ValueError("dsd_range must be an integer or a float") + if not isinstance(dsd_range, (int, float)): + self.broker.logger.log_this(f"dsd_range must be an int or a float",1,self.get_pair()) + return 1 self.config_dictionary["dsd_range"] = dsd_range return 0 def set_cleanup(self, cleanup: bool): + if not isinstance(cleanup, bool): + self.broker.logger.log_this(f"cleanup must be a boolean",1,self.get_pair()) + return 1 self.config_dictionary["cleanup"] = cleanup return 0 def set_autoswitch(self, autoswitch: bool): + if not isinstance(autoswitch, bool): + self.broker.logger.log_this(f"autoswitch must be a boolean",1,self.get_pair()) + return 1 self.config_dictionary["autoswitch"] = autoswitch return 0 def set_tp_mode(self, tp_mode: int): + if not isinstance(tp_mode, int): + self.broker.logger.log_this(f"tp_mode must be an integer",1,self.get_pair()) + return 1 self.config_dictionary["tp_mode"] = tp_mode return 0 def set_tp_level(self, tp_level: float): + if not isinstance(tp_level, float): + self.broker.logger.log_this(f"tp_level must be a float",1,self.get_pair()) + return 1 self.config_dictionary["tp_level"] = tp_level return 0 def set_tp_table(self, tp_table: list): + if not isinstance(tp_table, list): + self.broker.logger.log_this(f"tp_table must be a list",1,self.get_pair()) + return 1 self.config_dictionary["tp_table"] = tp_table return 0 def set_check_slippage(self, check_slippage: bool): + if not isinstance(check_slippage, bool): + self.broker.logger.log_this(f"check_slippage must be a boolean",1,self.get_pair()) + return 1 self.config_dictionary["check_slippage"] = check_slippage return 0 def set_programmed_stop(self, programmed_stop: bool): + if not isinstance(programmed_stop, bool): + self.broker.logger.log_this(f"programmed_stop must be a boolean",1,self.get_pair()) + return 1 self.config_dictionary["programmed_stop"] = programmed_stop return 0 - def set_programmed_stop_time(self, programmed_stop_time): - #if not isinstance(programmed_stop_time, (int, float)): - # raise ValueError("programmed_stop_time be an integer or a float") + def set_programmed_stop_time(self, programmed_stop_time): + if not isinstance(programmed_stop_time, (int,float)): + self.broker.logger.log_this(f"programmed_stop_time must be an int or a float",1,self.get_pair()) + return 1 self.config_dictionary["programmed_stop_time"] = programmed_stop_time return 0 def set_boosted_deals_range(self, boosted_deals_range: int): + if not isinstance(boosted_deals_range, int): + self.broker.logger.log_this(f"boosted_deals_range must be an int",1,self.get_pair()) + return 1 self.config_dictionary["boosted_deals_range"] = boosted_deals_range return 0 def set_boosted_time_range(self, boosted_time_range: int): + if not isinstance(boosted_time_range, int): + self.broker.logger.log_this(f"boosted_time_range must be an int",1,self.get_pair()) + return 1 self.config_dictionary["boosted_time_range"] = boosted_time_range return 0 def set_boosted_amount(self, boosted_amount: float): + if not isinstance(boosted_amount, float): + self.broker.logger.log_this(f"boosted_amount must be a float",1,self.get_pair()) + return 1 self.config_dictionary["boosted_amount"] = boosted_amount return 0 def set_force_restart_if_retries_exhausted(self, force_restart_if_retries_exhausted: bool): + if not isinstance(force_restart_if_retries_exhausted, bool): + self.broker.logger.log_this(f"force_restart_if_retries_exhausted must be a bool",1,self.get_pair()) + return 1 self.config_dictionary["force_restart_if_retries_exhausted"] = force_restart_if_retries_exhausted return 0 def set_check_old_long_price(self, check_old_long_price: bool): + if not isinstance(check_old_long_price, bool): + self.broker.logger.log_this(f"check_old_long_price must be a bool",1,self.get_pair()) + return 1 self.config_dictionary["check_old_long_price"] = check_old_long_price return 0 @@ -231,6 +298,9 @@ class ConfigHandler: def save_to_file(self, file_path = None): if file_path is None: file_path = self.config_file_path + if not isinstance(file_path, str): + self.broker.logger.log_this(f"file_path must be a string",1,self.get_pair()) + return 1 try: with open(file_path, "w") as f: f.write(json.dumps(self.config_dictionary, indent=4)) @@ -241,7 +311,10 @@ class ConfigHandler: def load_from_file(self, file_path = None): if file_path is None: - file_path = self.config_file_path + file_path = self.config_file_path + if not isinstance(file_path, str): + self.broker.logger.log_this(f"file_path must be a string",1,self.get_pair()) + return 1 try: with open(file_path, "r") as f: self.set_config({**self.default_config_dictionary, **json.load(f)}) @@ -257,5 +330,8 @@ class ConfigHandler: ''' Validates every key in the config dictionary and sets the config dictionary ''' + if not isinstance(config_dictionary, dict): + self.broker.logger.log_this(f"config_dictionary must be a dictionary",1,self.get_pair()) + return 1 self.config_dictionary = config_dictionary return 0 \ No newline at end of file diff --git a/status_handler.py b/status_handler.py index 843bebc..6364e1e 100644 --- a/status_handler.py +++ b/status_handler.py @@ -49,6 +49,8 @@ class StatusHandler: self.status_dictionary = {**self.status_dictionary, **status_dict} self.save_to_file() + def get_pair(self): + return self.status_dictionary["pair"] def get_take_profit_order(self): return self.status_dictionary["take_profit_order"] @@ -143,23 +145,36 @@ class StatusHandler: def get_status_file_path(self): return self.status_file_path - def set_status_file_path(self, new_file_path): + def set_status_file_path(self, new_file_path: str): + if not isinstance(new_file_path, str): + self.broker.logger.log_this(f"File path provided is not a string",1,self.get_pair()) + return 1 self.status_file_path = new_file_path return 0 def set_tp_order_id(self, order_id: str): + if not isinstance(order_id, str): + self.broker.logger.log_this(f"Order id provided is not a string",1,self.get_pair()) + return 1 self.status_dictionary["tp_order_id"] = order_id return 0 def set_take_profit_order(self, order): + #Validate order self.status_dictionary["take_profit_order"] = order return 0 def set_take_profit_price(self, price: float): + if not isinstance(price, float): + self.broker.logger.log_this(f"Price provided is not a float",1,self.get_pair()) + return 1 self.status_dictionary["take_profit_price"] = price return 0 def set_so_order_id(self, order_id: str): + if not isinstance(order_id, str): + self.broker.logger.log_this(f"Order id provided is not a string",1,self.get_pair()) + return 1 self.status_dictionary["so_order_id"] = order_id return 0 @@ -168,118 +183,191 @@ class StatusHandler: return 0 def set_next_so_price(self, price: float): + if not isinstance(price, float): + self.broker.logger.log_this(f"Price provided is not a float",1,self.get_pair()) + return 1 self.status_dictionary["next_so_price"] = price return 0 def set_order_size(self, size: float): + if not isinstance(size, float): + self.broker.logger.log_this(f"Size provided is not a float",1,self.get_pair()) + return 1 self.status_dictionary["order_size"] = size return 0 def set_partial_profit(self, profit: float): + if not isinstance(profit, float): + self.broker.logger.log_this(f"Profit provided is not a float",1,self.get_pair()) + return 1 self.status_dictionary["partial_profit"] = profit return 0 def set_price(self, price: float): + if not isinstance(price, float): + self.broker.logger.log_this(f"Price provided is not a float",1,self.get_pair()) + return 1 self.status_dictionary["price"] = price return 0 def set_is_boosted(self, is_boosted: bool): + if not isinstance(is_boosted, bool): + self.broker.logger.log_this(f"is_boosted provided is not a bool",1,self.get_pair()) + return 1 self.status_dictionary["is_boosted"] = is_boosted return 0 def set_is_short(self, is_short: bool): + if not isinstance(is_short, bool): + self.broker.logger.log_this(f"is_short provided is not a bool",1,self.get_pair()) + return 1 self.status_dictionary["is_short"] = is_short return 0 def set_is_paused(self, is_paused: bool): + if not isinstance(is_paused, bool): + self.broker.logger.log_this(f"is_paused provided is not a bool",1,self.get_pair()) + return 1 self.status_dictionary["is_paused"] = is_paused return 0 def set_quote_spent(self, quote_spent: float): + if not isinstance(quote_spent, float): + self.broker.logger.log_this(f"quote_spent provided is not a float",1,self.get_pair()) + return 1 self.status_dictionary["quote_spent"] = quote_spent return 0 def set_base_bought(self, base_bought: float): + if not isinstance(base_bought, float): + self.broker.logger.log_this(f"base_bought provided is not a float",1,self.get_pair()) + return 1 self.status_dictionary["base_bought"] = base_bought return 0 def set_so_amount(self, so_amount: int): + if not isinstance(so_amount, int): + self.broker.logger.log_this(f"so_amount provided is not an integer",1,self.get_pair()) + return 1 self.status_dictionary["so_amount"] = so_amount return 0 def set_no_of_safety_orders(self, number: int): + if not isinstance(number, int): + self.broker.logger.log_this(f"number provided is not an integer",1,self.get_pair()) + return 1 self.status_dictionary["no_of_safety_orders"] = number return 0 def set_safety_price_table(self, table: list): + if not isinstance(table, list): + self.broker.logger.log_this(f"table provided is not a list",1,self.get_pair()) + return 1 self.status_dictionary["safety_price_table"] = table return 0 def set_deal_uptime(self, uptime): - #if not isinstance(uptime, (int, float)): - # raise ValueError("uptime be an integer or a float") + if not isinstance(uptime, (int, float)): + self.broker.logger.log_this(f"uptime provided is not a number",1,self.get_pair()) + return 1 self.status_dictionary["deal_uptime"] = uptime return 0 - def set_total_uptime(self, uptime): - #if not isinstance(uptime, (int, float)): - # raise ValueError("uptime be an integer or a float") + def set_total_uptime(self, uptime): + if not isinstance(uptime, (int, float)): + self.broker.logger.log_this(f"uptime provided is not a number",1,self.get_pair()) + return 1 self.status_dictionary["total_uptime"] = uptime return 0 def set_fees_paid_in_base(self, fees: float): + if not isinstance(fees, float): + self.broker.logger.log_this(f"value provided is not a float",1,self.get_pair()) + return 1 self.status_dictionary["fees_paid_in_base"] = fees return 0 def set_fees_paid_in_quote(self, fees: float): + if not isinstance(fees, float): + self.broker.logger.log_this(f"value provided is not a float",1,self.get_pair()) + return 1 self.status_dictionary["fees_paid_in_quote"] = fees return 0 def set_start_price(self, price: float): + if not isinstance(price, float): + self.broker.logger.log_this(f"value provided is not a float",1,self.get_pair()) + return 1 self.status_dictionary["start_price"] = price return 0 def set_tp_mode(self, mode: int): + if not isinstance(mode, int): + self.broker.logger.log_this(f"value provided is not an integer",1,self.get_pair()) + return 1 self.status_dictionary["tp_mode"] = mode return 0 def set_profit_table(self, table: list): + if not isinstance(table, list): + self.broker.logger.log_this(f"value provided is not a list",1,self.get_pair()) + return 1 self.status_dictionary["profit_table"] = table return 0 - def set_start_time(self, time): - #if not isinstance(uptime, (int, float)): - # raise ValueError("uptime be an integer or a float") + def set_start_time(self, time): + if not isinstance(time, (int, float)): + self.broker.logger.log_this(f"value provided is not a number",1,self.get_pair()) + return 1 self.status_dictionary["start_time"] = time return 0 - def set_deal_start_time(self, time): - #if not isinstance(uptime, (int, float)): - # raise ValueError("uptime be an integer or a float") + def set_deal_start_time(self, time): + if not isinstance(time, (int, float)): + self.broker.logger.log_this(f"value provided is not a number",1,self.get_pair()) + return 1 self.status_dictionary["deal_start_time"] = time return 0 def set_stop_when_profit(self, stop: bool): + if not isinstance(stop, bool): + self.broker.logger.log_this(f"value provided is not a boolean",1,self.get_pair()) + return 1 self.status_dictionary["stop_when_profit"] = stop return 0 def set_autoswitch(self, switch: bool): + if not isinstance(switch, bool): + self.broker.logger.log_this(f"value provided is not a boolean",1,self.get_pair()) + return 1 self.status_dictionary["autoswitch"] = switch return 0 def set_old_long(self, old_long: dict): + if not isinstance(old_long, dict): + self.broker.logger.log_this(f"value provided is not a dictionary",1,self.get_pair()) + return 1 self.status_dictionary["old_long"] = old_long return 0 def set_pause_reason(self, reason: str): + if not isinstance(reason, str): + self.broker.logger.log_this(f"value provided is not a string",1,self.get_pair()) + return 1 self.status_dictionary["pause_reason"] = reason return 0 def set_status_string(self, string: str): + if not isinstance(string, str): + self.broker.logger.log_this(f"value provided is not a string",1,self.get_pair()) + return 1 self.status_dictionary["status_string"] = string return 0 def set_deal_order_history(self, deal_history: list): + if not isinstance(deal_history, list): + self.broker.logger.log_this(f"value provided is not a list",1,self.get_pair()) + return 1 self.status_dictionary["deal_order_history"] = deal_history return 0 @@ -288,6 +376,8 @@ class StatusHandler: return 0 def update_deal_order_history(self, new_deal: dict): + if not isinstance(new_deal, dict): + self.broker.logger.log_this(f"value provided is not a dict",1,self.get_pair()) self.status_dictionary["deal_order_history"].append(new_deal) return 0 @@ -327,6 +417,8 @@ class StatusHandler: ''' Validates every key in the dictionary and then sets the status dictionary ''' - + if not isinstance(dictionary, dict): + self.broker.logger.log_this(f"status_dictionary provided is not a dictionary",1,self.get_pair()) + return 1 self.status_dictionary = dictionary return 0 \ No newline at end of file diff --git a/todo.txt b/todo.txt index 20649a7..db0ced6 100755 --- a/todo.txt +++ b/todo.txt @@ -8,8 +8,8 @@ Mandatory: 5. Multiple safety orders open at the same time (to catch big volatility spikes more effectively) 6. Things that should be objects (it's not 1994): * Orders. - * Config (parameter validation remains to be implemented). - * Status (parameter validation remains to be implemented). + * Config (Mostly done). + * Status (Mostly done). 7. Implement the ability to add safety orders to a short trader depending on the amount of free funds available, not just any number of orders. 8. API documentation. 9. Implement api key hashing.