diff --git a/freqtrade/arguments.py b/freqtrade/arguments.py index 930342e5a..327915b61 100644 --- a/freqtrade/arguments.py +++ b/freqtrade/arguments.py @@ -325,6 +325,15 @@ class Arguments(object): type=Arguments.check_int_positive, metavar='INT', ) + parser.add_argument( + '--min-trades', + help="Set minimal desired number of trades for evaluations in the hyperopt " + "optimization path (default: 1).", + dest='hyperopt_min_trades', + default=1, + type=Arguments.check_int_positive, + metavar='INT', + ) def _build_subcommands(self) -> None: """ diff --git a/freqtrade/configuration.py b/freqtrade/configuration.py index 54862ff70..c19580c36 100644 --- a/freqtrade/configuration.py +++ b/freqtrade/configuration.py @@ -312,6 +312,10 @@ class Configuration(object): self._args_to_config(config, argname='hyperopt_random_state', logstring='Parameter --random-state detected: {}') + + self._args_to_config(config, argname='hyperopt_min_trades', + logstring='Parameter --min-trades detected: {}') + return config def _validate_config_schema(self, conf: Dict[str, Any]) -> Dict[str, Any]: diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 52821d93b..235a20156 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -204,7 +204,11 @@ class Hyperopt(Backtesting): trade_count = len(results.index) trade_duration = results.trade_duration.mean() - if trade_count == 0: + # If this evaluation contains too short small amount of trades + # to be interesting -- consider it as 'bad' (assign max. loss value) + # in order to cast this hyperspace point away from optimization + # path. We do not want to optimize 'hodl' strategies. + if trade_count < self.config['hyperopt_min_trades']: return { 'loss': MAX_LOSS, 'params': params, diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index eb2506f00..8bd5ffd0b 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -410,6 +410,7 @@ def test_generate_optimizer(mocker, default_conf) -> None: default_conf.update({'config': 'config.json.example'}) default_conf.update({'timerange': None}) default_conf.update({'spaces': 'all'}) + default_conf.update({'hyperopt_min_trades': 1}) trades = [ ('POWR/BTC', 0.023117, 0.000233, 100)