Re: Weighted Moving Average (WMA) Explained + Custom Pine Script for ScalpersHey everyone, When trading lower timeframe
Posted: Fri Sep 04, 2026 10:50 am
Pine Script (v5) Implementation
Code: Select all
//@version=5
indicator("WMA Scalping System: Signals, Vol + ATR Stop", overlay=true, timeframe="")
// --- Moving Average Parameters ---
fast_length = input.int(7, title="Fast WMA", minval=1, group="Moving Averages")
slow_length = input.int(21, title="Slow WMA", minval=1, group="Moving Averages")
src = input.source(close, title="Source", group="Moving Averages")
// --- Volume Filter Parameters ---
use_vol_filter = input.bool(true, title="Enable Volume Filter", group="Volume Filter")
vol_length = input.int(20, title="Volume MA Length", minval=1, group="Volume Filter")
// --- ATR Stop Parameters ---
atr_length = input.int(14, title="ATR Length", minval=1, group="ATR Trailing Stop")
atr_mult = input.float(1.5, title="ATR Multiplier", step=0.1, group="ATR Trailing Stop")
// --- Core Calculations ---
fast_wma = ta.wma(src, fast_length)
slow_wma = ta.wma(src, slow_length)
vol_ma = ta.sma(volume, vol_length)
atr_val = ta.atr(atr_length)
// --- Signal Logic ---
bull_cross = ta.crossover(fast_wma, slow_wma)
bear_cross = ta.crossunder(fast_wma, slow_wma)
vol_valid = not use_vol_filter or (volume > vol_ma)
long_signal = bull_cross and vol_valid
short_signal = bear_cross and vol_valid
// --- Stateful ATR Trailing Stop Logic ---
// Initializes memory states across historical bars
var float trail_stop = na
var int pos_dir = 0 // 1 for Long, -1 for Short
if long_signal
pos_dir := 1
trail_stop := close - (atr_val * atr_mult)
else if short_signal
pos_dir := -1
trail_stop := close + (atr_val * atr_mult)
else if pos_dir == 1
// Long position: Stop level can only increase
prev_stop = na(trail_stop[1]) ? close - (atr_val * atr_mult) : trail_stop[1]
trail_stop := math.max(prev_stop, close - (atr_val * atr_mult))
else if pos_dir == -1
// Short position: Stop level can only decrease
prev_stop = na(trail_stop[1]) ? close + (atr_val * atr_mult) : trail_stop[1]
trail_stop := math.min(prev_stop, close + (atr_val * atr_mult))
// --- UI / Rendering ---
fast_color = fast_wma > fast_wma[1] ? color.new(#26a69a, 0) : fast_wma < fast_wma[1] ? color.new(#ef5350, 0) : color.new(color.gray, 0)
plot(fast_wma, title="Fast WMA", color=fast_color, linewidth=2)
plot(slow_wma, title="Slow WMA", color=color.new(color.white, 50), linewidth=2)
stop_color = pos_dir == 1 ? color.new(#26a69a, 30) : pos_dir == -1 ? color.new(#ef5350, 30) : na
plot(trail_stop, title="ATR Trailing Stop", color=stop_color, style=plot.style_cross, linewidth=1)
plotshape(long_signal, title="Long Signal", style=shape.triangleup, location=location.belowbar, color=color.new(#26a69a, 0), size=size.small)
plotshape(short_signal, title="Short Signal", style=shape.triangledown, location=location.abovebar, color=color.new(#ef5350, 0), size=size.small)
// --- Webhook Alerts ---
alertcondition(long_signal, title="Long Entry Triggered", message="LONG ALERT: WMA Cross with Volume Confirmed")
alertcondition(short_signal, title="Short Entry Triggered", message="SHORT ALERT: WMA Cross with Volume Confirmed")