Repository: freqtrade/freqtrade

Issue:
Default strategy has to be changed as it is misleading for new users.
as discussed in #1362 the default strategy has to be changed to a more reasonable one. 
some basic things are not respected in default strategy which can be misleading and discouraging for new users.
Issues I can think of: 
- It doesn't check the volume so price can deviate radically from TA.
- Buy/Sell moments are propagated to many frames.


Discussion:
@creslinux feel free to add to the list, and if you are ok we replace #1362 with this one.
Are you talking about the `DefaultStrategy` in `freqtrade/strategy/default_strategy.py` - or rather about `TestStrategy` in `user_data/strategies/test_strategy.py` - which  is the sample code for users ... or both?

while at that - maybe we can also improve / fix the issue with documentation pointed out in #818 ... as i assume the above points will need additions / changes to the documentation as well.
I am talking about DefaultStrategy.

```
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Based on TA indicators, populates the buy signal for the given dataframe
        :param dataframe: DataFrame
        :param metadata: Additional information, like the currently traded pair
        :return: DataFrame with buy column
        """
        dataframe.loc[
            (
                (dataframe['rsi'] < 35) &
                (dataframe['fastd'] < 35) &
                (dataframe['adx'] > 30) &
                (dataframe['plus_di'] > 0.5)
            ) |
            (
                (dataframe['adx'] > 65) &
                (dataframe['plus_di'] > 0.5)
            ),
            'buy'] = 1

        return dataframe

    def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Based on TA indicators, populates the sell signal for the given dataframe
        :param dataframe: DataFrame
        :param metadata: Additional information, like the currently traded pair
        :return: DataFrame with buy column
        """
        dataframe.loc[
            (
                (
                    (qtpylib.crossed_above(dataframe['rsi'], 70)) |
                    (qtpylib.crossed_above(dataframe['fastd'], 70))
                ) &
                (dataframe['adx'] > 10) &
                (dataframe['minus_di'] > 0)
            ) |
            (
                (dataframe['adx'] > 70) &
                (dataframe['minus_di'] > 0.5)
            ),
            'sell'] = 1
        return dataframe 
```


Yes, good idea 👍 we should add some documentation on it (inline though). we can add some hints but it should not become a trading tutorial ...

