Strategy · Pine Script v6 · On the chart

VWAP Reclaim Strategy

by skipp-dev· code credited to VWAP Reclaim Strategy (Long + Short)

This overlay strategy trades long and short when price reclaims an anchored VWAP and then breaks a recent pullback high or low.

View on GitHub

Repaints

GitHub stars1on the repository
Pine versionv6current
Lines of code466
Settings31inputs
LicenceNone statedfile: MPL-2.0
Last update4 days ago26 Oct 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

466 lines of Pine Script v6 from pine/legacy/VWAP_Reclaim_Strategy.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

VWAP_Reclaim_Strategy.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © 2026 VWAP Reclaim Strategy (Long + Short)

//@version=6
strategy(
    title="VWAP Reclaim Strategy",
    shorttitle="VWAP Reclaim",
    overlay=true,
    default_qty_type=strategy.percent_of_equity,
    default_qty_value=3,
    initial_capital=1000,
    pyramiding=0,
    commission_type=strategy.commission.percent,
    commission_value=0.025,
    // T-2 (TEMPORAL_NUMERICAL_AUDIT_2026-04-24): tick-only execution.
    // Vorher: process_orders_on_close=true + calc_on_every_tick=true erzeugte
    // hybride Semantik (intrabar berechnet, am Close ausgeführt) -> Backtest-PnL
    // wich von Live-PnL ab. Jetzt konsistent tick-basiert.
    process_orders_on_close=false,
    calc_on_every_tick=true
)

// ==================== HELPER FUNCTIONS ====================

// Zero-Lag error-corrected EMA source (from SkippALGO USI Quantum Pulse).
// Leads classic EMA by ~2-5 bars, enabling earlier RSI flips.
f_zl_src(src, len) =>
    e1 = ta.ema(src, len)
    e2 = ta.ema(e1, len)
    2.0 * e1 - e2

// ==================== INPUTS ====================

// Direction Toggle
tradeDirection = input.string("Both", "Trade Direction",
    options=["Long", "Short", "Both"],
    tooltip="Long = nur Long-Trades. Short = nur Short-Trades. Both = beides gleichzeitig.",
    group="Strategy")
allowLong  = tradeDirection == "Long" or tradeDirection == "Both"
allowShort = tradeDirection == "Short" or tradeDirection == "Both"

// VWAP Settings
hideonDWM = input(false, title="Hide VWAP on 1D or Above", group="VWAP Settings")
var anchor = input.string(defval="Session", title="Anchor Period",
    options=["Session", "Week", "Month", "Quarter", "Year", "Decade", "Century", "Earnings", "Dividends", "Splits"],
    group="VWAP Settings")
src = input(title="Source", defval=hlc3, group="VWAP Settings")
offset = input(0, title="Offset", group="VWAP Settings")

// Standard Deviation Bands Settings
showBand_1 = input(false, title="Show Band 1", group="Standard Deviation Bands Settings")
stdevMult_1 = input(0.88, title="Standard Deviation Multiplier", group="Standard Deviation Bands Settings")

// Strategy Settings
simpleVwapCross = input.bool(false, "Simple VWAP Cross Entry",
    tooltip="Einstieg sobald der Preis den VWAP kreuzt (Long: von unten, Short: von oben). Überspringt die Reclaim→Retest→Go Sequenz.",
    group="Strategy")
breakoutEntry = input.bool(true, "Breakout Entry (Pullback High/Low)",
    tooltip="Long: BUY wenn Close den rollenden Pullback High bricht. Short: SELL wenn Close den rollenden Pullback Low bricht (Reclaim→Retest→Go).",
    group="Strategy")
matchedTrends = input.bool(true, "Only Enter on Matched Trends",
    tooltip="Long nur bei VWAP-Aufwärtstrend, Short nur bei VWAP-Abwärtstrend.",
    group="Strategy")
allowSameBarReversal = input.bool(true, "Same-Bar Reversal (Cover→Buy / Exit→Short)",
    tooltip="Erlaubt sofortigen Richtungswechsel auf derselben Candle: Cover + Buy bzw. Exit + Short.",
    group="Strategy")

