OPEN-SOURCE SCRIPT

XAUUSD 1m SMC Zones (BOS + Flexible TP Modes + Trailing Runner)

105
//version=6
strategy("XAUUSD 1m SMC Zones (BOS + Flexible TP Modes + Trailing Runner)",
overlay = true,
initial_capital = 10000,
pyramiding = 10,
process_orders_on_close = true)

//━━━━━━━━━━━━━━━━━━━
// 1. INPUTS
//━━━━━━━━━━━━━━━━━━━

// TP / SL
tp1Pips = input.int(10, "TP1 (pips)", minval = 1)
fixedSLpips = input.int(50, "Fixed SL (pips)", minval = 5)
runnerRR = input.float(3.0, "Runner RR (TP2 = SL * RR)", step = 0.1, minval = 1.0)

// Daily risk
maxDailyLossPct = input.float(5.0, "Max daily loss % (stop trading)", step = 0.5)
maxDailyProfitPct = input.float(20.0, "Max daily profit % (stop trading)", step = 1.0)

// HTF S/R (1H)
htfTF = input.string("60", "HTF timeframe (minutes) for S/R block")

// Profit strategy (Option C)
profitStrategy = input.string("Minimal Risk | Full BE after TP1", "Profit Strategy", options = [ "Minimal Risk | Full BE after TP1", "Hybrid | Scalp TP + Runner TP"])

// Runner stop mode (your option 4)
runnerStopMode = input.string( "BE only", "Runner Stop Mode", options = ["BE only", "Structure trail", "ATR trail" ])

// ATR trail settings (only used if ATR mode selected)
atrTrailLen = input.int(14, "ATR Length (trail)", minval = 1)
atrTrailMult = input.float(1.0, "ATR Multiplier (trail)", step = 0.1, minval = 0.1)

// Pip size (for XAUUSD: 1 pip = 0.10 if tick = 0.01)
pipSize = syminfo.mintick * 10.0
tp1Points = tp1Pips * pipSize
slPoints = fixedSLpips * pipSize

baseQty = input.float (1.0, "Base order size" , step = 0.01, minval = 0.01)

//━━━━━━━━━━━━━━━━━━━
// 2. DAILY RISK MANAGEMENT
//━━━━━━━━━━━━━━━━━━━

isNewDay = ta.change(time("D")) != 0

var float dayStartEquity = na
var bool dailyStopped = false

equityNow = strategy.initial_capital + strategy.netprofit

if isNewDay or na(dayStartEquity)
dayStartEquity := equityNow
dailyStopped := false

dailyPnL = equityNow - dayStartEquity
dailyPnLPct = dayStartEquity != 0 ? (dailyPnL / dayStartEquity) * 100.0 : 0.0

if not dailyStopped
if dailyPnLPct <= -maxDailyLossPct
dailyStopped := true
if dailyPnLPct >= maxDailyProfitPct
dailyStopped := true

canTradeToday = not dailyStopped

//━━━━━━━━━━━━━━━━━━━
// 3. 1H S/R ZONES (for direction block)
//━━━━━━━━━━━━━━━━━━━

htOpen = request.security(syminfo.tickerid, htfTF, open)
htHigh = request.security(syminfo.tickerid, htfTF, high)
htLow = request.security(syminfo.tickerid, htfTF, low)
htClose = request.security(syminfo.tickerid, htfTF, close)

// Engulf logic on HTF
htBullPrev = htClose[1] > htOpen[1]
htBearPrev = htClose[1] < htOpen[1]

htBearEngulf = htClose < htOpen and htBullPrev and htOpen >= htClose[1] and htClose <= htOpen[1]
htBullEngulf = htClose > htOpen and htBearPrev and htOpen <= htClose[1] and htClose >= htOpen[1]

// Liquidity sweep on HTF previous candle
htSweepHigh = htHigh[1] > ta.highest(htHigh, 5)[2]
htSweepLow = htLow[1] < ta.lowest(htLow, 5)[2]

// Store last HTF zones
var float htResHigh = na
var float htResLow = na
var float htSupHigh = na
var float htSupLow = na

