diff --git a/docs/strategy-customization.md b/docs/strategy-customization.md index adcdf0208..ca76071af 100644 --- a/docs/strategy-customization.md +++ b/docs/strategy-customization.md @@ -138,15 +138,19 @@ 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 + (dataframe['tema'] > dataframe['tema'].shift(1)) & # Guard + (dataframe['volume'] > 0) # Make sure Volume is not 0 ), 'buy'] = 1 return dataframe ``` +!!! Note + Buying requires sellers to buy from - therefore volume needs to be > 0 (`dataframe['volume'] > 0`) to make sure that the bot does not buy/sell in no-activity periods. + ### Sell signal rules Edit the method `populate_sell_trend()` into your strategy file to update your sell strategy. @@ -168,9 +172,10 @@ 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 + (dataframe['tema'] < dataframe['tema'].shift(1)) & # Guard + (dataframe['volume'] > 0) # Make sure Volume is not 0 ), 'sell'] = 1 return dataframe diff --git a/tests/strategy/test_strategy.py b/tests/strategy/test_strategy.py index 88e29b40e..52216e0ef 100644 --- 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) diff --git a/user_data/strategies/sample_strategy.py b/user_data/strategies/sample_strategy.py index 623addb1e..35ddbdf68 100644 --- 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 @@ class SampleStrategy(IStrategy): :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 @@ class SampleStrategy(IStrategy): # 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 @@ class SampleStrategy(IStrategy): 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 @@ class SampleStrategy(IStrategy): """ 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 @@ class SampleStrategy(IStrategy): """ 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