displaybars = input.bool(true, "Barcolors", group="Display")
showTradeLabels = input.bool(true, "Show Trade Labels", group="Display")

// Trend Detection Settings
trendSlopeBars = input.int(5, "VWAP Slope Lookback", minval=1, maxval=20,
    tooltip="Bars for VWAP slope calculation. Lower = faster but noisier.",
    group="Trend Detection")
trendEmaLen = input.int(8, "Price Bias EMA Length", minval=3, maxval=50,
    tooltip="EMA length for price-above/below-VWAP bias. Lower = earlier signal.",
    group="Trend Detection")

// Reclaim Settings
preset3m = input.string("Neutral", "3m Preset", options=["Aggressive", "Neutral", "Conservative", "Custom"], group="Reclaim Settings")
reclaimWindowBars = input.int(12, "Reclaim: Max Bars bis Retest", minval=1, group="Reclaim Settings")
retestTolATR = input.float(0.10, "Retest Toleranz (ATR-Anteil)", minval=0.0, step=0.01, group="Reclaim Settings")
useAtrTol = input.bool(true, "Toleranz via ATR", group="Reclaim Settings")
debug = input.bool(false, "Debug Markers", group="Reclaim Settings")
showStatusTable = input.bool(false, "Show Status Table", group="Reclaim Settings")
pullbackLookback = input.int(5, "Pullback Lookback", minval=2, maxval=30,
    tooltip="Rolling-Fenster für Pullback High (Long) / Pullback Low (Short) — Donchian. Kleiner = schneller. Default 5.",
    group="Reclaim Settings")

// USI Bull/Bear Stack Filter Settings (aggressive, early-tuned)
useUsiFilter = input.bool(true, "USI Bull/Bear Stack",
    tooltip="Signale nur wenn der USI (Universal Strength Index) den passenden Trend zeigt. Long = Bull-Stack, Short = Bear-Stack.",
    group="⚡ USI Bull/Bear Stack")
usiLen1 = input.int(5, "USI Slow RSI Length (Blue)", minval=2, maxval=30,
    tooltip="Längster RSI im Stack (Blue Line). Default 5 — identisch mit SkippALGO Trend Filter.",
    group="⚡ USI Bull/Bear Stack")
usiLen2 = input.int(3, "USI Mid RSI Length", minval=2, maxval=30,
    tooltip="Mittlerer RSI im Stack. Default 3 — identisch mit SkippALGO Trend Filter.",
    group="⚡ USI Bull/Bear Stack")
usiLen3 = input.int(2, "USI Fast RSI Length (Red)", minval=1, maxval=30,
    tooltip="Kürzester/schnellster RSI (Red Line). Default 2 — identisch mit SkippALGO Trend Filter.",
    group="⚡ USI Bull/Bear Stack")
usiMinStack = input.int(2, "Min Stack Count", minval=1, maxval=2,
    tooltip="Mindest-Stacking: Wie viele kürzere RSIs müssen gestapelt sein? 1 = aggressiv, 2 = alle gestapelt.",
    group="⚡ USI Bull/Bear Stack")

// Signal Filter Settings — bar-close confirmation + volume gate
barCloseOnly = input.bool(false, "Bar Close Only",
    tooltip="Labels und Alerts nur auf geschlossenen Bars. Verhindert Intra-Bar-Flicker bei Live-Daten.",
    group="🔒 Signal Filters")
useVolFilter = input.bool(true, "Volume Filter",
    tooltip="Signale nur wenn das aktuelle Barvolumen über dem Durchschnitt liegt. Filtert Signale in ruhigen/illiquiden Phasen.",
    group="🔒 Signal Filters")
minVolRatio = input.float(1.4, "Min Volume Ratio", minval=0.1, step=0.1,
    tooltip="Mindest-Verhältnis: Aktuelles Barvolumen / SMA(Volumen). 1.0 = Durchschnitt, 1.5 = 50% über Durchschnitt.",
    group="🔒 Signal Filters")
