2021-03-23 08:02:32 +00:00
|
|
|
"""
|
|
|
|
HyperOptAuto class.
|
2021-03-24 08:32:34 +00:00
|
|
|
This module implements a convenience auto-hyperopt class, which can be used together with strategies
|
|
|
|
that implement IHyperStrategy interface.
|
2021-03-23 08:02:32 +00:00
|
|
|
"""
|
|
|
|
from typing import Any, Callable, Dict, List
|
|
|
|
from pandas import DataFrame
|
|
|
|
from skopt.space import Categorical, Dimension, Integer, Real # noqa
|
|
|
|
|
2021-03-24 09:17:17 +00:00
|
|
|
from freqtrade.exceptions import OperationalException
|
2021-03-23 08:02:32 +00:00
|
|
|
from freqtrade.optimize.hyperopt_interface import IHyperOpt
|
|
|
|
|
|
|
|
|
|
|
|
class HyperOptAuto(IHyperOpt):
|
|
|
|
"""
|
2021-03-24 08:32:34 +00:00
|
|
|
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.
|
2021-03-23 08:02:32 +00:00
|
|
|
"""
|
2021-03-24 08:32:34 +00:00
|
|
|
|
2021-03-23 08:02:32 +00:00
|
|
|
def buy_strategy_generator(self, params: Dict[str, Any]) -> Callable:
|
2021-03-24 08:32:34 +00:00
|
|
|
if not getattr(self.strategy, 'HYPER_STRATEGY', False):
|
|
|
|
raise OperationalException('Strategy must inherit from IHyperStrategy.')
|
2021-03-23 08:02:32 +00:00
|
|
|
|
|
|
|
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)
|
2021-03-24 08:32:34 +00:00
|
|
|
|
2021-03-23 08:02:32 +00:00
|
|
|
return populate_buy_trend
|
|
|
|
|
|
|
|
def sell_strategy_generator(self, params: Dict[str, Any]) -> Callable:
|
2021-03-24 08:32:34 +00:00
|
|
|
if not getattr(self.strategy, 'HYPER_STRATEGY', False):
|
|
|
|
raise OperationalException('Strategy must inherit from IHyperStrategy.')
|
2021-03-23 08:02:32 +00:00
|
|
|
|
|
|
|
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)
|
2021-03-24 08:32:34 +00:00
|
|
|
|
2021-03-23 08:02:32 +00:00
|
|
|
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):
|
2021-03-24 08:32:34 +00:00
|
|
|
if not getattr(self.strategy, 'HYPER_STRATEGY', False):
|
|
|
|
raise OperationalException('Strategy must inherit from IHyperStrategy.')
|
2021-03-23 08:02:32 +00:00
|
|
|
|
|
|
|
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')()
|