diff --git a/docs/hyperopt.md b/docs/hyperopt.md index 2755cae2d..0b5d1a50e 100644 --- a/docs/hyperopt.md +++ b/docs/hyperopt.md @@ -303,8 +303,10 @@ Given the following result from hyperopt: ``` Best result: - 135 trades. Avg profit 0.57%. Total profit 0.03871918 BTC (0.7722Σ%). Avg duration 180.4 mins. -with values: + + 44/100: 135 trades. Avg profit 0.57%. Total profit 0.03871918 BTC (0.7722Σ%). Avg duration 180.4 mins. Objective: 1.94367 + +Buy hyperspace params: { 'adx-value': 44, 'rsi-value': 29, 'adx-enabled': False, @@ -347,21 +349,15 @@ If you are optimizing ROI, you're result will look as follows and include a ROI ``` Best result: - 135 trades. Avg profit 0.57%. Total profit 0.03871918 BTC (0.7722Σ%). Avg duration 180.4 mins. -with values: + + 44/100: 135 trades. Avg profit 0.57%. Total profit 0.03871918 BTC (0.7722Σ%). Avg duration 180.4 mins. Objective: 1.94367 + +Buy hyperspace params: { 'adx-value': 44, 'rsi-value': 29, - 'adx-enabled': false, + 'adx-enabled': False, 'rsi-enabled': True, - 'trigger': 'bb_lower', - 'roi_t1': 40, - 'roi_t2': 57, - 'roi_t3': 21, - 'roi_p1': 0.03634636907306948, - 'roi_p2': 0.055237357937802885, - 'roi_p3': 0.015163796015548354, - 'stoploss': -0.37996664668703606 -} + 'trigger': 'bb_lower'} ROI table: { 0: 0.10674752302642071, 21: 0.09158372701087236, @@ -372,9 +368,9 @@ ROI table: This would translate to the following ROI table: ``` python - minimal_roi = { +minimal_roi = { "118": 0, - "78": 0.0363463, + "78": 0.0363, "21": 0.0915, "0": 0.106 } diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 479f8c70a..427b17cb8 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -11,7 +11,7 @@ import sys from operator import itemgetter from pathlib import Path from pprint import pprint -from typing import Any, Dict, List +from typing import Any, Dict, List, Optional from joblib import Parallel, delayed, dump, load, wrap_non_picklable_objects, cpu_count from pandas import DataFrame @@ -70,7 +70,7 @@ class Hyperopt(Backtesting): if hasattr(self.custom_hyperopt, 'populate_sell_trend'): self.advise_sell = self.custom_hyperopt.populate_sell_trend # type: ignore - # Use max_open_trades for hyperopt as well, except --disable-max-market-positions is set + # Use max_open_trades for hyperopt as well, except --disable-max-market-positions is set if self.config.get('use_max_market_positions', True): self.max_open_trades = self.config['max_open_trades'] else: @@ -133,11 +133,20 @@ class Hyperopt(Backtesting): params = best_result['params'] log_str = self.format_results_logstring(best_result) - print(f"\nBest result:\n{log_str}\nwith values:") - pprint(params, indent=4) + print(f"\nBest result:\n\n{log_str}\n") + if self.has_space('buy'): + print('Buy hyperspace params:') + pprint({p.name: params.get(p.name) for p in self.hyperopt_space('buy')}, + indent=4) + if self.has_space('sell'): + print('Sell hyperspace params:') + pprint({p.name: params.get(p.name) for p in self.hyperopt_space('sell')}, + indent=4) if self.has_space('roi'): print("ROI table:") pprint(self.custom_hyperopt.generate_roi_table(params), indent=4) + if self.has_space('stoploss'): + print(f"Stoploss: {params.get('stoploss')}") def log_results(self, results) -> None: """ @@ -171,21 +180,24 @@ class Hyperopt(Backtesting): """ return any(s in self.config['spaces'] for s in [space, 'all']) - def hyperopt_space(self) -> List[Dimension]: + def hyperopt_space(self, space: Optional[str] = None) -> List[Dimension]: """ - Return the space to use during Hyperopt + Return the dimensions in the hyperoptimization space. + :param space: Defines hyperspace to return dimensions for. + If None, then the self.has_space() will be used to return dimensions + for all hyperspaces used. """ spaces: List[Dimension] = [] - if self.has_space('buy'): + if space == 'buy' or (space is None and self.has_space('buy')): logger.debug("Hyperopt has 'buy' space") spaces += self.custom_hyperopt.indicator_space() - if self.has_space('sell'): + if space == 'sell' or (space is None and self.has_space('sell')): logger.debug("Hyperopt has 'sell' space") spaces += self.custom_hyperopt.sell_indicator_space() - if self.has_space('roi'): + if space == 'roi' or (space is None and self.has_space('roi')): logger.debug("Hyperopt has 'roi' space") spaces += self.custom_hyperopt.roi_space() - if self.has_space('stoploss'): + if space == 'stoploss' or (space is None and self.has_space('stoploss')): logger.debug("Hyperopt has 'stoploss' space") spaces += self.custom_hyperopt.stoploss_space() return spaces diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index e114dceaf..e3b049c06 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -463,7 +463,7 @@ def test_start_calls_optimizer(mocker, default_conf, caplog, capsys) -> None: parallel.assert_called_once() out, err = capsys.readouterr() - assert 'Best result:\n* 1/1: foo result Objective: 1.00000\nwith values:\n' in out + assert 'Best result:\n\n* 1/1: foo result Objective: 1.00000\n' in out assert dumper.called # Should be called twice, once for tickerdata, once to save evaluations assert dumper.call_count == 2