volSmaLen = input.int(20, "Volume SMA Length", minval=5, maxval=100,
    tooltip="Lookback für den Volumen-Durchschnitt.",
    group="🔒 Signal Filters")

reclaimWindowBarsEff = preset3m == "Aggressive" ? 20 : preset3m == "Conservative" ? 8 : preset3m == "Neutral" ? 12 : reclaimWindowBars
retestTolATREff = preset3m == "Aggressive" ? 0.16 : preset3m == "Conservative" ? 0.06 : preset3m == "Neutral" ? 0.10 : retestTolATR

cumVolume = ta.cum(volume)
if barstate.islast and cumVolume == 0
    runtime.error("No volume is provided by the data vendor.")

// Signal filter gates (evaluated on every bar)
volSma = ta.sma(volume, volSmaLen)
volRatio = volSma > 0 ? volume / volSma : 0.0
volGate = useVolFilter ? volRatio >= minVolRatio : true
barCloseGate = barCloseOnly ? barstate.isconfirmed : true

// ==================== DATA REQUESTS ====================

new_earnings = request.earnings(syminfo.tickerid, earnings.actual, barmerge.gaps_on, barmerge.lookahead_on, ignore_invalid_symbol=true)
new_dividends = request.dividends(syminfo.tickerid, dividends.gross, barmerge.gaps_on, barmerge.lookahead_on, ignore_invalid_symbol=true)
new_split = request.splits(syminfo.tickerid, splits.denominator, barmerge.gaps_on, barmerge.lookahead_on, ignore_invalid_symbol=true)

// ==================== VWAP ANCHOR PERIOD ====================

isNewPeriod = switch anchor
    "Earnings"  => not na(new_earnings)
    "Dividends" => not na(new_dividends)
    "Splits"    => not na(new_split)
    "Session"   => timeframe.change("D")
    "Week"      => timeframe.change("W")
    "Month"     => timeframe.change("M")
    "Quarter"   => timeframe.change("3M")
    "Year"      => timeframe.change("12M")
    "Decade"    => timeframe.change("12M") and year % 10 == 0
    "Century"   => timeframe.change("12M") and year % 100 == 0
    => false

isEsdAnchor = anchor == "Earnings" or anchor == "Dividends" or anchor == "Splits"
if na(src[1]) and not isEsdAnchor
    isNewPeriod := true

// ==================== VWAP CALCULATION ====================

var float vwapValue = na
var float upperBandValue1 = na
var float lowerBandValue1 = na
var float upperBandValue2 = na
var float lowerBandValue2 = na

if not (hideonDWM and timeframe.isdwm)
    [_vwap, _stdevUpper, _] = ta.vwap(src, isNewPeriod, 1)
    vwapValue := _vwap
    stdevAbs = _stdevUpper - _vwap
    upperBandValue1 := _vwap + stdevAbs * stdevMult_1
    lowerBandValue1 := _vwap - stdevAbs * stdevMult_1
    upperBandValue2 := _vwap + 2 * stdevAbs * stdevMult_1
    lowerBandValue2 := _vwap - 2 * stdevAbs * stdevMult_1

// ==================== COMMON TA ====================

atr = nz(ta.atr(14), syminfo.mintick * 10)
tol = useAtrTol ? atr * retestTolATREff : syminfo.mintick * 2

// Trend detection: slope + price bias (mutually exclusive)
vwapSlope = ta.change(vwapValue, trendSlopeBars)
emaClose = ta.ema(close, trendEmaLen)
priceBiasLong  = emaClose > vwapValue
priceBiasShort = emaClose < vwapValue
// Slope takes priority; when slope ≈ 0, fall back to price bias.
// Prevents both isUpTrend and isDownTrend being true simultaneously.
isUpTrend   = vwapSlope > 0 or (vwapSlope == 0 and priceBiasLong)
isDownTrend = vwapSlope < 0 or (vwapSlope == 0 and priceBiasShort)

matchedTrendsFilter_long  = not matchedTrends ? true : isUpTrend
matchedTrendsFilter_short = not matchedTrends ? true : isDownTrend