if htBearEngulf and htSweepHigh
htResHigh := htHigh[1]
htResLow := htLow[1]

if htBullEngulf and htSweepLow
htSupHigh := htHigh[1]
htSupLow := htLow[1]

// Are we inside HTF zones?
inHtfRes = not na(htResHigh) and close <= htResHigh and close >= htResLow
inHtfSup = not na(htSupLow) and close >= htSupLow and close <= htSupHigh

// Block direction against HTF zones
longBlockedByZone = inHtfRes // no buys in HTF resistance
shortBlockedByZone = inHtfSup // no sells in HTF support

//━━━━━━━━━━━━━━━━━━━
// 4. 1m LOCAL ZONES (LIQUIDITY SWEEP + ENGULF + QUALITY SCORE)
//━━━━━━━━━━━━━━━━━━━

// 1m engulf patterns
bullPrev1 = close[1] > open[1]
bearPrev1 = close[1] < open[1]

bearEngulfNow = close < open and bullPrev1 and open >= close[1] and close <= open[1]
bullEngulfNow = close > open and bearPrev1 and open <= close[1] and close >= open[1]

// Liquidity sweep by previous candle on 1m
sweepHighPrev = high[1] > ta.highest(high, 5)[2]
sweepLowPrev = low[1] < ta.lowest(low, 5)[2]

// Local zone storage (one active support + one active resistance)
// Quality score: 1 = engulf only, 2 = engulf + sweep (we only trade ≥2)
var float supLow = na
var float supHigh = na
var int supQ = 0
var bool supUsed = false

var float resLow = na
var float resHigh = na
var int resQ = 0
var bool resUsed = false

// New resistance zone: previous bullish candle -> bear engulf
if bearEngulfNow
resLow := low[1]
resHigh := high[1]
resQ := sweepHighPrev ? 2 : 1
resUsed := false

// New support zone: previous bearish candle -> bull engulf
if bullEngulfNow
supLow := low[1]
supHigh := high[1]
supQ := sweepLowPrev ? 2 : 1
supUsed := false

// Raw "inside zone" detection
inSupRaw = not na(supLow) and close >= supLow and close <= supHigh
inResRaw = not na(resHigh) and close <= resHigh and close >= resLow

// QUALITY FILTER: only trade zones with quality ≥ 2 (engulf + sweep)
highQualitySup = supQ >= 2
highQualityRes = resQ >= 2

inSupZone = inSupRaw and highQualitySup and not supUsed
inResZone = inResRaw and highQualityRes and not resUsed

// Plot zones
plot(supLow, "Sup Low", color = color.new(color.lime, 60), style = plot.style_linebr)
plot(supHigh, "Sup High", color = color.new(color.lime, 60), style = plot.style_linebr)
plot(resLow, "Res Low", color = color.new(color.red, 60), style = plot.style_linebr)
plot(resHigh, "Res High", color = color.new(color.red, 60), style = plot.style_linebr)

//━━━━━━━━━━━━━━━━━━━
// 5. MODERATE BOS (3-BAR FRACTAL STRUCTURE)
//━━━━━━━━━━━━━━━━━━━

// 3-bar swing highs/lows
swHigh = high[1] > high[0] and high[1] > high[2]
swLow = low[1] < low[0] and low[1] < low[2]

var float lastSwingHigh = na
var float lastSwingLow = na

if swHigh
lastSwingHigh := high[1]
if swLow
lastSwingLow := low[1]

// BOS conditions
bosUp = not na(lastSwingHigh) and close > lastSwingHigh
bosDown = not na(lastSwingLow) and close < lastSwingLow

// Zone “arming” and BOS validation
var bool supArmed = false
var bool resArmed = false
var bool supBosOK = false
var bool resBosOK = false

// Arm zones when first touched
if inSupZone
supArmed := true
if inResZone
resArmed := true

// BOS after arming → zone becomes valid for entries
if supArmed and bosUp
supBosOK := true
if resArmed and bosDown
resBosOK := true

// Reset BOS flags when new zones are created
if bullEngulfNow
supArmed := false
supBosOK := false
if bearEngulfNow
resArmed := false
resBosOK := false

