DEV Community

Cover image for Quality-Controlled Trend Strategy (Non-Repainting, Risk-Defined)
Ranga
Ranga

Posted on • Edited on

Quality-Controlled Trend Strategy (Non-Repainting, Risk-Defined)

This script focuses on quality control rather than curve-fitting.
No repainting, no intrabar tricks, no fake equity curves.
It uses confirmed-bar entries, ATR-based risk, and clean trend logic so backtests reflect what could actually be traded live.
If you publish scripts, this is the minimum structure worth sharing.

Why this script exists

TradingView’s public scripts are flooded with:

  1. repainting indicators
  2. no stop-loss logic
  3. curve-fit entries that collapse live
  4. strategies that look good only in hindsight

This script is intentionally boring but honest.

  • No repainting.
  • No intrabar tricks.
  • No fake equity curves. The goal is quality control, not hype.

What this strategy enforces

✔ Confirmed bars only
✔ Single source of truth for indicators
✔ Fixed risk structure
✔ No signal repainting
✔ Clean exits with unique IDs
✔ Works on any liquid market

Trading Logic (simple & auditable)

Trend filter
EMA 50 vs EMA 200

Entry
Pullback to EMA 50
RSI confirms momentum (not oversold/overbought)

Risk
ATR-based stop
Fixed R:R
One position at a time
This is the minimum bar for a strategy to be considered publish-worthy.

Why this helps TradingView quality

Most low-value scripts fail because they:

  • hide repainting logic
  • skip exits entirely
  • use inconsistent calculations
  • rely on hindsight candles

This strategy forces discipline:

  • every signal is confirmed
  • every trade has defined risk
  • behavior is repeatable across symbols & timeframes

If more scripts followed this baseline, TradingView’s public library would be far more usable.

//@version=6
strategy(
     title = "Quality-Controlled Trend Strategy",
     overlay = true,
     initial_capital = 100000,
     default_qty_type = strategy.percent_of_equity,
     default_qty_value = 5,
     commission_type = strategy.commission.percent,
     commission_value = 0.05,
     slippage = 1
)

// ==============================
// Inputs
// ==============================

// Trend & Entry
fastEmaLen = input.int(50, "Fast EMA Length")
slowEmaLen = input.int(200, "Slow EMA Length")
rsiLen     = input.int(14, "RSI Length")
rsiMid     = input.float(50, "RSI Midline")

// Risk (isolated block)
atrLen     = input.int(14, "ATR Length")
atrSLMult  = input.float(1.5, "Stop Loss ATR Multiplier")
rrRatio    = input.float(2.0, "Risk-Reward Ratio")

// ==============================
// Indicator Calculations
// ==============================

emaFast = ta.ema(close, fastEmaLen)
emaSlow = ta.ema(close, slowEmaLen)
rsiVal  = ta.rsi(close, rsiLen)
atrVal  = ta.atr(atrLen)

// ==============================
// Trend Context
// ==============================

trendUp   = emaFast > emaSlow
trendDown = emaFast < emaSlow

// ==============================
// Entry Logic (Confirmed Bar)
// ==============================

longCondition =
     trendUp and
     close > emaFast and
     rsiVal > rsiMid

shortCondition =
     trendDown and
     close < emaFast and
     rsiVal < rsiMid

// ==============================
// Entries
// ==============================

if longCondition and strategy.position_size == 0
    strategy.entry("Long", strategy.long)

if shortCondition and strategy.position_size == 0
    strategy.entry("Short", strategy.short)

// ==============================
// Risk Management (Editable Without Touching Entries)
// ==============================

longStop  = strategy.position_avg_price - atrVal * atrSLMult
longLimit = strategy.position_avg_price + atrVal * atrSLMult * rrRatio

shortStop  = strategy.position_avg_price + atrVal * atrSLMult
shortLimit = strategy.position_avg_price - atrVal * atrSLMult * rrRatio

strategy.exit("Long Exit",  from_entry = "Long",  stop = longStop,  limit = longLimit)
strategy.exit("Short Exit", from_entry = "Short", stop = shortStop, limit = shortLimit)

// ==============================
// Visuals
// ==============================

plot(emaFast, color=color.orange)
plot(emaSlow, color=color.blue)

Enter fullscreen mode Exit fullscreen mode

Top comments (0)