// Donchian channels
pullbackHigh = ta.highest(high, pullbackLookback)
pullbackLow  = ta.lowest(low, pullbackLookback)

// ==================== USI QUANTUM PULSE (EARLY-TUNED) ====================

usiSrc1 = f_zl_src(close, usiLen1)   // slowest (default 5) — "Blue Line"
usiSrc2 = f_zl_src(close, usiLen2)   // mid     (default 3)
usiSrc3 = f_zl_src(close, usiLen3)   // fastest (default 2) — "Red Line"

usiLine1 = ta.rsi(usiSrc1, usiLen1)
usiLine2 = ta.rsi(usiSrc2, usiLen2)
usiLine3 = ta.rsi(usiSrc3, usiLen3)

// Bull stacking
usiBullStack = (usiLine3 > usiLine2 ? 1 : 0) + (usiLine2 > usiLine1 ? 1 : 0)
usiBullState = usiLine3 > usiLine1
usiUpTrend = usiBullStack >= usiMinStack and usiBullState

// Bear stacking (mirror)
usiBearStack = (usiLine3 < usiLine2 ? 1 : 0) + (usiLine2 < usiLine1 ? 1 : 0)
usiBearState = usiLine3 < usiLine1
usiDownTrend = usiBearStack >= usiMinStack and usiBearState

usiGateLong  = useUsiFilter ? usiUpTrend   : true
usiGateShort = useUsiFilter ? usiDownTrend : true

// ==================== RECLAIM → RETEST → GO  (LONG) ====================

wasBelowVwap = close[1] < vwapValue[1]
reclaimUp = wasBelowVwap and close > vwapValue and not isNewPeriod

var int   reclaimBarL   = na
var float retestLowL    = na
var bool  inReclaimSeqL = false
var bool  retestSeenL   = false
var bool  inPositionL   = false

// Reset on new anchor period — close ALL positions, reset both sides
if isNewPeriod
    if strategy.position_size != 0
        strategy.close_all("Period Reset")
    inPositionL   := false
    inReclaimSeqL := false
    retestSeenL   := false
    retestLowL    := na
    reclaimBarL   := na

if reclaimUp
    reclaimBarL   := bar_index
    inReclaimSeqL := true
    retestSeenL   := false
    retestLowL    := na

if inReclaimSeqL
    expired = (bar_index - reclaimBarL) > reclaimWindowBarsEff
    hardFail = close < vwapValue - tol
    if expired or hardFail
        inReclaimSeqL := false
        retestSeenL   := false

    else if not retestSeenL
        retestCond = low <= vwapValue + tol and close >= vwapValue - tol
        if retestCond
            retestSeenL := true
            retestLowL  := low

goLong = inReclaimSeqL and retestSeenL and close > pullbackHigh[1] and bar_index > reclaimBarL

entryTriggerL = simpleVwapCross ? reclaimUp : (breakoutEntry and goLong)
longSignal = allowLong and entryTriggerL and matchedTrendsFilter_long and usiGateLong and usiBullState and barCloseGate and volGate and not inPositionL

// ==================== RECLAIM → RETEST → GO  (SHORT — mirror) ====================

wasAboveVwap = close[1] > vwapValue[1]
reclaimDown = wasAboveVwap and close < vwapValue and not isNewPeriod

var int   reclaimBarS    = na
var float retestHighS    = na
var bool  inReclaimSeqS  = false
var bool  retestSeenS    = false
var bool  inPositionS    = false

// Reset on new anchor period (short side state only — close_all already fired above)
if isNewPeriod
    inPositionS    := false
    inReclaimSeqS  := false
    retestSeenS    := false
    retestHighS    := na
    reclaimBarS    := na

if reclaimDown
    reclaimBarS    := bar_index
    inReclaimSeqS  := true
    retestSeenS    := false
    retestHighS    := na

if inReclaimSeqS
    expired = (bar_index - reclaimBarS) > reclaimWindowBarsEff
    hardFail = close > vwapValue + tol
    if expired or hardFail
        inReclaimSeqS := false
        retestSeenS   := false

    else if not retestSeenS
        retestCond = high >= vwapValue - tol and close <= vwapValue + tol
        if retestCond
            retestSeenS := true
            retestHighS := high

