""" No Exit Signals Strategy - Target 30% Monthly Based on analysis showing exit signals have 12-30% win rate while ROI has 100% win rate Key Changes: 1. NO EXIT SIGNALS (they kill profits) 2. Only use ROI and trailing stops 3. 6x leverage (aggressive but safer than 10x) 4. Tight, fast ROI targets (30%+ monthly needs fast profits) 5. BTC/ETH only (most liquid) 6. Keep proven TEMA entry logic """ import numpy as np from pandas import DataFrame from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter import talib.abstract as ta from datetime import datetime from typing import Optional class NoExitSignals(IStrategy): INTERFACE_VERSION = 3 can_short = True # ULTRA-FAST ROI - Exit winners VERY quickly minimal_roi = { "0": 0.04, # 4% immediate (0.67% real with 6x) "2": 0.025, # 2.5% after 2 min "5": 0.02, # 2% after 5 min "10": 0.015, # 1.5% after 10 min "20": 0.01 # 1% after 20 min } # Balanced stop loss stoploss = -0.12 # 12% (2% real move with 6x leverage) # Aggressive trailing stop trailing_stop = True trailing_stop_positive = 0.008 # Start trailing at 0.8% trailing_stop_positive_offset = 0.012 # Trail by 1.2% trailing_only_offset_is_reached = True timeframe = '5m' # Fast timeframe for more opportunities startup_candle_count = 50 # 6x leverage (aggressive but not crazy) leverage_num = IntParameter(5, 7, default=6, space='buy', optimize=False) # Looser entry filters (more opportunities) rsi_buy_long = IntParameter(35, 50, default=42, space='buy', optimize=True) rsi_buy_short = IntParameter(50, 65, default=58, space='buy', optimize=True) adx_min = IntParameter(15, 25, default=20, space='buy', optimize=True) volume_mult = DecimalParameter(0.8, 1.5, default=1.0, decimals=1, space='buy', optimize=True) # NO EXIT SIGNALS - This is critical! use_exit_signal = False def leverage(self, pair: str, current_time, current_rate: float, proposed_leverage: float, max_leverage: float, side: str, **kwargs) -> float: return self.leverage_num.value def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # Fast indicators for 5min timeframe dataframe['rsi'] = ta.RSI(dataframe, timeperiod=9) dataframe['adx'] = ta.ADX(dataframe, timeperiod=9) # Fast EMAs for trend dataframe['ema12'] = ta.EMA(dataframe, timeperiod=12) dataframe['ema26'] = ta.EMA(dataframe, timeperiod=26) dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50) # MACD for momentum macd = ta.MACD(dataframe, fastperiod=12, slowperiod=26, signalperiod=9) dataframe['macd'] = macd['macd'] dataframe['macdsignal'] = macd['macdsignal'] dataframe['macdhist'] = macd['macdhist'] # Bollinger Bands bollinger = ta.BBANDS(dataframe, timeperiod=20, nbdevup=2.0, nbdevdn=2.0) dataframe['bb_lower'] = bollinger['lowerband'] dataframe['bb_middle'] = bollinger['middleband'] dataframe['bb_upper'] = bollinger['upperband'] # Volume dataframe['volume_mean'] = dataframe['volume'].rolling(window=20).mean() # ATR dataframe['atr'] = ta.ATR(dataframe, timeperiod=14) # Stochastic for oversold/overbought stoch = ta.STOCH(dataframe, fastk_period=14, slowk_period=3, slowd_period=3) dataframe['slowk'] = stoch['slowk'] dataframe['slowd'] = stoch['slowd'] return dataframe def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """ Two types of trades: 1. NORMAL trades - Standard signals 2. SURE trades - All signals align (bigger position size) """ # LONG - Oversold bounce in uptrend (STRICTER = fewer bad trades) long_conditions = ( # Trend: Price above EMA50 AND price trending up (dataframe['close'] > dataframe['ema50']) & (dataframe['ema12'] > dataframe['ema26']) & # EMA cross (dataframe['ema26'] > dataframe['ema50']) & # All EMAs aligned # Momentum: RSI oversold in a CONTROLLED way (dataframe['rsi'] < self.rsi_buy_long.value) & (dataframe['rsi'] > 30) & # Not TOO oversold (avoid falling knives) (dataframe['rsi'] > dataframe['rsi'].shift(1)) & # RSI turning up # Trend strength - MUST be in a trend (dataframe['adx'] > 22) & # Higher minimum # MACD MUST be bullish (not "or turning") (dataframe['macd'] > dataframe['macdsignal']) & (dataframe['macdhist'] > 0) & # MACD above zero line # Volume confirmation - STRONG volume (dataframe['volume'] > dataframe['volume_mean'] * 1.2) & # Price structure: MUST be near lower BB (clear oversold) (dataframe['close'] < dataframe['bb_lower'] * 1.01) & # Stochastic oversold (dataframe['slowk'] < 35) ) # SURE LONG - All signals strongly align (high confidence) sure_long = ( long_conditions & (dataframe['adx'] > 25) & # Strong trend (dataframe['macd'] > dataframe['macdsignal']) & # MACD bullish (dataframe['slowk'] < 25) & # Very oversold (dataframe['volume'] > dataframe['volume_mean'] * 1.3) & # High volume (dataframe['macdhist'] > dataframe['macdhist'].shift(1)) # MACD turning up ) dataframe.loc[long_conditions, 'enter_long'] = 1 dataframe.loc[sure_long, 'enter_tag'] = 'sure_long' # Tag for bigger position # SHORT - Overbought rejection in downtrend (STRICTER) short_conditions = ( # Trend: Price below EMA50 AND price trending down (dataframe['close'] < dataframe['ema50']) & (dataframe['ema12'] < dataframe['ema26']) & # EMA cross (dataframe['ema26'] < dataframe['ema50']) & # All EMAs aligned # Momentum: RSI overbought in a CONTROLLED way (dataframe['rsi'] > self.rsi_buy_short.value) & (dataframe['rsi'] < 70) & # Not TOO overbought (dataframe['rsi'] < dataframe['rsi'].shift(1)) & # RSI turning down # Trend strength - MUST be in a trend (dataframe['adx'] > 22) & # MACD MUST be bearish (not "or turning") (dataframe['macd'] < dataframe['macdsignal']) & (dataframe['macdhist'] < 0) & # MACD below zero line # Volume confirmation - STRONG volume (dataframe['volume'] > dataframe['volume_mean'] * 1.2) & # Price structure: MUST be near upper BB (clear overbought) (dataframe['close'] > dataframe['bb_upper'] * 0.99) & # Stochastic overbought (dataframe['slowk'] > 65) ) # SURE SHORT - All signals strongly align (high confidence) sure_short = ( short_conditions & (dataframe['adx'] > 25) & # Strong trend (dataframe['macd'] < dataframe['macdsignal']) & # MACD bearish (dataframe['slowk'] > 75) & # Very overbought (dataframe['volume'] > dataframe['volume_mean'] * 1.3) & # High volume (dataframe['macdhist'] < dataframe['macdhist'].shift(1)) # MACD turning down ) dataframe.loc[short_conditions, 'enter_short'] = 1 dataframe.loc[sure_short, 'enter_tag'] = 'sure_short' # Tag for bigger position return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """ NO EXIT SIGNALS - Let ROI and trailing stops handle exits Exit signals have 12-30% win rate, ROI has 100% win rate """ # Never exit based on signals dataframe.loc[:, 'exit_long'] = 0 dataframe.loc[:, 'exit_short'] = 0 return dataframe def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float, proposed_stake: float, min_stake: Optional[float], max_stake: float, leverage: float, entry_tag: Optional[str], side: str, **kwargs) -> float: """ Dynamic position sizing: - SURE trades (all signals align): Use 95% of capital (GO BIG!) - NORMAL trades: Use 70% of capital (standard) """ if entry_tag in ['sure_long', 'sure_short']: # SURE TRADE - All signals align, bet BIG! multiplier = 0.95 else: # NORMAL TRADE - Standard sizing multiplier = 0.70 stake = max_stake * multiplier if min_stake is not None: stake = max(stake, min_stake) return min(stake, max_stake)