diff --git a/docs/utils.md b/docs/utils.md index 91dd6eae0..abb7fd0db 100644 --- a/docs/utils.md +++ b/docs/utils.md @@ -416,7 +416,9 @@ usage: freqtrade hyperopt-list [-h] [-v] [--logfile FILE] [-V] [-c PATH] [--profitable] [--min-trades INT] [--max-trades INT] [--min-avg-time FLOAT] [--max-avg-time FLOAT] [--min-avg-profit FLOAT] - [--min-total-profit FLOAT] [--no-color] + [--max-avg-profit FLOAT] + [--min-total-profit FLOAT] + [--max-total-profit FLOAT] [--no-color] [--print-json] [--no-details] optional arguments: @@ -429,8 +431,12 @@ optional arguments: --max-avg-time FLOAT Select epochs on under average time. --min-avg-profit FLOAT Select epochs on above average profit. + --max-avg-profit FLOAT + Select epochs on below average profit. --min-total-profit FLOAT Select epochs on above total profit. + --max-total-profit FLOAT + Select epochs on below total profit. --no-color Disable colorization of hyperopt results. May be useful if you are redirecting output to a file. --print-json Print best result detailization in JSON format. diff --git a/freqtrade/commands/arguments.py b/freqtrade/commands/arguments.py index 1b2c4482e..fe6f49039 100644 --- a/freqtrade/commands/arguments.py +++ b/freqtrade/commands/arguments.py @@ -64,7 +64,8 @@ ARGS_PLOT_PROFIT = ["pairs", "timerange", "export", "exportfilename", "db_url", ARGS_HYPEROPT_LIST = ["hyperopt_list_best", "hyperopt_list_profitable", "hyperopt_list_min_trades", "hyperopt_list_max_trades", "hyperopt_list_min_avg_time", "hyperopt_list_max_avg_time", - "hyperopt_list_min_avg_profit", "hyperopt_list_min_total_profit", + "hyperopt_list_min_avg_profit", "hyperopt_list_max_avg_profit", + "hyperopt_list_min_total_profit", "hyperopt_list_max_total_profit", "print_colorized", "print_json", "hyperopt_list_no_details"] ARGS_HYPEROPT_SHOW = ["hyperopt_list_best", "hyperopt_list_profitable", "hyperopt_show_index", diff --git a/freqtrade/commands/cli_options.py b/freqtrade/commands/cli_options.py index c3b79ae3a..1776955b1 100644 --- a/freqtrade/commands/cli_options.py +++ b/freqtrade/commands/cli_options.py @@ -428,12 +428,24 @@ AVAILABLE_CLI_OPTIONS = { type=float, metavar='FLOAT', ), + "hyperopt_list_max_avg_profit": Arg( + '--max-avg-profit', + help='Select epochs on below average profit.', + type=float, + metavar='FLOAT', + ), "hyperopt_list_min_total_profit": Arg( '--min-total-profit', help='Select epochs on above total profit.', type=float, metavar='FLOAT', ), + "hyperopt_list_max_total_profit": Arg( + '--max-total-profit', + help='Select epochs on below total profit.', + type=float, + metavar='FLOAT', + ), "hyperopt_list_no_details": Arg( '--no-details', help='Do not print best epoch details.', diff --git a/freqtrade/commands/hyperopt_commands.py b/freqtrade/commands/hyperopt_commands.py index c3baf2406..8c1c80d98 100755 --- a/freqtrade/commands/hyperopt_commands.py +++ b/freqtrade/commands/hyperopt_commands.py @@ -32,7 +32,9 @@ def start_hyperopt_list(args: Dict[str, Any]) -> None: 'filter_min_avg_time': config.get('hyperopt_list_min_avg_time', None), 'filter_max_avg_time': config.get('hyperopt_list_max_avg_time', None), 'filter_min_avg_profit': config.get('hyperopt_list_min_avg_profit', None), - 'filter_min_total_profit': config.get('hyperopt_list_min_total_profit', None) + 'filter_max_avg_profit': config.get('hyperopt_list_max_avg_profit', None), + 'filter_min_total_profit': config.get('hyperopt_list_min_total_profit', None), + 'filter_max_total_profit': config.get('hyperopt_list_max_total_profit', None) } trials_file = (config['user_data_dir'] / @@ -81,7 +83,9 @@ def start_hyperopt_show(args: Dict[str, Any]) -> None: 'filter_min_avg_time': config.get('hyperopt_list_min_avg_time', None), 'filter_max_avg_time': config.get('hyperopt_list_max_avg_time', None), 'filter_min_avg_profit': config.get('hyperopt_list_min_avg_profit', None), - 'filter_min_total_profit': config.get('hyperopt_list_min_total_profit', None) + 'filter_max_avg_profit': config.get('hyperopt_list_max_avg_profit', None), + 'filter_min_total_profit': config.get('hyperopt_list_min_total_profit', None), + 'filter_max_total_profit': config.get('hyperopt_list_max_total_profit', None) } no_header = config.get('hyperopt_show_no_header', False) @@ -152,12 +156,25 @@ def _hyperopt_filter_trials(trials: List, filteroptions: dict) -> List: if x['results_metrics']['avg_profit'] > filteroptions['filter_min_avg_profit'] ] + if filteroptions['filter_max_avg_profit'] is not None: + trials = [x for x in trials if x['results_metrics']['trade_count'] > 0] + trials = [ + x for x in trials + if x['results_metrics']['avg_profit'] + < filteroptions['filter_max_avg_profit'] + ] if filteroptions['filter_min_total_profit'] is not None: trials = [x for x in trials if x['results_metrics']['trade_count'] > 0] trials = [ x for x in trials if x['results_metrics']['profit'] > filteroptions['filter_min_total_profit'] ] + if filteroptions['filter_max_total_profit'] is not None: + trials = [x for x in trials if x['results_metrics']['trade_count'] > 0] + trials = [ + x for x in trials + if x['results_metrics']['profit'] < filteroptions['filter_max_total_profit'] + ] logger.info(f"{len(trials)} " + ("best " if filteroptions['only_best'] else "") + diff --git a/freqtrade/configuration/configuration.py b/freqtrade/configuration/configuration.py index 41f24e55c..c2613ba99 100644 --- a/freqtrade/configuration/configuration.py +++ b/freqtrade/configuration/configuration.py @@ -325,9 +325,15 @@ class Configuration: self._args_to_config(config, argname='hyperopt_list_min_avg_profit', logstring='Parameter --min-avg-profit detected: {}') + self._args_to_config(config, argname='hyperopt_list_max_avg_profit', + logstring='Parameter --max-avg-profit detected: {}') + self._args_to_config(config, argname='hyperopt_list_min_total_profit', logstring='Parameter --min-total-profit detected: {}') + self._args_to_config(config, argname='hyperopt_list_max_total_profit', + logstring='Parameter --max-total-profit detected: {}') + self._args_to_config(config, argname='hyperopt_list_no_details', logstring='Parameter --no-details detected: {}') diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py index e02a721a4..ee1db5db5 100644 --- a/tests/commands/test_commands.py +++ b/tests/commands/test_commands.py @@ -822,6 +822,20 @@ def test_hyperopt_list(mocker, capsys, hyperopt_results): assert all(x not in captured.out for x in [" 1/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12", " 8/12", " 9/12", " 10/12", " 11/12", " 12/12"]) + args = [ + "hyperopt-list", + "--no-details", + "--max-avg-profit", "0.10" + ] + pargs = get_args(args) + pargs['config'] = None + start_hyperopt_list(pargs) + captured = capsys.readouterr() + assert all(x in captured.out + for x in [" 1/12", " 3/12", " 5/12", " 6/12", " 7/12", " 8/12", " 9/12", + " 11/12"]) + assert all(x not in captured.out + for x in [" 2/12", " 4/12", " 10/12", " 12/12"]) args = [ "hyperopt-list", "--no-details", @@ -836,6 +850,20 @@ def test_hyperopt_list(mocker, capsys, hyperopt_results): assert all(x not in captured.out for x in [" 1/12", " 2/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12", " 8/12", " 9/12", " 11/12", " 12/12"]) + args = [ + "hyperopt-list", + "--no-details", + "--max-total-profit", "0.4" + ] + pargs = get_args(args) + pargs['config'] = None + start_hyperopt_list(pargs) + captured = capsys.readouterr() + assert all(x in captured.out + for x in [" 1/12", " 2/12", " 3/12", " 5/12", " 6/12", " 7/12", " 8/12", + " 9/12", " 11/12"]) + assert all(x not in captured.out + for x in [" 4/12", " 10/12", " 12/12"]) args = [ "hyperopt-list", "--profitable",