goShort = inReclaimSeqS and retestSeenS and close < pullbackLow[1] and bar_index > reclaimBarS

entryTriggerS = simpleVwapCross ? reclaimDown : (breakoutEntry and goShort)
shortSignal = allowShort and entryTriggerS and matchedTrendsFilter_short and usiGateShort and usiBearState and barCloseGate and volGate and not inPositionS

// Exit conditions (computed before entries for same-bar reversal logic)
exitLongCond  = inPositionL and close < vwapValue - tol and barCloseGate
exitShortCond = inPositionS and close > vwapValue + tol and barCloseGate

// Same-bar reversal: when exiting one side, enter the other if conditions are met
reversalLong  = allowSameBarReversal and exitShortCond and allowLong  and matchedTrendsFilter_long  and usiGateLong  and usiBullState and volGate
reversalShort = allowSameBarReversal and exitLongCond  and allowShort and matchedTrendsFilter_short and usiGateShort and usiBearState and volGate

longSignal  := longSignal  or reversalLong
shortSignal := shortSignal or reversalShort

// ==================== STRATEGY LOGIC ====================

var float longStop  = na
var float shortStop = na

// --- LONG ---
if longSignal
    strategy.entry("Long", strategy.long)
    longStop := simpleVwapCross ? vwapValue - tol : nz(retestLowL, vwapValue) - tol
    inReclaimSeqL := false
    retestSeenL   := false
    inPositionL   := true

if strategy.position_size > 0 and not na(longStop)
    strategy.exit("L-Stop", "Long", stop=longStop)

if exitLongCond
    strategy.close("Long")
    inPositionL := false

// Sync flag if stopped out (guard against same-bar entry to avoid
// false reset when an opposite-side position offsets position_size)
if strategy.position_size <= 0 and inPositionL and not longSignal
    inPositionL := false

// --- SHORT ---
if shortSignal
    strategy.entry("Short", strategy.short)
    shortStop := simpleVwapCross ? vwapValue + tol : nz(retestHighS, vwapValue) + tol
    inReclaimSeqS := false
    retestSeenS   := false
    inPositionS   := true

if strategy.position_size < 0 and not na(shortStop)
    strategy.exit("S-Stop", "Short", stop=shortStop)

if exitShortCond
    strategy.close("Short")
    inPositionS := false

// Sync flag if stopped out (guard against same-bar entry)
if strategy.position_size >= 0 and inPositionS and not shortSignal
    inPositionS := false

// ==================== PLOTS ====================

plot(vwapValue, title="VWAP", color=color.white, linewidth=2, offset=offset)

upperBand_1 = plot(showBand_1 ? upperBandValue1 : na, title="Upper Band #1", color=color.new(color.gray, 50), offset=offset, linewidth=1)
lowerBand_1 = plot(showBand_1 ? lowerBandValue1 : na, title="Lower Band #1", color=color.new(color.gray, 50), offset=offset, linewidth=1)

plot(upperBandValue2, title="Upper Band #2", color=color.lime, linewidth=1, display=display.none)
plot(lowerBandValue2, title="Lower Band #2", color=color.red, linewidth=1, display=display.none)

hl2_plot = plot(hl2, color=na, title="HL2", display=display.none)

// ==================== FILLS ====================

fill(hl2_plot, upperBand_1, color=hl2 > upperBandValue1 ? color.new(color.green, 50) : na, title="Above Upper Band")
fill(hl2_plot, lowerBand_1, color=hl2 < lowerBandValue1 ? color.new(color.red, 50) : na, title="Below Lower Band")
fill(upperBand_1, lowerBand_1, title="Bands Fill", color=isUpTrend ? color.new(color.lime, 88) : color.new(color.red, 88))

// ==================== BAR COLORING ====================

barcolor(displaybars ? (isUpTrend ? color.new(color.lime, 30) : color.new(color.red, 30)) : na, title="Trade Direction")

// ==================== ENTRY/EXIT MARKERS ====================

