parameter validation

This commit is contained in:
Nicolás Sánchez 2025-05-21 15:54:25 -03:00
parent eddbb005ad
commit 0ef0a512d8
3 changed files with 192 additions and 24 deletions

View File

@ -1,4 +1,5 @@
import json import json
import os
class ConfigHandler: class ConfigHandler:
''' '''
@ -125,105 +126,171 @@ class ConfigHandler:
def get_config_file_path(self): def get_config_file_path(self):
return self.config_file_path 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 self.config_file_path = new_file_path
return 0 return 0
def set_pair(self, pair: str): 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 self.config_dictionary["pair"] = pair
return 0 return 0
def set_is_short(self, is_short: bool): 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 self.config_dictionary["is_short"] = is_short
return 0 return 0
def set_order_size(self, order_size): def set_order_size(self, order_size):
#if not isinstance(order_size, (int, float)): if not isinstance(order_size, (int, float)):
# raise ValueError("order_size must be an integer or a 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 self.config_dictionary["order_size"] = order_size
return 0 return 0
def set_no_of_safety_orders(self, no_of_safety_orders: int): 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 self.config_dictionary["no_of_safety_orders"] = no_of_safety_orders
return 0 return 0
def set_max_short_safety_orders(self, max_short_safety_orders: int): 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 self.config_dictionary["max_short_safety_orders"] = max_short_safety_orders
return 0 return 0
def set_safety_order_deviance(self, safety_order_deviance: int): 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 self.config_dictionary["safety_order_deviance"] = safety_order_deviance
return 0 return 0
def set_safety_order_scale(self, safety_order_scale: float): 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 self.config_dictionary["safety_order_scale"] = safety_order_scale
return 0 return 0
def set_dynamic_so_deviance(self, dynamic_so_deviance: bool): 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 self.config_dictionary["dynamic_so_deviance"] = dynamic_so_deviance
return 0 return 0
def set_bias(self, bias: float): 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 self.config_dictionary["bias"] = bias
return 0 return 0
def set_dsd_range(self, dsd_range): def set_dsd_range(self, dsd_range):
#if not isinstance(dsd_range, (int, float)): if not isinstance(dsd_range, (int, float)):
# raise ValueError("dsd_range must be an integer or a 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 self.config_dictionary["dsd_range"] = dsd_range
return 0 return 0
def set_cleanup(self, cleanup: bool): 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 self.config_dictionary["cleanup"] = cleanup
return 0 return 0
def set_autoswitch(self, autoswitch: bool): 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 self.config_dictionary["autoswitch"] = autoswitch
return 0 return 0
def set_tp_mode(self, tp_mode: int): 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 self.config_dictionary["tp_mode"] = tp_mode
return 0 return 0
def set_tp_level(self, tp_level: float): 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 self.config_dictionary["tp_level"] = tp_level
return 0 return 0
def set_tp_table(self, tp_table: list): 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 self.config_dictionary["tp_table"] = tp_table
return 0 return 0
def set_check_slippage(self, check_slippage: bool): 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 self.config_dictionary["check_slippage"] = check_slippage
return 0 return 0
def set_programmed_stop(self, programmed_stop: bool): 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 self.config_dictionary["programmed_stop"] = programmed_stop
return 0 return 0
def set_programmed_stop_time(self, programmed_stop_time): def set_programmed_stop_time(self, programmed_stop_time):
#if not isinstance(programmed_stop_time, (int, float)): if not isinstance(programmed_stop_time, (int,float)):
# raise ValueError("programmed_stop_time be an integer or a 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 self.config_dictionary["programmed_stop_time"] = programmed_stop_time
return 0 return 0
def set_boosted_deals_range(self, boosted_deals_range: int): 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 self.config_dictionary["boosted_deals_range"] = boosted_deals_range
return 0 return 0
def set_boosted_time_range(self, boosted_time_range: int): 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 self.config_dictionary["boosted_time_range"] = boosted_time_range
return 0 return 0
def set_boosted_amount(self, boosted_amount: float): 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 self.config_dictionary["boosted_amount"] = boosted_amount
return 0 return 0
def set_force_restart_if_retries_exhausted(self, force_restart_if_retries_exhausted: bool): 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 self.config_dictionary["force_restart_if_retries_exhausted"] = force_restart_if_retries_exhausted
return 0 return 0
def set_check_old_long_price(self, check_old_long_price: bool): 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 self.config_dictionary["check_old_long_price"] = check_old_long_price
return 0 return 0
@ -231,6 +298,9 @@ class ConfigHandler:
def save_to_file(self, file_path = None): def save_to_file(self, file_path = None):
if file_path is 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: try:
with open(file_path, "w") as f: with open(file_path, "w") as f:
f.write(json.dumps(self.config_dictionary, indent=4)) f.write(json.dumps(self.config_dictionary, indent=4))
@ -241,7 +311,10 @@ class ConfigHandler:
def load_from_file(self, file_path = None): def load_from_file(self, file_path = None):
if file_path is 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: try:
with open(file_path, "r") as f: with open(file_path, "r") as f:
self.set_config({**self.default_config_dictionary, **json.load(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 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 self.config_dictionary = config_dictionary
return 0 return 0

View File

@ -49,6 +49,8 @@ class StatusHandler:
self.status_dictionary = {**self.status_dictionary, **status_dict} self.status_dictionary = {**self.status_dictionary, **status_dict}
self.save_to_file() self.save_to_file()
def get_pair(self):
return self.status_dictionary["pair"]
def get_take_profit_order(self): def get_take_profit_order(self):
return self.status_dictionary["take_profit_order"] return self.status_dictionary["take_profit_order"]
@ -143,23 +145,36 @@ class StatusHandler:
def get_status_file_path(self): def get_status_file_path(self):
return self.status_file_path 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 self.status_file_path = new_file_path
return 0 return 0
def set_tp_order_id(self, order_id: str): 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 self.status_dictionary["tp_order_id"] = order_id
return 0 return 0
def set_take_profit_order(self, order): def set_take_profit_order(self, order):
#Validate order
self.status_dictionary["take_profit_order"] = order self.status_dictionary["take_profit_order"] = order
return 0 return 0
def set_take_profit_price(self, price: float): 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 self.status_dictionary["take_profit_price"] = price
return 0 return 0
def set_so_order_id(self, order_id: str): 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 self.status_dictionary["so_order_id"] = order_id
return 0 return 0
@ -168,118 +183,191 @@ class StatusHandler:
return 0 return 0
def set_next_so_price(self, price: float): 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 self.status_dictionary["next_so_price"] = price
return 0 return 0
def set_order_size(self, size: float): 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 self.status_dictionary["order_size"] = size
return 0 return 0
def set_partial_profit(self, profit: float): 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 self.status_dictionary["partial_profit"] = profit
return 0 return 0
def set_price(self, price: float): 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 self.status_dictionary["price"] = price
return 0 return 0
def set_is_boosted(self, is_boosted: bool): 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 self.status_dictionary["is_boosted"] = is_boosted
return 0 return 0
def set_is_short(self, is_short: bool): 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 self.status_dictionary["is_short"] = is_short
return 0 return 0
def set_is_paused(self, is_paused: bool): 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 self.status_dictionary["is_paused"] = is_paused
return 0 return 0
def set_quote_spent(self, quote_spent: float): 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 self.status_dictionary["quote_spent"] = quote_spent
return 0 return 0
def set_base_bought(self, base_bought: float): 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 self.status_dictionary["base_bought"] = base_bought
return 0 return 0
def set_so_amount(self, so_amount: int): 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 self.status_dictionary["so_amount"] = so_amount
return 0 return 0
def set_no_of_safety_orders(self, number: int): 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 self.status_dictionary["no_of_safety_orders"] = number
return 0 return 0
def set_safety_price_table(self, table: list): 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 self.status_dictionary["safety_price_table"] = table
return 0 return 0
def set_deal_uptime(self, uptime): def set_deal_uptime(self, uptime):
#if not isinstance(uptime, (int, float)): if not isinstance(uptime, (int, float)):
# raise ValueError("uptime be an integer or a 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 self.status_dictionary["deal_uptime"] = uptime
return 0 return 0
def set_total_uptime(self, uptime): def set_total_uptime(self, uptime):
#if not isinstance(uptime, (int, float)): if not isinstance(uptime, (int, float)):
# raise ValueError("uptime be an integer or a 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 self.status_dictionary["total_uptime"] = uptime
return 0 return 0
def set_fees_paid_in_base(self, fees: float): 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 self.status_dictionary["fees_paid_in_base"] = fees
return 0 return 0
def set_fees_paid_in_quote(self, fees: float): 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 self.status_dictionary["fees_paid_in_quote"] = fees
return 0 return 0
def set_start_price(self, price: float): 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 self.status_dictionary["start_price"] = price
return 0 return 0
def set_tp_mode(self, mode: int): 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 self.status_dictionary["tp_mode"] = mode
return 0 return 0
def set_profit_table(self, table: list): 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 self.status_dictionary["profit_table"] = table
return 0 return 0
def set_start_time(self, time): def set_start_time(self, time):
#if not isinstance(uptime, (int, float)): if not isinstance(time, (int, float)):
# raise ValueError("uptime be an integer or a 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 self.status_dictionary["start_time"] = time
return 0 return 0
def set_deal_start_time(self, time): def set_deal_start_time(self, time):
#if not isinstance(uptime, (int, float)): if not isinstance(time, (int, float)):
# raise ValueError("uptime be an integer or a 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 self.status_dictionary["deal_start_time"] = time
return 0 return 0
def set_stop_when_profit(self, stop: bool): 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 self.status_dictionary["stop_when_profit"] = stop
return 0 return 0
def set_autoswitch(self, switch: bool): 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 self.status_dictionary["autoswitch"] = switch
return 0 return 0
def set_old_long(self, old_long: dict): 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 self.status_dictionary["old_long"] = old_long
return 0 return 0
def set_pause_reason(self, reason: str): 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 self.status_dictionary["pause_reason"] = reason
return 0 return 0
def set_status_string(self, string: str): 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 self.status_dictionary["status_string"] = string
return 0 return 0
def set_deal_order_history(self, deal_history: list): 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 self.status_dictionary["deal_order_history"] = deal_history
return 0 return 0
@ -288,6 +376,8 @@ class StatusHandler:
return 0 return 0
def update_deal_order_history(self, new_deal: dict): 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) self.status_dictionary["deal_order_history"].append(new_deal)
return 0 return 0
@ -327,6 +417,8 @@ class StatusHandler:
''' '''
Validates every key in the dictionary and then sets the status dictionary 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 self.status_dictionary = dictionary
return 0 return 0

View File

@ -8,8 +8,8 @@ Mandatory:
5. Multiple safety orders open at the same time (to catch big volatility spikes more effectively) 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): 6. Things that should be objects (it's not 1994):
* Orders. * Orders.
* Config (parameter validation remains to be implemented). * Config (Mostly done).
* Status (parameter validation remains to be implemented). * 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. 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. 8. API documentation.
9. Implement api key hashing. 9. Implement api key hashing.