Merge pull request #7396 from freqtrade/hyperopt_per_epoch
Hyperopt per epoch
This commit is contained in:
		| @@ -196,7 +196,9 @@ class DataProvider: | |||||||
|         Clear pair dataframe cache. |         Clear pair dataframe cache. | ||||||
|         """ |         """ | ||||||
|         self.__cached_pairs = {} |         self.__cached_pairs = {} | ||||||
|         self.__cached_pairs_backtesting = {} |         # Don't reset backtesting pairs - | ||||||
|  |         # otherwise they're reloaded each time during hyperopt due to with analyze_per_epoch | ||||||
|  |         # self.__cached_pairs_backtesting = {} | ||||||
|         self.__slice_index = 0 |         self.__slice_index = 0 | ||||||
|  |  | ||||||
|     # Exchange functions |     # Exchange functions | ||||||
|   | |||||||
| @@ -580,11 +580,23 @@ class Hyperopt: | |||||||
|                     max_value=self.total_epochs, redirect_stdout=False, redirect_stderr=False, |                     max_value=self.total_epochs, redirect_stdout=False, redirect_stderr=False, | ||||||
|                     widgets=widgets |                     widgets=widgets | ||||||
|                 ) as pbar: |                 ) as pbar: | ||||||
|                     EVALS = ceil(self.total_epochs / jobs) |                     start = 0 | ||||||
|                     for i in range(EVALS): |  | ||||||
|  |                     if self.analyze_per_epoch: | ||||||
|  |                         # First analysis not in parallel mode when using --analyze-per-epoch. | ||||||
|  |                         # This allows dataprovider to load it's informative cache. | ||||||
|  |                         asked, is_random = self.get_asked_points(n_points=1) | ||||||
|  |                         f_val0 = self.generate_optimizer(asked[0]) | ||||||
|  |                         self.opt.tell(asked, [f_val0['loss']]) | ||||||
|  |                         self.evaluate_result(f_val0, 1, is_random[0]) | ||||||
|  |                         pbar.update(1) | ||||||
|  |                         start += 1 | ||||||
|  |  | ||||||
|  |                     evals = ceil((self.total_epochs - start) / jobs) | ||||||
|  |                     for i in range(evals): | ||||||
|                         # Correct the number of epochs to be processed for the last |                         # Correct the number of epochs to be processed for the last | ||||||
|                         # iteration (should not exceed self.total_epochs in total) |                         # iteration (should not exceed self.total_epochs in total) | ||||||
|                         n_rest = (i + 1) * jobs - self.total_epochs |                         n_rest = (i + 1) * jobs - (self.total_epochs - start) | ||||||
|                         current_jobs = jobs - n_rest if n_rest > 0 else jobs |                         current_jobs = jobs - n_rest if n_rest > 0 else jobs | ||||||
|  |  | ||||||
|                         asked, is_random = self.get_asked_points(n_points=current_jobs) |                         asked, is_random = self.get_asked_points(n_points=current_jobs) | ||||||
| @@ -594,7 +606,7 @@ class Hyperopt: | |||||||
|                         # Calculate progressbar outputs |                         # Calculate progressbar outputs | ||||||
|                         for j, val in enumerate(f_val): |                         for j, val in enumerate(f_val): | ||||||
|                             # Use human-friendly indexes here (starting from 1) |                             # Use human-friendly indexes here (starting from 1) | ||||||
|                             current = i * jobs + j + 1 |                             current = i * jobs + j + 1 + start | ||||||
|  |  | ||||||
|                             self.evaluate_result(val, current, is_random[j]) |                             self.evaluate_result(val, current, is_random[j]) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -922,6 +922,45 @@ def test_in_strategy_auto_hyperopt_with_parallel(mocker, hyperopt_conf, tmpdir, | |||||||
|     hyperopt.start() |     hyperopt.start() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_in_strategy_auto_hyperopt_per_epoch(mocker, hyperopt_conf, tmpdir, fee) -> None: | ||||||
|  |     patch_exchange(mocker) | ||||||
|  |     mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) | ||||||
|  |     (Path(tmpdir) / 'hyperopt_results').mkdir(parents=True) | ||||||
|  |  | ||||||
|  |     hyperopt_conf.update({ | ||||||
|  |         'strategy': 'HyperoptableStrategy', | ||||||
|  |         'user_data_dir': Path(tmpdir), | ||||||
|  |         'hyperopt_random_state': 42, | ||||||
|  |         'spaces': ['all'], | ||||||
|  |         'epochs': 3, | ||||||
|  |         'analyze_per_epoch': True, | ||||||
|  |     }) | ||||||
|  |     go = mocker.patch('freqtrade.optimize.hyperopt.Hyperopt.generate_optimizer', | ||||||
|  |                       return_value={ | ||||||
|  |                             'loss': 0.05, | ||||||
|  |                             'results_explanation': 'foo result', 'params': {}, | ||||||
|  |                             'results_metrics': generate_result_metrics(), | ||||||
|  |                         }) | ||||||
|  |     hyperopt = Hyperopt(hyperopt_conf) | ||||||
|  |     hyperopt.backtesting.exchange.get_max_leverage = MagicMock(return_value=1.0) | ||||||
|  |     assert isinstance(hyperopt.custom_hyperopt, HyperOptAuto) | ||||||
|  |     assert isinstance(hyperopt.backtesting.strategy.buy_rsi, IntParameter) | ||||||
|  |     assert hyperopt.backtesting.strategy.bot_loop_started is True | ||||||
|  |  | ||||||
|  |     assert hyperopt.backtesting.strategy.buy_rsi.in_space is True | ||||||
|  |     assert hyperopt.backtesting.strategy.buy_rsi.value == 35 | ||||||
|  |     assert hyperopt.backtesting.strategy.sell_rsi.value == 74 | ||||||
|  |     assert hyperopt.backtesting.strategy.protection_cooldown_lookback.value == 30 | ||||||
|  |     buy_rsi_range = hyperopt.backtesting.strategy.buy_rsi.range | ||||||
|  |     assert isinstance(buy_rsi_range, range) | ||||||
|  |     # Range from 0 - 50 (inclusive) | ||||||
|  |     assert len(list(buy_rsi_range)) == 51 | ||||||
|  |  | ||||||
|  |     hyperopt.start() | ||||||
|  |     # backtesting should be called 3 times (once per epoch) | ||||||
|  |     assert go.call_count == 3 | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_SKDecimal(): | def test_SKDecimal(): | ||||||
|     space = SKDecimal(1, 2, decimals=2) |     space = SKDecimal(1, 2, decimals=2) | ||||||
|     assert 1.5 in space |     assert 1.5 in space | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user