//━━━━━━━━━━━━━━━━━━━
// 6. ENTRY CONDITIONS (ZONE + BOS + RISK STATE)
//━━━━━━━━━━━━━━━━━━━

flatOrShort = strategy.position_size <= 0
flatOrLong = strategy.position_size >= 0

longSignal = canTradeToday and not longBlockedByZone and inSupZone and supBosOK and flatOrShort
shortSignal = canTradeToday and not shortBlockedByZone and inResZone and resBosOK and flatOrLong

//━━━━━━━━━━━━━━━━━━━
// 7. ORDER LOGIC – TWO PROFIT STRATEGIES
//━━━━━━━━━━━━━━━━━━━

// Common metrics
atrTrail = ta.atr(atrTrailLen)

// MINIMAL MODE: single trade, BE after TP1, optional trailing
// HYBRID MODE: two trades (Scalp @ TP1, Runner @ TP2)

// Persistent tracking
var float longEntry = na
var float longTP1 = na
var float longTP2 = na
var float longSL = na
var bool longBE = false

var float longRunEntry = na
var float longRunTP1 = na
var float longRunTP2 = na
var float longRunSL = na
var bool longRunBE = false

var float shortEntry = na
var float shortTP1 = na
var float shortTP2 = na
var float shortSL = na
var bool shortBE = false

var float shortRunEntry = na
var float shortRunTP1 = na
var float shortRunTP2 = na
var float shortRunSL = na
var bool shortRunBE = false

isMinimal = profitStrategy == "Minimal Risk | Full BE after TP1"
isHybrid = profitStrategy == "Hybrid | Scalp TP + Runner TP"

//━━━━━━━━━━ LONG ENTRIES ━━━━━━━━━━

if longSignal
if isMinimal
longEntry := close
longSL := longEntry - slPoints
longTP1 := longEntry + tp1Points
longTP2 := longEntry + slPoints * runnerRR
longBE := false
strategy.entry("Long", strategy.long)
supUsed := true
supArmed := false
supBosOK := false
else if isHybrid
longRunEntry := close
longRunSL := longRunEntry - slPoints
longRunTP1 := longRunEntry + tp1Points
longRunTP2 := longRunEntry + slPoints * runnerRR
longRunBE := false
// Two separate entries, each 50% of baseQty (for backtest)
strategy.entry("LongScalp", strategy.long, qty = baseQty * 0.5)
strategy.entry("LongRun", strategy.long, qty = baseQty * 0.5)
supUsed := true
supArmed := false
supBosOK := false

//━━━━━━━━━━ SHORT ENTRIES ━━━━━━━━━━

if shortSignal
if isMinimal
shortEntry := close
shortSL := shortEntry + slPoints
shortTP1 := shortEntry - tp1Points
shortTP2 := shortEntry - slPoints * runnerRR
shortBE := false
strategy.entry("Short", strategy.short)
resUsed := true
resArmed := false
resBosOK := false
else if isHybrid
shortRunEntry := close
shortRunSL := shortRunEntry + slPoints
shortRunTP1 := shortRunEntry - tp1Points
shortRunTP2 := shortRunEntry - slPoints * runnerRR
shortRunBE := false
strategy.entry("ShortScalp", strategy.short, qty = baseQty * 50)
strategy.entry("ShortRun", strategy.short, qty = baseQty * 50)
resUsed := true
resArmed := false
resBosOK := false

//━━━━━━━━━━━━━━━━━━━
// 8. EXIT LOGIC – MINIMAL MODE
//━━━━━━━━━━━━━━━━━━━

// LONG – Minimal Risk: 1 trade, BE after TP1, runner to TP2
if isMinimal and strategy.position_size > 0 and not na(longEntry)
// Move to BE once TP1 is touched
if not longBE and high >= longTP1
longBE := true
// Base SL: BE or initial SL
float dynLongSL = longBE ? longEntry : longSL

// Optional trailing after BE
if longBE
if runnerStopMode == "Structure trail" and not na(lastSwingLow) and lastSwingLow > longEntry
dynLongSL := math.max(dynLongSL, lastSwingLow)
if runnerStopMode == "ATR trail"
trailSL = close - atrTrailMult * atrTrail
dynLongSL := math.max(dynLongSL, trailSL)

