mirror of
https://github.com/freqtrade/freqtrade.git
synced 2025-11-29 00:23:07 +00:00
change CategoricalParameter and IntParameter in parameters.py to use optuna.distributions CategoricalDistribution and IntDistribution instead of skopt
This commit is contained in:
@@ -39,6 +39,7 @@ with warnings.catch_warnings():
|
||||
from skopt.space import Categorical, Dimension, Integer, Real
|
||||
|
||||
from freqtrade.optimize.space.decimalspace import SKDecimal
|
||||
from freqtrade.strategy.parameters import ft_CategoricalDistribution, ft_IntDistribution
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -420,6 +421,11 @@ class HyperOptimizer:
|
||||
o_dimensions[original_dim.name] = optuna.distributions.CategoricalDistribution(
|
||||
list(original_dim.bounds)
|
||||
)
|
||||
# for preparing to remove old skopt spaces
|
||||
elif isinstance(
|
||||
original_dim, ft_CategoricalDistribution
|
||||
) or isinstance(original_dim, ft_IntDistribution):
|
||||
o_dimensions[original_dim.name] = original_dim
|
||||
else:
|
||||
raise Exception(f"Unknown search space {original_dim} / {type(original_dim)}")
|
||||
# logger.info(f"convert_dimensions_to_optuna_space: {s_dimensions} - {o_dimensions}")
|
||||
@@ -429,7 +435,9 @@ class HyperOptimizer:
|
||||
self,
|
||||
random_state: int,
|
||||
):
|
||||
o_sampler = self.custom_hyperopt.generate_estimator(dimensions=self.dimensions)
|
||||
o_sampler = self.custom_hyperopt.generate_estimator(
|
||||
dimensions=self.dimensions, random_state=random_state
|
||||
)
|
||||
self.o_dimensions = self.convert_dimensions_to_optuna_space(self.dimensions)
|
||||
|
||||
# for save/restore
|
||||
|
||||
@@ -14,7 +14,8 @@ from freqtrade.optimize.hyperopt_tools import HyperoptStateContainer
|
||||
|
||||
|
||||
with suppress(ImportError):
|
||||
from skopt.space import Categorical, Integer, Real
|
||||
from optuna.distributions import CategoricalDistribution, IntDistribution
|
||||
from skopt.space import Integer, Real # Categorical
|
||||
|
||||
from freqtrade.optimize.space import SKDecimal
|
||||
|
||||
@@ -24,6 +25,25 @@ from freqtrade.exceptions import OperationalException
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ft_CategoricalDistribution(CategoricalDistribution):
|
||||
name: str
|
||||
def __init__(
|
||||
self,
|
||||
categories: Sequence[Any],
|
||||
**kwargs,
|
||||
):
|
||||
return super().__init__(categories)
|
||||
|
||||
class ft_IntDistribution(IntDistribution):
|
||||
name: str
|
||||
def __init__(
|
||||
self,
|
||||
low: int,
|
||||
high: int,
|
||||
**kwargs,
|
||||
):
|
||||
return super().__init__(low, high, **kwargs)
|
||||
|
||||
class BaseParameter(ABC):
|
||||
"""
|
||||
Defines a parameter that can be optimized by hyperopt.
|
||||
@@ -51,7 +71,8 @@ class BaseParameter(ABC):
|
||||
name is prefixed with 'buy_' or 'sell_'.
|
||||
:param optimize: Include parameter in hyperopt optimizations.
|
||||
:param load: Load parameter value from {space}_params.
|
||||
:param kwargs: Extra parameters to skopt.space.(Integer|Real|Categorical).
|
||||
:param kwargs: Extra parameters to optuna.distributions.
|
||||
(IntDistribution|Real|CategoricalDistribution).
|
||||
"""
|
||||
if "name" in kwargs:
|
||||
raise OperationalException(
|
||||
@@ -67,7 +88,9 @@ class BaseParameter(ABC):
|
||||
return f"{self.__class__.__name__}({self.value})"
|
||||
|
||||
@abstractmethod
|
||||
def get_space(self, name: str) -> Union["Integer", "Real", "SKDecimal", "Categorical"]:
|
||||
def get_space(self, name: str) -> Union[
|
||||
"ft_IntDistribution", "Real", "SKDecimal", "ft_CategoricalDistribution"
|
||||
]:
|
||||
"""
|
||||
Get-space - will be used by Hyperopt to get the hyperopt Space
|
||||
"""
|
||||
@@ -151,7 +174,7 @@ class IntParameter(NumericParameter):
|
||||
parameter fieldname is prefixed with 'buy_' or 'sell_'.
|
||||
:param optimize: Include parameter in hyperopt optimizations.
|
||||
:param load: Load parameter value from {space}_params.
|
||||
:param kwargs: Extra parameters to skopt.space.Integer.
|
||||
:param kwargs: Extra parameters to optuna.distributions.IntDistribution.
|
||||
"""
|
||||
|
||||
super().__init__(
|
||||
@@ -160,10 +183,15 @@ class IntParameter(NumericParameter):
|
||||
|
||||
def get_space(self, name: str) -> "Integer":
|
||||
"""
|
||||
Create skopt optimization space.
|
||||
Create optuna distribution space.
|
||||
:param name: A name of parameter field.
|
||||
"""
|
||||
return Integer(low=self.low, high=self.high, name=name, **self._space_params)
|
||||
# return Integer(low=self.low, high=self.high, name=name, **self._space_params)
|
||||
result = ft_IntDistribution(
|
||||
self.low, self.high, **self._space_params
|
||||
)
|
||||
result.name = name
|
||||
return result
|
||||
|
||||
@property
|
||||
def range(self):
|
||||
@@ -174,7 +202,7 @@ class IntParameter(NumericParameter):
|
||||
calculating 100ds of indicators.
|
||||
"""
|
||||
if self.can_optimize():
|
||||
# Scikit-optimize ranges are "inclusive", while python's "range" is exclusive
|
||||
# optuna distributions ranges are "inclusive", while python's "range" is exclusive
|
||||
return range(self.low, self.high + 1)
|
||||
else:
|
||||
return range(self.value, self.value + 1)
|
||||
@@ -305,7 +333,7 @@ class CategoricalParameter(BaseParameter):
|
||||
name is prefixed with 'buy_' or 'sell_'.
|
||||
:param optimize: Include parameter in hyperopt optimizations.
|
||||
:param load: Load parameter value from {space}_params.
|
||||
:param kwargs: Extra parameters to skopt.space.Categorical.
|
||||
:param kwargs: Extra parameters to optuna.distributions.CategoricalDistribution.
|
||||
"""
|
||||
if len(categories) < 2:
|
||||
raise OperationalException(
|
||||
@@ -314,12 +342,15 @@ class CategoricalParameter(BaseParameter):
|
||||
self.opt_range = categories
|
||||
super().__init__(default=default, space=space, optimize=optimize, load=load, **kwargs)
|
||||
|
||||
def get_space(self, name: str) -> "Categorical":
|
||||
def get_space(self, name: str) -> "ft_CategoricalDistribution":
|
||||
"""
|
||||
Create skopt optimization space.
|
||||
Create optuna distribution space.
|
||||
:param name: A name of parameter field.
|
||||
"""
|
||||
return Categorical(self.opt_range, name=name, **self._space_params)
|
||||
# Categorical(self.opt_range, name=name, **self._space_params)
|
||||
result = ft_CategoricalDistribution(self.opt_range)
|
||||
result.name = name
|
||||
return result
|
||||
|
||||
@property
|
||||
def range(self):
|
||||
@@ -355,7 +386,7 @@ class BooleanParameter(CategoricalParameter):
|
||||
name is prefixed with 'buy_' or 'sell_'.
|
||||
:param optimize: Include parameter in hyperopt optimizations.
|
||||
:param load: Load parameter value from {space}_params.
|
||||
:param kwargs: Extra parameters to skopt.space.Categorical.
|
||||
:param kwargs: Extra parameters to optuna.distributions.CategoricalDistribution.
|
||||
"""
|
||||
|
||||
categories = [True, False]
|
||||
|
||||
@@ -895,7 +895,8 @@ def test_is_informative_pairs_callback(default_conf):
|
||||
|
||||
def test_hyperopt_parameters():
|
||||
HyperoptStateContainer.set_state(HyperoptState.INDICATORS)
|
||||
from skopt.space import Categorical, Integer, Real
|
||||
from optuna.distributions import CategoricalDistribution, IntDistribution
|
||||
from skopt.space import Real
|
||||
|
||||
with pytest.raises(OperationalException, match=r"Name is determined.*"):
|
||||
IntParameter(low=0, high=5, default=1, name="hello")
|
||||
@@ -926,7 +927,7 @@ def test_hyperopt_parameters():
|
||||
|
||||
intpar = IntParameter(low=0, high=5, default=1, space="buy")
|
||||
assert intpar.value == 1
|
||||
assert isinstance(intpar.get_space(""), Integer)
|
||||
assert isinstance(intpar.get_space(""), IntDistribution)
|
||||
assert isinstance(intpar.range, range)
|
||||
assert len(list(intpar.range)) == 1
|
||||
# Range contains ONLY the default / value.
|
||||
@@ -955,7 +956,7 @@ def test_hyperopt_parameters():
|
||||
["buy_rsi", "buy_macd", "buy_none"], default="buy_macd", space="buy"
|
||||
)
|
||||
assert catpar.value == "buy_macd"
|
||||
assert isinstance(catpar.get_space(""), Categorical)
|
||||
assert isinstance(catpar.get_space(""), CategoricalDistribution)
|
||||
assert isinstance(catpar.range, list)
|
||||
assert len(list(catpar.range)) == 1
|
||||
# Range contains ONLY the default / value.
|
||||
@@ -966,7 +967,7 @@ def test_hyperopt_parameters():
|
||||
|
||||
boolpar = BooleanParameter(default=True, space="buy")
|
||||
assert boolpar.value is True
|
||||
assert isinstance(boolpar.get_space(""), Categorical)
|
||||
assert isinstance(boolpar.get_space(""), CategoricalDistribution)
|
||||
assert isinstance(boolpar.range, list)
|
||||
assert len(list(boolpar.range)) == 1
|
||||
|
||||
|
||||
Reference in New Issue
Block a user