From 77f0b51d77311af531bca8c21b2dac6219416d94 Mon Sep 17 00:00:00 2001 From: psionyx2311 <42845289+psionyx2311@users.noreply.github.com> Date: Sat, 9 May 2020 17:58:30 -0400 Subject: [PATCH 1/3] Create ReinforcedSmoothScalp_hyperopt.py --- .../hyperopts/ReinforcedSmoothScalp_hyperopt | 211 ++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 user_data/hyperopts/ReinforcedSmoothScalp_hyperopt diff --git a/user_data/hyperopts/ReinforcedSmoothScalp_hyperopt b/user_data/hyperopts/ReinforcedSmoothScalp_hyperopt new file mode 100644 index 0000000..448cf68 --- /dev/null +++ b/user_data/hyperopts/ReinforcedSmoothScalp_hyperopt @@ -0,0 +1,211 @@ +# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement + +from functools import reduce +from typing import Any, Callable, Dict, List + +import talib.abstract as ta +from pandas import DataFrame +from skopt.space import Categorical, Dimension, Integer + +import freqtrade.vendor.qtpylib.indicators as qtpylib +from freqtrade.optimize.hyperopt_interface import IHyperOpt + + +class ReinforcedSmoothScalp(IHyperOpt): + """ + Default hyperopt provided by the Freqtrade bot. + You can override it with your own Hyperopt + """ + @staticmethod + def populate_indicators(dataframe: DataFrame, metadata: dict) -> DataFrame: + + dataframe['ema_high'] = ta.EMA(dataframe, timeperiod=5, price='high') + dataframe['ema_close'] = ta.EMA(dataframe, timeperiod=5, price='close') + dataframe['ema_low'] = ta.EMA(dataframe, timeperiod=5, price='low') + stoch_fast = ta.STOCHF(dataframe, 5, 3, 0, 3, 0) + dataframe['fastd'] = stoch_fast['fastd'] + dataframe['fastk'] = stoch_fast['fastk'] + dataframe['adx'] = ta.ADX(dataframe) + dataframe['cci'] = ta.CCI(dataframe, timeperiod=20) + dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) + dataframe['mfi'] = ta.MFI(dataframe) + + # required for graphing + bollinger = qtpylib.bollinger_bands(dataframe['close'], window=20, stds=2) + dataframe['bb_lowerband'] = bollinger['lower'] + dataframe['bb_upperband'] = bollinger['upper'] + dataframe['bb_middleband'] = bollinger['mid'] + + return dataframe + + @staticmethod + def buy_strategy_generator(params: Dict[str, Any]) -> Callable: + """ + Define the buy strategy parameters to be used by Hyperopt. + """ + def populate_buy_trend(dataframe: DataFrame, metadata: dict) -> DataFrame: + """ + Buy strategy Hyperopt will build and use. + """ + conditions = [] + + # GUARDS AND TRENDS + if 'mfi-enabled' in params and params['mfi-enabled']: + conditions.append(dataframe['mfi'] < params['mfi-value']) + if 'fastd-enabled' in params and params['fastd-enabled']: + conditions.append(dataframe['fastd'] < params['fastd-value']) + if 'adx-enabled' in params and params['adx-enabled']: + conditions.append(dataframe['adx'] > params['adx-value']) + #if 'rsi-enabled' in params and params['rsi-enabled']: + # conditions.append(dataframe['rsi'] < params['rsi-value']) + if 'fastk-enabled' in params and params['fastk-enabled']: + conditions.append(dataframe['fastk'] < params['fastk-value']) + # TRIGGERS + #if 'trigger' in params: + # if params['trigger'] == 'bb_lower': + # conditions.append(dataframe['close'] < dataframe['bb_lowerband']) + # if params['trigger'] == 'macd_cross_signal': + # conditions.append(qtpylib.crossed_above( + # dataframe['macd'], dataframe['macdsignal'] + # )) + # if params['trigger'] == 'sar_reversal': + # conditions.append(qtpylib.crossed_above( + # dataframe['close'], dataframe['sar'] + # )) + + + if conditions: + dataframe.loc[ + reduce(lambda x, y: x & y, conditions), + 'buy'] = 1 + + return dataframe + + return populate_buy_trend + + @staticmethod + def indicator_space() -> List[Dimension]: + """ + Define your Hyperopt space for searching buy strategy parameters. + """ + return [ + Integer(10, 25, name='mfi-value'), + Integer(15, 45, name='fastd-value'), + Integer(15, 45, name='fastk-value'), + Integer(20, 50, name='adx-value'), + #Integer(20, 40, name='rsi-value'), + Categorical([True, False], name='mfi-enabled'), + Categorical([True, False], name='fastd-enabled'), + Categorical([True, False], name='adx-enabled'), + Categorical([True, False], name='fastk-enabled'), + #Categorical([True, False], name='rsi-enabled'), + #Categorical(['bb_lower', 'macd_cross_signal', 'sar_reversal'], name='trigger') + ] + + @staticmethod + def sell_strategy_generator(params: Dict[str, Any]) -> Callable: + """ + Define the sell strategy parameters to be used by Hyperopt. + """ + def populate_sell_trend(dataframe: DataFrame, metadata: dict) -> DataFrame: + """ + Sell strategy Hyperopt will build and use. + """ + conditions = [] + + # GUARDS AND TRENDS + if 'sell-mfi-enabled' in params and params['sell-mfi-enabled']: + conditions.append(dataframe['mfi'] > params['sell-mfi-value']) + if 'sell-fastd-enabled' in params and params['sell-fastd-enabled']: + conditions.append(dataframe['fastd'] > params['sell-fastd-value']) + if 'sell-adx-enabled' in params and params['sell-adx-enabled']: + conditions.append(dataframe['adx'] < params['sell-adx-value']) + if 'sell-fastk-enabled' in params and params['sell-fastk-enabled']: + conditions.append(dataframe['fastk'] > params['sell-fastk-value']) + if 'sell-cci-enabled' in params and params['sell-cci-enabled']: + conditions.append(dataframe['cci'] > params['sell-cci-value']) + + # TRIGGERS + if 'sell-trigger' in params: + #if params['sell-trigger'] == 'sell-bb_upper': + # conditions.append(dataframe['close'] > dataframe['bb_upperband']) + #if params['sell-trigger'] == 'sell-macd_cross_signal': + # conditions.append(qtpylib.crossed_above( + # dataframe['macdsignal'], dataframe['macd'] + # )) + #if params['sell-trigger'] == 'sell-sar_reversal': + # conditions.append(qtpylib.crossed_above( + # dataframe['sar'], dataframe['close'] + # )) + + if conditions: + dataframe.loc[ + reduce(lambda x, y: x & y, conditions), + 'sell'] = 1 + + return dataframe + + return populate_sell_trend + + @staticmethod + def sell_indicator_space() -> List[Dimension]: + """ + Define your Hyperopt space for searching sell strategy parameters. + """ + return [ + Integer(75, 100, name='sell-mfi-value'), + Integer(50, 100, name='sell-fastd-value'), + Integer(50, 100, name='sell-fastk-value'), + Integer(50, 100, name='sell-adx-value'), + Integer(100, 200, name='sell-cci-value'), + Categorical([True, False], name='sell-mfi-enabled'), + Categorical([True, False], name='sell-fastd-enabled'), + Categorical([True, False], name='sell-adx-enabled'), + Categorical([True, False], name='sell-cci-enabled'), + Categorical([True, False], name='sell-fastk-enabled'), + #Categorical(['sell-bb_upper', + # 'sell-macd_cross_signal', + # 'sell-sar_reversal'], name='sell-trigger') + ] + + def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + dataframe.loc[ + ( + ( + (dataframe['open'] < dataframe['ema_low']) & + (dataframe['adx'] > 30) & + (dataframe['mfi'] < 30) & + ( + (dataframe['fastk'] < 30) & + (dataframe['fastd'] < 30) & + (qtpylib.crossed_above(dataframe['fastk'], dataframe['fastd'])) + ) & + (dataframe['resample_sma'] < dataframe['close']) + ) + # | + # # try to get some sure things independent of resample + # ((dataframe['rsi'] - dataframe['mfi']) < 10) & + # (dataframe['mfi'] < 30) & + # (dataframe['cci'] < -200) + ), + 'buy'] = 1 + return dataframe + + def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + dataframe.loc[ + ( + ( + ( + (dataframe['open'] >= dataframe['ema_high']) + + ) | + ( + (qtpylib.crossed_above(dataframe['fastk'], 70)) | + (qtpylib.crossed_above(dataframe['fastd'], 70)) + + ) + ) & (dataframe['cci'] > 100) + ) + , + 'sell'] = 1 + return dataframe From 533a9ee90746bc3d7b50578416b396610955a89a Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 2 Aug 2020 10:56:31 +0200 Subject: [PATCH 2/3] Align hyperopt to best practices --- ...ropt => ReinforcedSmoothScalp_hyperopt.py} | 66 +++++++------------ .../berlinguyinca/ReinforcedSmoothScalp.py | 25 +------ 2 files changed, 26 insertions(+), 65 deletions(-) rename user_data/hyperopts/{ReinforcedSmoothScalp_hyperopt => ReinforcedSmoothScalp_hyperopt.py} (77%) diff --git a/user_data/hyperopts/ReinforcedSmoothScalp_hyperopt b/user_data/hyperopts/ReinforcedSmoothScalp_hyperopt.py similarity index 77% rename from user_data/hyperopts/ReinforcedSmoothScalp_hyperopt rename to user_data/hyperopts/ReinforcedSmoothScalp_hyperopt.py index 448cf68..fcdffa9 100644 --- a/user_data/hyperopts/ReinforcedSmoothScalp_hyperopt +++ b/user_data/hyperopts/ReinforcedSmoothScalp_hyperopt.py @@ -16,27 +16,6 @@ class ReinforcedSmoothScalp(IHyperOpt): Default hyperopt provided by the Freqtrade bot. You can override it with your own Hyperopt """ - @staticmethod - def populate_indicators(dataframe: DataFrame, metadata: dict) -> DataFrame: - - dataframe['ema_high'] = ta.EMA(dataframe, timeperiod=5, price='high') - dataframe['ema_close'] = ta.EMA(dataframe, timeperiod=5, price='close') - dataframe['ema_low'] = ta.EMA(dataframe, timeperiod=5, price='low') - stoch_fast = ta.STOCHF(dataframe, 5, 3, 0, 3, 0) - dataframe['fastd'] = stoch_fast['fastd'] - dataframe['fastk'] = stoch_fast['fastk'] - dataframe['adx'] = ta.ADX(dataframe) - dataframe['cci'] = ta.CCI(dataframe, timeperiod=20) - dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) - dataframe['mfi'] = ta.MFI(dataframe) - - # required for graphing - bollinger = qtpylib.bollinger_bands(dataframe['close'], window=20, stds=2) - dataframe['bb_lowerband'] = bollinger['lower'] - dataframe['bb_upperband'] = bollinger['upper'] - dataframe['bb_middleband'] = bollinger['mid'] - - return dataframe @staticmethod def buy_strategy_generator(params: Dict[str, Any]) -> Callable: @@ -56,12 +35,12 @@ class ReinforcedSmoothScalp(IHyperOpt): conditions.append(dataframe['fastd'] < params['fastd-value']) if 'adx-enabled' in params and params['adx-enabled']: conditions.append(dataframe['adx'] > params['adx-value']) - #if 'rsi-enabled' in params and params['rsi-enabled']: - # conditions.append(dataframe['rsi'] < params['rsi-value']) + # if 'rsi-enabled' in params and params['rsi-enabled']: + # conditions.append(dataframe['rsi'] < params['rsi-value']) if 'fastk-enabled' in params and params['fastk-enabled']: conditions.append(dataframe['fastk'] < params['fastk-value']) # TRIGGERS - #if 'trigger' in params: + # if 'trigger' in params: # if params['trigger'] == 'bb_lower': # conditions.append(dataframe['close'] < dataframe['bb_lowerband']) # if params['trigger'] == 'macd_cross_signal': @@ -73,11 +52,13 @@ class ReinforcedSmoothScalp(IHyperOpt): # dataframe['close'], dataframe['sar'] # )) - - if conditions: - dataframe.loc[ - reduce(lambda x, y: x & y, conditions), - 'buy'] = 1 + # Check that volume is not 0 + conditions.append(dataframe['volume'] > 0) + + if conditions: + dataframe.loc[ + reduce(lambda x, y: x & y, conditions), + 'buy'] = 1 return dataframe @@ -93,13 +74,13 @@ class ReinforcedSmoothScalp(IHyperOpt): Integer(15, 45, name='fastd-value'), Integer(15, 45, name='fastk-value'), Integer(20, 50, name='adx-value'), - #Integer(20, 40, name='rsi-value'), + # Integer(20, 40, name='rsi-value'), Categorical([True, False], name='mfi-enabled'), Categorical([True, False], name='fastd-enabled'), Categorical([True, False], name='adx-enabled'), Categorical([True, False], name='fastk-enabled'), - #Categorical([True, False], name='rsi-enabled'), - #Categorical(['bb_lower', 'macd_cross_signal', 'sar_reversal'], name='trigger') + # Categorical([True, False], name='rsi-enabled'), + # Categorical(['bb_lower', 'macd_cross_signal', 'sar_reversal'], name='trigger') ] @staticmethod @@ -126,22 +107,25 @@ class ReinforcedSmoothScalp(IHyperOpt): conditions.append(dataframe['cci'] > params['sell-cci-value']) # TRIGGERS - if 'sell-trigger' in params: - #if params['sell-trigger'] == 'sell-bb_upper': + # if 'sell-trigger' in params: + # if params['sell-trigger'] == 'sell-bb_upper': # conditions.append(dataframe['close'] > dataframe['bb_upperband']) - #if params['sell-trigger'] == 'sell-macd_cross_signal': + # if params['sell-trigger'] == 'sell-macd_cross_signal': # conditions.append(qtpylib.crossed_above( # dataframe['macdsignal'], dataframe['macd'] # )) - #if params['sell-trigger'] == 'sell-sar_reversal': + # if params['sell-trigger'] == 'sell-sar_reversal': # conditions.append(qtpylib.crossed_above( # dataframe['sar'], dataframe['close'] # )) - if conditions: - dataframe.loc[ - reduce(lambda x, y: x & y, conditions), - 'sell'] = 1 + # Check that volume is not 0 + conditions.append(dataframe['volume'] > 0) + + if conditions: + dataframe.loc[ + reduce(lambda x, y: x & y, conditions), + 'sell'] = 1 return dataframe @@ -163,7 +147,7 @@ class ReinforcedSmoothScalp(IHyperOpt): Categorical([True, False], name='sell-adx-enabled'), Categorical([True, False], name='sell-cci-enabled'), Categorical([True, False], name='sell-fastk-enabled'), - #Categorical(['sell-bb_upper', + # Categorical(['sell-bb_upper', # 'sell-macd_cross_signal', # 'sell-sar_reversal'], name='sell-trigger') ] diff --git a/user_data/strategies/berlinguyinca/ReinforcedSmoothScalp.py b/user_data/strategies/berlinguyinca/ReinforcedSmoothScalp.py index 70f9b74..685d590 100644 --- a/user_data/strategies/berlinguyinca/ReinforcedSmoothScalp.py +++ b/user_data/strategies/berlinguyinca/ReinforcedSmoothScalp.py @@ -23,7 +23,7 @@ class ReinforcedSmoothScalp(IStrategy): # This attribute will be overridden if the config file contains "stoploss" # should not be below 3% loss - stoploss = -0.8 + stoploss = -0.1 # Optimal ticker interval for the strategy # the shorter the better ticker_interval = '1m' @@ -32,7 +32,6 @@ class ReinforcedSmoothScalp(IStrategy): resample_factor = 5 def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - dataframe = self.resample(dataframe, self.ticker_interval, self.resample_factor) dataframe['ema_high'] = ta.EMA(dataframe, timeperiod=5, price='high') dataframe['ema_close'] = ta.EMA(dataframe, timeperiod=5, price='close') @@ -94,25 +93,3 @@ class ReinforcedSmoothScalp(IStrategy): , 'sell'] = 1 return dataframe - - def resample(self, dataframe, interval, factor): - # defines the reinforcement logic - # resampled dataframe to establish if we are in an uptrend, downtrend or sideways trend - df = dataframe.copy() - df = df.set_index(DatetimeIndex(df['date'])) - ohlc_dict = { - 'open': 'first', - 'high': 'max', - 'low': 'min', - 'close': 'last' - } - df = df.resample(str(int(interval[:-1]) * factor) + 'min', - label="right").agg(ohlc_dict).dropna(how='any') - df['resample_sma'] = ta.SMA(df, timeperiod=50, price='close') - df = df.drop(columns=['open', 'high', 'low', 'close']) - df = df.resample(interval[:-1] + 'min') - df = df.interpolate(method='time') - df['date'] = df.index - df.index = range(len(df)) - dataframe = merge(dataframe, df, on='date', how='left') - return dataframe From 6312732255c10f00bc290c33da1b56d9e104362f Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 2 Aug 2020 11:01:27 +0200 Subject: [PATCH 3/3] Add volume > 0 check --- user_data/hyperopts/AverageHyperopt.py | 3 +++ user_data/hyperopts/MACDStrategy_hyperopt.py | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/user_data/hyperopts/AverageHyperopt.py b/user_data/hyperopts/AverageHyperopt.py index 0e6797b..75b5f95 100644 --- a/user_data/hyperopts/AverageHyperopt.py +++ b/user_data/hyperopts/AverageHyperopt.py @@ -48,6 +48,9 @@ class AverageHyperopt(IHyperOpt): dataframe[f"maMedium({params['trigger'][1]})"]) ) + # Check that volume is not 0 + conditions.append(dataframe['volume'] > 0) + if conditions: dataframe.loc[ reduce(lambda x, y: x & y, conditions), diff --git a/user_data/hyperopts/MACDStrategy_hyperopt.py b/user_data/hyperopts/MACDStrategy_hyperopt.py index d10b566..473e9c6 100644 --- a/user_data/hyperopts/MACDStrategy_hyperopt.py +++ b/user_data/hyperopts/MACDStrategy_hyperopt.py @@ -52,7 +52,8 @@ class MACDStrategy_hyperopt(IHyperOpt): dataframe.loc[ ( (dataframe['macd'] > dataframe['macdsignal']) & - (dataframe['cci'] <= params['buy-cci-value']) + (dataframe['cci'] <= params['buy-cci-value']) & + (dataframe['volume'] > 0) # Make sure Volume is not 0 ), 'buy'] = 1