Strategy · Pine Script v6 · On the chart

VWAP Reversion Bands [QuantForge]

by QuantForgeHQ

This strategy plots an anchored volume-weighted average price and two standard-deviation bands on the price chart.

View on GitHub

GitHub stars1on the repository
Pine versionv6current
Lines of code127
Settings15inputs
LicenceMIT
Last update3 months ago6 Jul 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new strategy, select all of the template text and paste. Press Save and give it a name.
  4. 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.

Details

Published by

QuantForgeHQ on GitHub

Draws

On the price chart

Markets

Stocks

Timeframes

M15-H1

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
VWAP anchorstringWeekanchorStr
Inner band (st dev)float1.0band1Mult
Outer band (st dev)float2.0band2Mult
Warm-up bars after anchorint12warmupBars
Trade directionstringLong onlytradeDir
Use EMA trend filterbooltrueuseTrend
Trend EMA lengthint200emaLen
RSI lengthint3rsiLen
RSI oversold (longs)float25rsiBuy
RSI overbought (shorts)float75rsiSell
ATR lengthint14atrLen
Catastrophic stop (ATR mult)float3.0atrStopMult
Show all 15 settings
SettingTypeDefaultVariable
Time stop (bars in trade)int20maxBars
Start datetimetimestamp("1 Jan 2023 00:00 +0000")startDate
End datetimetimestamp("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.

Similar Pine Scripts

330 stars

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

Strategy v5 Mean reversionMoving averages
Updated 2 months ago · None stated GitHub repository of MEMA + BB + RSI [Alorse]
7 stars

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

Strategy v5 Volatility & bandsOscillators & momentum
Updated 4 years ago · GPL-3.0 GitHub repository of Bollinger Bands Strategy

Simpleton GROK

by eltonaguiar
4 stars

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

Strategy v5 Oscillators & momentumMoving averages
Updated 2 days ago · None stated GitHub repository of Simpleton GROK

BB RSI Strategy

by infinityhao
3 stars

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

Strategy v4 Volatility & bandsOscillators & momentum Repaints
Updated 5 years ago · None stated GitHub repository of BB RSI Strategy

Mean Reversion Trading Bot

by BenjaminLettner
1 stars

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

Strategy v5 Mean reversionOscillators & momentum
Updated 8 months ago · None stated GitHub repository of Mean Reversion Trading Bot
1 stars

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

Strategy v5 Mean reversionOscillators & momentum
Updated 9 months ago · None stated GitHub repository of Reversal Confidence Strategy

More Mean reversion scripts

Related on ForexR

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers