Merge pull request #5644 from slyons/develop

Add ability to ignore unparameterized spaces
This commit is contained in:
Matthias 2021-10-14 08:07:07 +02:00 committed by GitHub
commit 0e7d903a6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 43 additions and 11 deletions

View File

@ -51,6 +51,7 @@ usage: freqtrade hyperopt [-h] [-v] [--logfile FILE] [-V] [-c PATH] [-d PATH]
[--print-all] [--no-color] [--print-json] [-j JOBS] [--print-all] [--no-color] [--print-json] [-j JOBS]
[--random-state INT] [--min-trades INT] [--random-state INT] [--min-trades INT]
[--hyperopt-loss NAME] [--disable-param-export] [--hyperopt-loss NAME] [--disable-param-export]
[--ignore-missing-spaces]
optional arguments: optional arguments:
-h, --help show this help message and exit -h, --help show this help message and exit
@ -118,6 +119,9 @@ optional arguments:
MaxDrawDownHyperOptLoss MaxDrawDownHyperOptLoss
--disable-param-export --disable-param-export
Disable automatic hyperopt parameter export. Disable automatic hyperopt parameter export.
--ignore-missing-spaces, --ignore-unparameterized-spaces
Suppress errors for any requested Hyperopt spaces that
do not contain any parameters.
Common arguments: Common arguments:
-v, --verbose Verbose mode (-vv for more, -vvv to get all messages). -v, --verbose Verbose mode (-vv for more, -vvv to get all messages).

View File

@ -31,7 +31,8 @@ ARGS_HYPEROPT = ARGS_COMMON_OPTIMIZE + ["hyperopt", "hyperopt_path",
"epochs", "spaces", "print_all", "epochs", "spaces", "print_all",
"print_colorized", "print_json", "hyperopt_jobs", "print_colorized", "print_json", "hyperopt_jobs",
"hyperopt_random_state", "hyperopt_min_trades", "hyperopt_random_state", "hyperopt_min_trades",
"hyperopt_loss", "disableparamexport"] "hyperopt_loss", "disableparamexport",
"hyperopt_ignore_missing_space"]
ARGS_EDGE = ARGS_COMMON_OPTIMIZE + ["stoploss_range"] ARGS_EDGE = ARGS_COMMON_OPTIMIZE + ["stoploss_range"]

View File

@ -558,4 +558,10 @@ AVAILABLE_CLI_OPTIONS = {
help='Do not print epoch details header.', help='Do not print epoch details header.',
action='store_true', action='store_true',
), ),
"hyperopt_ignore_missing_space": Arg(
"--ignore-missing-spaces", "--ignore-unparameterized-spaces",
help=("Suppress errors for any requested Hyperopt spaces "
"that do not contain any parameters."),
action="store_true",
),
} }

View File

