fix optuna userwarning the range is not divisible by step
This commit is contained in:
@@ -331,6 +331,7 @@ class Hyperopt:
|
|||||||
self.config,
|
self.config,
|
||||||
self.hyperopter.get_strategy_name(),
|
self.hyperopter.get_strategy_name(),
|
||||||
self.current_best_epoch,
|
self.current_best_epoch,
|
||||||
|
self.hyperopter.o_dimensions,
|
||||||
)
|
)
|
||||||
|
|
||||||
HyperoptTools.show_epoch_details(
|
HyperoptTools.show_epoch_details(
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from typing import Any
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import rapidjson
|
import rapidjson
|
||||||
|
from optuna.distributions import BaseDistribution
|
||||||
from pandas import isna, json_normalize
|
from pandas import isna, json_normalize
|
||||||
|
|
||||||
from freqtrade.constants import FTHYPT_FILEVERSION, Config
|
from freqtrade.constants import FTHYPT_FILEVERSION, Config
|
||||||
@@ -14,6 +15,7 @@ from freqtrade.enums import HyperoptState
|
|||||||
from freqtrade.exceptions import OperationalException
|
from freqtrade.exceptions import OperationalException
|
||||||
from freqtrade.misc import deep_merge_dicts, round_dict, safe_value_fallback2
|
from freqtrade.misc import deep_merge_dicts, round_dict, safe_value_fallback2
|
||||||
from freqtrade.optimize.hyperopt_epoch_filters import hyperopt_filter_epochs
|
from freqtrade.optimize.hyperopt_epoch_filters import hyperopt_filter_epochs
|
||||||
|
from freqtrade.optimize.space import SKDecimal, _adjust_discrete_uniform
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -61,11 +63,26 @@ class HyperoptTools:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def export_params(params, strategy_name: str, filename: Path):
|
def export_params(
|
||||||
|
params,
|
||||||
|
strategy_name: str,
|
||||||
|
filename: Path,
|
||||||
|
o_dimensions: dict[str, BaseDistribution] | None = None,
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Generate files
|
Generate files
|
||||||
"""
|
"""
|
||||||
final_params = deepcopy(params["params_not_optimized"])
|
final_params = deepcopy(params["params_not_optimized"])
|
||||||
|
if o_dimensions:
|
||||||
|
for key, val in params["params_details"].items():
|
||||||
|
if isinstance(val, dict):
|
||||||
|
for key1, val1 in val.items():
|
||||||
|
if isinstance(o_dimensions.get(key1), SKDecimal):
|
||||||
|
step = getattr(o_dimensions.get(key1), "step", None)
|
||||||
|
if step:
|
||||||
|
params["params_details"][key][key1] = _adjust_discrete_uniform(
|
||||||
|
val1, step
|
||||||
|
)
|
||||||
final_params = deep_merge_dicts(params["params_details"], final_params)
|
final_params = deep_merge_dicts(params["params_details"], final_params)
|
||||||
final_params = {
|
final_params = {
|
||||||
"strategy_name": strategy_name,
|
"strategy_name": strategy_name,
|
||||||
@@ -73,6 +90,7 @@ class HyperoptTools:
|
|||||||
"ft_stratparam_v": 1,
|
"ft_stratparam_v": 1,
|
||||||
"export_time": datetime.now(timezone.utc),
|
"export_time": datetime.now(timezone.utc),
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(f"Dumping parameters to {filename}")
|
logger.info(f"Dumping parameters to {filename}")
|
||||||
with filename.open("w") as f:
|
with filename.open("w") as f:
|
||||||
rapidjson.dump(
|
rapidjson.dump(
|
||||||
@@ -93,12 +111,19 @@ class HyperoptTools:
|
|||||||
return params
|
return params
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def try_export_params(config: Config, strategy_name: str, params: dict):
|
def try_export_params(
|
||||||
|
config: Config,
|
||||||
|
strategy_name: str,
|
||||||
|
params: dict,
|
||||||
|
o_dimensions: dict[str, BaseDistribution] | None = None,
|
||||||
|
):
|
||||||
if params.get(FTHYPT_FILEVERSION, 1) >= 2 and not config.get("disableparamexport", False):
|
if params.get(FTHYPT_FILEVERSION, 1) >= 2 and not config.get("disableparamexport", False):
|
||||||
# Export parameters ...
|
# Export parameters ...
|
||||||
fn = HyperoptTools.get_strategy_filename(config, strategy_name)
|
fn = HyperoptTools.get_strategy_filename(config, strategy_name)
|
||||||
if fn:
|
if fn:
|
||||||
HyperoptTools.export_params(params, strategy_name, fn.with_suffix(".json"))
|
HyperoptTools.export_params(
|
||||||
|
params, strategy_name, fn.with_suffix(".json"), o_dimensions
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
logger.warning("Strategy not found, not exporting parameter file.")
|
logger.warning("Strategy not found, not exporting parameter file.")
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from .decimalspace import SKDecimal
|
from .decimalspace import SKDecimal, _adjust_discrete_uniform
|
||||||
from .optunaspaces import (
|
from .optunaspaces import (
|
||||||
DimensionProtocol,
|
DimensionProtocol,
|
||||||
ft_CategoricalDistribution,
|
ft_CategoricalDistribution,
|
||||||
@@ -13,10 +13,4 @@ Categorical = ft_CategoricalDistribution
|
|||||||
Integer = ft_IntDistribution
|
Integer = ft_IntDistribution
|
||||||
Real = ft_FloatDistribution
|
Real = ft_FloatDistribution
|
||||||
|
|
||||||
__all__ = [
|
__all__ = ["Categorical", "Dimension", "Integer", "Real", "SKDecimal", "_adjust_discrete_uniform"]
|
||||||
"Categorical",
|
|
||||||
"Dimension",
|
|
||||||
"Integer",
|
|
||||||
"Real",
|
|
||||||
"SKDecimal",
|
|
||||||
]
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import decimal
|
||||||
|
|
||||||
from optuna.distributions import FloatDistribution
|
from optuna.distributions import FloatDistribution
|
||||||
|
|
||||||
|
|
||||||
@@ -20,7 +22,32 @@ class SKDecimal(FloatDistribution):
|
|||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
super().__init__(
|
super().__init__(
|
||||||
low=low,
|
low=_adjust_discrete_uniform(low, self.step),
|
||||||
high=high,
|
high=_adjust_discrete_uniform_high(low, high, self.step),
|
||||||
step=self.step,
|
step=self.step,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _adjust_discrete_uniform_high(low: float, high: float, step: float | None) -> float:
|
||||||
|
if step:
|
||||||
|
d_high = decimal.Decimal(str(high))
|
||||||
|
d_low = decimal.Decimal(str(low))
|
||||||
|
d_step = decimal.Decimal(str(step))
|
||||||
|
|
||||||
|
d_r = d_high - d_low
|
||||||
|
|
||||||
|
if d_r % d_step != decimal.Decimal("0"):
|
||||||
|
high = float((d_r // d_step) * d_step + d_low)
|
||||||
|
|
||||||
|
return high
|
||||||
|
|
||||||
|
|
||||||
|
def _adjust_discrete_uniform(val: float, step: float | None) -> float:
|
||||||
|
if step:
|
||||||
|
d_val = decimal.Decimal(str(val))
|
||||||
|
d_step = decimal.Decimal(str(step))
|
||||||
|
|
||||||
|
if d_val % d_step != decimal.Decimal("0"):
|
||||||
|
val = float((d_val // d_step) * d_step)
|
||||||
|
|
||||||
|
return val
|
||||||
|
|||||||
Reference in New Issue
Block a user