//@version=5 strategy("Dual Signal Trend Sentinel v3", "DST Sentinel [PRO]", overlay=true, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100) // ========================================== // --- Strategy Inputs --- // ========================================== grp_core = "Core Parameters" emaLen = input.int(65, "EMA Length", group=grp_core) stdLen = input.int(65, "StdDev Length", group=grp_core) bullFilter = input.float(0.7, "Bull Filter (Entry)", step=0.1, group=grp_core) bearFilter = input.float(0.2, "Bear Filter (Exit)", step=0.1, group=grp_core) grp_risk = "Risk Management (Optional)" useTrail = input.bool(false, "Enable ATR Trailing Stop?", group=grp_risk) atrLen = input.int(14, "ATR Length", group=grp_risk) atrMult = input.float(3.5, "ATR Multiplier", step=0.1, group=grp_risk) grp_vis = "Visuals & Dashboard" showDash = input.bool(true, "Show Dashboard", group=grp_vis) startDate = input.time(timestamp("2014-05-01"), "Backtest Start Date", group=grp_vis) // ========================================== // --- Calculations --- // ========================================== isInDateRange = time >= startDate emaValue = ta.ema(close, emaLen) stdValue = ta.stdev(close, stdLen) zScore = stdValue != 0 ? (close - emaValue) / stdValue : 0 // ATR Trailing Stop Logic atr = ta.atr(atrLen) longStop = close - (atr * atrMult) var float trailPrice = na // ========================================== // --- Strategy Logic --- // ========================================== longCondition = isInDateRange and zScore > bullFilter exitCondition = zScore < bearFilter if (longCondition) strategy.entry("Long", strategy.long) trailPrice := longStop if (exitCondition) strategy.close("Long", comment="Z-Exit") trailPrice := na // Optional Trailing Stop Execution if (useTrail and strategy.position_size > 0) trailPrice := math.max(longStop, trailPrice[1]) if (close < trailPrice) strategy.close("Long", comment="ATR-Stop") trailPrice := na // ========================================== // --- Visuals --- // ========================================== plot(emaValue, "Baseline EMA", color.new(color.blue, 0), linewidth=2) plot(useTrail and strategy.position_size > 0 ? trailPrice : na, "Trailing Stop", color.new(color.red, 30), style=plot.style_linebr) stateCol = zScore > bullFilter ? color.new(color.green, 90) : zScore < bearFilter ? color.new(color.red, 90) : color.new(color.gray, 90) bgcolor(isInDateRange ? stateCol : na) plotshape(ta.crossover(zScore, bullFilter), "Entry Triangle", shape.triangleup, location.belowbar, color.green, size=size.small) plotshape(ta.crossunder(zScore, bearFilter), "Exit Triangle", shape.triangledown, location.abovebar, color.red, size=size.small) // ========================================== // --- Dashboard --- // ========================================== var table dash = table.new(position.top_right, 2, 4, bgcolor=color.new(color.black, 20), border_color=color.gray, border_width=1) if showDash and barstate.islast trendText = zScore > bullFilter ? "BULLISH" : zScore < bearFilter ? "BEARISH" : "NEUTRAL" trendCol = zScore > bullFilter ? color.green : zScore < bearFilter ? color.red : color.gray table.cell(dash, 0, 0, "DST SENTINEL", text_color=color.white, text_size=size.small) table.cell(dash, 1, 0, trendText, text_color=trendCol, text_size=size.small) table.cell(dash, 0, 1, "CURRENT Z-SCORE", text_color=color.white, text_size=size.small) table.cell(dash, 1, 1, str.tostring(zScore, "#.##"), text_color=color.white, text_size=size.small) table.cell(dash, 0, 2, "BULL THRESHOLD", text_color=color.white, text_size=size.small) table.cell(dash, 1, 2, str.tostring(bullFilter, "#.##"), text_color=color.white, text_size=size.small) table.cell(dash, 0, 3, "BEAR THRESHOLD", text_color=color.white, text_size=size.small) table.cell(dash, 1, 3, str.tostring(bearFilter, "#.##"), text_color=color.white, text_size=size.small)