// Long debug markers
plotshape(debug and barCloseGate and reclaimUp and allowLong, title="ReclaimUp", style=shape.triangleup, location=location.belowbar, color=color.new(color.white, 0), size=size.tiny, text="R")
plotshape(debug and barCloseGate and retestSeenL and inReclaimSeqL and allowLong, title="RetestSeenL", style=shape.circle, location=location.belowbar, color=color.new(color.yellow, 0), size=size.tiny, text="T")

// Short debug markers
plotshape(debug and barCloseGate and reclaimDown and allowShort, title="ReclaimDown", style=shape.triangledown, location=location.abovebar, color=color.new(color.white, 0), size=size.tiny, text="R↓")
plotshape(debug and barCloseGate and retestSeenS and inReclaimSeqS and allowShort, title="RetestSeenS", style=shape.circle, location=location.abovebar, color=color.new(color.yellow, 0), size=size.tiny, text="T↓")

// Entry/Exit labels
plotshape(showTradeLabels and longSignal,  title="Long Entry",  style=shape.labelup,   location=location.belowbar, color=color.new(color.lime, 0),   textcolor=color.white, size=size.tiny, text="Buy")
plotshape(showTradeLabels and exitLongCond,  title="Long Exit",   style=shape.labeldown, location=location.abovebar, color=color.new(color.orange, 0), textcolor=color.white, size=size.tiny, text="Exit")
plotshape(showTradeLabels and shortSignal,   title="Short Entry", style=shape.labeldown, location=location.abovebar, color=color.new(color.red, 0),    textcolor=color.white, size=size.tiny, text="Short")
plotshape(showTradeLabels and exitShortCond, title="Short Exit",  style=shape.labelup,   location=location.belowbar, color=color.new(color.orange, 0), textcolor=color.white, size=size.tiny, text="Cover")

// Pullback channels
plot(allowLong  and (inReclaimSeqL or inPositionL) ? pullbackHigh : na, title="Pullback High", color=color.new(color.aqua, 0), linewidth=1, display=display.none)
plot(allowShort and (inReclaimSeqS or inPositionS) ? pullbackLow  : na, title="Pullback Low",  color=color.new(color.fuchsia, 0), linewidth=1, display=display.none)

// ==================== STATUS TABLE ====================

