extract detect_parameters to separate function
This commit is contained in:
parent
5bf021be2e
commit
8e2c7e1298
@ -4,7 +4,7 @@ This module defines a base class for auto-hyperoptable strategies.
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, Iterator, List, Tuple
|
from typing import Any, Dict, Iterator, List, Tuple, Type, Union
|
||||||
|
|
||||||
from freqtrade.exceptions import OperationalException
|
from freqtrade.exceptions import OperationalException
|
||||||
from freqtrade.misc import deep_merge_dicts, json_load
|
from freqtrade.misc import deep_merge_dicts, json_load
|
||||||
@ -53,27 +53,13 @@ class HyperStrategyMixin:
|
|||||||
for par in params:
|
for par in params:
|
||||||
yield par.name, par
|
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):
|
|
||||||
if not attr_name.startswith('__'): # Ignore internals, not strictly necessary.
|
|
||||||
attr = getattr(self, attr_name)
|
|
||||||
if issubclass(attr.__class__, BaseParameter):
|
|
||||||
if (attr_name.startswith(category + '_')
|
|
||||||
and attr.category is not None and attr.category != category):
|
|
||||||
raise OperationalException(
|
|
||||||
f'Inconclusive parameter name {attr_name}, category: {attr.category}.')
|
|
||||||
if (category == attr.category or
|
|
||||||
(attr_name.startswith(category + '_') and attr.category is None)):
|
|
||||||
yield attr_name, attr
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def detect_all_parameters(cls) -> Dict:
|
def detect_all_parameters(cls) -> Dict:
|
||||||
""" Detect all parameters and return them as a list"""
|
""" Detect all parameters and return them as a list"""
|
||||||
params: Dict[str, Any] = {
|
params: Dict[str, Any] = {
|
||||||
'buy': list(cls.detect_parameters('buy')),
|
'buy': list(detect_parameters(cls, 'buy')),
|
||||||
'sell': list(cls.detect_parameters('sell')),
|
'sell': list(detect_parameters(cls, 'sell')),
|
||||||
'protection': list(cls.detect_parameters('protection')),
|
'protection': list(detect_parameters(cls, 'protection')),
|
||||||
}
|
}
|
||||||
params.update({
|
params.update({
|
||||||
'count': len(params['buy'] + params['sell'] + params['protection'])
|
'count': len(params['buy'] + params['sell'] + params['protection'])
|
||||||
@ -155,7 +141,7 @@ class HyperStrategyMixin:
|
|||||||
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")
|
param_container: List[BaseParameter] = getattr(self, f"ft_{space}_params")
|
||||||
|
|
||||||
for attr_name, attr in self.detect_parameters(space):
|
for attr_name, attr in detect_parameters(self, space):
|
||||||
attr.name = attr_name
|
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:
|
if not attr.category:
|
||||||
@ -186,3 +172,25 @@ class HyperStrategyMixin:
|
|||||||
if not p.optimize or not p.in_space:
|
if not p.optimize or not p.in_space:
|
||||||
params[p.category][name] = p.value
|
params[p.category][name] = p.value
|
||||||
return params
|
return params
|
||||||
|
|
||||||
|
|
||||||
|
def detect_parameters(
|
||||||
|
obj: Union[HyperStrategyMixin, Type[HyperStrategyMixin]],
|
||||||
|
category: str
|
||||||
|
) -> Iterator[Tuple[str, BaseParameter]]:
|
||||||
|
"""
|
||||||
|
Detect all parameters for 'category' for "obj"
|
||||||
|
:param obj: Strategy object or class
|
||||||
|
:param category: category - usually `'buy', 'sell', 'protection',...
|
||||||
|
"""
|
||||||
|
for attr_name in dir(obj):
|
||||||
|
if not attr_name.startswith('__'): # Ignore internals, not strictly necessary.
|
||||||
|
attr = getattr(obj, attr_name)
|
||||||
|
if issubclass(attr.__class__, BaseParameter):
|
||||||
|
if (attr_name.startswith(category + '_')
|
||||||
|
and attr.category is not None and attr.category != category):
|
||||||
|
raise OperationalException(
|
||||||
|
f'Inconclusive parameter name {attr_name}, category: {attr.category}.')
|
||||||
|
if (category == attr.category or
|
||||||
|
(attr_name.startswith(category + '_') and attr.category is None)):
|
||||||
|
yield attr_name, attr
|
||||||
|
@ -16,6 +16,7 @@ from freqtrade.exceptions import OperationalException, StrategyError
|
|||||||
from freqtrade.optimize.space import SKDecimal
|
from freqtrade.optimize.space import SKDecimal
|
||||||
from freqtrade.persistence import PairLocks, Trade
|
from freqtrade.persistence import PairLocks, Trade
|
||||||
from freqtrade.resolvers import StrategyResolver
|
from freqtrade.resolvers import StrategyResolver
|
||||||
|
from freqtrade.strategy.hyper import detect_parameters
|
||||||
from freqtrade.strategy.parameters import (BaseParameter, BooleanParameter, CategoricalParameter,
|
from freqtrade.strategy.parameters import (BaseParameter, BooleanParameter, CategoricalParameter,
|
||||||
DecimalParameter, IntParameter, RealParameter)
|
DecimalParameter, IntParameter, RealParameter)
|
||||||
from freqtrade.strategy.strategy_wrapper import strategy_safe_wrapper
|
from freqtrade.strategy.strategy_wrapper import strategy_safe_wrapper
|
||||||
@ -908,15 +909,18 @@ def test_auto_hyperopt_interface(default_conf):
|
|||||||
assert strategy.sell_minusdi.value == 0.5
|
assert strategy.sell_minusdi.value == 0.5
|
||||||
all_params = strategy.detect_all_parameters()
|
all_params = strategy.detect_all_parameters()
|
||||||
assert isinstance(all_params, dict)
|
assert isinstance(all_params, dict)
|
||||||
assert len(all_params['buy']) == 2
|
# Only one buy param at class level
|
||||||
|
assert len(all_params['buy']) == 1
|
||||||
|
# Running detect params at instance level reveals both parameters.
|
||||||
|
assert len(list(detect_parameters(strategy, 'buy'))) == 2
|
||||||
assert len(all_params['sell']) == 2
|
assert len(all_params['sell']) == 2
|
||||||
# Number of Hyperoptable parameters
|
# Number of Hyperoptable parameters
|
||||||
assert all_params['count'] == 6
|
assert all_params['count'] == 5
|
||||||
|
|
||||||
strategy.__class__.sell_rsi = IntParameter([0, 10], default=5, space='buy')
|
strategy.__class__.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.detect_parameters('sell')]
|
[x for x in detect_parameters(strategy, 'sell')]
|
||||||
|
|
||||||
|
|
||||||
def test_auto_hyperopt_interface_loadparams(default_conf, mocker, caplog):
|
def test_auto_hyperopt_interface_loadparams(default_conf, mocker, caplog):
|
||||||
|
Loading…
Reference in New Issue
Block a user