//@version=5 strategy("BTC Trend Breakout (ATR Risk)", overlay = true, initial_capital = 10000, currency = currency.USD, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, commission_type = strategy.commission.percent, commission_value = 0.1, slippage = 2, pyramiding = 0, calc_on_every_tick = false) // ───────── Inputs ───────── grpT = "Trend / Entry" trendLen = input.int(200, "Trend EMA", minval = 10, group = grpT) fastLen = input.int(21, "Fast EMA", minval = 2, group = grpT) slowLen = input.int(55, "Slow EMA", minval = 3, group = grpT) entryLen = input.int(20, "Breakout lookback", minval = 2, group = grpT) exitLen = input.int(10, "Reversal exit lookback", minval = 2, group = grpT) useAdx = input.bool(true, "Use ADX filter", group = grpT) adxLen = input.int(14, "ADX length", minval = 2, group = grpT) adxMin = input.float(20, "ADX minimum", minval = 0, group = grpT) allowShort = input.bool(false, "Allow shorts", group = grpT) grpR = "Risk" atrLen = input.int(14, "ATR length", minval = 1, group = grpR) stopMult = input.float(2.5, "Initial stop (×ATR)", minval = 0.1, step = 0.1, group = grpR) trailMult = input.float(3.0, "Trailing stop (×ATR)", minval = 0.1, step = 0.1, group = grpR) riskPct = input.float(1.0, "Risk per trade (% equity)", minval = 0.1, maxval = 10, step = 0.1, group = grpR) maxLev = input.float(1.0, "Max leverage (1 = none)", minval = 0.1, maxval = 10, step = 0.1, group = grpR) grpD = "Backtest window" startTime = input.time(timestamp("2018-01-01T00:00:00"), "Start", group = grpD) endTime = input.time(timestamp("2099-12-31T00:00:00"), "End", group = grpD) inWindow = time >= startTime and time <= endTime // ───────── Indicators ───────── emaTrend = ta.ema(close, trendLen) emaFast = ta.ema(close, fastLen) emaSlow = ta.ema(close, slowLen) atr = ta.atr(atrLen) [diPlus, diMinus, adx] = ta.dmi(adxLen, adxLen) hiEntry = ta.highest(high, entryLen)[1] loEntry = ta.lowest(low, entryLen)[1] hiExit = ta.highest(high, exitLen)[1] loExit = ta.lowest(low, exitLen)[1] trendOk = not useAdx or adx > adxMin longCond = inWindow and close > emaTrend and emaFast > emaSlow and close > hiEntry and trendOk shortCond = inWindow and allowShort and close < emaTrend and emaFast < emaSlow and close < loEntry and trendOk // ───────── Position sizing (fixed fractional risk) ───────── stopDist = stopMult * atr riskQty = stopDist > 0 ? (strategy.equity * riskPct / 100) / stopDist : 0.0 capQty = strategy.equity * maxLev / close qty = math.max(math.min(riskQty, capQty), 0) // ───────── Stop state ───────── var float longStop = na var float shortStop = na // ───────── Entries ───────── if longCond and strategy.position_size <= 0 and qty > 0 strategy.entry("Long", strategy.long, qty = qty) longStop := close - stopDist strategy.exit("L-Stop", "Long", stop = longStop) if shortCond and strategy.position_size >= 0 and qty > 0 strategy.entry("Short", strategy.short, qty = qty) shortStop := close + stopDist strategy.exit("S-Stop", "Short", stop = shortStop) // ───────── Trade management ───────── if strategy.position_size > 0 longStop := math.max(nz(longStop, close - stopDist), high - trailMult * atr) strategy.exit("L-Stop", "Long", stop = longStop) if close < loExit strategy.close("Long", comment = "L-Reversal") if strategy.position_size < 0 shortStop := math.min(nz(shortStop, close + stopDist), low + trailMult * atr) strategy.exit("S-Stop", "Short", stop = shortStop) if close > hiExit strategy.close("Short", comment = "S-Reversal") if strategy.position_size == 0 and not longCond longStop := na if strategy.position_size == 0 and not shortCond shortStop := na // Close anything open when the backtest window ends if not inWindow and strategy.position_size != 0 strategy.close_all(comment = "Window end") // ───────── Plots ───────── plot(emaTrend, "Trend EMA", color = color.orange, linewidth = 2) plot(emaFast, "Fast EMA", color = color.teal) plot(emaSlow, "Slow EMA", color = color.purple) plot(strategy.position_size > 0 ? longStop : na, "Long stop", color = color.green, style = plot.style_linebr, linewidth = 2) plot(strategy.position_size < 0 ? shortStop : na, "Short stop", color = color.red, style = plot.style_linebr, linewidth = 2) plotshape(longCond and strategy.position_size <= 0, "Long signal", shape.triangleup, location.belowbar, color.green, size = size.tiny) plotshape(shortCond and strategy.position_size >= 0, "Short signal", shape.triangledown, location.abovebar, color.red, size = size.tiny) bgcolor(strategy.position_size > 0 ? color.new(color.green, 92) : strategy.position_size < 0 ? color.new(color.red, 92) : na)