var table statusTable = table.new(position.top_right, 2, 12, border_width=1)
if barstate.islast
    if showStatusTable
        table.cell(statusTable, 0, 0, "Direction", text_color=color.white, bgcolor=color.new(color.blue, 65))
        table.cell(statusTable, 1, 0, tradeDirection, text_color=color.white, bgcolor=color.new(color.blue, 80))

        table.cell(statusTable, 0, 1, "Preset", text_color=color.white, bgcolor=color.new(color.blue, 65))
        table.cell(statusTable, 1, 1, preset3m, text_color=color.white, bgcolor=color.new(color.blue, 80))

        table.cell(statusTable, 0, 2, "Window", text_color=color.white, bgcolor=color.new(color.gray, 70))
        table.cell(statusTable, 1, 2, str.tostring(reclaimWindowBarsEff), text_color=color.white, bgcolor=color.new(color.gray, 85))

        table.cell(statusTable, 0, 3, "Tol ATR", text_color=color.white, bgcolor=color.new(color.gray, 70))
        table.cell(statusTable, 1, 3, str.tostring(retestTolATREff, "#.##"), text_color=color.white, bgcolor=color.new(color.gray, 85))

        table.cell(statusTable, 0, 4, "Tol Mode", text_color=color.white, bgcolor=color.new(color.gray, 70))
        table.cell(statusTable, 1, 4, useAtrTol ? "ATR" : "Ticks", text_color=color.white, bgcolor=color.new(color.gray, 85))

        table.cell(statusTable, 0, 5, "Tol Px", text_color=color.white, bgcolor=color.new(color.gray, 70))
        table.cell(statusTable, 1, 5, str.tostring(tol, format.mintick), text_color=color.white, bgcolor=color.new(color.gray, 85))

        table.cell(statusTable, 0, 6, "Anchor", text_color=color.white, bgcolor=color.new(color.gray, 70))
        table.cell(statusTable, 1, 6, anchor, text_color=color.white, bgcolor=color.new(color.gray, 85))

        anchorHint = anchor == "Session" ? "OK" : "3m daytrade: Session"
        anchorBg = anchor == "Session" ? color.new(color.green, 75) : color.new(color.orange, 65)
        table.cell(statusTable, 0, 7, "Hint", text_color=color.white, bgcolor=color.new(color.gray, 70))
        table.cell(statusTable, 1, 7, anchorHint, text_color=color.white, bgcolor=anchorBg)

        usiLabel = not useUsiFilter ? "OFF" : (usiUpTrend ? "BULL" : (usiDownTrend ? "BEAR" : "FLAT"))
        usiBg = not useUsiFilter ? color.new(color.gray, 70) : (usiUpTrend ? color.new(color.green, 65) : (usiDownTrend ? color.new(color.red, 65) : color.new(color.gray, 70)))
        table.cell(statusTable, 0, 8, "USI", text_color=color.white, bgcolor=color.new(color.gray, 70))
        table.cell(statusTable, 1, 8, usiLabel, text_color=color.white, bgcolor=usiBg)

        bcLabel = barCloseOnly ? "ON" : "OFF"
        bcBg = barCloseOnly ? color.new(color.green, 65) : color.new(color.gray, 70)
        table.cell(statusTable, 0, 9, "BarClose", text_color=color.white, bgcolor=color.new(color.gray, 70))
        table.cell(statusTable, 1, 9, bcLabel, text_color=color.white, bgcolor=bcBg)

        volLabel = useVolFilter ? str.tostring(volRatio, "#.##") + "x" : "OFF"
        volBg = not useVolFilter ? color.new(color.gray, 70) : (volGate ? color.new(color.green, 65) : color.new(color.red, 65))
        table.cell(statusTable, 0, 10, "VolFilt", text_color=color.white, bgcolor=color.new(color.gray, 70))
        table.cell(statusTable, 1, 10, volLabel, text_color=color.white, bgcolor=volBg)

        revLabel = allowSameBarReversal ? "ON" : "OFF"
        revBg = allowSameBarReversal ? color.new(color.green, 65) : color.new(color.gray, 70)
        table.cell(statusTable, 0, 11, "Reversal", text_color=color.white, bgcolor=color.new(color.gray, 70))
        table.cell(statusTable, 1, 11, revLabel, text_color=color.white, bgcolor=revBg)
    else
        table.clear(statusTable, 0, 0, 1, 11)

// ==================== ALERTING ====================

// T-4 (TEMPORAL_NUMERICAL_AUDIT_2026-04-24): bar-close gate.
bool _alertGate = barstate.isconfirmed
alertcondition(longSignal    and _alertGate, title="Buy",   message="VWAP Reclaim — Buy")
alertcondition(exitLongCond  and _alertGate, title="Exit",  message="VWAP Reclaim — Exit")
alertcondition(shortSignal   and _alertGate, title="Short", message="VWAP Reclaim — Short")
alertcondition(exitShortCond and _alertGate, title="Cover", message="VWAP Reclaim — Cover")

Overview

Optional modes enter on a simple VWAP cross instead. It filters with VWAP slope, a short price-bias EMA, a stacked RSI bias, and relative volume, and it can reverse on the same bar. Settings change anchor, band display, direction, retest tolerance, and those filters. It draws on the price chart. Signals can change on the live bar, and the listed inputs do not define a stop loss.

Details

Published by

skipp-dev on GitHub

Code credit

VWAP Reclaim Strategy (Long + Short), as written in the script's header

Draws

On the price chart

Markets

Any symbol

Timeframes

M1-M5, M15-H1

Risk Notes

  • Signals can change on the live bar or after it closes (repainting)
  • The strategy enters trades without a stop loss

Settings

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

