diff --git a/freqtrade/optimize/hyperopt/hyperopt_interface.py b/freqtrade/optimize/hyperopt/hyperopt_interface.py index 98b9c806f..61565910f 100644 --- a/freqtrade/optimize/hyperopt/hyperopt_interface.py +++ b/freqtrade/optimize/hyperopt/hyperopt_interface.py @@ -14,12 +14,12 @@ from freqtrade.constants import Config from freqtrade.exchange import timeframe_to_minutes from freqtrade.misc import round_dict from freqtrade.optimize.space import SKDecimal -from freqtrade.strategy import IStrategy -from freqtrade.strategy.parameters import ( +from freqtrade.optimize.space.optunaspaces import ( DimensionProtocol, ft_CategoricalDistribution, ft_IntDistribution, ) +from freqtrade.strategy import IStrategy logger = logging.getLogger(__name__) @@ -137,9 +137,9 @@ class IHyperOpt(ABC): logger.info(f"Max roi table: {round_dict(self.generate_roi_table(p), 3)}") return [ - ft_IntDistribution("roi_t1", roi_limits["roi_t1_min"], roi_limits["roi_t1_max"]), - ft_IntDistribution("roi_t2", roi_limits["roi_t2_min"], roi_limits["roi_t2_max"]), - ft_IntDistribution("roi_t3", roi_limits["roi_t3_min"], roi_limits["roi_t3_max"]), + ft_IntDistribution(roi_limits["roi_t1_min"], roi_limits["roi_t1_max"], "roi_t1"), + ft_IntDistribution(roi_limits["roi_t2_min"], roi_limits["roi_t2_max"], "roi_t2"), + ft_IntDistribution(roi_limits["roi_t3_min"], roi_limits["roi_t3_max"], "roi_t3"), SKDecimal( roi_limits["roi_p1_min"], roi_limits["roi_p1_max"], decimals=3, name="roi_p1" ), @@ -188,7 +188,7 @@ class IHyperOpt(ABC): # This parameter is included into the hyperspace dimensions rather than assigning # it explicitly in the code in order to have it printed in the results along with # other 'trailing' hyperspace parameters. - ft_CategoricalDistribution("trailing_stop", [True]), + ft_CategoricalDistribution([True], "trailing_stop"), SKDecimal(0.01, 0.35, decimals=3, name="trailing_stop_positive"), # 'trailing_stop_positive_offset' should be greater than 'trailing_stop_positive', # so this intermediate parameter is used as the value of the difference between @@ -196,7 +196,7 @@ class IHyperOpt(ABC): # generate_trailing_params() method. # This is similar to the hyperspace dimensions used for constructing the ROI tables. SKDecimal(0.001, 0.1, decimals=3, name="trailing_stop_positive_offset_p1"), - ft_CategoricalDistribution("trailing_only_offset_is_reached", [True, False]), + ft_CategoricalDistribution([True, False], "trailing_only_offset_is_reached"), ] def max_open_trades_space(self) -> list[DimensionProtocol]: @@ -205,7 +205,7 @@ class IHyperOpt(ABC): You may override it in your custom Hyperopt class. """ - return [ft_IntDistribution("max_open_trades", -1, 10)] + return [ft_IntDistribution(-1, 10, "max_open_trades")] # This is needed for proper unpickling the class attribute timeframe # which is set to the actual value by the resolver. diff --git a/freqtrade/optimize/hyperopt/hyperopt_optimizer.py b/freqtrade/optimize/hyperopt/hyperopt_optimizer.py index b5d495228..3105d5f1c 100644 --- a/freqtrade/optimize/hyperopt/hyperopt_optimizer.py +++ b/freqtrade/optimize/hyperopt/hyperopt_optimizer.py @@ -30,7 +30,6 @@ from freqtrade.optimize.hyperopt_loss.hyperopt_loss_interface import IHyperOptLo from freqtrade.optimize.hyperopt_tools import HyperoptStateContainer, HyperoptTools from freqtrade.optimize.optimize_reports import generate_strategy_stats from freqtrade.resolvers.hyperopt_resolver import HyperOptLossResolver -from freqtrade.strategy.parameters import DimensionProtocol from freqtrade.util.dry_run_wallet import get_dry_run_wallet @@ -43,7 +42,8 @@ with warnings.catch_warnings(): import optuna from freqtrade.optimize.space.decimalspace import SKDecimal - from freqtrade.strategy.parameters import ( + from freqtrade.optimize.space.optunaspaces import ( + DimensionProtocol, ft_CategoricalDistribution, ft_FloatDistribution, ft_IntDistribution, diff --git a/freqtrade/optimize/space/__init__.py b/freqtrade/optimize/space/__init__.py index 6c59a4d8f..2e81a5e4b 100644 --- a/freqtrade/optimize/space/__init__.py +++ b/freqtrade/optimize/space/__init__.py @@ -1,3 +1,6 @@ -from skopt.space import Categorical, Dimension, Integer, Real # noqa: F401 - +# from skopt.space import Categorical, Dimension, Integer, Real # noqa: F401 from .decimalspace import SKDecimal # noqa: F401 +from .optunaspaces import DimensionProtocol # noqa: F401 +from .optunaspaces import ft_CategoricalDistribution as Categorical # noqa: F401 +from .optunaspaces import ft_FloatDistribution as Real # noqa: F401 +from .optunaspaces import ft_IntDistribution as Integer # noqa: F401 diff --git a/freqtrade/optimize/space/decimalspace.py b/freqtrade/optimize/space/decimalspace.py index 2a46f2d33..63ae38aad 100644 --- a/freqtrade/optimize/space/decimalspace.py +++ b/freqtrade/optimize/space/decimalspace.py @@ -1,3 +1,5 @@ +from decimal import Decimal + from optuna.distributions import FloatDistribution @@ -7,7 +9,7 @@ class SKDecimal(FloatDistribution): low: float, high: float, step: float | None = None, - decimals: int | None = 3, + decimals: int = 4, name=None, ): """ @@ -19,6 +21,7 @@ class SKDecimal(FloatDistribution): self.step = step or 1 / 10**decimals self.name = name + # with localcontext(prec=max(decimals, 4)) as ctx: super().__init__( low=low, high=high, diff --git a/freqtrade/strategy/parameters.py b/freqtrade/strategy/parameters.py index 0c049d355..f738ca526 100644 --- a/freqtrade/strategy/parameters.py +++ b/freqtrade/strategy/parameters.py @@ -7,16 +7,19 @@ import logging from abc import ABC, abstractmethod from collections.abc import Sequence from contextlib import suppress -from typing import Any, Protocol, Union +from typing import Any, Union from freqtrade.enums import HyperoptState from freqtrade.optimize.hyperopt_tools import HyperoptStateContainer with suppress(ImportError): - from optuna.distributions import CategoricalDistribution, FloatDistribution, IntDistribution - from freqtrade.optimize.space import SKDecimal + from freqtrade.optimize.space.optunaspaces import ( + ft_CategoricalDistribution, + ft_FloatDistribution, + ft_IntDistribution, + ) from freqtrade.exceptions import OperationalException @@ -24,43 +27,43 @@ from freqtrade.exceptions import OperationalException logger = logging.getLogger(__name__) -class DimensionProtocol(Protocol): - name: str +# class DimensionProtocol(Protocol): +# name: str -class ft_CategoricalDistribution(CategoricalDistribution): - def __init__( - self, - name: str, - categories: Sequence[Any], - **kwargs, - ): - self.name = name - return super().__init__(categories) +# class ft_CategoricalDistribution(CategoricalDistribution): +# def __init__( +# self, +# name: str, +# categories: Sequence[Any], +# **kwargs, +# ): +# self.name = name +# return super().__init__(categories) -class ft_IntDistribution(IntDistribution): - def __init__( - self, - name: str, - low: int | float, - high: int | float, - **kwargs, - ): - self.name = name - return super().__init__(int(low), int(high), **kwargs) +# class ft_IntDistribution(IntDistribution): +# def __init__( +# self, +# name: str, +# low: int | float, +# high: int | float, +# **kwargs, +# ): +# self.name = name +# return super().__init__(int(low), int(high), **kwargs) -class ft_FloatDistribution(FloatDistribution): - def __init__( - self, - name: str, - low: float, - high: float, - **kwargs, - ): - self.name = name - return super().__init__(low, high, **kwargs) +# class ft_FloatDistribution(FloatDistribution): +# def __init__( +# self, +# name: str, +# low: float, +# high: float, +# **kwargs, +# ): +# self.name = name +# return super().__init__(low, high, **kwargs) class BaseParameter(ABC): @@ -207,7 +210,7 @@ class IntParameter(NumericParameter): Create optuna distribution space. :param name: A name of parameter field. """ - return ft_IntDistribution(name, self.low, self.high, **self._space_params) + return ft_IntDistribution(self.low, self.high, name, **self._space_params) @property def range(self): @@ -260,7 +263,7 @@ class RealParameter(NumericParameter): Create optimization space. :param name: A name of parameter field. """ - return ft_FloatDistribution(name, self.low, self.high, **self._space_params) + return ft_FloatDistribution(self.low, self.high, name, **self._space_params) class DecimalParameter(NumericParameter): @@ -363,7 +366,7 @@ class CategoricalParameter(BaseParameter): Create optuna distribution space. :param name: A name of parameter field. """ - return ft_CategoricalDistribution(name, self.opt_range) + return ft_CategoricalDistribution(self.opt_range, name) @property def range(self): diff --git a/tests/optimize/test_hyperopt.py b/tests/optimize/test_hyperopt.py index 91635857b..9d5a6f918 100644 --- a/tests/optimize/test_hyperopt.py +++ b/tests/optimize/test_hyperopt.py @@ -17,10 +17,8 @@ from freqtrade.optimize.hyperopt.hyperopt_auto import HyperOptAuto from freqtrade.optimize.hyperopt_tools import HyperoptTools from freqtrade.optimize.optimize_reports import generate_strategy_stats from freqtrade.optimize.space import SKDecimal +from freqtrade.optimize.space.optunaspaces import ft_IntDistribution from freqtrade.strategy import IntParameter - -# from skopt.space import Integer -from freqtrade.strategy.parameters import ft_IntDistribution from freqtrade.util import dt_utc from tests.conftest import ( CURRENT_TEST_STRATEGY, @@ -1305,7 +1303,7 @@ def test_max_open_trades_consistency(mocker, hyperopt_conf, tmp_path, fee) -> No assert isinstance(hyperopt.hyperopter.custom_hyperopt, HyperOptAuto) hyperopt.hyperopter.custom_hyperopt.max_open_trades_space = lambda: [ - ft_IntDistribution("max_open_trades", 1, 10) + ft_IntDistribution(1, 10, "max_open_trades") ] first_time_evaluated = False