# --- Imports --- import freqtrade.vendor.qtpylib.indicators as qtpylib import pandas as pd import talib.abstract as ta from freqtrade.strategy import DecimalParameter, IntParameter, IStrategy class Dopeyting(IStrategy): """ From Dopeyting see: https://old.reddit.com/r/algotrading/comments/1mcngpl/making_5_monthly_on_my_crypto_algorithm_here_is/ This is a trading strategy that enters a trade if 2 out of 3 conditions are met. Conditions for BUY: 1. 7-period SMA crosses above 25-period SMA. 2. RSI is below 32. 3. Price closes at or below the lower Bollinger Band * 1.002. Conditions for SELL: 1. 7-period SMA crosses below 25-period SMA. 2. RSI is above 70. 3. Price closes at or above the upper Bollinger Band. All parameters are optimizable via Hyperopt. """ # --- Strategy Configuration --- timeframe = "1h" # Stoploss configuration stoploss = -0.10 # Minimal ROI (disables ROI-based selling in favor of sell signals) minimal_roi = {"0": 100} # Trailing stoploss trailing_stop = False # --- Hyperoptable Parameters --- # MA Parameters ma_short_period = IntParameter(5, 20, default=7, space="buy", optimize=True) ma_long_period = IntParameter(20, 50, default=25, space="buy", optimize=True) # RSI Parameters rsi_period = IntParameter(10, 25, default=14, space="buy", optimize=True) rsi_buy_level = IntParameter(20, 40, default=32, space="buy", optimize=True) rsi_sell_level = IntParameter(60, 80, default=70, space="sell", optimize=True) # Bollinger Bands Parameters bb_period = IntParameter(15, 30, default=20, space="buy", optimize=True) bb_stddev = DecimalParameter(1.5, 2.5, default=2.0, space="buy", optimize=True) bb_buy_factor = DecimalParameter( 0.99, 1.01, default=1.002, space="buy", optimize=True ) bb_sell_factor = DecimalParameter( 0.99, 1.01, default=1.0, space="sell", optimize=True ) def populate_indicators( self, dataframe: pd.DataFrame, metadata: dict ) -> pd.DataFrame: """ Adds all necessary indicators to the given DataFrame. """ # Moving Averages dataframe["sma_short"] = ta.SMA( dataframe, timeperiod=self.ma_short_period.value ) dataframe["sma_long"] = ta.SMA(dataframe, timeperiod=self.ma_long_period.value) # RSI dataframe["rsi"] = ta.RSI(dataframe, timeperiod=self.rsi_period.value) # Bollinger Bands bollinger = qtpylib.bollinger_bands( qtpylib.typical_price(dataframe), window=self.bb_period.value, stds=self.bb_stddev.value, ) dataframe["bb_lowerband"] = bollinger["lower"] dataframe["bb_upperband"] = bollinger["upper"] return dataframe def populate_buy_trend( self, dataframe: pd.DataFrame, metadata: dict ) -> pd.DataFrame: """ Defines the buy signal logic. A buy signal is generated if at least 2 of the 3 conditions are met. """ # --- Define the 3 buy conditions --- # Condition 1: MA Crossover buy_cond_1 = qtpylib.crossed_above( dataframe["sma_short"], dataframe["sma_long"] ) # Condition 2: RSI Oversold buy_cond_2 = dataframe["rsi"] < self.rsi_buy_level.value # Condition 3: Price below Lower Bollinger Band buy_cond_3 = ( dataframe["close"] <= dataframe["bb_lowerband"] * self.bb_buy_factor.value ) # --- Combine conditions (at least 2 must be True) --- # In pandas, True is treated as 1 and False as 0, so we can sum them buy_conditions_sum = ( buy_cond_1.astype(int) + buy_cond_2.astype(int) + buy_cond_3.astype(int) ) # Set the buy signal dataframe.loc[(buy_conditions_sum >= 2), "buy"] = 1 return dataframe def populate_sell_trend( self, dataframe: pd.DataFrame, metadata: dict ) -> pd.DataFrame: """ Defines the sell signal logic. A sell signal is generated if at least 2 of the 3 conditions are met. """ # --- Define the 3 sell conditions --- # Condition 1: MA Crossunder sell_cond_1 = qtpylib.crossed_below( dataframe["sma_short"], dataframe["sma_long"] ) # Condition 2: RSI Overbought sell_cond_2 = dataframe["rsi"] > self.rsi_sell_level.value # Condition 3: Price above Upper Bollinger Band sell_cond_3 = ( dataframe["close"] >= dataframe["bb_upperband"] * self.bb_sell_factor.value ) # --- Combine conditions (at least 2 must be True) --- sell_conditions_sum = ( sell_cond_1.astype(int) + sell_cond_2.astype(int) + sell_cond_3.astype(int) ) # Set the sell signal dataframe.loc[(sell_conditions_sum >= 2), "sell"] = 1 return dataframe