From 8f8da51808a8be356c310a8406d8445a62747761 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 8 May 2025 19:24:31 +0200 Subject: [PATCH] feat: round hyperopt results to 13 digits (this removes floating point errors) --- .../optimize/hyperopt/hyperopt_optimizer.py | 41 +++++++++++-------- tests/optimize/test_hyperopt.py | 2 +- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/freqtrade/optimize/hyperopt/hyperopt_optimizer.py b/freqtrade/optimize/hyperopt/hyperopt_optimizer.py index 8247ccc35..891bfcbee 100644 --- a/freqtrade/optimize/hyperopt/hyperopt_optimizer.py +++ b/freqtrade/optimize/hyperopt/hyperopt_optimizer.py @@ -22,7 +22,7 @@ from freqtrade.data.history import get_timerange from freqtrade.data.metrics import calculate_market_change from freqtrade.enums import HyperoptState from freqtrade.exceptions import OperationalException -from freqtrade.misc import deep_merge_dicts +from freqtrade.misc import deep_merge_dicts, round_dict from freqtrade.optimize.backtesting import Backtesting # Import IHyperOptLoss to allow unpickling classes from these modules @@ -145,27 +145,36 @@ class HyperOptimizer: result: dict = {} if HyperoptTools.has_space(self.config, "buy"): - result["buy"] = {p.name: params.get(p.name) for p in self.buy_space} + result["buy"] = round_dict({p.name: params.get(p.name) for p in self.buy_space}, 13) if HyperoptTools.has_space(self.config, "sell"): - result["sell"] = {p.name: params.get(p.name) for p in self.sell_space} + result["sell"] = round_dict({p.name: params.get(p.name) for p in self.sell_space}, 13) if HyperoptTools.has_space(self.config, "protection"): - result["protection"] = {p.name: params.get(p.name) for p in self.protection_space} + result["protection"] = round_dict( + {p.name: params.get(p.name) for p in self.protection_space}, 13 + ) if HyperoptTools.has_space(self.config, "roi"): - result["roi"] = { - str(k): v for k, v in self.custom_hyperopt.generate_roi_table(params).items() - } + result["roi"] = round_dict( + {str(k): v for k, v in self.custom_hyperopt.generate_roi_table(params).items()}, 13 + ) if HyperoptTools.has_space(self.config, "stoploss"): - result["stoploss"] = {p.name: params.get(p.name) for p in self.stoploss_space} + result["stoploss"] = round_dict( + {p.name: params.get(p.name) for p in self.stoploss_space}, 13 + ) if HyperoptTools.has_space(self.config, "trailing"): - result["trailing"] = self.custom_hyperopt.generate_trailing_params(params) + result["trailing"] = round_dict( + self.custom_hyperopt.generate_trailing_params(params), 13 + ) if HyperoptTools.has_space(self.config, "trades"): - result["max_open_trades"] = { - "max_open_trades": ( - self.backtesting.strategy.max_open_trades - if self.backtesting.strategy.max_open_trades != float("inf") - else -1 - ) - } + result["max_open_trades"] = round_dict( + { + "max_open_trades": ( + self.backtesting.strategy.max_open_trades + if self.backtesting.strategy.max_open_trades != float("inf") + else -1 + ) + }, + 13, + ) return result diff --git a/tests/optimize/test_hyperopt.py b/tests/optimize/test_hyperopt.py index 76825cc03..97d7c0464 100644 --- a/tests/optimize/test_hyperopt.py +++ b/tests/optimize/test_hyperopt.py @@ -577,7 +577,7 @@ def test_generate_optimizer(mocker, hyperopt_conf) -> None: "buy_plusdi": 0.02, "buy_rsi": 35, }, - "roi": {"0": 0.12000000000000001, "20.0": 0.02, "50.0": 0.01, "110.0": 0}, + "roi": {"0": 0.12, "20.0": 0.02, "50.0": 0.01, "110.0": 0}, "protection": { "protection_cooldown_lookback": 20, "protection_enabled": True,