Repository: freqtrade/freqtrade
Pull request: Move experimental settings to ask_strategy
* Experimental settings moved to `['ask_strategy']`.
* The default value for `ask_strategy.use_sell_signal` changed to True (true in json config)
* Docs adjusted (description of `use_sell_signal` slightly improved)
* Tests adjusted
* An error in json schema fixed (it was using `ignore_roi_if_buy_signal_true` instead of proper `ignore_roi_if_buy_signal`)

Resolves #2233 

TODO:
* [x] copy values of old experimental settings to ask_strategy with a deprecation message (we only have this implemented for deprecated cli options)


Problem statement:
Redesign experimental settings
The suggestion is:

* move experimental settings out of experimental to the root:
```
    "experimental": {
        "use_sell_signal": false,
        "sell_profit_only": false,
        "ignore_roi_if_buy_signal": false
    },
```
They are implemented for more than an year and should no longer be considered as experimental. The code for experimental branch of settings should be kept in the codebase since we could add some new settings to it in the future.

* assign the `use_sell_signal` the default value of true.

Hints from issue discussion:
yes and yes - we could (probably should) also have a grace-period - where these settings are "copied" to the root-level with a depreciation warning ... 

so people can slowly adapt to this.
right, fine,
the latter one (the default value of true for `use_sell_signal`) does not require adding deprecation messages.

Commit message: Move experimental settings to ask_strategy

Patch to review:
diff --git a/config.json.example b/config.json.example
index 94084434a98..41901903056 100644
--- a/config.json.example
+++ b/config.json.example
@@ -22,7 +22,10 @@
     "ask_strategy":{
         "use_order_book": false,
         "order_book_min": 1,
-        "order_book_max": 9
+        "order_book_max": 9,
+        "use_sell_signal": true,
+        "sell_profit_only": false,
+        "ignore_roi_if_buy_signal": false
     },
     "exchange": {
         "name": "bittrex",
@@ -49,11 +52,6 @@
             "DOGE/BTC"
         ]
     },
-    "experimental": {
-        "use_sell_signal": false,
-        "sell_profit_only": false,
-        "ignore_roi_if_buy_signal": false
-    },
     "edge": {
         "enabled": false,
         "process_throttle_secs": 3600,
diff --git a/config_binance.json.example b/config_binance.json.example
index 1d492fc3c35..58817a78eb1 100644
--- a/config_binance.json.example
+++ b/config_binance.json.example
@@ -22,7 +22,10 @@
     "ask_strategy":{
         "use_order_book": false,
         "order_book_min": 1,
-        "order_book_max": 9
+        "order_book_max": 9,
+        "use_sell_signal": true,
+        "sell_profit_only": false,
+        "ignore_roi_if_buy_signal": false
     },
     "exchange": {
         "name": "binance",
@@ -51,11 +54,6 @@
             "BNB/BTC"
         ]
     },
