//@version=5 strategy("Crypto 15m Multi-Layer Trading Strategy", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=10, commission_type=strategy.commission.percent, commission_value=0.05) group_basic = "Basic" group_ma = "Moving Averages" group_macd = "MACD" group_rsi = "RSI" group_atr = "ATR" group_advanced = "Advanced" group_display = "Display" initial_capital = input.float(1000, title="Initial Capital (USD)", group=group_basic) risk_per_trade = input.float(2.0, title="Risk Per Trade (%)", minval=0.5, maxval=5, group=group_basic) ma_fast_len = input.int(5, title="Fast MA Period", minval=3, maxval=20, group=group_ma) ma_mid_len = input.int(20, title="Mid MA Period", minval=10, maxval=50, group=group_ma) ma_slow_len = input.int(60, title="Slow MA Period", minval=30, maxval=200, group=group_ma) macd_fast = input.int(12, title="MACD Fast", minval=5, maxval=35, group=group_macd) macd_slow = input.int(26, title="MACD Slow", minval=10, maxval=50, group=group_macd) macd_signal_len = input.int(9, title="MACD Signal", minval=5, maxval=20, group=group_macd) rsi_len = input.int(14, title="RSI Period", minval=5, maxval=50, group=group_rsi) rsi_overbought = input.float(70, title="RSI Overbought", minval=50, maxval=90, group=group_rsi) rsi_oversold = input.float(30, title="RSI Oversold", minval=10, maxval=50, group=group_rsi) atr_len = input.int(14, title="ATR Period", minval=5, maxval=50, group=group_atr) atr_mult_stop = input.float(2.0, title="Stop Loss ATR Multiple", minval=1, maxval=3, group=group_atr) atr_mult_profit = input.float(3.0, title="Take Profit ATR Multiple", minval=1.5, maxval=5, group=group_atr) use_divergence = input.bool(true, title="Use Divergence Detection", group=group_advanced) use_volume_filter = input.bool(true, title="Use Volume Filter", group=group_advanced) divergence_lookback = input.int(5, title="Divergence Lookback Bars", minval=2, maxval=10, group=group_advanced) show_ma = input.bool(true, title="Show Moving Averages", group=group_display) show_signals = input.bool(true, title="Show Entry Signals", group=group_display) show_info = input.bool(true, title="Show Statistics", group=group_display) ma_fast = ta.sma(close, ma_fast_len) ma_mid = ta.sma(close, ma_mid_len) ma_slow = ta.sma(close, ma_slow_len) [macd_line, macd_signal_line, macd_hist] = ta.macd(close, macd_fast, macd_slow, macd_signal_len) rsi_value = ta.rsi(close, rsi_len) atr_value = ta.atr(atr_len) atr_basis = ta.sma(atr_value, 30) atr_ratio = atr_value / atr_basis volume_avg = ta.sma(volume, 20) volume_ratio = volume / volume_avg uptrend = ma_fast > ma_mid and ma_mid > ma_slow downtrend = ma_fast < ma_mid and ma_mid < ma_slow macd_bullish = ta.crossover(macd_line, macd_signal_line) and macd_hist > 0 macd_bearish = ta.crossunder(macd_line, macd_signal_line) and macd_hist < 0 rsi_bullish = ta.crossover(rsi_value, rsi_oversold) and uptrend rsi_bearish = ta.crossunder(rsi_value, rsi_overbought) and downtrend momentum_bullish = (macd_bullish or rsi_bullish) and uptrend momentum_bearish = (macd_bearish or rsi_bearish) and downtrend volume_confirmed = volume_ratio > 1.5 var float lowest_price = na var float lowest_macd = na var int lowest_bar = 0 if low < nz(lowest_price, high) lowest_price := low lowest_macd := macd_line lowest_bar := bar_index bottom_divergence = uptrend and (bar_index - lowest_bar <= divergence_lookback) and low < lowest_price and macd_line > lowest_macd var float highest_price = na var float highest_macd = na var int highest_bar = 0 if high > nz(highest_price, low) highest_price := high highest_macd := macd_line highest_bar := bar_index top_divergence = downtrend and (bar_index - highest_bar <= divergence_lookback) and high > highest_price and macd_line < highest_macd hammer = ((high - close) < (0.1 * (high - low))) and ((close - low) > (0.6 * (high - low))) and ((open - low) > (0.1 * (high - low))) inverted_hammer = ((close - low) < (0.1 * (high - low))) and ((high - close) > (0.6 * (high - low))) and ((high - open) > (0.1 * (high - low))) bullish_engulfing = (close[1] < open[1]) and (close > open) and (open <= close[1]) and (close >= open[1]) bearish_engulfing = (close[1] > open[1]) and (close < open) and (open >= close[1]) and (close <= open[1]) long_signal = uptrend and momentum_bullish and volume_confirmed and (not use_divergence or bottom_divergence or hammer or bullish_engulfing) short_signal = downtrend and momentum_bearish and volume_confirmed and (not use_divergence or top_divergence or inverted_hammer or bearish_engulfing) stop_distance = atr_value * atr_mult_stop profit_distance = atr_value * atr_mult_profit if long_signal and strategy.position_size == 0 strategy.entry("Long", strategy.long, when=long_signal) strategy.exit("Long Exit", from_entry="Long", stop=close - stop_distance, limit=close + profit_distance) if short_signal and strategy.position_size == 0 strategy.entry("Short", strategy.short, when=short_signal) strategy.exit("Short Exit", from_entry="Short", stop=close + stop_distance, limit=close - profit_distance) plot(show_ma ? ma_fast : na, title="MA 5", color=color.blue, linewidth=1) plot(show_ma ? ma_mid : na, title="MA 20", color=color.orange, linewidth=1) plot(show_ma ? ma_slow : na, title="MA 60", color=color.red, linewidth=1) plotshape(show_signals and long_signal ? long_signal : na, title="Long Signal", style=shape.labelup, location=location.belowbar, color=color.green, textcolor=color.white, size=size.small) plotshape(show_signals and short_signal ? short_signal : na, title="Short Signal", style=shape.labeldown, location=location.abovebar, color=color.red, textcolor=color.white, size=size.small) win_count = strategy.winstotal loss_count = strategy.losstotal total_trades = win_count + loss_count win_rate = total_trades > 0 ? (win_count / total_trades) * 100 : 0 profit_factor = strategy.grossloss > 0 ? strategy.grossprofit / strategy.grossloss : 0 info_text = "Trades: " + str.tostring(int(total_trades)) + "\nWins: " + str.tostring(int(win_count)) + "\nWin Rate: " + str.tostring(win_rate, "#0.0") + "%\nProfit Factor: " + str.tostring(profit_factor, "#0.00") var table info_table = na if na(info_table) and show_info info_table := table.new(position=position.top_right, columns=1, rows=1, bgcolor=color.new(color.black, 80), border_color=color.gray, frame_color=color.gray) if show_info and not na(info_table) table.cell(info_table, 0, 0, text=info_text, text_color=color.white, text_size=size.small) alertcondition(long_signal, title="Long Entry", message="Long signal") alertcondition(short_signal, title="Short Entry", message="Short signal")