SettingTypeDefaultVariable
Trade DirectionstringBothtradeDirection
Hide VWAP on 1D or AboveboolfalsehideonDWM
Anchor PeriodstringSessionanchor
Sourcesourcehlc3src
Offsetint0offset
Show Band 1boolfalseshowBand_1
Standard Deviation Multiplierfloat0.88stdevMult_1
Simple VWAP Cross EntryboolfalsesimpleVwapCross
Breakout Entry (Pullback High/Low)booltruebreakoutEntry
Only Enter on Matched TrendsbooltruematchedTrends
Same-Bar Reversal (Cover→Buy / Exit→Short)booltrueallowSameBarReversal
Barcolorsbooltruedisplaybars
Show all 31 settings
SettingTypeDefaultVariable
Show Trade LabelsbooltrueshowTradeLabels
VWAP Slope Lookbackint5trendSlopeBars
Price Bias EMA Lengthint8trendEmaLen
3m PresetstringNeutralpreset3m
Reclaim: Max Bars bis Retestint12reclaimWindowBars
Retest Toleranz (ATR-Anteil)float0.10retestTolATR
Toleranz via ATRbooltrueuseAtrTol
Debug Markersboolfalsedebug
Show Status TableboolfalseshowStatusTable
Pullback Lookbackint5pullbackLookback
USI Bull/Bear StackbooltrueuseUsiFilter
USI Slow RSI Length (Blue)int5usiLen1
USI Mid RSI Lengthint3usiLen2
USI Fast RSI Length (Red)int2usiLen3
Min Stack Countint2usiMinStack
Bar Close OnlyboolfalsebarCloseOnly
Volume FilterbooltrueuseVolFilter
Min Volume Ratiofloat1.4minVolRatio
Volume SMA Lengthint20volSmaLen
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

4 stars

This strategy draws on the price chart and is set up for daily ETF trading. It can enter through a classic surge-and-consolidation breakout, a pullback toward stacked EMAs, a relative-volume spike with price momentum, or a pause inside a strong trend. EMA leng

Strategy v6 BreakoutTrend
Updated 7 months ago · None stated GitHub repository of Qullamaggie Breakout Strategy

Q-Trend + KVO Strategy

by TradersPost
228 stars

This strategy combines the ATR-banded Q-Trend indicator with the Klinger Volume Oscillator (KVO) to execute confluence trades. It enters long when a Q-Trend buy trigger aligns with a positive KVO value and a bullish candle confirmation, taking short trades und

Strategy v6 TrendVolume
Updated 3 months ago · None stated GitHub repository of Q-Trend + KVO Strategy

Altered OBV On MACD

by hasnocool
106 stars

This strategy calculates and plots 9, 21, 50, 90, and 200-period Simple Moving Averages on the main price chart. It constructs a modified On-Balance Volume (OBV) metric and calculates a MACD oscillator based on this custom volume series rather than price. Long

Strategy v5 Moving averagesVolume
Updated 2 years ago · GPL-3.0 GitHub repository of Altered OBV On MACD
53 stars

This strategy enters long or short on the price chart when price is on the correct side of a 200-period EMA, MACD agrees, RSI is not at the opposing extreme, ADX exceeds a threshold, volume beats a 20-bar average, and close breaks the recent high or low. A tim

Strategy v6 TrendOscillators & momentum
Updated 2 months ago · MPL-2.0 GitHub repository of BTCUSD 5M Optimized Strategy

ADA4H Optuna Strategy

by skywalker0803r
42 stars

This strategy trades longs and shorts on the price chart. Long entries require a close above the prior Donchian high, a close above a long-term SMA, and RSI above a threshold, with size set as a percentage of equity. Long exits use a stop at the prior Donchian

Strategy v5 TrendOscillators & momentum
Updated 2 months ago · None stated GitHub repository of ADA4H Optuna Strategy
23 stars

This strategy evaluates breakout and trend opportunities on the price chart using a weighted composite score of volume, trend, and candlestick structure. It tracks volume spikes, fast and slow EMAs, higher-timeframe EMA trend alignment, opening ranges, and ses

Strategy v6 TrendVolume Repaints
Updated 4 weeks ago · Custom licence GitHub repository of TradingAlpha Point-Clip Strategy

More Trend 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