From 790e6146f504f6a3f1ae35a0630701ae4afe81b2 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 14 Oct 2019 20:13:34 +0200 Subject: [PATCH 1/5] Use crossed() in sample strategy --- docs/strategy-customization.md | 17 +++++++++++------ user_data/strategies/sample_strategy.py | 10 +++++----- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/docs/strategy-customization.md b/docs/strategy-customization.md index adcdf0208..39a36c469 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['adx'], 30)) & # Signal: ADX crosses baove 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 backtesting 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['adx'], 70)) & # Signal: ADX 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 ), 'sell'] = 1 return dataframe diff --git a/user_data/strategies/sample_strategy.py b/user_data/strategies/sample_strategy.py index 623addb1e..84ff9ec2c 100644 --- a/user_data/strategies/sample_strategy.py +++ b/user_data/strategies/sample_strategy.py @@ -277,9 +277,9 @@ class SampleStrategy(IStrategy): """ dataframe.loc[ ( - (dataframe['adx'] > 30) & - (dataframe['tema'] <= dataframe['bb_middleband']) & - (dataframe['tema'] > dataframe['tema'].shift(1)) & + (qtpylib.crossed_above(dataframe['adx'], 30)) & # Signal: ADX 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 +295,9 @@ class SampleStrategy(IStrategy): """ dataframe.loc[ ( - (dataframe['adx'] > 70) & + (qtpylib.crossed_above(dataframe['adx'], 70)) & # Signal: - ADX crosses above 70 (dataframe['tema'] > dataframe['bb_middleband']) & - (dataframe['tema'] < dataframe['tema'].shift(1)) & + (dataframe['tema'] < dataframe['tema'].shift(1)) & # Guard: tema is raising (dataframe['volume'] > 0) # Make sure Volume is not 0 ), 'sell'] = 1 From a320d4ccbae737b7103fa788644d19d395c42fb7 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 14 Oct 2019 20:42:08 +0200 Subject: [PATCH 2/5] Don't sell with 0 profit in samplestrategy --- user_data/strategies/sample_strategy.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/user_data/strategies/sample_strategy.py b/user_data/strategies/sample_strategy.py index 84ff9ec2c..6d544c667 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 } From ace70510f38902dd47f2a62484700fd08542207f Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 15 Oct 2019 14:50:51 +0200 Subject: [PATCH 3/5] Wording fixes --- docs/strategy-customization.md | 8 ++++---- user_data/strategies/sample_strategy.py | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/strategy-customization.md b/docs/strategy-customization.md index 39a36c469..40da697e6 100644 --- a/docs/strategy-customization.md +++ b/docs/strategy-customization.md @@ -138,7 +138,7 @@ def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """ dataframe.loc[ ( - (qtpylib.crossed_above(dataframe['adx'], 30)) & # Signal: ADX crosses baove 30 + (qtpylib.crossed_above(dataframe['adx'], 30)) & # Signal: ADX 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 @@ -149,7 +149,7 @@ def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: ``` !!! Note - Buying requires sellers to buy from - therefore volume needs to be > 0 (`dataframe['volume'] > 0`) to make sure backtesting does not buy/sell in no-activity periods. + Buying requires sellers to buy from - therefore volume needs to be > 0 (`dataframe['volume'] > 0`) to make sure that the does not buy/sell in no-activity periods. ### Sell signal rules @@ -172,9 +172,9 @@ def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame """ dataframe.loc[ ( - (qtpylib.crossed_above(dataframe['adx'], 70)) & # Signal: ADX crosses above 30 + (qtpylib.crossed_above(dataframe['adx'], 70)) & # Signal: ADX crosses above 70 (dataframe['tema'] > dataframe['bb_middleband']) & # Guard - (dataframe['tema'] < dataframe['tema'].shift(1)) & #Guard + (dataframe['tema'] < dataframe['tema'].shift(1)) & # Guard (dataframe['volume'] > 0) # Make sure Volume is not 0 ), 'sell'] = 1 diff --git a/user_data/strategies/sample_strategy.py b/user_data/strategies/sample_strategy.py index 6d544c667..61f4fc15f 100644 --- a/user_data/strategies/sample_strategy.py +++ b/user_data/strategies/sample_strategy.py @@ -294,9 +294,9 @@ class SampleStrategy(IStrategy): """ dataframe.loc[ ( - (qtpylib.crossed_above(dataframe['adx'], 70)) & # Signal: - ADX crosses above 70 - (dataframe['tema'] > dataframe['bb_middleband']) & - (dataframe['tema'] < dataframe['tema'].shift(1)) & # Guard: tema is raising + (qtpylib.crossed_above(dataframe['adx'], 70)) & # Signal: ADX 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 From e6e35c25849160774883e0ed4ed2a2ec56c41430 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 15 Oct 2019 19:38:23 +0200 Subject: [PATCH 4/5] Switch samplestrategy from ADX to RSI --- docs/strategy-customization.md | 6 +++--- tests/strategy/test_strategy.py | 4 ++-- user_data/strategies/sample_strategy.py | 11 +++++------ 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/docs/strategy-customization.md b/docs/strategy-customization.md index 40da697e6..ca76071af 100644 --- a/docs/strategy-customization.md +++ b/docs/strategy-customization.md @@ -138,7 +138,7 @@ def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """ dataframe.loc[ ( - (qtpylib.crossed_above(dataframe['adx'], 30)) & # Signal: ADX crosses above 30 + (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 @@ -149,7 +149,7 @@ def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: ``` !!! Note - Buying requires sellers to buy from - therefore volume needs to be > 0 (`dataframe['volume'] > 0`) to make sure that the does not buy/sell in no-activity periods. + 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 @@ -172,7 +172,7 @@ def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame """ dataframe.loc[ ( - (qtpylib.crossed_above(dataframe['adx'], 70)) & # Signal: ADX crosses above 70 + (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 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 61f4fc15f..6870de190 100644 --- a/user_data/strategies/sample_strategy.py +++ b/user_data/strategies/sample_strategy.py @@ -102,8 +102,10 @@ class SampleStrategy(IStrategy): # ------------------------------------ # ADX - dataframe['adx'] = ta.ADX(dataframe) + # dataframe['adx'] = ta.ADX(dataframe) + # RSI + dataframe['rsi'] = ta.RSI(dataframe) """ # Awesome oscillator dataframe['ao'] = qtpylib.awesome_oscillator(dataframe) @@ -132,9 +134,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) @@ -276,7 +275,7 @@ class SampleStrategy(IStrategy): """ dataframe.loc[ ( - (qtpylib.crossed_above(dataframe['adx'], 30)) & # Signal: ADX crosses above 30 + (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 @@ -294,7 +293,7 @@ class SampleStrategy(IStrategy): """ dataframe.loc[ ( - (qtpylib.crossed_above(dataframe['adx'], 70)) & # Signal: ADX crosses above 70 + (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 From 36d5bb6f9939c91510f4721b358aff3568d921a6 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Tue, 15 Oct 2019 21:11:41 +0300 Subject: [PATCH 5/5] Adjust ADX placement in the comments --- user_data/strategies/sample_strategy.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/user_data/strategies/sample_strategy.py b/user_data/strategies/sample_strategy.py index 6870de190..35ddbdf68 100644 --- a/user_data/strategies/sample_strategy.py +++ b/user_data/strategies/sample_strategy.py @@ -98,15 +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) @@ -253,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