1Copy the scriptPress Copy script above, or the copy button on the code below.
2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
3Paste over the templateCreate a new strategy, select all of the template text and paste. Press Save and give it a name.
4Add it to the chartPress Add to chart. The trades and results appear in the Strategy Tester tab; adjust the settings with the gear icon.
Source Code
127 lines of Pine Script v6 from vwap_reversion_bands_v3.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.
vwap_reversion_bands_v3.pine
//@version=6
strategy("VWAP Reversion Bands [QuantForge]",
overlay = true,
initial_capital = 10000,
default_qty_type = strategy.percent_of_equity,
default_qty_value = 10,
commission_type = strategy.commission.percent,
commission_value = 0.05,
slippage = 2)
// ============================================================
// v3: structural redesign of the trade engine.
// Entry: trend filter + price in the discount zone below the
// inner band + short-length RSI oversold (dip buying).
// Exit: mean touch (close crosses VWAP), OR time stop,
// OR wide catastrophic ATR stop. No anchor flush.
// ============================================================
// ---------- Inputs ----------
anchorStr = input.string("Week", "VWAP anchor", options = ["Day", "Week", "Month"], group = "VWAP")
band1Mult = input.float(1.0, "Inner band (st dev)", step = 0.25, minval = 0.25, group = "VWAP")
band2Mult = input.float(2.0, "Outer band (st dev)", step = 0.25, minval = 0.5, group = "VWAP")
warmupBars = input.int(12, "Warm-up bars after anchor", minval = 0, group = "VWAP")
tradeDir = input.string("Long only", "Trade direction", options = ["Long only", "Short only", "Both"], group = "Strategy")
useTrend = input.bool(true, "Use EMA trend filter", group = "Strategy")
emaLen = input.int(200, "Trend EMA length", minval = 10, group = "Strategy")
rsiLen = input.int(3, "RSI length", minval = 2, group = "Strategy")
rsiBuy = input.float(25, "RSI oversold (longs)", minval = 1, maxval = 50, group = "Strategy")
rsiSell = input.float(75, "RSI overbought (shorts)", minval = 50, maxval = 99, group = "Strategy")
atrLen = input.int(14, "ATR length", minval = 1, group = "Risk")
atrStopMult = input.float(3.0, "Catastrophic stop (ATR mult)", step = 0.25, minval = 1.0, group = "Risk")
maxBars = input.int(20, "Time stop (bars in trade)", minval = 1, group = "Risk")
startDate = input.time(timestamp("1 Jan 2023 00:00 +0000"), "Start date", group = "Test window")
endDate = input.time(timestamp("1 Jan 2030 00:00 +0000"), "End date", group = "Test window")
// ---------- Anchored VWAP with deviation bands ----------
anchorTF = anchorStr == "Day" ? "D" : anchorStr == "Week" ? "W" : "M"
newAnchor = timeframe.change(anchorTF)
src = hlc3
var float sumPV = 0.0
var float sumV = 0.0
var float sumPV2 = 0.0
var int barsInAnchor = 0
if newAnchor
sumPV := 0.0
sumV := 0.0
sumPV2 := 0.0
barsInAnchor := 0
else
barsInAnchor += 1
sumPV += src * volume
sumV += volume
sumPV2 += src * src * volume
vwapVal = sumV > 0 ? sumPV / sumV : src
variance = sumV > 0 ? math.max(sumPV2 / sumV - vwapVal * vwapVal, 0.0) : 0.0
dev = math.sqrt(variance)
upper1 = vwapVal + band1Mult * dev
upper2 = vwapVal + band2Mult * dev
lower1 = vwapVal - band1Mult * dev
lower2 = vwapVal - band2Mult * dev
// ---------- Filters ----------
atrVal = ta.atr(atrLen)
emaVal = ta.ema(close, emaLen)
rsiVal = ta.rsi(close, rsiLen)
warm = barsInAnchor >= warmupBars and dev > 0
trendLongOK = not useTrend or close > emaVal
trendShortOK = not useTrend or close < emaVal
inWindow = time >= startDate and time <= endDate
allowLong = tradeDir != "Short only"
allowShort = tradeDir != "Long only"
// ---------- Signals: dip buying in trend direction ----------
longSignal = warm and trendLongOK and close < lower1 and rsiVal < rsiBuy
shortSignal = warm and trendShortOK and close > upper1 and rsiVal > rsiSell
var float entryAtr = na
var int entryBar = na
if longSignal and allowLong and inWindow and strategy.position_size == 0
strategy.entry("Long", strategy.long)
entryAtr := atrVal
entryBar := bar_index
if shortSignal and allowShort and inWindow and strategy.position_size == 0
strategy.entry("Short", strategy.short)
entryAtr := atrVal
entryBar := bar_index
// ---------- Exits ----------
if strategy.position_size > 0
strategy.exit("Long stop", from_entry = "Long",
stop = strategy.position_avg_price - atrStopMult * entryAtr)
if close >= vwapVal
strategy.close("Long", comment = "Mean touch")
else if bar_index - entryBar >= maxBars
strategy.close("Long", comment = "Time stop")
if strategy.position_size < 0
strategy.exit("Short stop", from_entry = "Short",
stop = strategy.position_avg_price + atrStopMult * entryAtr)
if close <= vwapVal
strategy.close("Short", comment = "Mean touch")
else if bar_index - entryBar >= maxBars
strategy.close("Short", comment = "Time stop")
// ---------- Visuals ----------
pVwap = plot(vwapVal, "VWAP", color = color.new(color.orange, 0), linewidth = 2)
pU1 = plot(upper1, "Upper 1", color = color.new(color.teal, 60))
pU2 = plot(upper2, "Upper 2", color = color.new(color.teal, 20))
pL1 = plot(lower1, "Lower 1", color = color.new(color.teal, 60))
pL2 = plot(lower2, "Lower 2", color = color.new(color.teal, 20))
plot(emaVal, "Trend EMA", color = color.new(color.purple, 50))
fill(pU1, pU2, color = color.new(color.red, 88), title = "Upper zone")
fill(pL1, pL2, color = color.new(color.green, 88), title = "Lower zone")
// ---------- Alerts ----------
alertcondition(longSignal, "Long dip signal", "Discount zone dip with trend and RSI confluence")
alertcondition(shortSignal, "Short rip signal", "Premium zone rip with trend and RSI confluence")
Overview
VWAP Reversion Bands [QuantForge] buys dips below the inner band when a short RSI is oversold and an optional EMA trend filter agrees, and it can sell rallies above the inner band when short trades are enabled. It exits when price crosses back to the VWAP, after a set number of bars, or at a wide ATR stop. Settings change the anchor period, band width, trade direction, filters, and the backtest window. Entries wait until a warm-up period after each new anchor.
Anchored VWAP with standard deviation bands
Optional EMA trend filter
Short-length RSI confluence
Mean-touch, time, and ATR stop exits
Percent-of-equity sizing with commission and slippage
The inputs you can change from the gear icon on the chart. Defaults are the author's.
Setting
Type
Default
Variable
VWAP anchor
string
Week
anchorStr
Inner band (st dev)
float
1.0
band1Mult
Outer band (st dev)
float
2.0
band2Mult
Warm-up bars after anchor
int
12
warmupBars
Trade direction
string
Long only
tradeDir
Use EMA trend filter
bool
true
useTrend
Trend EMA length
int
200
emaLen
RSI length
int
3
rsiLen
RSI oversold (longs)
float
25
rsiBuy
RSI overbought (shorts)
float
75
rsiSell
ATR length
int
14
atrLen
Catastrophic stop (ATR mult)
float
3.0
atrStopMult
Show all 15 settings
Setting
Type
Default
Variable
Time stop (bars in trade)
int
20
maxBars
Start date
time
timestamp("1 Jan 2023 00:00 +0000")
startDate
End date
time
timestamp("1 Jan 2030 00:00 +0000")
endDate
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.
This mean-reversion strategy combines multi-timeframe exponential moving averages, Bollinger Bands, and the Relative Strength Index. It generates long and optional short trade signals when price interacts with the Bollinger Bands alongside RSI threshold confir
This strategy plots a simple moving average basis and upper and lower Bollinger bands on the price chart, with a fill between the bands. It also calculates RSI. It opens one long trade when RSI is above 25, price is at or below the lower band, and no position
This strategy plots on the price chart and combines up to seven optional modules that vote for long or short conditions. The modules use a 20-period simple moving average, a five-period RSI, Bollinger Band squeezes, a simplified prior-bar break, stacked expone
BB RSI Strategy combines Bollinger Bands, RSI, and multiple simple moving averages directly on the main price chart. It enters long positions when price drops below the lower Bollinger Band while RSI is below a set limit, and enters short positions when price
This strategy executes mean-reversion trades by combining RSI momentum, Bollinger Bands volatility, dynamic ATR stops, and Exponential Moving Averages for trend filtering. It seeks entry opportunities when price reaches extreme Bollinger Band boundaries alongs
Calculates a reversal confidence score combining Bollinger Band overextension, RSI exhaustion, and price distance from a exponential moving average. The strategy overlays VWAP, EMA, and Bollinger Bands directly on the price chart. Long signals trigger when pri