Optional support for defining hyperopt parameters in a strategy file and reusing common hyperopt/strategy parts.

This commit is contained in:
Rokas Kupstys
2021-03-23 10:02:32 +02:00
parent 8da7d5c009
commit 0a205f52b0
4 changed files with 183 additions and 2 deletions

View File

@@ -0,0 +1,83 @@
"""
HyperOptAuto class.
This module implements a convenience auto-hyperopt class, which can be used together with strategies that implement
IHyperStrategy interface.
"""
from typing import Any, Callable, Dict, List
from pandas import DataFrame
from skopt.space import Categorical, Dimension, Integer, Real # noqa
from freqtrade.optimize.hyperopt_interface import IHyperOpt
# noinspection PyUnresolvedReferences
class HyperOptAuto(IHyperOpt):
"""
This class delegates functionality to Strategy(IHyperStrategy) and Strategy.HyperOpt classes. Most of the time
Strategy.HyperOpt class would only implement indicator_space and sell_indicator_space methods, but other hyperopt
methods can be overridden as well.
"""
def buy_strategy_generator(self, params: Dict[str, Any]) -> Callable:
assert hasattr(self.strategy, 'enumerate_parameters'), 'Strategy must inherit from IHyperStrategy.'
def populate_buy_trend(dataframe: DataFrame, metadata: dict):
for attr_name, attr in self.strategy.enumerate_parameters('buy'):
attr.value = params[attr_name]
return self.strategy.populate_buy_trend(dataframe, metadata)
return populate_buy_trend
def sell_strategy_generator(self, params: Dict[str, Any]) -> Callable:
assert hasattr(self.strategy, 'enumerate_parameters'), 'Strategy must inherit from IHyperStrategy.'
def populate_buy_trend(dataframe: DataFrame, metadata: dict):
for attr_name, attr in self.strategy.enumerate_parameters('sell'):
attr.value = params[attr_name]
return self.strategy.populate_sell_trend(dataframe, metadata)
return populate_buy_trend
def _get_func(self, name) -> Callable:
"""
Return a function defined in Strategy.HyperOpt class, or one defined in super() class.
:param name: function name.
:return: a requested function.
"""
hyperopt_cls = getattr(self.strategy, 'HyperOpt')
default_func = getattr(super(), name)
if hyperopt_cls:
return getattr(hyperopt_cls, name, default_func)
else:
return default_func
def _generate_indicator_space(self, category):
assert hasattr(self.strategy, 'enumerate_parameters'), 'Strategy must inherit from IHyperStrategy.'
for attr_name, attr in self.strategy.enumerate_parameters(category):
yield attr.get_space(attr_name)
def _get_indicator_space(self, category, fallback_method_name):
indicator_space = list(self._generate_indicator_space(category))
if len(indicator_space) > 0:
return indicator_space
else:
return self._get_func(fallback_method_name)()
def indicator_space(self) -> List[Dimension]:
return self._get_indicator_space('buy', 'indicator_space')
def sell_indicator_space(self) -> List[Dimension]:
return self._get_indicator_space('sell', 'sell_indicator_space')
def generate_roi_table(self, params: Dict) -> Dict[int, float]:
return self._get_func('generate_roi_table')(params)
def roi_space(self) -> List[Dimension]:
return self._get_func('roi_space')()
def stoploss_space(self) -> List[Dimension]:
return self._get_func('stoploss_space')()
def generate_trailing_params(self, params: Dict) -> Dict:
return self._get_func('generate_trailing_params')(params)
def trailing_space(self) -> List[Dimension]:
return self._get_func('trailing_space')()