If you're talking DefaultStrategy, then i don't see much sense in it for the average user, as the documentation [here](https://github.com/freqtrade/freqtrade/blob/develop/docs/bot-optimization.md#change-your-strategy) points to the `TestStrategy`, not `DefaultStrategy`.


This documentation also explains how to add indicators, but lacks information on the other areas (stoploss, roi, ...) as pointed out in #818. 
My assumption based on the above is that you intend to add notes pointing out that volume should be included as indicator for reasons - and that "crossed" should be used to avoid problem Y ... 
which you can add inline - but i would also add that in the documentation.
And no, it should not be a trading tutorial - but a howto change the strategy to your strategy idea...
Going to close this one as I think we cannot do more than #1562.
not sure i agree ... 
something like 
```
                (
                    (qtpylib.crossed_above(dataframe['rsi'], 70)) |
                    (qtpylib.crossed_above(dataframe['fastd'], 70))
```

could still be added - but fixing this was not necessarily the purpose of that PR - it was really aimed at fixing my copy/paste error / typo


Resolving patch:
diff --git a/user_data/strategies/sample_strategy.py b/user_data/strategies/sample_strategy.py
--- a/user_data/strategies/sample_strategy.py
+++ b/user_data/strategies/sample_strategy.py
@@ -34,9 +34,8 @@ class SampleStrategy(IStrategy):
     # Minimal ROI designed for the strategy.
     # This attribute will be overridden if the config file contains "minimal_roi".
     minimal_roi = {
-        "40": 0.0,
-        "30": 0.01,
-        "20": 0.02,
+        "60": 0.01,
+        "30": 0.02,
         "0": 0.04
     }
 
@@ -99,13 +98,16 @@ def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame
         :return: a Dataframe with all mandatory indicators for the strategies
         """
 
-        # Momentum Indicator
+        # Momentum Indicators
         # ------------------------------------
 
-        # ADX
-        dataframe['adx'] = ta.ADX(dataframe)
+        # RSI
+        dataframe['rsi'] = ta.RSI(dataframe)
 
         """
+        # ADX
+        # dataframe['adx'] = ta.ADX(dataframe)
+
         # Awesome oscillator
         dataframe['ao'] = qtpylib.awesome_oscillator(dataframe)
 
@@ -133,9 +135,6 @@ def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame
         # ROC
         dataframe['roc'] = ta.ROC(dataframe)
 
-        # RSI
-        dataframe['rsi'] = ta.RSI(dataframe)
-
         # Inverse Fisher transform on RSI, values [-1.0, 1.0] (https://goo.gl/2JGGoy)
         rsi = 0.1 * (dataframe['rsi'] - 50)
         dataframe['fisher_rsi'] = (numpy.exp(2 * rsi) - 1) / (numpy.exp(2 * rsi) + 1)
@@ -255,7 +254,7 @@ def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame
         dataframe['ha_low'] = heikinashi['low']
         """
 
-        # Retrieve best bid and best ask
+        # Retrieve best bid and best ask from the orderbook
         # ------------------------------------
         """
         # first check if dataprovider is available
@@ -277,9 +276,9 @@ def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
         """
         dataframe.loc[
             (
-                (dataframe['adx'] > 30) &
-                (dataframe['tema'] <= dataframe['bb_middleband']) &
-                (dataframe['tema'] > dataframe['tema'].shift(1)) &
+                (qtpylib.crossed_above(dataframe['rsi'], 30)) &  # Signal: RSI crosses above 30
+                (dataframe['tema'] <= dataframe['bb_middleband']) &  # Guard: tema below BB middle
+                (dataframe['tema'] > dataframe['tema'].shift(1)) &  # Guard: tema is raising
                 (dataframe['volume'] > 0)  # Make sure Volume is not 0
             ),
             'buy'] = 1
@@ -295,9 +294,9 @@ def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame
         """
         dataframe.loc[
             (
-                (dataframe['adx'] > 70) &
-                (dataframe['tema'] > dataframe['bb_middleband']) &
-                (dataframe['tema'] < dataframe['tema'].shift(1)) &
+                (qtpylib.crossed_above(dataframe['rsi'], 70)) &  # Signal: RSI crosses above 70
+                (dataframe['tema'] > dataframe['bb_middleband']) &  # Guard: tema above BB middle
+                (dataframe['tema'] < dataframe['tema'].shift(1)) &  # Guard: tema is falling
                 (dataframe['volume'] > 0)  # Make sure Volume is not 0
             ),
             'sell'] = 1


Test patch:
diff --git a/tests/strategy/test_strategy.py b/tests/strategy/test_strategy.py
--- a/tests/strategy/test_strategy.py
+++ b/tests/strategy/test_strategy.py
@@ -39,7 +39,7 @@ def test_search_strategy():
 def test_load_strategy(default_conf, result):
     default_conf.update({'strategy': 'SampleStrategy'})
     resolver = StrategyResolver(default_conf)
-    assert 'adx' in resolver.strategy.advise_indicators(result, {'pair': 'ETH/BTC'})
+    assert 'rsi' in resolver.strategy.advise_indicators(result, {'pair': 'ETH/BTC'})
 
 
 def test_load_strategy_base64(result, caplog, default_conf):
@@ -48,7 +48,7 @@ def test_load_strategy_base64(result, caplog, default_conf):
     default_conf.update({'strategy': 'SampleStrategy:{}'.format(encoded_string)})
 
     resolver = StrategyResolver(default_conf)
-    assert 'adx' in resolver.strategy.advise_indicators(result, {'pair': 'ETH/BTC'})
+    assert 'rsi' in resolver.strategy.advise_indicators(result, {'pair': 'ETH/BTC'})
     # Make sure strategy was loaded from base64 (using temp directory)!!
     assert log_has_re(r"Using resolved strategy SampleStrategy from '"
                       + tempfile.gettempdir() + r"/.*/SampleStrategy\.py'\.\.\.", caplog)