Code: Select all
//@version=5
strategy("Institutional XAUUSD Scalper Pro (MTF) [Forex-Scalping.com]", overlay=true, initial_capital=1000, default_qty_type=strategy.percent_of_equity, default_qty_value=5, commission_type=strategy.commission.cash_per_order, commission_value=3, slippage=2)
// ==========================================
// 1. USER INPUTS
// ==========================================
grp1 = "Trend & Trigger Settings (LTF)"
fastEmaLen = input.int(9, title="Fast EMA Length", group=grp1)
slowEmaLen = input.int(21, title="Slow EMA Length", group=grp1)
trendEmaLen = input.int(200, title="LTF Baseline EMA", group=grp1)
grp2 = "Higher Timeframe (MTF) Filter"
useHtfFilter = input.bool(true, title="Use HTF Filter?", group=grp2)
htfRes = input.timeframe("60", title="Higher Timeframe", group=grp2)
htfEmaLen = input.int(200, title="HTF EMA Length", group=grp2)
grp3 = "Momentum, Volatility & Chop Filter"
rsiLen = input.int(14, title="RSI Length", group=grp3)
atrLen = input.int(14, title="ATR Length", group=grp3)
useAdxFilter = input.bool(true, title="Use ADX Chop Filter?", group=grp3)
adxLen = input.int(14, title="ADX Length", group=grp3)
adxThreshold = input.int(20, title="ADX Minimum Strength", group=grp3)
grp4 = "Risk Management (Scaling & SL/TP)"
slMultiplier = input.float(1.5, title="Stop Loss ATR Multiplier", step=0.1, group=grp4)
tp1Ratio = input.float(1.0, title="TP1 Ratio (Closes 50%)", step=0.1, group=grp4)
tp2Ratio = input.float(2.0, title="TP2 Ratio (Closes Runner)", step=0.1, group=grp4)
useBreakEven = input.bool(true, title="Move SL to Break-Even after TP1?", group=grp4)
grp5 = "Session & Time Filters"
useSession = input.bool(true, title="Only Trade Specific Sessions?", group=grp5)
sessionTime = input.session("0800-1600", title="Trading Hours (EST)", group=grp5)
// ==========================================
// 2. CALCULATIONS (LTF & HTF)
// ==========================================
fastEma = ta.ema(close, fastEmaLen)
slowEma = ta.ema(close, slowEmaLen)
trendEma = ta.ema(close, trendEmaLen)
rsiVal = ta.rsi(close, rsiLen)
atrVal = ta.atr(atrLen)
// ADX Calculation
[diPlus, diMinus, adx] = ta.dmi(14, adxLen)
// MTF Calculation (Non-Repainting)
// We request the [1] value with lookahead_on to lock in the last closed HTF candle.
// This prevents the HTF EMA from repainting during real-time trading.
htfEma = request.security(syminfo.tickerid, htfRes, ta.ema(close, htfEmaLen)[1], lookahead=barmerge.lookahead_on)
// Session Logic
inSession = not useSession or not na(time(timeframe.period, sessionTime, "America/New_York"))
// ==========================================
// 3. LOGIC & CONDITIONS
// ==========================================
bullishTrend = close > trendEma
bearishTrend = close < trendEma
trendStrong = not useAdxFilter or adx > adxThreshold
// MTF Alignment
htfBullish = not useHtfFilter or close > htfEma
htfBearish = not useHtfFilter or close < htfEma
buySignal = ta.crossover(fastEma, slowEma) and bullishTrend and rsiVal > 50 and trendStrong and inSession and htfBullish
sellSignal = ta.crossunder(fastEma, slowEma) and bearishTrend and rsiVal < 50 and trendStrong and inSession and htfBearish
// ==========================================
// 4. STRATEGY EXECUTION & PARTIAL EXITS
// ==========================================
var float entryPrice = na
var float slLevel = na
var float tp1Level = na
var float tp2Level = na
var bool tp1Hit = false
var float riskDist = na
// --- ENTRY EXECUTION ---
if buySignal and strategy.position_size == 0
entryPrice := close
riskDist := atrVal * slMultiplier
slLevel := entryPrice - riskDist
tp1Level := entryPrice + (riskDist * tp1Ratio)
tp2Level := entryPrice + (riskDist * tp2Ratio)
tp1Hit := false
strategy.entry("Long", strategy.long)
strategy.exit("Exit L-TP1", from_entry="Long", qty_percent=50, stop=slLevel, limit=tp1Level)
strategy.exit("Exit L-TP2", from_entry="Long", stop=slLevel, limit=tp2Level)
if sellSignal and strategy.position_size == 0
entryPrice := close
riskDist := atrVal * slMultiplier
slLevel := entryPrice + riskDist
tp1Level := entryPrice - (riskDist * tp1Ratio)
tp2Level := entryPrice - (riskDist * tp2Ratio)
tp1Hit := false
strategy.entry("Short", strategy.short)
strategy.exit("Exit S-TP1", from_entry="Short", qty_percent=50, stop=slLevel, limit=tp1Level)
strategy.exit("Exit S-TP2", from_entry="Short", stop=slLevel, limit=tp2Level)
// --- TRADE MANAGEMENT (BREAK-EVEN ON RUNNER) ---
if strategy.position_size > 0 and not tp1Hit
if high >= tp1Level
tp1Hit := true
if useBreakEven
slLevel := entryPrice
strategy.exit("Exit L-TP2", from_entry="Long", stop=slLevel, limit=tp2Level)
if strategy.position_size < 0 and not tp1Hit
if low <= tp1Level
tp1Hit := true
if useBreakEven
slLevel := entryPrice
strategy.exit("Exit S-TP2", from_entry="Short", stop=slLevel, limit=tp2Level)
// Reset levels when flat
if strategy.position_size == 0
slLevel := na
tp1Level := na
tp2Level := na
entryPrice := na
tp1Hit := false
// ==========================================
// 5. PLOTTING
// ==========================================
// LTF EMAs
plot(fastEma, color=color.new(color.blue, 0), title="Fast EMA", linewidth=1)
plot(slowEma, color=color.new(color.orange, 0), title="Slow EMA", linewidth=1)
plot(trendEma, color=color.new(color.white, 0), title="LTF 200 EMA Baseline", linewidth=2)
// HTF EMA (Plotted as a Step Line)
plot(useHtfFilter ? htfEma : na, color=color.new(color.yellow, 0), title="HTF 200 EMA", linewidth=3, style=plot.style_stepline)
// Stop Loss Line (Turns Gray when moved to Breakeven)
plot(strategy.position_size != 0 ? slLevel : na, title="Stop Loss", color=tp1Hit ? color.new(color.gray, 20) : color.new(color.red, 20), style=plot.style_linebr, linewidth=2)
// TP1 Line (Hides once TP1 is hit)
plot(strategy.position_size != 0 and not tp1Hit ? tp1Level : na, title="Take Profit 1 (50%)", color=color.new(color.teal, 0), style=plot.style_linebr, linewidth=2)
// TP2 Line (Remains active for runner)
plot(strategy.position_size != 0 ? tp2Level : na, title="Take Profit 2 (Final)", color=color.new(color.green, 0), style=plot.style_linebr, linewidth=2)
// Session background shading
bgcolor(inSession and useSession ? color.new(color.blue, 95) : na, title="Session Window")
// ==========================================
// 6. PRO DASHBOARD
// ==========================================
var table dash = table.new(position.top_right, 2, 6, border_color=color.new(color.gray, 80), border_width=1, frame_color=color.new(color.gray, 80), frame_width=1)
string posStatus = "FLAT"
color statusBg = color.new(color.black, 0)
if strategy.position_size > 0
posStatus := tp1Hit ? "LONG (50% Runner)" : "LONG (Full)"
statusBg := color.new(color.green, 30)
else if strategy.position_size < 0
posStatus := tp1Hit ? "SHORT (50% Runner)" : "SHORT (Full)"
statusBg := color.new(color.red, 30)
// HTF Status String Processing
string htfStatus = not useHtfFilter ? "OFF" : (close > htfEma ? "BULL" : "BEAR")
color htfColor = not useHtfFilter ? color.gray : (close > htfEma ? color.green : color.red)
if barstate.islast
table.cell(dash, 0, 0, "PRO SCALPER (MTF)", text_color=color.white, bgcolor=color.new(#0800ff, 20), text_size=size.small)
table.cell(dash, 1, 0, "STATUS", text_color=color.white, bgcolor=color.new(#0800ff, 20), text_size=size.small)
table.cell(dash, 0, 1, "LTF Trend", text_color=color.gray, bgcolor=color.new(color.black, 0), text_size=size.small)
table.cell(dash, 1, 1, bullishTrend ? "BULL" : "BEAR", text_color=bullishTrend ? color.green : color.red, bgcolor=color.new(color.black, 0), text_size=size.small)
table.cell(dash, 0, 2, "HTF Trend (" + htfRes + ")", text_color=color.gray, bgcolor=color.new(color.black, 0), text_size=size.small)
table.cell(dash, 1, 2, htfStatus, text_color=htfColor, bgcolor=color.new(color.black, 0), text_size=size.small)
table.cell(dash, 0, 3, "ADX Filter (>20)", text_color=color.gray, bgcolor=color.new(color.black, 0), text_size=size.small)
table.cell(dash, 1, 3, str.tostring(math.round(adx, 1)), text_color=trendStrong ? color.green : color.orange, bgcolor=color.new(color.black, 0), text_size=size.small)
table.cell(dash, 0, 4, "Session Active", text_color=color.gray, bgcolor=color.new(color.black, 0), text_size=size.small)
table.cell(dash, 1, 4, inSession ? "YES" : "NO", text_color=inSession ? color.green : color.red, bgcolor=color.new(color.black, 0), text_size=size.small)
table.cell(dash, 0, 5, "Open Position", text_color=color.gray, bgcolor=color.new(color.black, 0), text_size=size.small)
table.cell(dash, 1, 5, posStatus, text_color=color.white, bgcolor=statusBg, text_size=size.small)