-    "experimental": {
-        "use_sell_signal": false,
-        "sell_profit_only": false,
-        "ignore_roi_if_buy_signal": false
-    },
     "edge": {
         "enabled": false,
         "process_throttle_secs": 3600,
diff --git a/config_full.json.example b/config_full.json.example
index 95796704205..c6b229ea32e 100644
--- a/config_full.json.example
+++ b/config_full.json.example
@@ -33,7 +33,10 @@
     "ask_strategy":{
         "use_order_book": false,
         "order_book_min": 1,
-        "order_book_max": 9
+        "order_book_max": 9,
+        "use_sell_signal": true,
+        "sell_profit_only": false,
+        "ignore_roi_if_buy_signal": false
     },
     "order_types": {
         "buy": "limit",
@@ -100,11 +103,6 @@
         "max_trade_duration_minute": 1440,
         "remove_pumps": false
     },
-    "experimental": {
-        "use_sell_signal": false,
-        "sell_profit_only": false,
-        "ignore_roi_if_buy_signal": false
-    },
     "telegram": {
         "enabled": true,
         "token": "your_telegram_token",
diff --git a/config_kraken.json.example b/config_kraken.json.example
index ea3677b2d83..51aa9a8e9a4 100644
--- a/config_kraken.json.example
+++ b/config_kraken.json.example
@@ -22,7 +22,11 @@
     "ask_strategy":{
         "use_order_book": false,
         "order_book_min": 1,
-        "order_book_max": 9
+        "order_book_max": 9,
+        "use_sell_signal": true,
+        "sell_profit_only": false,
+        "ignore_roi_if_buy_signal": false
+
     },
     "exchange": {
         "name": "kraken",
diff --git a/docs/configuration.md b/docs/configuration.md
index 0d902766af7..a31650f7877 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -65,6 +65,9 @@ Mandatory parameters are marked as **Required**, which means that they are requi
 | `ask_strategy.use_order_book` | false | Allows selling of open traded pair using the rates in Order Book Asks.
 | `ask_strategy.order_book_min` | 0 | Bot will scan from the top min to max Order Book Asks searching for a profitable rate.
 | `ask_strategy.order_book_max` | 0 | Bot will scan from the top min to max Order Book Asks searching for a profitable rate.
+| `ask_strategy.use_sell_signal` | true | Use your strategy sell signals in addition to the `minimal_roi`. [Strategy Override](#parameters-in-the-strategy).
+| `ask_strategy.sell_profit_only` | false | Wait until you have made a positive profit before taking a sell decision. [Strategy Override](#parameters-in-the-strategy).
+| `ask_strategy.ignore_roi_if_buy_signal` | false | Do not sell if the buy-signal is still active. This setting takes preference over `minimal_roi` and `use_sell_signal`. [Strategy Override](#parameters-in-the-strategy).
 | `order_types` | None | Configure order-types depending on the action (`"buy"`, `"sell"`, `"stoploss"`, `"stoploss_on_exchange"`). [More information below](#understand-order_types). [Strategy Override](#parameters-in-the-strategy).
 | `order_time_in_force` | None | Configure time in force for buy and sell orders. [More information below](#understand-order_time_in_force). [Strategy Override](#parameters-in-the-strategy).
 | `exchange.name` |  | **Required.** Name of the exchange class to use. [List below](#user-content-what-values-for-exchangename).
@@ -78,9 +81,6 @@ Mandatory parameters are marked as **Required**, which means that they are requi
 | `exchange.ccxt_async_config` | None | Additional CCXT parameters passed to the async ccxt instance. Parameters may differ from exchange to exchange  and are documented in the [ccxt documentation](https://ccxt.readthedocs.io/en/latest/manual.html#instantiation)
 | `exchange.markets_refresh_interval` | 60 | The interval in minutes in which markets are reloaded.
 | `edge` | false | Please refer to [edge configuration document](edge.md) for detailed explanation.
-| `experimental.use_sell_signal` | false | Use your sell strategy in addition of the `minimal_roi`. [Strategy Override](#parameters-in-the-strategy).
-| `experimental.sell_profit_only` | false | Waits until you have made a positive profit before taking a sell decision. [Strategy Override](#parameters-in-the-strategy).
-| `experimental.ignore_roi_if_buy_signal` | false | Does not sell if the buy-signal is still active. Takes preference over `minimal_roi` and `use_sell_signal`. [Strategy Override](#parameters-in-the-strategy).
 | `experimental.block_bad_exchanges` | true | Block exchanges known to not work with freqtrade. Leave on default unless you want to test if that exchange works now.
 | `pairlist.method` | StaticPairList | Use static or dynamic volume-based pairlist. [More information below](#dynamic-pairlists).
 | `pairlist.config` | None | Additional configuration for dynamic pairlists. [More information below](#dynamic-pairlists).
@@ -116,9 +116,9 @@ Values set in the configuration file always overwrite values set in the strategy
 * `process_only_new_candles`
 * `order_types`
 * `order_time_in_force`
-* `use_sell_signal` (experimental)
-* `sell_profit_only` (experimental)
-* `ignore_roi_if_buy_signal` (experimental)
+* `use_sell_signal` (ask_strategy)
+* `sell_profit_only` (ask_strategy)
+* `ignore_roi_if_buy_signal` (ask_strategy)
 
 ### Understand stake_amount
 
diff --git a/freqtrade/constants.py b/freqtrade/constants.py
index abf43b24d05..697bc280fb2 100644
--- a/freqtrade/constants.py
+++ b/freqtrade/constants.py
@@ -114,7 +114,10 @@
             'properties': {
                 'use_order_book': {'type': 'boolean'},
                 'order_book_min': {'type': 'number', 'minimum': 1},
-                'order_book_max': {'type': 'number', 'minimum': 1, 'maximum': 50}
+                'order_book_max': {'type': 'number', 'minimum': 1, 'maximum': 50},
+                'use_sell_signal': {'type': 'boolean'},
+                'sell_profit_only': {'type': 'boolean'},
+                'ignore_roi_if_buy_signal': {'type': 'boolean'}
             }
         },
         'order_types': {
@@ -144,7 +147,8 @@
             'properties': {
                 'use_sell_signal': {'type': 'boolean'},
                 'sell_profit_only': {'type': 'boolean'},
-                'ignore_roi_if_buy_signal_true': {'type': 'boolean'}
+                'ignore_roi_if_buy_signal': {'type': 'boolean'},
+                'block_bad_exchanges': {'type': 'boolean'}
             }
         },
         'pairlist': {
diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py
index 3f7eab27aa2..9a2f2cdc41a 100644
--- a/freqtrade/freqtradebot.py
+++ b/freqtrade/freqtradebot.py
@@ -580,13 +580,15 @@ def handle_trade(self, trade: Trade) -> bool:
         logger.debug('Handling %s ...', trade)
 
         (buy, sell) = (False, False)
-        experimental = self.config.get('experimental', {})
-        if experimental.get('use_sell_signal') or experimental.get('ignore_roi_if_buy_signal'):
+
+        config_ask_strategy = self.config.get('ask_strategy', {})
+
+        if (config_ask_strategy.get('use_sell_signal', True) or
+                config_ask_strategy.get('ignore_roi_if_buy_signal')):
             (buy, sell) = self.strategy.get_signal(
                 trade.pair, self.strategy.ticker_interval,
                 self.dataprovider.ohlcv(trade.pair, self.strategy.ticker_interval))
 
-        config_ask_strategy = self.config.get('ask_strategy', {})
         if config_ask_strategy.get('use_order_book', False):
             logger.info('Using order book for selling...')
             # logger.debug('Order book %s',orderBook)
diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py
index a70ff814212..07258a048af 100644
--- a/freqtrade/optimize/hyperopt.py
+++ b/freqtrade/optimize/hyperopt.py
@@ -98,10 +98,10 @@ def __init__(self, config: Dict[str, Any]) -> None:
         self.position_stacking = self.config.get('position_stacking', False)
 
         if self.has_space('sell'):
-            # Make sure experimental is enabled
-            if 'experimental' not in self.config:
-                self.config['experimental'] = {}
-            self.config['experimental']['use_sell_signal'] = True
+            # Make sure use_sell_signal is enabled
+            if 'ask_strategy' not in self.config:
+                self.config['ask_strategy'] = {}
+            self.config['ask_strategy']['use_sell_signal'] = True
 
     @staticmethod
     def get_lock_filename(config) -> str:
diff --git a/freqtrade/resolvers/strategy_resolver.py b/freqtrade/resolvers/strategy_resolver.py
index ca7e1165b55..43197e5bc0d 100644
--- a/freqtrade/resolvers/strategy_resolver.py
+++ b/freqtrade/resolvers/strategy_resolver.py
@@ -38,13 +38,13 @@ def __init__(self, config: Optional[Dict] = None) -> None:
                                                        config=config,
                                                        extra_dir=config.get('strategy_path'))
 
-        # make sure experimental dict is available
-        if 'experimental' not in config:
-            config['experimental'] = {}
+        # make sure ask_strategy dict is available
+        if 'ask_strategy' not in config:
+            config['ask_strategy'] = {}
 
         # Set attributes
         # Check if we need to override configuration
-        # (Attribute name,                              default, experimental)
+        #             (Attribute name,                    default,     ask_strategy)
         attributes = [("minimal_roi",                     {"0": 10.0}, False),
                       ("ticker_interval",                 None,        False),
                       ("stoploss",                        None,        False),
@@ -57,20 +57,20 @@ def __init__(self, config: Optional[Dict] = None) -> None:
                       ("order_time_in_force",             None,        False),
                       ("stake_currency",                  None,        False),
                       ("stake_amount",                    None,        False),
-                      ("use_sell_signal",                 False,       True),
+                      ("use_sell_signal",                 True,        True),
                       ("sell_profit_only",                False,       True),
                       ("ignore_roi_if_buy_signal",        False,       True),
                       ]
-        for attribute, default, experimental in attributes:
-            if experimental:
-                self._override_attribute_helper(config['experimental'], attribute, default)
+        for attribute, default, ask_strategy in attributes:
+            if ask_strategy:
+                self._override_attribute_helper(config['ask_strategy'], attribute, default)
             else:
                 self._override_attribute_helper(config, attribute, default)
 
         # Loop this list again to have output combined
         for attribute, _, exp in attributes:
-            if exp and attribute in config['experimental']:
-                logger.info("Strategy using %s: %s", attribute, config['experimental'][attribute])
+            if exp and attribute in config['ask_strategy']:
+                logger.info("Strategy using %s: %s", attribute, config['ask_strategy'][attribute])
             elif attribute in config:
                 logger.info("Strategy using %s: %s", attribute, config[attribute])
 
diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py
index 17246ecf71d..b35ebabbb32 100644
--- a/freqtrade/strategy/interface.py
+++ b/freqtrade/strategy/interface.py
@@ -309,9 +309,9 @@ def should_sell(self, trade: Trade, rate: float, date: datetime, buy: bool,
         # Set current rate to high for backtesting sell
         current_rate = high or rate
         current_profit = trade.calc_profit_percent(current_rate)
-        experimental = self.config.get('experimental', {})
+        config_ask_strategy = self.config.get('ask_strategy', {})
 
-        if buy and experimental.get('ignore_roi_if_buy_signal', False):
+        if buy and config_ask_strategy.get('ignore_roi_if_buy_signal', False):
             # This one is noisy, commented out
             # logger.debug(f"{trade.pair} - Buy signal still active. sell_flag=False")
             return SellCheckTuple(sell_flag=False, sell_type=SellType.NONE)
@@ -322,7 +322,7 @@ def should_sell(self, trade: Trade, rate: float, date: datetime, buy: bool,
                          f"sell_type=SellType.ROI")
             return SellCheckTuple(sell_flag=True, sell_type=SellType.ROI)
 
-        if experimental.get('sell_profit_only', False):
+        if config_ask_strategy.get('sell_profit_only', False):
             # This one is noisy, commented out
             # logger.debug(f"{trade.pair} - Checking if trade is profitable...")
             if trade.calc_profit(rate=rate) <= 0:
@@ -330,7 +330,7 @@ def should_sell(self, trade: Trade, rate: float, date: datetime, buy: bool,
                 # logger.debug(f"{trade.pair} - Trade is not profitable. sell_flag=False")
                 return SellCheckTuple(sell_flag=False, sell_type=SellType.NONE)
 
-        if sell and not buy and experimental.get('use_sell_signal', False):
+        if sell and not buy and config_ask_strategy.get('use_sell_signal', True):
             logger.debug(f"{trade.pair} - Sell signal received. sell_flag=True, "
                          f"sell_type=SellType.SELL_SIGNAL")
             return SellCheckTuple(sell_flag=True, sell_type=SellType.SELL_SIGNAL)
diff --git a/tests/config_test_comments.json b/tests/config_test_comments.json
index 85becc3e8a1..8af39d6bab8 100644
--- a/tests/config_test_comments.json
+++ b/tests/config_test_comments.json
@@ -103,11 +103,6 @@
         "max_trade_duration_minute": 1440,
         "remove_pumps": false
     },
-    "experimental": {
-        "use_sell_signal": false,
-        "sell_profit_only": false,
-        "ignore_roi_if_buy_signal": false
-    },
     "telegram": {
 // We can now comment out some settings
 //        "enabled": true,
diff --git a/tests/optimize/test_backtest_detail.py b/tests/optimize/test_backtest_detail.py
index d8a4190e22f..a85dc99c39f 100644
--- a/tests/optimize/test_backtest_detail.py
+++ b/tests/optimize/test_backtest_detail.py
@@ -285,7 +285,7 @@ def test_backtest_results(default_conf, fee, mocker, caplog, data) -> None:
     if data.trailing_stop_positive:
         default_conf["trailing_stop_positive"] = data.trailing_stop_positive
     default_conf["trailing_stop_positive_offset"] = data.trailing_stop_positive_offset
-    default_conf["experimental"] = {"use_sell_signal": data.use_sell_signal}
+    default_conf["ask_strategy"] = {"use_sell_signal": data.use_sell_signal}
 
     mocker.patch("freqtrade.exchange.Exchange.get_fee", MagicMock(return_value=0.0))
     patch_exchange(mocker)
diff --git a/tests/optimize/test_backtesting.py b/tests/optimize/test_backtesting.py
index fa40809d8c5..589896c3951 100644
--- a/tests/optimize/test_backtesting.py
+++ b/tests/optimize/test_backtesting.py
@@ -507,6 +507,7 @@ def get_timeframe(input1):
 
 
 def test_backtest(default_conf, fee, mocker, testdatadir) -> None:
+    default_conf['ask_strategy']['use_sell_signal'] = False
     mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
     patch_exchange(mocker)
     backtesting = Backtesting(default_conf)
@@ -561,6 +562,7 @@ def test_backtest(default_conf, fee, mocker, testdatadir) -> None:
 
 
 def test_backtest_1min_ticker_interval(default_conf, fee, mocker, testdatadir) -> None:
+    default_conf['ask_strategy']['use_sell_signal'] = False
     mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
     patch_exchange(mocker)
     backtesting = Backtesting(default_conf)
@@ -603,8 +605,9 @@ def test_backtest_pricecontours(default_conf, fee, mocker, testdatadir) -> None:
     # TODO: Evaluate usefullness of this, the patterns and buy-signls are unrealistic
     mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
     tests = [['raise', 19], ['lower', 0], ['sine', 35]]
-    # We need to enable sell-signal - otherwise it sells on ROI!!
-    default_conf['experimental'] = {"use_sell_signal": True}
+    # use_sell_signal is True by default now, it will sell on the sell signal instead of ROI,
+    # which is what we need here
+#    default_conf['ask_strategy'] = {"use_sell_signal": True}
 
     for [contour, numres] in tests:
         simple_backtest(default_conf, contour, numres, mocker, testdatadir)
@@ -645,8 +648,9 @@ def test_backtest_alternate_buy_sell(default_conf, fee, mocker, testdatadir):
     mocker.patch('freqtrade.optimize.backtesting.file_dump_json', MagicMock())
     backtest_conf = _make_backtest_conf(mocker, conf=default_conf,
                                         pair='UNITTEST/BTC', datadir=testdatadir)
-    # We need to enable sell-signal - otherwise it sells on ROI!!
-    default_conf['experimental'] = {"use_sell_signal": True}
+    # use_sell_signal is True by default now, it will sell on the sell signal instead of ROI,
+    # which is what we need here
+#    default_conf['ask_strategy'] = {"use_sell_signal": True}
     default_conf['ticker_interval'] = '1m'
     backtesting = Backtesting(default_conf)
     backtesting.strategy.advise_buy = _trend_alternate  # Override
@@ -687,8 +691,9 @@ def _trend_alternate_hold(dataframe=None, metadata=None):
 
     # Remove data for one pair from the beginning of the data
     data[pair] = data[pair][tres:].reset_index()
-    # We need to enable sell-signal - otherwise it sells on ROI!!
-    default_conf['experimental'] = {"use_sell_signal": True}
+    # use_sell_signal is True by default now, it will sell on the sell signal instead of ROI,
+    # which is what we need here
+#    default_conf['ask_strategy'] = {"use_sell_signal": True}
     default_conf['ticker_interval'] = '5m'
 
     backtesting = Backtesting(default_conf)
diff --git a/tests/strategy/test_strategy.py b/tests/strategy/test_strategy.py
index 6992d1aa551..88e29b40ec4 100644
--- a/tests/strategy/test_strategy.py
+++ b/tests/strategy/test_strategy.py
@@ -256,23 +256,23 @@ def test_strategy_override_use_sell_signal(caplog, default_conf):
         'strategy': 'DefaultStrategy',
     })
     resolver = StrategyResolver(default_conf)
-    assert not resolver.strategy.use_sell_signal
+    assert resolver.strategy.use_sell_signal
     assert isinstance(resolver.strategy.use_sell_signal, bool)
     # must be inserted to configuration
-    assert 'use_sell_signal' in default_conf['experimental']
-    assert not default_conf['experimental']['use_sell_signal']
+    assert 'use_sell_signal' in default_conf['ask_strategy']
+    assert default_conf['ask_strategy']['use_sell_signal']
 
     default_conf.update({
         'strategy': 'DefaultStrategy',
-        'experimental': {
-            'use_sell_signal': True,
+        'ask_strategy': {
+            'use_sell_signal': False,
         },
     })
     resolver = StrategyResolver(default_conf)
 
-    assert resolver.strategy.use_sell_signal
+    assert not resolver.strategy.use_sell_signal
     assert isinstance(resolver.strategy.use_sell_signal, bool)
-    assert log_has("Override strategy 'use_sell_signal' with value in config file: True.", caplog)
+    assert log_has("Override strategy 'use_sell_signal' with value in config file: False.", caplog)
 
 
 def test_strategy_override_use_sell_profit_only(caplog, default_conf):
@@ -284,12 +284,12 @@ def test_strategy_override_use_sell_profit_only(caplog, default_conf):
     assert not resolver.strategy.sell_profit_only
     assert isinstance(resolver.strategy.sell_profit_only, bool)
     # must be inserted to configuration
-    assert 'sell_profit_only' in default_conf['experimental']
-    assert not default_conf['experimental']['sell_profit_only']
+    assert 'sell_profit_only' in default_conf['ask_strategy']
+    assert not default_conf['ask_strategy']['sell_profit_only']
 
     default_conf.update({
         'strategy': 'DefaultStrategy',
-        'experimental': {
+        'ask_strategy': {
             'sell_profit_only': True,
         },
     })
diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py
index ee28f2e5856..a9c85b4c37b 100644
--- a/tests/test_freqtradebot.py
+++ b/tests/test_freqtradebot.py
@@ -1768,8 +1768,6 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order,
 
 def test_handle_overlpapping_signals(default_conf, ticker, limit_buy_order,
                                      fee, markets, mocker) -> None:
-    default_conf.update({'experimental': {'use_sell_signal': True}})
-
     patch_RPCManager(mocker)
     patch_exchange(mocker)
     mocker.patch.multiple(
@@ -1824,7 +1822,6 @@ def test_handle_overlpapping_signals(default_conf, ticker, limit_buy_order,
 def test_handle_trade_roi(default_conf, ticker, limit_buy_order,
                           fee, mocker, markets, caplog) -> None:
     caplog.set_level(logging.DEBUG)
-    default_conf.update({'experimental': {'use_sell_signal': True}})
 
     patch_RPCManager(mocker)
     patch_exchange(mocker)
@@ -1856,10 +1853,10 @@ def test_handle_trade_roi(default_conf, ticker, limit_buy_order,
                    caplog)
 
 
-def test_handle_trade_experimental(
+def test_handle_trade_use_sell_signal(
         default_conf, ticker, limit_buy_order, fee, mocker, markets, caplog) -> None:
+    # use_sell_signal is True buy default
     caplog.set_level(logging.DEBUG)
-    default_conf.update({'experimental': {'use_sell_signal': True}})
     patch_RPCManager(mocker)
     patch_exchange(mocker)
     mocker.patch.multiple(
@@ -2600,7 +2597,7 @@ def test_sell_profit_only_enable_profit(default_conf, limit_buy_order,
         get_fee=fee,
         markets=PropertyMock(return_value=markets)
     )
-    default_conf['experimental'] = {
+    default_conf['ask_strategy'] = {
         'use_sell_signal': True,
         'sell_profit_only': True,
     }
@@ -2632,7 +2629,7 @@ def test_sell_profit_only_disable_profit(default_conf, limit_buy_order,
         get_fee=fee,
         markets=PropertyMock(return_value=markets)
     )
-    default_conf['experimental'] = {
+    default_conf['ask_strategy'] = {
         'use_sell_signal': True,
         'sell_profit_only': False,
     }
@@ -2662,7 +2659,7 @@ def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, fee, market
         get_fee=fee,
         markets=PropertyMock(return_value=markets)
     )
-    default_conf['experimental'] = {
+    default_conf['ask_strategy'] = {
         'use_sell_signal': True,
         'sell_profit_only': True,
     }
@@ -2692,7 +2689,7 @@ def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, fee, marke
         get_fee=fee,
         markets=PropertyMock(return_value=markets)
     )
-    default_conf['experimental'] = {
+    default_conf['ask_strategy'] = {
         'use_sell_signal': True,
         'sell_profit_only': False,
     }
@@ -2761,7 +2758,7 @@ def test_ignore_roi_if_buy_signal(default_conf, limit_buy_order, fee, markets, m
         get_fee=fee,
         markets=PropertyMock(return_value=markets)
     )
-    default_conf['experimental'] = {
+    default_conf['ask_strategy'] = {
         'ignore_roi_if_buy_signal': True
     }
     freqtrade = FreqtradeBot(default_conf)
@@ -3029,7 +3026,7 @@ def test_disable_ignore_roi_if_buy_signal(default_conf, limit_buy_order,
         get_fee=fee,
         markets=PropertyMock(return_value=markets)
     )
-    default_conf['experimental'] = {
+    default_conf['ask_strategy'] = {
         'ignore_roi_if_buy_signal': False
     }
     freqtrade = FreqtradeBot(default_conf)


Code review comments:
diff_hunk: @@ -65,6 +65,9 @@ Mandatory parameters are marked as **Required**, which means that they are requi
 | `ask_strategy.use_order_book` | false | Allows selling of open traded pair using the rates in Order Book Asks.
 | `ask_strategy.order_book_min` | 0 | Bot will scan from the top min to max Order Book Asks searching for a profitable rate.
 | `ask_strategy.order_book_max` | 0 | Bot will scan from the top min to max Order Book Asks searching for a profitable rate.
+| `ask_strategy.use_sell_signal` | true | Use your strategy sell signals in addition to the `minimal_roi`. [Strategy Override](#parameters-in-the-strategy).
+| `ask_strategy.sell_profit_only` | false | Wait until you have made a positive profit before taking a sell decision. [Strategy Override](#parameters-in-the-strategy).
path: docs/configuration.md
text: @user1:
maybe we should not use "you" and "your" here but instead "use the strategy" and "Wait until the bot has made" ... ? 


@author:
pls review

diff_hunk: @@ -645,8 +648,9 @@ def test_backtest_alternate_buy_sell(default_conf, fee, mocker, testdatadir):
     mocker.patch('freqtrade.optimize.backtesting.file_dump_json', MagicMock())
     backtest_conf = _make_backtest_conf(mocker, conf=default_conf,
                                         pair='UNITTEST/BTC', datadir=testdatadir)
-    # We need to enable sell-signal - otherwise it sells on ROI!!
-    default_conf['experimental'] = {"use_sell_signal": True}
+    # use_sell_signal is True by default now, it will sell on the sell signal instead of ROI,
+    # which is what we need here
+#    default_conf['ask_strategy'] = {"use_sell_signal": True}
path: tests/optimize/test_backtesting.py
text: @user1:
i guess since this is not needed anymore we can also remove this part (?) from the tests? (the comment does not make sense in the future - if you look at it from a "after the PR is merged" perspective ... (same with the others in this file ...)

@author:
I thought I would be better 'from a "after the PR is merged" perspective' to emphasize that use_sell_signal: True is required for these tests... Okay, removed, even better...


@user1:
it's the new default - someone new will not know that this was different in the past, so might be confused by this comment