mirror of
https://github.com/freqtrade/freqtrade.git
synced 2025-12-18 22:01:15 +00:00
feat: improve hyperopt detection logic
This commit is contained in:
@@ -19,6 +19,11 @@ from freqtrade.strategy.parameters import BaseParameter
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
# Type aliases
|
||||||
|
SpaceParams = dict[str, BaseParameter]
|
||||||
|
AllSpaceParams = dict[str, SpaceParams]
|
||||||
|
|
||||||
|
|
||||||
class HyperStrategyMixin:
|
class HyperStrategyMixin:
|
||||||
"""
|
"""
|
||||||
A helper base class which allows HyperOptAuto class to reuse implementations of buy/sell
|
A helper base class which allows HyperOptAuto class to reuse implementations of buy/sell
|
||||||
@@ -91,18 +96,13 @@ class HyperStrategyMixin:
|
|||||||
* Parameters defined in parameters objects (buy_params, sell_params, ...)
|
* Parameters defined in parameters objects (buy_params, sell_params, ...)
|
||||||
* Parameter defaults
|
* Parameter defaults
|
||||||
"""
|
"""
|
||||||
spaces = ["buy", "sell", "protection"]
|
params = detect_all_parameters(self)
|
||||||
spaces += [
|
|
||||||
s
|
|
||||||
for s in self.config.get("spaces", [])
|
|
||||||
if s not in spaces and s not in HYPEROPT_BUILTIN_SPACES
|
|
||||||
]
|
|
||||||
|
|
||||||
for space in spaces:
|
for space in params.keys():
|
||||||
params = deep_merge_dicts(
|
params_values = deep_merge_dicts(
|
||||||
self._ft_params_from_file.get(space, {}), getattr(self, f"{space}_params", {})
|
self._ft_params_from_file.get(space, {}), getattr(self, f"{space}_params", {})
|
||||||
)
|
)
|
||||||
self._ft_load_params(params, space, hyperopt)
|
self._ft_load_params(params[space], params_values, space, hyperopt)
|
||||||
|
|
||||||
def load_params_from_file(self) -> dict:
|
def load_params_from_file(self) -> dict:
|
||||||
filename_str = getattr(self, "__file__", "")
|
filename_str = getattr(self, "__file__", "")
|
||||||
@@ -136,34 +136,35 @@ class HyperStrategyMixin:
|
|||||||
setattr(self, container_name, [])
|
setattr(self, container_name, [])
|
||||||
return getattr(self, container_name)
|
return getattr(self, container_name)
|
||||||
|
|
||||||
def _ft_load_params(self, params: dict, space: str, hyperopt: bool = False) -> None:
|
def _ft_load_params(
|
||||||
|
self, params: SpaceParams, param_values: dict, space: str, hyperopt: bool = False
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Set optimizable parameter values.
|
Set optimizable parameter values.
|
||||||
:param params: Dictionary with new parameter values.
|
:param params: Dictionary with new parameter values.
|
||||||
"""
|
"""
|
||||||
if not params:
|
if not param_values:
|
||||||
logger.info(f"No params for {space} found, using default values.")
|
logger.info(f"No params for {space} found, using default values.")
|
||||||
param_container: list[BaseParameter] = self._ft_get_param_container(space)
|
param_container: list[BaseParameter] = self._ft_get_param_container(space)
|
||||||
|
|
||||||
for attr_name, attr in detect_parameters(self, space):
|
for param_name, param in params.items():
|
||||||
attr.name = attr_name
|
param.in_space = hyperopt and HyperoptTools.has_space(self.config, space)
|
||||||
attr.in_space = hyperopt and HyperoptTools.has_space(self.config, space)
|
if not param.category:
|
||||||
if not attr.category:
|
param.category = space
|
||||||
attr.category = space
|
|
||||||
|
|
||||||
param_container.append(attr)
|
param_container.append(param)
|
||||||
|
|
||||||
if params and attr_name in params:
|
if param_values and param_name in param_values:
|
||||||
if attr.load:
|
if param.load:
|
||||||
attr.value = params[attr_name]
|
param.value = param_values[param_name]
|
||||||
logger.info(f"Strategy Parameter: {attr_name} = {attr.value}")
|
logger.info(f"Strategy Parameter: {param_name} = {param.value}")
|
||||||
else:
|
else:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f'Parameter "{attr_name}" exists, but is disabled. '
|
f'Parameter "{param_name}" exists, but is disabled. '
|
||||||
f'Default value "{attr.value}" used.'
|
f'Default value "{param.value}" used.'
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
logger.info(f"Strategy Parameter(default): {attr_name} = {attr.value}")
|
logger.info(f"Strategy Parameter(default): {param_name} = {param.value}")
|
||||||
|
|
||||||
def get_no_optimize_params(self) -> dict[str, dict]:
|
def get_no_optimize_params(self) -> dict[str, dict]:
|
||||||
"""
|
"""
|
||||||
@@ -210,13 +211,13 @@ def detect_parameters(
|
|||||||
|
|
||||||
def detect_all_parameters(
|
def detect_all_parameters(
|
||||||
obj: HyperStrategyMixin | type[HyperStrategyMixin],
|
obj: HyperStrategyMixin | type[HyperStrategyMixin],
|
||||||
) -> dict[str, list[BaseParameter]]:
|
) -> AllSpaceParams:
|
||||||
"""
|
"""
|
||||||
Detect all hyperoptable parameters for this object.
|
Detect all hyperoptable parameters for this object.
|
||||||
:param obj: Strategy object or class
|
:param obj: Strategy object or class
|
||||||
"""
|
"""
|
||||||
auto_categories = ["buy", "sell", "protection"]
|
auto_categories = ["buy", "sell", "protection"]
|
||||||
result: dict[str, list[BaseParameter]] = defaultdict(list)
|
result: AllSpaceParams = defaultdict(dict)
|
||||||
for attr_name in dir(obj):
|
for attr_name in dir(obj):
|
||||||
if attr_name.startswith("__"): # Ignore internals
|
if attr_name.startswith("__"): # Ignore internals
|
||||||
continue
|
continue
|
||||||
@@ -239,6 +240,6 @@ def detect_all_parameters(
|
|||||||
raise OperationalException(
|
raise OperationalException(
|
||||||
f"Inconclusive parameter name {attr_name}, space: {attr.category}."
|
f"Inconclusive parameter name {attr_name}, space: {attr.category}."
|
||||||
)
|
)
|
||||||
|
attr.name = attr_name
|
||||||
result[attr.category].append(attr)
|
result[attr.category][attr_name] = attr
|
||||||
return result
|
return result
|
||||||
|
|||||||
Reference in New Issue
Block a user