And here is the upgraded professional algorithm with the dynamic ATR (Average True Range) trailing stop built directly into the core execution engine.
I set this up with a dropdown menu in the UI so you can seamlessly toggle between your classic Fixed Points and the new ATR Trailing Stop without having to rewrite code. Because different assets behave differently (e.g., Forex pairs trend smoother, whereas Silver can be highly erratic), this allows you to rapidly adapt your exit engine during backtesting to fit the specific market's volatility profile.
Code: Select all
//@version=5
strategy("Pro HTF Scalper with ATR Trail", overlay=true, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=2, commission_type=strategy.commission.cash_per_order, commission_value=3, slippage=1)
// =====================================================================
// 1. INPUT PARAMETERS
// =====================================================================
var G_HTF = "1. Higher Timeframe Context"
htf1_tf = input.timeframe("60", title="Primary HTF", group=G_HTF)
htf2_tf = input.timeframe("240", title="Secondary HTF", group=G_HTF)
htf_len = input.int(50, title="HTF Trend EMA", group=G_HTF)
var G_LTF = "2. Scalp Triggers (Current Chart)"
fast_len = input.int(9, title="Fast EMA Trigger", inline="EMA", group=G_LTF)
slow_len = input.int(21, title="Slow EMA Trigger", inline="EMA", group=G_LTF)
var G_RISK = "3. Risk Management & Exits"
exit_mode = input.string("ATR Trailing Stop", options=["Fixed Points", "ATR Trailing Stop"], title="Exit Mode", group=G_RISK)
// Fixed point settings
sl_pts = input.int(100, title="Fixed Stop Loss (Points)", group=G_RISK, tooltip="Only used if 'Fixed Points' is selected.")
tp_pts = input.int(200, title="Fixed Take Profit (Points)", group=G_RISK, tooltip="Only used if 'Fixed Points' is selected.")
// ATR Settings
atr_len = input.int(14, title="ATR Length", inline="ATR", group=G_RISK)
atr_mult = input.float(2.0, title="ATR Multiplier", step=0.1, inline="ATR", group=G_RISK)
var G_TIME = "4. Trading Window"
use_sess = input.bool(true, title="Enable Time Filter", group=G_TIME)
session = input.session("0800-1700", title="Active Session", group=G_TIME)
var G_DASH = "5. Display"
show_hud = input.bool(true, title="Show On-Chart Dashboard", group=G_DASH)
// =====================================================================
// 2. TIME, SESSIONS & STATE
// =====================================================================
in_session = not use_sess or not na(time(timeframe.period, session))
is_flat = strategy.position_size == 0
// =====================================================================
// 3. HIGHER TIMEFRAME (HTF) LOGIC
// =====================================================================
get_htf_trend(tf, len) =>
request.security(syminfo.tickerid, tf, close[1] > ta.ema(close, len)[1], lookahead=barmerge.lookahead_off)
is_htf1_bull = get_htf_trend(htf1_tf, htf_len)
is_htf2_bull = get_htf_trend(htf2_tf, htf_len)
is_htf1_bear = not is_htf1_bull
is_htf2_bear = not is_htf2_bull
htf_uptrend = is_htf1_bull and is_htf2_bull
htf_downtrend = is_htf1_bear and is_htf2_bear
// =====================================================================
// 4. LOWER TIMEFRAME (LTF) TRIGGERS
// =====================================================================
fast_ema = ta.ema(close, fast_len)
slow_ema = ta.ema(close, slow_len)
buy_trigger = ta.crossover(fast_ema, slow_ema)
sell_trigger = ta.crossunder(fast_ema, slow_ema)
// =====================================================================
// 5. EXECUTION & TRAILING STOP LOGIC
// =====================================================================
var float trail_stop = na
atr_val = ta.atr(atr_len)
// Entry Logic
if in_session and is_flat
if htf_uptrend and buy_trigger
strategy.entry("Long", strategy.long)
if exit_mode == "Fixed Points"
strategy.exit("Exit Long", "Long", loss=sl_pts, profit=tp_pts)
else
trail_stop := close - (atr_val * atr_mult) // Initialize starting stop
if htf_downtrend and sell_trigger
strategy.entry("Short", strategy.short)
if exit_mode == "Fixed Points"
strategy.exit("Exit Short", "Short", loss=sl_pts, profit=tp_pts)
else
trail_stop := close + (atr_val * atr_mult) // Initialize starting stop
// Dynamic ATR Ratchet Logic
if exit_mode == "ATR Trailing Stop"
if strategy.position_size > 0
new_stop = close - (atr_val * atr_mult)
trail_stop := math.max(nz(trail_stop, new_stop), new_stop) // Ratchet up only
strategy.exit("Trail Long", "Long", stop=trail_stop)
if strategy.position_size < 0
new_stop = close + (atr_val * atr_mult)
trail_stop := math.min(nz(trail_stop, new_stop), new_stop) // Ratchet down only
strategy.exit("Trail Short", "Short", stop=trail_stop)
// Reset trailing stop memory when flat
if is_flat
trail_stop := na
// End of session flatten
if use_sess and ta.crossunder(time(timeframe.period, session) ? 1 : 0, 0.5)
strategy.close_all(comment="Session Close")
// =====================================================================
// 6. VISUALS & HUD
// =====================================================================
plot(fast_ema, color=color.new(#2962FF, 0), title="Fast EMA", linewidth=2)
plot(slow_ema, color=color.new(#FF6D00, 0), title="Slow EMA", linewidth=2)
// Plot the Trailing Stop Line (Stepline style makes it look mechanical)
plot(exit_mode == "ATR Trailing Stop" and not is_flat ? trail_stop : na, color=color.new(color.fuchsia, 0), style=plot.style_stepline, linewidth=2, title="ATR Trailing Stop")
bg_color = htf_uptrend ? color.new(color.green, 95) : htf_downtrend ? color.new(color.red, 95) : na
bgcolor(bg_color, title="HTF Context")
if show_hud
var table hud = table.new(position.top_right, 2, 4, border_width=1, border_color=color.gray, frame_color=color.gray, frame_width=1)
table.cell(hud, 0, 0, "HTF FILTER", text_color=color.white, bgcolor=color.black, text_halign=text.align_center)
table.cell(hud, 1, 0, "STATUS", text_color=color.white, bgcolor=color.black, text_halign=text.align_center)
table.cell(hud, 0, 1, "Primary (" + htf1_tf + ")", text_color=color.white, bgcolor=color.gray)
table.cell(hud, 1, 1, is_htf1_bull ? "BULL" : "BEAR", text_color=color.white, bgcolor=is_htf1_bull ? color.green : color.red)
table.cell(hud, 0, 2, "Secondary (" + htf2_tf + ")", text_color=color.white, bgcolor=color.gray)
table.cell(hud, 1, 2, is_htf2_bull ? "BULL" : "BEAR", text_color=color.white, bgcolor=is_htf2_bull ? color.green : color.red)
table.cell(hud, 0, 3, "Master Context", text_color=color.white, bgcolor=color.gray)
table.cell(hud, 1, 3, htf_uptrend ? "LONG ONLY" : htf_downtrend ? "SHORT ONLY" : "CHOP", text_color=color.white, bgcolor=htf_uptrend ? color.green : htf_downtrend ? color.red : color.orange)