strategy.exit("Long Exit", "Long", stop = dynLongSL, limit = longTP2)

// SHORT – Minimal Risk: 1 trade, BE after TP1, runner to TP2
if isMinimal and strategy.position_size < 0 and not na(shortEntry)
if not shortBE and low <= shortTP1
shortBE := true
float dynShortSL = shortBE ? shortEntry : shortSL

if shortBE
if runnerStopMode == "Structure trail" and not na(lastSwingHigh) and lastSwingHigh < shortEntry
dynShortSL := math.min(dynShortSL, lastSwingHigh)
if runnerStopMode == "ATR trail"
trailSLs = close + atrTrailMult * atrTrail
dynShortSL := math.min(dynShortSL, trailSLs)

strategy.exit("Short Exit", "Short", stop = dynShortSL, limit = shortTP2)

//━━━━━━━━━━━━━━━━━━━
// 9. EXIT LOGIC – HYBRID MODE
//━━━━━━━━━━━━━━━━━━━

// LONG – Hybrid: Scalp + Runner
if isHybrid
// Scalp leg: full TP at TP1
if strategy.opentrades > 0
strategy.exit("LScalp TP", "LongScalp", stop = longRunSL, limit = longRunTP1)

// Runner leg
if strategy.position_size > 0 and not na(longRunEntry)
if not longRunBE and high >= longRunTP1
longRunBE := true
float dynLongRunSL = longRunBE ? longRunEntry : longRunSL

if longRunBE
if runnerStopMode == "Structure trail" and not na(lastSwingLow) and lastSwingLow > longRunEntry
dynLongRunSL := math.max(dynLongRunSL, lastSwingLow)
if runnerStopMode == "ATR trail"
trailRunSL = close - atrTrailMult * atrTrail
dynLongRunSL := math.max(dynLongRunSL, trailRunSL)

strategy.exit("LRun TP", "LongRun", stop = dynLongRunSL, limit = longRunTP2)

// SHORT – Hybrid: Scalp + Runner
if isHybrid
if strategy.opentrades > 0
strategy.exit("SScalp TP", "ShortScalp", stop = shortRunSL, limit = shortRunTP1)

if strategy.position_size < 0 and not na(shortRunEntry)
if not shortRunBE and low <= shortRunTP1
shortRunBE := true
float dynShortRunSL = shortRunBE ? shortRunEntry : shortRunSL

if shortRunBE
if runnerStopMode == "Structure trail" and not na(lastSwingHigh) and lastSwingHigh < shortRunEntry
dynShortRunSL := math.min(dynShortRunSL, lastSwingHigh)
if runnerStopMode == "ATR trail"
trailRunSLs = close + atrTrailMult * atrTrail
dynShortRunSL := math.min(dynShortRunSL, trailRunSLs)

strategy.exit("SRun TP", "ShortRun", stop = dynShortRunSL, limit = shortRunTP2)

//━━━━━━━━━━━━━━━━━━━
// 10. RESET STATE WHEN FLAT
//━━━━━━━━━━━━━━━━━━━

if strategy.position_size == 0
longEntry := na
shortEntry := na
longBE := false
shortBE := false
longRunEntry := na
shortRunEntry := na
longRunBE := false
shortRunBE := false

//━━━━━━━━━━━━━━━━━━━
// 11. VISUAL ENTRY MARKERS
//━━━━━━━━━━━━━━━━━━━

plotshape(longSignal, title = "Long Signal", style = shape.triangleup,
location = location.belowbar, color = color.lime, size = size.tiny, text = "L")

plotshape(shortSignal, title = "Short Signal", style = shape.triangledown,
location = location.abovebar, color = color.red, size = size.tiny, text = "S")

Declinazione di responsabilità

Le informazioni e le pubblicazioni non sono intese come, e non costituiscono, consulenza o raccomandazioni finanziarie, di investimento, di trading o di altro tipo fornite o approvate da TradingView. Per ulteriori informazioni, consultare i Termini di utilizzo.