@ -369,6 +369,9 @@ class Configuration:
self._args_to_config(config, argname='hyperopt_show_no_header', self._args_to_config(config, argname='hyperopt_show_no_header',
logstring='Parameter --no-header detected: {}') logstring='Parameter --no-header detected: {}')
self._args_to_config(config, argname="hyperopt_ignore_missing_space",
logstring="Paramter --ignore-missing-space detected: {}")
def _process_plot_options(self, config: Dict[str, Any]) -> None: def _process_plot_options(self, config: Dict[str, Any]) -> None:
self._args_to_config(config, argname='pairs', self._args_to_config(config, argname='pairs',

View File

@ -258,6 +258,7 @@ class Hyperopt:
if HyperoptTools.has_space(self.config, 'trailing'): if HyperoptTools.has_space(self.config, 'trailing'):
logger.debug("Hyperopt has 'trailing' space") logger.debug("Hyperopt has 'trailing' space")
self.trailing_space = self.custom_hyperopt.trailing_space() self.trailing_space = self.custom_hyperopt.trailing_space()
self.dimensions = (self.buy_space + self.sell_space + self.protection_space self.dimensions = (self.buy_space + self.sell_space + self.protection_space
+ self.roi_space + self.stoploss_space + self.trailing_space) + self.roi_space + self.stoploss_space + self.trailing_space)

View File

@ -3,6 +3,7 @@ HyperOptAuto class.
This module implements a convenience auto-hyperopt class, which can be used together with strategies This module implements a convenience auto-hyperopt class, which can be used together with strategies
that implement IHyperStrategy interface. that implement IHyperStrategy interface.
""" """
import logging
from contextlib import suppress from contextlib import suppress
from typing import Callable, Dict, List from typing import Callable, Dict, List
@ -15,12 +16,19 @@ with suppress(ImportError):
from freqtrade.optimize.hyperopt_interface import EstimatorType, IHyperOpt from freqtrade.optimize.hyperopt_interface import EstimatorType, IHyperOpt
def _format_exception_message(space: str) -> str: logger = logging.getLogger(__name__)
raise OperationalException(
f"The '{space}' space is included into the hyperoptimization "
f"but no parameter for this space was not found in your Strategy. " def _format_exception_message(space: str, ignore_missing_space: bool) -> None:
f"Please make sure to have parameters for this space enabled for optimization " msg = (f"The '{space}' space is included into the hyperoptimization "
f"or remove the '{space}' space from hyperoptimization.") f"but no parameter for this space was not found in your Strategy. "
)
if ignore_missing_space:
logger.warning(msg + "This space will be ignored.")
else:
raise OperationalException(
msg + f"Please make sure to have parameters for this space enabled for optimization "
f"or remove the '{space}' space from hyperoptimization.")
class HyperOptAuto(IHyperOpt): class HyperOptAuto(IHyperOpt):
@ -48,13 +56,16 @@ class HyperOptAuto(IHyperOpt):
if attr.optimize: if attr.optimize:
yield attr.get_space(attr_name) yield attr.get_space(attr_name)
def _get_indicator_space(self, category): def _get_indicator_space(self, category) -> List:
# TODO: is this necessary, or can we call "generate_space" directly? # TODO: is this necessary, or can we call "generate_space" directly?
indicator_space = list(self._generate_indicator_space(category)) indicator_space = list(self._generate_indicator_space(category))
if len(indicator_space) > 0: if len(indicator_space) > 0:
return indicator_space return indicator_space
else: else:
_format_exception_message(category) _format_exception_message(
category,
self.config.get("hyperopt_ignore_missing_space", False))
return []
def buy_indicator_space(self) -> List['Dimension']: def buy_indicator_space(self) -> List['Dimension']:
return self._get_indicator_space('buy') return self._get_indicator_space('buy')

View File

@ -702,7 +702,7 @@ def test_simplified_interface_roi_stoploss(mocker, hyperopt_conf, capsys) -> Non
assert hasattr(hyperopt, "position_stacking") assert hasattr(hyperopt, "position_stacking")
def test_simplified_interface_all_failed(mocker, hyperopt_conf) -> None: def test_simplified_interface_all_failed(mocker, hyperopt_conf, caplog) -> None:
mocker.patch('freqtrade.optimize.hyperopt.dump', MagicMock()) mocker.patch('freqtrade.optimize.hyperopt.dump', MagicMock())
mocker.patch('freqtrade.optimize.hyperopt.file_dump_json') mocker.patch('freqtrade.optimize.hyperopt.file_dump_json')
mocker.patch('freqtrade.optimize.backtesting.Backtesting.load_bt_data', mocker.patch('freqtrade.optimize.backtesting.Backtesting.load_bt_data',
@ -724,7 +724,13 @@ def test_simplified_interface_all_failed(mocker, hyperopt_conf) -> None:
hyperopt.custom_hyperopt.generate_roi_table = MagicMock(return_value={}) hyperopt.custom_hyperopt.generate_roi_table = MagicMock(return_value={})
with pytest.raises(OperationalException, match=r"The 'protection' space is included into *"): with pytest.raises(OperationalException, match=r"The 'protection' space is included into *"):
hyperopt.start() hyperopt.init_spaces()
hyperopt.config['hyperopt_ignore_missing_space'] = True
caplog.clear()
hyperopt.init_spaces()
assert log_has_re(r"The 'protection' space is included into *", caplog)
assert hyperopt.protection_space == []
def test_simplified_interface_buy(mocker, hyperopt_conf, capsys) -> None: def test_simplified_interface_buy(mocker, hyperopt_conf, capsys) -> None: