From 5b9711c00259de9eb587f6ab864a1d9a71878410 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Wed, 14 Aug 2019 13:25:49 +0300 Subject: [PATCH 1/8] adaptive roi_space --- freqtrade/optimize/hyperopt.py | 3 +- freqtrade/optimize/hyperopt_interface.py | 115 +++++++++++++++++++---- freqtrade/resolvers/hyperopt_resolver.py | 2 +- 3 files changed, 99 insertions(+), 21 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 550f13e28..89e1accdd 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -23,7 +23,8 @@ from skopt.space import Dimension from freqtrade.configuration import Arguments from freqtrade.data.history import load_data, get_timeframe from freqtrade.optimize.backtesting import Backtesting -# Import IHyperOptLoss to allow users import from this file +# Import IHyperOpt and IHyperOptLoss to allow unpickling classes from these modules +from freqtrade.optimize.hyperopt_interface import IHyperOpt # noqa: F4 from freqtrade.optimize.hyperopt_loss_interface import IHyperOptLoss # noqa: F4 from freqtrade.resolvers.hyperopt_resolver import HyperOptResolver, HyperOptLossResolver diff --git a/freqtrade/optimize/hyperopt_interface.py b/freqtrade/optimize/hyperopt_interface.py index f1f123653..b81dc25e3 100644 --- a/freqtrade/optimize/hyperopt_interface.py +++ b/freqtrade/optimize/hyperopt_interface.py @@ -2,6 +2,8 @@ IHyperOpt interface This module defines the interface to apply for hyperopts """ +import logging +import math from abc import ABC, abstractmethod from typing import Dict, Any, Callable, List @@ -9,15 +11,18 @@ from typing import Dict, Any, Callable, List from pandas import DataFrame from skopt.space import Dimension, Integer, Real +from freqtrade.exchange import timeframe_to_minutes + + +logger = logging.getLogger(__name__) + class IHyperOpt(ABC): """ Interface for freqtrade hyperopts - Defines the mandatory structure must follow any custom strategies + Defines the mandatory structure must follow any custom hyperopts - Attributes you can use: - minimal_roi -> Dict: Minimal ROI designed for the strategy - stoploss -> float: optimal stoploss designed for the strategy + Class attributes you can use: ticker_interval -> int: value of the ticker interval to use for the strategy """ ticker_interval: str @@ -75,6 +80,83 @@ class IHyperOpt(ABC): return roi_table + @staticmethod + def roi_space() -> List[Dimension]: + """ + Create a ROI space. + + Defines values to search for each ROI steps. + + This method implements adaptive roi hyperspace with varied + ranges for parameters which automatically adapts to the + ticker interval used. + + It's used by Freqtrade by default, if no custom roi_space method is defined. + """ + + # Default scaling coefficients for the roi hyperspace. Can be changed + # to adjust resulting ranges of the ROI tables. + # Increase if you need wider ranges in the roi hyperspace, decrease if shorter + # ranges are needed. + roi_t_alpha = 1.0 + roi_p_alpha = 1.0 + + ticker_interval_mins = timeframe_to_minutes(IHyperOpt.ticker_interval) + + # We define here limits for the ROI space parameters automagically adapted to the + # ticker_interval used by the bot: + # + # * 'roi_t' (limits for the time intervals in the ROI tables) components + # are scaled linearly. + # * 'roi_p' (limits for the ROI value steps) components are scaled logarithmically. + # + # The scaling is designed so that it maps exactly to the legacy Freqtrade roi_space() + # method for the 5m ticker interval. + roi_t_scale = ticker_interval_mins / 5 + roi_p_scale = math.log1p(ticker_interval_mins) / math.log1p(5) + roi_limits = { + 'roi_t1_min': int(10 * roi_t_scale * roi_t_alpha), + 'roi_t1_max': int(120 * roi_t_scale * roi_t_alpha), + 'roi_t2_min': int(10 * roi_t_scale * roi_t_alpha), + 'roi_t2_max': int(60 * roi_t_scale * roi_t_alpha), + 'roi_t3_min': int(10 * roi_t_scale * roi_t_alpha), + 'roi_t3_max': int(40 * roi_t_scale * roi_t_alpha), + 'roi_p1_min': 0.01 * roi_p_scale * roi_p_alpha, + 'roi_p1_max': 0.04 * roi_p_scale * roi_p_alpha, + 'roi_p2_min': 0.01 * roi_p_scale * roi_p_alpha, + 'roi_p2_max': 0.07 * roi_p_scale * roi_p_alpha, + 'roi_p3_min': 0.01 * roi_p_scale * roi_p_alpha, + 'roi_p3_max': 0.20 * roi_p_scale * roi_p_alpha, + } + logger.debug(f"Using roi space limits: {roi_limits}") + p = { + 'roi_t1': roi_limits['roi_t1_min'], + 'roi_t2': roi_limits['roi_t2_min'], + 'roi_t3': roi_limits['roi_t3_min'], + 'roi_p1': roi_limits['roi_p1_min'], + 'roi_p2': roi_limits['roi_p2_min'], + 'roi_p3': roi_limits['roi_p3_min'], + } + logger.info(f"Min roi table: {IHyperOpt.generate_roi_table(p)}") + p = { + 'roi_t1': roi_limits['roi_t1_max'], + 'roi_t2': roi_limits['roi_t2_max'], + 'roi_t3': roi_limits['roi_t3_max'], + 'roi_p1': roi_limits['roi_p1_max'], + 'roi_p2': roi_limits['roi_p2_max'], + 'roi_p3': roi_limits['roi_p3_max'], + } + logger.info(f"Max roi table: {IHyperOpt.generate_roi_table(p)}") + + return [ + Integer(roi_limits['roi_t1_min'], roi_limits['roi_t1_max'], name='roi_t1'), + Integer(roi_limits['roi_t2_min'], roi_limits['roi_t2_max'], name='roi_t2'), + Integer(roi_limits['roi_t3_min'], roi_limits['roi_t3_max'], name='roi_t3'), + Real(roi_limits['roi_p1_min'], roi_limits['roi_p1_max'], name='roi_p1'), + Real(roi_limits['roi_p2_min'], roi_limits['roi_p2_max'], name='roi_p2'), + Real(roi_limits['roi_p3_min'], roi_limits['roi_p3_max'], name='roi_p3'), + ] + @staticmethod def stoploss_space() -> List[Dimension]: """ @@ -87,19 +169,14 @@ class IHyperOpt(ABC): Real(-0.5, -0.02, name='stoploss'), ] - @staticmethod - def roi_space() -> List[Dimension]: - """ - Create a ROI space. + # This is needed for proper unpickling the class attribute ticker_interval + # which is set to the actual value by the resolver. + # Why do I still need such shamanic mantras in modern python? + def __getstate__(self): + state = self.__dict__.copy() + state['ticker_interval'] = self.ticker_interval + return state - Defines values to search for each ROI steps. - You may override it in your custom Hyperopt class. - """ - return [ - Integer(10, 120, name='roi_t1'), - Integer(10, 60, name='roi_t2'), - Integer(10, 40, name='roi_t3'), - Real(0.01, 0.04, name='roi_p1'), - Real(0.01, 0.07, name='roi_p2'), - Real(0.01, 0.20, name='roi_p3'), - ] + def __setstate__(self, state): + self.__dict__.update(state) + IHyperOpt.ticker_interval = state['ticker_interval'] diff --git a/freqtrade/resolvers/hyperopt_resolver.py b/freqtrade/resolvers/hyperopt_resolver.py index 5027d7ddf..540e1ca55 100644 --- a/freqtrade/resolvers/hyperopt_resolver.py +++ b/freqtrade/resolvers/hyperopt_resolver.py @@ -34,7 +34,7 @@ class HyperOptResolver(IResolver): self.hyperopt = self._load_hyperopt(hyperopt_name, extra_dir=config.get('hyperopt_path')) # Assign ticker_interval to be used in hyperopt - self.hyperopt.__class__.ticker_interval = str(config['ticker_interval']) + IHyperOpt.ticker_interval = str(config['ticker_interval']) if not hasattr(self.hyperopt, 'populate_buy_trend'): logger.warning("Custom Hyperopt does not provide populate_buy_trend. " From a12876da92e1f2db9c29cbdb91c30250de897cf5 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Tue, 20 Aug 2019 22:17:21 +0300 Subject: [PATCH 2/8] fine printing for floats in the roi tables (round to 5 digits after the decimal point) --- freqtrade/misc.py | 7 +++++++ freqtrade/optimize/hyperopt.py | 4 +++- freqtrade/optimize/hyperopt_interface.py | 7 ++++--- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/freqtrade/misc.py b/freqtrade/misc.py index 05946e008..ed9f5c1e9 100644 --- a/freqtrade/misc.py +++ b/freqtrade/misc.py @@ -113,3 +113,10 @@ def deep_merge_dicts(source, destination): destination[key] = value return destination + + +def round_dict(d, n): + """ + Rounds float values in the dict to n digits after the decimal point. + """ + return {k: (round(v, n) if isinstance(v, float) else v) for k, v in d.items()} diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 89e1accdd..d20134e0d 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -22,6 +22,7 @@ from skopt.space import Dimension from freqtrade.configuration import Arguments from freqtrade.data.history import load_data, get_timeframe +from freqtrade.misc import round_dict from freqtrade.optimize.backtesting import Backtesting # Import IHyperOpt and IHyperOptLoss to allow unpickling classes from these modules from freqtrade.optimize.hyperopt_interface import IHyperOpt # noqa: F4 @@ -147,7 +148,8 @@ class Hyperopt(Backtesting): indent=4) if self.has_space('roi'): print("ROI table:") - pprint(self.custom_hyperopt.generate_roi_table(params), indent=4) + # Round printed values to 5 digits after the decimal point + pprint(round_dict(self.custom_hyperopt.generate_roi_table(params), 5), indent=4) if self.has_space('stoploss'): print(f"Stoploss: {params.get('stoploss')}") diff --git a/freqtrade/optimize/hyperopt_interface.py b/freqtrade/optimize/hyperopt_interface.py index b81dc25e3..4202e5325 100644 --- a/freqtrade/optimize/hyperopt_interface.py +++ b/freqtrade/optimize/hyperopt_interface.py @@ -12,6 +12,7 @@ from pandas import DataFrame from skopt.space import Dimension, Integer, Real from freqtrade.exchange import timeframe_to_minutes +from freqtrade.misc import round_dict logger = logging.getLogger(__name__) @@ -128,7 +129,7 @@ class IHyperOpt(ABC): 'roi_p3_min': 0.01 * roi_p_scale * roi_p_alpha, 'roi_p3_max': 0.20 * roi_p_scale * roi_p_alpha, } - logger.debug(f"Using roi space limits: {roi_limits}") + logger.debug(f"Using roi space limits: {round_dict(roi_limits, 5)}") p = { 'roi_t1': roi_limits['roi_t1_min'], 'roi_t2': roi_limits['roi_t2_min'], @@ -137,7 +138,7 @@ class IHyperOpt(ABC): 'roi_p2': roi_limits['roi_p2_min'], 'roi_p3': roi_limits['roi_p3_min'], } - logger.info(f"Min roi table: {IHyperOpt.generate_roi_table(p)}") + logger.info(f"Min roi table: {round_dict(IHyperOpt.generate_roi_table(p), 5)}") p = { 'roi_t1': roi_limits['roi_t1_max'], 'roi_t2': roi_limits['roi_t2_max'], @@ -146,7 +147,7 @@ class IHyperOpt(ABC): 'roi_p2': roi_limits['roi_p2_max'], 'roi_p3': roi_limits['roi_p3_max'], } - logger.info(f"Max roi table: {IHyperOpt.generate_roi_table(p)}") + logger.info(f"Max roi table: {round_dict(IHyperOpt.generate_roi_table(p), 5)}") return [ Integer(roi_limits['roi_t1_min'], roi_limits['roi_t1_max'], name='roi_t1'), From cadf573170c8f4a9a541a500d9a70404d1eff6ec Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Tue, 20 Aug 2019 22:24:59 +0300 Subject: [PATCH 3/8] round printed stoploss value as well --- freqtrade/optimize/hyperopt.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index d20134e0d..eaa3a7e1d 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -151,7 +151,8 @@ class Hyperopt(Backtesting): # Round printed values to 5 digits after the decimal point pprint(round_dict(self.custom_hyperopt.generate_roi_table(params), 5), indent=4) if self.has_space('stoploss'): - print(f"Stoploss: {params.get('stoploss')}") + # Also round to 5 digits after the decimal point + print(f"Stoploss: {round(params.get('stoploss'), 5)}") def log_results(self, results) -> None: """ From 31669fde03f86f197d1d8d804aa1a7b84dfcd2e9 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Tue, 20 Aug 2019 23:28:16 +0300 Subject: [PATCH 4/8] test adjusted --- freqtrade/tests/optimize/test_hyperopt.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index 1c4e2445c..72c2741fd 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -417,7 +417,8 @@ def test_start_calls_optimizer(mocker, default_conf, caplog, capsys) -> None: parallel = mocker.patch( 'freqtrade.optimize.hyperopt.Hyperopt.run_optimizer_parallel', - MagicMock(return_value=[{'loss': 1, 'results_explanation': 'foo result', 'params': {}}]) + MagicMock(return_value=[{'loss': 1, 'results_explanation': 'foo result', + 'params': {'buy': {}, 'sell': {}, 'roi': {}, 'stoploss': 0.0}}]) ) patch_exchange(mocker) From fcb0ff1b60fa196e6244d68a8c3470d0fdd546e0 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Tue, 20 Aug 2019 23:42:44 +0300 Subject: [PATCH 5/8] do not round values in the debug message --- freqtrade/optimize/hyperopt_interface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/optimize/hyperopt_interface.py b/freqtrade/optimize/hyperopt_interface.py index 4202e5325..2b86e018e 100644 --- a/freqtrade/optimize/hyperopt_interface.py +++ b/freqtrade/optimize/hyperopt_interface.py @@ -129,7 +129,7 @@ class IHyperOpt(ABC): 'roi_p3_min': 0.01 * roi_p_scale * roi_p_alpha, 'roi_p3_max': 0.20 * roi_p_scale * roi_p_alpha, } - logger.debug(f"Using roi space limits: {round_dict(roi_limits, 5)}") + logger.debug(f"Using roi space limits: {roi_limits}") p = { 'roi_t1': roi_limits['roi_t1_min'], 'roi_t2': roi_limits['roi_t2_min'], From 87ae2430df83e8497cfe0b6f7bd81b337208c053 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Tue, 3 Sep 2019 11:32:18 +0300 Subject: [PATCH 6/8] ranges for ROI tables for different ticker_intervals in docs --- docs/hyperopt.md | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/docs/hyperopt.md b/docs/hyperopt.md index c1bf56a3d..fa3f3584d 100644 --- a/docs/hyperopt.md +++ b/docs/hyperopt.md @@ -389,16 +389,20 @@ minimal_roi = { } ``` -If you are optimizing ROI, Freqtrade creates the 'roi' optimization hyperspace for you -- it's the hyperspace of components for the ROI tables. By default, each ROI table generated by the Freqtrade consists of 4 rows (steps) with the values that can vary in the following ranges: +If you are optimizing ROI, Freqtrade creates the 'roi' optimization hyperspace for you -- it's the hyperspace of components for the ROI tables. By default, each ROI table generated by the Freqtrade consists of 4 rows (steps). Hyperopt implements adaptive ranges for ROI tables with ranges for values in the ROI steps that depend on the ticker_interval used. By default the values can vary in the following ranges: -| # | minutes | ROI percentage | -|---|---|---| -| 1 | always 0 | 0.03...0.31 | -| 2 | 10...40 | 0.02...0.11 | -| 3 | 20...100 | 0.01...0.04 | -| 4 | 30...220 | always 0 | +5m ticker_interval: -This structure of the ROI table is sufficient in most cases. Override the `roi_space()` method defining the ranges desired if you need components of the ROI tables to vary in other ranges. +| # | minutes / ROI percentage | +||---|---|---|---| +|| 1m | 5m | 1h | 1d | +|---|---|---|---|---| +| 1 | always 0 / 0.01161...0.11992 | always 0 / 0.03...0.31 | always 0 / 0.06883...0.71124 | always 0 / 0.12178...1.25835 | +| 2 | 2...8 / 0.00774...0.04255 | 10...40 / 0.02...0.11 | 120...480 / 0.04589...0.25238 | 2880...11520 / 0.08118...0.44651 | +| 3 | 4...20 / 0.00387...0.01547 | 20...100 / 0.01...0.04 | 240...1200 / 0.02294...0.09177 | 5760...28800 / 0.04059...0.16237 | +| 4 | 6...44 / always 0.0 | 30...220 / always 0.0 | 360...2640 / always 0.0 | 8640...63360 / always 0.0 | + +These ranges should be sufficient in most cases. Override the `roi_space()` method defining the ranges desired if you need components of the ROI tables to vary in other ranges. Override the `generate_roi_table()` and `roi_space()` methods and implement your own custom approach for generation of the ROI tables during hyperoptimization in these methods if you need a different structure of the ROI table or other amount of rows (steps) in the ROI tables. From e8614abc5d0fc7278ac0229a8802e9da1c321804 Mon Sep 17 00:00:00 2001 From: hroff-1902 <47309513+hroff-1902@users.noreply.github.com> Date: Tue, 3 Sep 2019 16:52:55 +0300 Subject: [PATCH 7/8] update table md formatting, enhance description --- docs/hyperopt.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/hyperopt.md b/docs/hyperopt.md index fa3f3584d..c7544df5b 100644 --- a/docs/hyperopt.md +++ b/docs/hyperopt.md @@ -389,22 +389,20 @@ minimal_roi = { } ``` -If you are optimizing ROI, Freqtrade creates the 'roi' optimization hyperspace for you -- it's the hyperspace of components for the ROI tables. By default, each ROI table generated by the Freqtrade consists of 4 rows (steps). Hyperopt implements adaptive ranges for ROI tables with ranges for values in the ROI steps that depend on the ticker_interval used. By default the values can vary in the following ranges: +If you are optimizing ROI, Freqtrade creates the 'roi' optimization hyperspace for you -- it's the hyperspace of components for the ROI tables. By default, each ROI table generated by the Freqtrade consists of 4 rows (steps). Hyperopt implements adaptive ranges for ROI tables with ranges for values in the ROI steps that depend on the ticker_interval used. By default the values can vary in the following ranges (for some of the most used ticker intervals, values are rounded to 5 digits after the decimal point): -5m ticker_interval: +| # step 1m 5m 1h 1d | +|---|---|---|---|---|---|---|---|---| +| 1 | 0 | 0.01161...0.11992 | 0 | 0.03...0.31 | 0 | 0.06883...0.71124 | 0 | 0.12178...1.25835 | +| 2 | 2...8 | 0.00774...0.04255 | 10...40 | 0.02...0.11 | 120...480 | 0.04589...0.25238 | 2880...11520 | 0.08118...0.44651 | +| 3 | 4...20 | 0.00387...0.01547 | 20...100 | 0.01...0.04 | 240...1200 | 0.02294...0.09177 | 5760...28800 | 0.04059...0.16237 | +| 4 | 6...44 | 0.0 | 30...220 | 0.0 | 360...2640 | 0.0 | 8640...63360 | 0.0 | -| # | minutes / ROI percentage | -||---|---|---|---| -|| 1m | 5m | 1h | 1d | -|---|---|---|---|---| -| 1 | always 0 / 0.01161...0.11992 | always 0 / 0.03...0.31 | always 0 / 0.06883...0.71124 | always 0 / 0.12178...1.25835 | -| 2 | 2...8 / 0.00774...0.04255 | 10...40 / 0.02...0.11 | 120...480 / 0.04589...0.25238 | 2880...11520 / 0.08118...0.44651 | -| 3 | 4...20 / 0.00387...0.01547 | 20...100 / 0.01...0.04 | 240...1200 / 0.02294...0.09177 | 5760...28800 / 0.04059...0.16237 | -| 4 | 6...44 / always 0.0 | 30...220 / always 0.0 | 360...2640 / always 0.0 | 8640...63360 / always 0.0 | +These ranges should be sufficient in most cases. The minutes in the steps (ROI dict keys) are scaled linearly depending on the ticker interval used. The ROI values in the steps (ROI dict values) are scaled logarithmically depending on the ticker interval used. -These ranges should be sufficient in most cases. Override the `roi_space()` method defining the ranges desired if you need components of the ROI tables to vary in other ranges. +If you use legacy freqtrade HyperOpts class samples where the `generate_roi_table()` and `roi_space()` methods were copied in each custom hyperopt file, simply remove them in order to utilize these adaptive ROI tables and the ROI hyperoptimization space generated by freqtrade by default. -Override the `generate_roi_table()` and `roi_space()` methods and implement your own custom approach for generation of the ROI tables during hyperoptimization in these methods if you need a different structure of the ROI table or other amount of rows (steps) in the ROI tables. +Override the `roi_space()` method if you need components of the ROI tables to vary in other ranges. Override the `generate_roi_table()` and `roi_space()` methods and implement your own custom approach for generation of the ROI tables during hyperoptimization if you need a different structure of the ROI tables or other amount of rows (steps). ### Understand Hyperopt Stoploss results @@ -426,6 +424,8 @@ Stoploss: -0.37996664668703606 If you are optimizing stoploss values, Freqtrade creates the 'stoploss' optimization hyperspace for you. By default, the stoploss values in that hyperspace can vary in the range -0.5...-0.02, which is sufficient in most cases. +If you use legacy freqtrade HyperOpts class samples where `stoploss_space()` method was copied in each custom hyperopt file, simply remove it in order to utilize Stoploss hyperoptimization space generated by freqtrade by default. + Override the `stoploss_space()` method and define the desired range in it if you need stoploss values to vary in other range during hyperoptimization. ### Validate backtesting results From e39d9111770a9bd7b73aa1addc5b7d14649c7d1a Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Thu, 5 Sep 2019 23:31:07 +0300 Subject: [PATCH 8/8] Improve wordings in hyperopt.md --- docs/hyperopt.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/hyperopt.md b/docs/hyperopt.md index c7544df5b..95bec8715 100644 --- a/docs/hyperopt.md +++ b/docs/hyperopt.md @@ -400,9 +400,9 @@ If you are optimizing ROI, Freqtrade creates the 'roi' optimization hyperspace f These ranges should be sufficient in most cases. The minutes in the steps (ROI dict keys) are scaled linearly depending on the ticker interval used. The ROI values in the steps (ROI dict values) are scaled logarithmically depending on the ticker interval used. -If you use legacy freqtrade HyperOpts class samples where the `generate_roi_table()` and `roi_space()` methods were copied in each custom hyperopt file, simply remove them in order to utilize these adaptive ROI tables and the ROI hyperoptimization space generated by freqtrade by default. +If you have the `generate_roi_table()` and `roi_space()` methods in your custom hyperopt file, remove them in order to utilize these adaptive ROI tables and the ROI hyperoptimization space generated by Freqtrade by default. -Override the `roi_space()` method if you need components of the ROI tables to vary in other ranges. Override the `generate_roi_table()` and `roi_space()` methods and implement your own custom approach for generation of the ROI tables during hyperoptimization if you need a different structure of the ROI tables or other amount of rows (steps). +Override the `roi_space()` method if you need components of the ROI tables to vary in other ranges. Override the `generate_roi_table()` and `roi_space()` methods and implement your own custom approach for generation of the ROI tables during hyperoptimization if you need a different structure of the ROI tables or other amount of rows (steps). A sample for these methods can be found in [user_data/hyperopts/sample_hyperopt_advanced.py](https://github.com/freqtrade/freqtrade/blob/develop/user_data/hyperopts/sample_hyperopt_advanced.py). ### Understand Hyperopt Stoploss results @@ -424,9 +424,9 @@ Stoploss: -0.37996664668703606 If you are optimizing stoploss values, Freqtrade creates the 'stoploss' optimization hyperspace for you. By default, the stoploss values in that hyperspace can vary in the range -0.5...-0.02, which is sufficient in most cases. -If you use legacy freqtrade HyperOpts class samples where `stoploss_space()` method was copied in each custom hyperopt file, simply remove it in order to utilize Stoploss hyperoptimization space generated by freqtrade by default. +If you have the `stoploss_space()` method in your custom hyperopt file, remove it in order to utilize Stoploss hyperoptimization space generated by Freqtrade by default. -Override the `stoploss_space()` method and define the desired range in it if you need stoploss values to vary in other range during hyperoptimization. +Override the `stoploss_space()` method and define the desired range in it if you need stoploss values to vary in other range during hyperoptimization. A sample for this method can be found in [user_data/hyperopts/sample_hyperopt_advanced.py](https://github.com/freqtrade/freqtrade/blob/develop/user_data/hyperopts/sample_hyperopt_advanced.py). ### Validate backtesting results