Reformat hyper to cache parameters

This commit is contained in:
Matthias 2021-05-02 10:45:21 +02:00
parent 46f0f66039
commit 9049d6b779
2 changed files with 40 additions and 5 deletions

View File

@ -5,7 +5,7 @@ This module defines a base class for auto-hyperoptable strategies.
import logging import logging
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from contextlib import suppress from contextlib import suppress
from typing import Any, Dict, Iterator, Optional, Sequence, Tuple, Union from typing import Any, Dict, Iterator, List, Optional, Sequence, Tuple, Union
from freqtrade.optimize.hyperopt_tools import HyperoptTools from freqtrade.optimize.hyperopt_tools import HyperoptTools
@ -29,6 +29,7 @@ class BaseParameter(ABC):
default: Any default: Any
value: Any value: Any
in_space: bool = False in_space: bool = False
name: str
def __init__(self, *, default: Any, space: Optional[str] = None, def __init__(self, *, default: Any, space: Optional[str] = None,
optimize: bool = True, load: bool = True, **kwargs): optimize: bool = True, load: bool = True, **kwargs):
@ -250,6 +251,9 @@ class HyperStrategyMixin(object):
Initialize hyperoptable strategy mixin. Initialize hyperoptable strategy mixin.
""" """
self.config = config self.config = config
self.ft_buy_params: List[BaseParameter] = []
self.ft_sell_params: List[BaseParameter] = []
self._load_hyper_params(config.get('runmode') == RunMode.HYPEROPT) self._load_hyper_params(config.get('runmode') == RunMode.HYPEROPT)
def enumerate_parameters(self, category: str = None) -> Iterator[Tuple[str, BaseParameter]]: def enumerate_parameters(self, category: str = None) -> Iterator[Tuple[str, BaseParameter]]:
@ -260,15 +264,26 @@ class HyperStrategyMixin(object):
""" """
if category not in ('buy', 'sell', None): if category not in ('buy', 'sell', None):
raise OperationalException('Category must be one of: "buy", "sell", None.') raise OperationalException('Category must be one of: "buy", "sell", None.')
if category is None:
params = self.ft_buy_params + self.ft_sell_params
else:
params = getattr(self, f"ft_{category}_params")
for par in params:
yield par.name, par
def _detect_parameters(self, category: str) -> Iterator[Tuple[str, BaseParameter]]:
""" Detect all parameters for 'category' """
for attr_name in dir(self): for attr_name in dir(self):
if not attr_name.startswith('__'): # Ignore internals, not strictly necessary. if not attr_name.startswith('__'): # Ignore internals, not strictly necessary.
attr = getattr(self, attr_name) attr = getattr(self, attr_name)
if issubclass(attr.__class__, BaseParameter): if issubclass(attr.__class__, BaseParameter):
if (category and attr_name.startswith(category + '_') if (attr_name.startswith(category + '_')
and attr.category is not None and attr.category != category): and attr.category is not None and attr.category != category):
raise OperationalException( raise OperationalException(
f'Inconclusive parameter name {attr_name}, category: {attr.category}.') f'Inconclusive parameter name {attr_name}, category: {attr.category}.')
if (category is None or category == attr.category or if (category == attr.category or
(attr_name.startswith(category + '_') and attr.category is None)): (attr_name.startswith(category + '_') and attr.category is None)):
yield attr_name, attr yield attr_name, attr
@ -286,9 +301,16 @@ class HyperStrategyMixin(object):
""" """
if not params: if not params:
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] = getattr(self, f"ft_{space}_params")
for attr_name, attr in self.enumerate_parameters(space): for attr_name, attr in self._detect_parameters(space):
attr.name = attr_name
attr.in_space = hyperopt and HyperoptTools.has_space(self.config, space) attr.in_space = hyperopt and HyperoptTools.has_space(self.config, space)
if not attr.category:
attr.category = space
param_container.append(attr)
if params and attr_name in params: if params and attr_name in params:
if attr.load: if attr.load:
attr.value = params[attr_name] attr.value = params[attr_name]
@ -298,3 +320,16 @@ class HyperStrategyMixin(object):
f'Default value "{attr.value}" used.') f'Default value "{attr.value}" used.')
else: else:
logger.info(f'Strategy Parameter(default): {attr_name} = {attr.value}') logger.info(f'Strategy Parameter(default): {attr_name} = {attr.value}')
def get_params_dict(self):
"""
Returns list of Parameters that are not part of the current optimize job
"""
params = {
'buy': {},
'sell': {}
}
for name, p in self.enumerate_parameters():
if not p.optimize or not p.in_space:
params[p.category][name] = p.value
return params

View File

@ -671,4 +671,4 @@ def test_auto_hyperopt_interface(default_conf):
strategy.sell_rsi = IntParameter([0, 10], default=5, space='buy') strategy.sell_rsi = IntParameter([0, 10], default=5, space='buy')
with pytest.raises(OperationalException, match=r"Inconclusive parameter.*"): with pytest.raises(OperationalException, match=r"Inconclusive parameter.*"):
[x for x in strategy.enumerate_parameters('sell')] [x for x in strategy._detect_parameters('sell')]