From 378b214a565c425e42309c9e94e0f08c008666db Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 5 Oct 2020 19:27:28 +0200 Subject: [PATCH 1/5] Remove hyperopt-loss default option Force users to make a concious choice on a hyperopt-loss function --- .github/workflows/ci.yml | 2 +- .travis.yml | 2 +- docs/advanced-hyperopt.md | 4 ++-- docs/bot-usage.md | 3 +-- docs/faq.md | 2 +- docs/hyperopt.md | 12 +++++------- freqtrade/commands/cli_options.py | 4 +--- freqtrade/constants.py | 1 - freqtrade/resolvers/hyperopt_resolver.py | 10 +++++----- 9 files changed, 17 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e6c6521eb..fa599f361 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,7 +88,7 @@ jobs: run: | cp config.json.example config.json freqtrade create-userdir --userdir user_data - freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt SampleHyperOpt --print-all + freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt SampleHyperOpt --hyperopt-loss SharpeHyperOptLossDaily --print-all - name: Flake8 run: | diff --git a/.travis.yml b/.travis.yml index 0cb76b78b..9b8448db5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,7 @@ jobs: - script: - cp config.json.example config.json - freqtrade create-userdir --userdir user_data - - freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt SampleHyperOpt + - freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt SampleHyperOpt --hyperopt-loss SharpeHyperOptLossDaily name: hyperopt - script: flake8 name: flake8 diff --git a/docs/advanced-hyperopt.md b/docs/advanced-hyperopt.md index dfabf2b91..59ebc16b5 100644 --- a/docs/advanced-hyperopt.md +++ b/docs/advanced-hyperopt.md @@ -27,9 +27,9 @@ class MyAwesomeHyperOpt2(MyAwesomeHyperOpt): and then quickly switch between hyperopt classes, running optimization process with hyperopt class you need in each particular case: ``` -$ freqtrade hyperopt --hyperopt MyAwesomeHyperOpt --strategy MyAwesomeStrategy ... +$ freqtrade hyperopt --hyperopt MyAwesomeHyperOpt --hyperopt-loss SharpeHyperOptLossDaily --strategy MyAwesomeStrategy ... or -$ freqtrade hyperopt --hyperopt MyAwesomeHyperOpt2 --strategy MyAwesomeStrategy ... +$ freqtrade hyperopt --hyperopt MyAwesomeHyperOpt2 --hyperopt-loss SharpeHyperOptLossDaily --strategy MyAwesomeStrategy ... ``` ## Creating and using a custom loss function diff --git a/docs/bot-usage.md b/docs/bot-usage.md index 62c515b44..a07a34b94 100644 --- a/docs/bot-usage.md +++ b/docs/bot-usage.md @@ -356,8 +356,7 @@ optional arguments: Hyperopt-loss-functions are: DefaultHyperOptLoss, OnlyProfitHyperOptLoss, SharpeHyperOptLoss, SharpeHyperOptLossDaily, SortinoHyperOptLoss, - SortinoHyperOptLossDaily.(default: - `DefaultHyperOptLoss`). + SortinoHyperOptLossDaily. Common arguments: -v, --verbose Verbose mode (-vv for more, -vvv to get all messages). diff --git a/docs/faq.md b/docs/faq.md index d8af7798c..a775060de 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -140,7 +140,7 @@ Since hyperopt uses Bayesian search, running for too many epochs may not produce It's therefore recommended to run between 500-1000 epochs over and over until you hit at least 10.000 epochs in total (or are satisfied with the result). You can best judge by looking at the results - if the bot keeps discovering better strategies, it's best to keep on going. ```bash -freqtrade hyperopt --hyperop SampleHyperopt --strategy SampleStrategy -e 1000 +freqtrade hyperopt --hyperop SampleHyperopt --hyperopt-loss SharpeHyperOptLossDaily --strategy SampleStrategy -e 1000 ``` ### Why does it take a long time to run hyperopt? diff --git a/docs/hyperopt.md b/docs/hyperopt.md index d26cbeeb2..ff1c4a3d7 100644 --- a/docs/hyperopt.md +++ b/docs/hyperopt.md @@ -80,7 +80,7 @@ Rarely you may also need to override: # Have a working strategy at hand. freqtrade new-hyperopt --hyperopt EmptyHyperopt - freqtrade hyperopt --hyperopt EmptyHyperopt --spaces roi stoploss trailing --strategy MyWorkingStrategy --config config.json -e 100 + freqtrade hyperopt --hyperopt EmptyHyperopt --hyperopt-loss SharpeHyperOptLossDaily --spaces roi stoploss trailing --strategy MyWorkingStrategy --config config.json -e 100 ``` ### 1. Install a Custom Hyperopt File @@ -205,14 +205,12 @@ add it to the `populate_indicators()` method in your custom hyperopt file. Each hyperparameter tuning requires a target. This is usually defined as a loss function (sometimes also called objective function), which should decrease for more desirable results, and increase for bad results. -By default, Freqtrade uses a loss function, which has been with freqtrade since the beginning and optimizes mostly for short trade duration and avoiding losses. - -A different loss function can be specified by using the `--hyperopt-loss ` argument. +A loss function must be specified via the `--hyperopt-loss ` argument (or optionally via the configuration under the `"hyperopt_loss"` key). This class should be in its own file within the `user_data/hyperopts/` directory. Currently, the following loss functions are builtin: -* `DefaultHyperOptLoss` (default legacy Freqtrade hyperoptimization loss function) +* `DefaultHyperOptLoss` (default legacy Freqtrade hyperoptimization loss function) - Mostly for short trade duration and avoiding losses. * `OnlyProfitHyperOptLoss` (which takes only amount of profit into consideration) * `SharpeHyperOptLoss` (optimizes Sharpe Ratio calculated on trade returns relative to standard deviation) * `SharpeHyperOptLossDaily` (optimizes Sharpe Ratio calculated on **daily** trade returns relative to standard deviation) @@ -229,7 +227,7 @@ Because hyperopt tries a lot of combinations to find the best parameters it will We strongly recommend to use `screen` or `tmux` to prevent any connection loss. ```bash -freqtrade hyperopt --config config.json --hyperopt --strategy -e 500 --spaces all +freqtrade hyperopt --config config.json --hyperopt --hyperopt-loss --strategy -e 500 --spaces all ``` Use `` as the name of the custom hyperopt used. @@ -263,7 +261,7 @@ freqtrade hyperopt --hyperopt --strategy --timeran Hyperopt can reuse `populate_indicators`, `populate_buy_trend`, `populate_sell_trend` from your strategy, assuming these methods are **not** in your custom hyperopt file, and a strategy is provided. ```bash -freqtrade hyperopt --strategy SampleStrategy --hyperopt SampleHyperopt +freqtrade hyperopt --hyperopt SampleHyperopt --hyperopt-loss SharpeHyperOptLossDaily --strategy SampleStrategy ``` ### Running Hyperopt with Smaller Search Space diff --git a/freqtrade/commands/cli_options.py b/freqtrade/commands/cli_options.py index 3c5775768..f991f6a4d 100644 --- a/freqtrade/commands/cli_options.py +++ b/freqtrade/commands/cli_options.py @@ -258,10 +258,8 @@ AVAILABLE_CLI_OPTIONS = { 'Different functions can generate completely different results, ' 'since the target for optimization is different. Built-in Hyperopt-loss-functions are: ' 'DefaultHyperOptLoss, OnlyProfitHyperOptLoss, SharpeHyperOptLoss, SharpeHyperOptLossDaily, ' - 'SortinoHyperOptLoss, SortinoHyperOptLossDaily.' - '(default: `%(default)s`).', + 'SortinoHyperOptLoss, SortinoHyperOptLossDaily.', metavar='NAME', - default=constants.DEFAULT_HYPEROPT_LOSS, ), "hyperoptexportfilename": Arg( '--hyperopt-filename', diff --git a/freqtrade/constants.py b/freqtrade/constants.py index de663bd4b..8e92d3ed8 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -11,7 +11,6 @@ DEFAULT_EXCHANGE = 'bittrex' PROCESS_THROTTLE_SECS = 5 # sec HYPEROPT_EPOCH = 100 # epochs RETRY_TIMEOUT = 30 # sec -DEFAULT_HYPEROPT_LOSS = 'DefaultHyperOptLoss' DEFAULT_DB_PROD_URL = 'sqlite:///tradesv3.sqlite' DEFAULT_DB_DRYRUN_URL = 'sqlite:///tradesv3.dryrun.sqlite' UNLIMITED_STAKE_AMOUNT = 'unlimited' diff --git a/freqtrade/resolvers/hyperopt_resolver.py b/freqtrade/resolvers/hyperopt_resolver.py index 5e73498ae..2fd7abb93 100644 --- a/freqtrade/resolvers/hyperopt_resolver.py +++ b/freqtrade/resolvers/hyperopt_resolver.py @@ -7,7 +7,7 @@ import logging from pathlib import Path from typing import Dict -from freqtrade.constants import DEFAULT_HYPEROPT_LOSS, USERPATH_HYPEROPTS +from freqtrade.constants import USERPATH_HYPEROPTS from freqtrade.exceptions import OperationalException from freqtrade.optimize.hyperopt_interface import IHyperOpt from freqtrade.optimize.hyperopt_loss_interface import IHyperOptLoss @@ -70,10 +70,10 @@ class HyperOptLossResolver(IResolver): :param config: configuration dictionary """ - # Verify the hyperopt_loss is in the configuration, otherwise fallback to the - # default hyperopt loss - hyperoptloss_name = config.get('hyperopt_loss') or DEFAULT_HYPEROPT_LOSS - + hyperoptloss_name = config.get('hyperopt_loss') + if not hyperoptloss_name: + raise OperationalException("No Hyperopt loss set. Please use `--hyperopt-loss` to " + "specify the Hyperopt-Loss class to use.") hyperoptloss = HyperOptLossResolver.load_object(hyperoptloss_name, config, kwargs={}, extra_dir=config.get('hyperopt_path')) From fa1d1679f0310c5ee2cd7942a45a57f873ab0149 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 5 Oct 2020 19:33:50 +0200 Subject: [PATCH 2/5] Adapt tests to work without default hyperoptloss --- tests/optimize/test_hyperopt.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tests/optimize/test_hyperopt.py b/tests/optimize/test_hyperopt.py index 6c49f090c..636c24c97 100644 --- a/tests/optimize/test_hyperopt.py +++ b/tests/optimize/test_hyperopt.py @@ -33,6 +33,7 @@ def hyperopt_conf(default_conf): hyperconf = deepcopy(default_conf) hyperconf.update({ 'hyperopt': 'DefaultHyperOpt', + 'hyperopt_loss': 'DefaultHyperOptLoss', 'hyperopt_path': str(Path(__file__).parent / 'hyperopts'), 'epochs': 1, 'timerange': None, @@ -236,6 +237,7 @@ def test_hyperoptlossresolver(mocker, default_conf) -> None: 'freqtrade.resolvers.hyperopt_resolver.HyperOptLossResolver.load_object', MagicMock(return_value=hl) ) + default_conf.update({'hyperopt_loss': 'DefaultHyperoptLoss'}) x = HyperOptLossResolver.load_hyperoptloss(default_conf) assert hasattr(x, "hyperopt_loss_function") @@ -278,6 +280,7 @@ def test_start(mocker, hyperopt_conf, caplog) -> None: 'hyperopt', '--config', 'config.json', '--hyperopt', 'DefaultHyperOpt', + '--hyperopt-loss', 'DefaultHyperOptLoss', '--epochs', '5' ] pargs = get_args(args) @@ -301,6 +304,7 @@ def test_start_no_data(mocker, hyperopt_conf) -> None: 'hyperopt', '--config', 'config.json', '--hyperopt', 'DefaultHyperOpt', + '--hyperopt-loss', 'DefaultHyperOptLoss', '--epochs', '5' ] pargs = get_args(args) @@ -318,6 +322,7 @@ def test_start_filelock(mocker, hyperopt_conf, caplog) -> None: 'hyperopt', '--config', 'config.json', '--hyperopt', 'DefaultHyperOpt', + '--hyperopt-loss', 'DefaultHyperOptLoss', '--epochs', '5' ] pargs = get_args(args) @@ -325,8 +330,8 @@ def test_start_filelock(mocker, hyperopt_conf, caplog) -> None: assert log_has("Another running instance of freqtrade Hyperopt detected.", caplog) -def test_loss_calculation_prefer_correct_trade_count(default_conf, hyperopt_results) -> None: - hl = HyperOptLossResolver.load_hyperoptloss(default_conf) +def test_loss_calculation_prefer_correct_trade_count(hyperopt_conf, hyperopt_results) -> None: + hl = HyperOptLossResolver.load_hyperoptloss(hyperopt_conf) correct = hl.hyperopt_loss_function(hyperopt_results, 600, datetime(2019, 1, 1), datetime(2019, 5, 1)) over = hl.hyperopt_loss_function(hyperopt_results, 600 + 100, @@ -337,11 +342,11 @@ def test_loss_calculation_prefer_correct_trade_count(default_conf, hyperopt_resu assert under > correct -def test_loss_calculation_prefer_shorter_trades(default_conf, hyperopt_results) -> None: +def test_loss_calculation_prefer_shorter_trades(hyperopt_conf, hyperopt_results) -> None: resultsb = hyperopt_results.copy() resultsb.loc[1, 'trade_duration'] = 20 - hl = HyperOptLossResolver.load_hyperoptloss(default_conf) + hl = HyperOptLossResolver.load_hyperoptloss(hyperopt_conf) longer = hl.hyperopt_loss_function(hyperopt_results, 100, datetime(2019, 1, 1), datetime(2019, 5, 1)) shorter = hl.hyperopt_loss_function(resultsb, 100, @@ -349,13 +354,13 @@ def test_loss_calculation_prefer_shorter_trades(default_conf, hyperopt_results) assert shorter < longer -def test_loss_calculation_has_limited_profit(default_conf, hyperopt_results) -> None: +def test_loss_calculation_has_limited_profit(hyperopt_conf, hyperopt_results) -> None: results_over = hyperopt_results.copy() results_over['profit_percent'] = hyperopt_results['profit_percent'] * 2 results_under = hyperopt_results.copy() results_under['profit_percent'] = hyperopt_results['profit_percent'] / 2 - hl = HyperOptLossResolver.load_hyperoptloss(default_conf) + hl = HyperOptLossResolver.load_hyperoptloss(hyperopt_conf) correct = hl.hyperopt_loss_function(hyperopt_results, 600, datetime(2019, 1, 1), datetime(2019, 5, 1)) over = hl.hyperopt_loss_function(results_over, 600, From a4a8abfdc058542b8a2b85db3625318bc842cd1e Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 5 Oct 2020 20:06:34 +0200 Subject: [PATCH 3/5] Update hyperopt documentation --- docs/hyperopt.md | 80 +++++++++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 32 deletions(-) diff --git a/docs/hyperopt.md b/docs/hyperopt.md index ff1c4a3d7..87302a675 100644 --- a/docs/hyperopt.md +++ b/docs/hyperopt.md @@ -37,12 +37,20 @@ pip install -r requirements-hyperopt.txt Before we start digging into Hyperopt, we recommend you to take a look at the sample hyperopt file located in [user_data/hyperopts/](https://github.com/freqtrade/freqtrade/blob/develop/freqtrade/templates/sample_hyperopt.py). -Configuring hyperopt is similar to writing your own strategy, and many tasks will be similar and a lot of code can be copied across from the strategy. +Configuring hyperopt is similar to writing your own strategy, and many tasks will be similar. -The simplest way to get started is to use `freqtrade new-hyperopt --hyperopt AwesomeHyperopt`. -This will create a new hyperopt file from a template, which will be located under `user_data/hyperopts/AwesomeHyperopt.py`. +!!! Tip "About this page" + For this page, we will be using a fictional strategy called `AwesomeStrategy` - which will be optimized using the `AwesomeHyperopt` class. -### Checklist on all tasks / possibilities in hyperopt +The simplest way to get started is to use the following, command, which will create a new hyperopt file from a template, which will be located under `user_data/hyperopts/AwesomeHyperopt.py`. + +``` bash +freqtrade new-hyperopt --hyperopt AwesomeHyperopt +``` + +### Hyperopt checklist + +Checklist on all tasks / possibilities in hyperopt Depending on the space you want to optimize, only some of the below are required: @@ -54,17 +62,15 @@ Depending on the space you want to optimize, only some of the below are required !!! Note `populate_indicators` needs to create all indicators any of thee spaces may use, otherwise hyperopt will not work. -Optional - can also be loaded from a strategy: +Optional in hyperopt - can also be loaded from a strategy (recommended): * copy `populate_indicators` from your strategy - otherwise default-strategy will be used * copy `populate_buy_trend` from your strategy - otherwise default-strategy will be used * copy `populate_sell_trend` from your strategy - otherwise default-strategy will be used -!!! Note - Assuming the optional methods are not in your hyperopt file, please use `--strategy AweSomeStrategy` which contains these methods so hyperopt can use these methods instead. - !!! Note You always have to provide a strategy to Hyperopt, even if your custom Hyperopt class contains all methods. + Assuming the optional methods are not in your hyperopt file, please use `--strategy AweSomeStrategy` which contains these methods so hyperopt can use these methods instead. Rarely you may also need to override: @@ -83,14 +89,17 @@ Rarely you may also need to override: freqtrade hyperopt --hyperopt EmptyHyperopt --hyperopt-loss SharpeHyperOptLossDaily --spaces roi stoploss trailing --strategy MyWorkingStrategy --config config.json -e 100 ``` -### 1. Install a Custom Hyperopt File +### Create a Custom Hyperopt File -Put your hyperopt file into the directory `user_data/hyperopts`. +Let assume you want a hyperopt file `AwesomeHyperopt.py`: -Let assume you want a hyperopt file `awesome_hyperopt.py`: -Copy the file `user_data/hyperopts/sample_hyperopt.py` into `user_data/hyperopts/awesome_hyperopt.py` +``` bash +freqtrade new-hyperopt --hyperopt AwesomeHyperopt +``` -### 2. Configure your Guards and Triggers +This command will create a new hyperopt file from a template, allowing you to get started quickly. + +### Configure your Guards and Triggers There are two places you need to change in your hyperopt file to add a new buy hyperopt for testing: @@ -102,14 +111,16 @@ There you have two different types of indicators: 1. `guards` and 2. `triggers`. 1. Guards are conditions like "never buy if ADX < 10", or never buy if current price is over EMA10. 2. Triggers are ones that actually trigger buy in specific moment, like "buy when EMA5 crosses over EMA10" or "buy when close price touches lower Bollinger band". +!!! Hint "Guards and Triggers" + Technically, there is no difference between Guards and Triggers. + However, this guide will make this distinction to make it clear that signals should not be "sticking". + Sticking signals are signals that are active for multiple candles. This can lead into buying a signal late (right before the signal disappears - which means that the chance of success is a lot lower than right at the beginning). + Hyper-optimization will, for each epoch round, pick one trigger and possibly -multiple guards. The constructed strategy will be something like -"*buy exactly when close price touches lower Bollinger band, BUT only if +multiple guards. The constructed strategy will be something like "*buy exactly when close price touches lower Bollinger band, BUT only if ADX > 10*". -If you have updated the buy strategy, i.e. changed the contents of -`populate_buy_trend()` method, you have to update the `guards` and -`triggers` your hyperopt must use correspondingly. +If you have updated the buy strategy, i.e. changed the contents of `populate_buy_trend()` method, you have to update the `guards` and `triggers` your hyperopt must use correspondingly. #### Sell optimization @@ -154,7 +165,7 @@ We will start by defining a search space: Above definition says: I have five parameters I want you to randomly combine to find the best combination. Two of them are integer values (`adx-value` -and `rsi-value`) and I want you test in the range of values 20 to 40. +and `rsi-value`) and I want you test in the range of values 20 to 40. Then we have three category variables. First two are either `True` or `False`. We use these to either enable or disable the ADX and RSI guards. The last one we call `trigger` and use it to decide which buy trigger we want to use. @@ -192,14 +203,14 @@ So let's write the buy strategy using these values: return populate_buy_trend ``` -Hyperopting will now call this `populate_buy_trend` as many times you ask it (`epochs`) -with different value combinations. It will then use the given historical data and make -buys based on the buy signals generated with the above function and based on the results -it will end with telling you which parameter combination produced the best profits. +Hyperopt will now call `populate_buy_trend()` many times (`epochs`) with different value combinations. +It will use the given historical data and make buys based on the buy signals generated with the above function. +Based on the results, hyperopt will tell you which parameter combination produced the best results (based on the configured [loss function](#loss-functions)). -The above setup expects to find ADX, RSI and Bollinger Bands in the populated indicators. -When you want to test an indicator that isn't used by the bot currently, remember to -add it to the `populate_indicators()` method in your custom hyperopt file. +!!! Note + The above setup expects to find ADX, RSI and Bollinger Bands in the populated indicators. + When you want to test an indicator that isn't used by the bot currently, remember to + add it to the `populate_indicators()` method in your strategy or hyperopt file. ## Loss-functions @@ -232,14 +243,15 @@ freqtrade hyperopt --config config.json --hyperopt --hyperopt-los Use `` as the name of the custom hyperopt used. -The `-e` option will set how many evaluations hyperopt will do. We recommend -running at least several thousand evaluations. +The `-e` option will set how many evaluations hyperopt will do. Since hyperopt uses Bayesian search, running too many epochs at once may not produce greater results. Experience has shown that best results are usually not improving much after 500-1000 epochs. +Doing multiple runs (executions) with a few 1000 epochs and different random state will most likely produce different results. The `--spaces all` option determines that all possible parameters should be optimized. Possibilities are listed below. !!! Note Hyperopt will store hyperopt results with the timestamp of the hyperopt start time. Reading commands (`hyperopt-list`, `hyperopt-show`) can use `--hyperopt-filename ` to read and display older hyperopt results. + You can find a list of filenames with `ls -l user_data/hyperopt_results/`. ### Execute Hyperopt with different historical data source @@ -247,7 +259,7 @@ If you would like to hyperopt parameters using an alternate historical data set you have on-disk, use the `--datadir PATH` option. By default, hyperopt uses data from directory `user_data/data`. -### Running Hyperopt with Smaller Testset +### Running Hyperopt with a smaller test-set Use the `--timerange` argument to change how much of the test-set you want to use. For example, to use one month of data, pass the following parameter to the hyperopt call: @@ -437,7 +449,7 @@ Stoploss: -0.27996 In order to use this best stoploss value found by Hyperopt in backtesting and for live trades/dry-run, copy-paste it as the value of the `stoploss` attribute of your custom strategy: -``` +``` python # Optimal stoploss designed for the strategy # This attribute will be overridden if the config file contains "stoploss" stoploss = -0.27996 @@ -471,7 +483,7 @@ Trailing stop: In order to use these best trailing stop parameters found by Hyperopt in backtesting and for live trades/dry-run, copy-paste them as the values of the corresponding attributes of your custom strategy: -``` +``` python # Trailing stop # These attributes will be overridden if the config file contains corresponding values. trailing_stop = True @@ -496,4 +508,8 @@ After you run Hyperopt for the desired amount of epochs, you can later list all Once the optimized strategy has been implemented into your strategy, you should backtest this strategy to make sure everything is working as expected. -To achieve same results (number of trades, their durations, profit, etc.) than during Hyperopt, please use same set of arguments `--dmmp`/`--disable-max-market-positions` and `--eps`/`--enable-position-stacking` for Backtesting. +To achieve same results (number of trades, their durations, profit, etc.) than during Hyperopt, please use same configuration and parameters (timerange, timeframe, ...) used for hyperopt `--dmmp`/`--disable-max-market-positions` and `--eps`/`--enable-position-stacking` for Backtesting. + +Should results don't match, please double-check to make sure you transferred all conditions correctly. +Pay special care to the stoploss (and trailing stoploss) parameters, as these are often set in configuration files, which override changes to the strategy. +You should also carefully review the log of your backtest to ensure that there were no parameters inadvertently set by the configuration (like `stoploss` or `trailing_stop`). From 14e87ed4a172ae3ecaa80cfce2f7a0130e36d150 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 5 Oct 2020 20:13:09 +0200 Subject: [PATCH 4/5] Improvements to hyperopt docs --- docs/hyperopt.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/hyperopt.md b/docs/hyperopt.md index 87302a675..91bc32e48 100644 --- a/docs/hyperopt.md +++ b/docs/hyperopt.md @@ -137,7 +137,7 @@ To avoid naming collisions in the search-space, please prefix all sell-spaces wi The Strategy class exposes the timeframe value as the `self.timeframe` attribute. The same value is available as class-attribute `HyperoptName.timeframe`. -In the case of the linked sample-value this would be `SampleHyperOpt.timeframe`. +In the case of the linked sample-value this would be `AwesomeHyperopt.timeframe`. ## Solving a Mystery @@ -273,16 +273,15 @@ freqtrade hyperopt --hyperopt --strategy --timeran Hyperopt can reuse `populate_indicators`, `populate_buy_trend`, `populate_sell_trend` from your strategy, assuming these methods are **not** in your custom hyperopt file, and a strategy is provided. ```bash -freqtrade hyperopt --hyperopt SampleHyperopt --hyperopt-loss SharpeHyperOptLossDaily --strategy SampleStrategy +freqtrade hyperopt --hyperopt AwesomeHyperopt --hyperopt-loss SharpeHyperOptLossDaily --strategy AwesomeStrategy ``` ### Running Hyperopt with Smaller Search Space Use the `--spaces` option to limit the search space used by hyperopt. -Letting Hyperopt optimize everything is a huuuuge search space. Often it -might make more sense to start by just searching for initial buy algorithm. -Or maybe you just want to optimize your stoploss or roi table for that awesome -new buy strategy you have. +Letting Hyperopt optimize everything is a huuuuge search space. +Often it might make more sense to start by just searching for initial buy algorithm. +Or maybe you just want to optimize your stoploss or roi table for that awesome new buy strategy you have. Legal values are: @@ -427,7 +426,9 @@ These ranges should be sufficient in most cases. The minutes in the steps (ROI d 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). A sample for these methods can be found in [user_data/hyperopts/sample_hyperopt_advanced.py](https://github.com/freqtrade/freqtrade/blob/develop/freqtrade/templates/sample_hyperopt_advanced.py). +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 [sample_hyperopt_advanced.py](https://github.com/freqtrade/freqtrade/blob/develop/freqtrade/templates/sample_hyperopt_advanced.py). ### Understand Hyperopt Stoploss results From 8c2f7631939e89118715349ef3277b4b942652cf Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 5 Oct 2020 20:36:16 +0200 Subject: [PATCH 5/5] Add test to ensure --hyperopt-loss is mandatory --- .github/workflows/ci.yml | 2 +- freqtrade/resolvers/hyperopt_resolver.py | 4 ---- tests/optimize/test_hyperopt.py | 7 +++++++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa599f361..5e9612837 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -154,7 +154,7 @@ jobs: run: | cp config.json.example config.json freqtrade create-userdir --userdir user_data - freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt SampleHyperOpt --print-all + freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt SampleHyperOpt --hyperopt-loss SharpeHyperOptLossDaily --print-all - name: Flake8 run: | diff --git a/freqtrade/resolvers/hyperopt_resolver.py b/freqtrade/resolvers/hyperopt_resolver.py index 2fd7abb93..328dc488b 100644 --- a/freqtrade/resolvers/hyperopt_resolver.py +++ b/freqtrade/resolvers/hyperopt_resolver.py @@ -82,8 +82,4 @@ class HyperOptLossResolver(IResolver): hyperoptloss.__class__.ticker_interval = str(config['timeframe']) hyperoptloss.__class__.timeframe = str(config['timeframe']) - if not hasattr(hyperoptloss, 'hyperopt_loss_function'): - raise OperationalException( - f"Found HyperoptLoss class {hyperoptloss_name} does not " - "implement `hyperopt_loss_function`.") return hyperoptloss diff --git a/tests/optimize/test_hyperopt.py b/tests/optimize/test_hyperopt.py index 636c24c97..f699473f7 100644 --- a/tests/optimize/test_hyperopt.py +++ b/tests/optimize/test_hyperopt.py @@ -230,6 +230,13 @@ def test_hyperoptresolver_noname(default_conf): HyperOptResolver.load_hyperopt(default_conf) +def test_hyperoptlossresolver_noname(default_conf): + with pytest.raises(OperationalException, + match="No Hyperopt loss set. Please use `--hyperopt-loss` to specify " + "the Hyperopt-Loss class to use."): + HyperOptLossResolver.load_hyperoptloss(default_conf) + + def test_hyperoptlossresolver(mocker, default_conf) -> None: hl = DefaultHyperOptLoss