Appearance
Personalize your experience
Anchored VWAP Reclaim
Admin's ChoiceFreeBuys the reclaim of the swing-low VWAP after a flush
Live engine preview
The QuaScript engine's own output on the chart the terminal uses. Change the settings or edit the code and press Run to recompute it.
About
Trades the moment the crowd that bought the last swing low is back in profit. A VWAP is anchored at every confirmed swing low and swing high. In an uptrend, a pullback that closes below the swing-low VWAP puts those buyers under water; when price closes back above it within a few bars, the dip was absorbed and the buyers defend their average. Shorts mirror this with the swing-high VWAP in a downtrend. Entry: trend filter (close beyond a rising 200-bar EMA), a close at least `flush` ATR below the newest swing-low VWAP, then a close back above it by the margin within `window` bars (mirror for shorts). Exit: stop beyond the dip extreme (at least 1 ATR), target `reward` R, trailing exit on a close back through the VWAP. Risk: 1 % per trade.
Settings
Swing bars left: 10
Swing bars right: 5
Trend EMA: 200
Reclaim window (bars): 6
Reclaim margin (ATR): 0.15
Flush depth (ATR): 0.3
Target (R): 2.5
Measured backtests
Run by the backtest engine on public candles, 2025-11-01 to 2026-11-01, with the script's own commission and slippage, on BTCUSDT 1h (Binance) and ETHUSDT 1h (Binance). The figures per market are in the Measured backtest panel below. Past results do not predict future returns.
Backtest it yourself
Open it on the backtesting page to run it on any symbol, interval and date range, then use Monte Carlo, optimisation, walk-forward and robustness tests.
Strategy Rules
Entry Conditions
- ▸ trend filter (close beyond a rising 200-bar EMA), a close at least `flush` ATR below the newest swing-low VWAP, then a close back above it by the margin within `window` bars (mirror for shorts)
Exit Conditions
- ▸ stop beyond the dip extreme (at least 1 ATR), target `reward` R, trailing exit on a close back through the VWAP
Measured backtest
BTCUSDT 1h (Binance), 2025-11-01 to 2026-11-01 · backtest engine, script costs included
-18.5%
Return
-1.43
Sharpe
-23.1%
Max DD
26.6%
Win Rate
139
Trades
| Market | Trades | Return | Sharpe | Max DD | Win rate | Profit factor |
|---|---|---|---|---|---|---|
| BTCUSDT 1h | 139 | -18.5% | -1.43 | -23.1% | 26.6% | 0.74 |
| ETHUSDT 1h | 109 | -6.0% | -0.35 | -14.3% | 31.2% | 0.91 |
Past results on historical data do not predict future returns.
Source Code
Edit in IDE| 1 | strategy "Anchored VWAP Reclaim" { |
| 2 | overlay = true |
| 3 | capital = 100000 |
| 4 | commission = 0.05 |
| 5 | slippage = 1 |
| 6 | sizing = risk_percent |
| 7 | max_leverage = 1 |
| 8 | size = 1 |
| 9 | pyramiding = 1 |
| 10 | } |
| 11 | /// Trades the moment the crowd that bought the last swing low is back in profit. A VWAP is anchored |
| 12 | /// at every confirmed swing low and swing high. In an uptrend, a pullback that closes below the |
| 13 | /// swing-low VWAP puts those buyers under water; when price closes back above it within a few |
| 14 | /// bars, the dip was absorbed and the buyers defend their average. Shorts mirror this with the |
| 15 | /// swing-high VWAP in a downtrend. |
| 16 | /// Entry: trend filter (close beyond a rising 200-bar EMA), a close at least `flush` ATR below the |
| 17 | /// newest swing-low VWAP, then a |
| 18 | /// close back above it by the margin within `window` bars (mirror for shorts). Exit: stop beyond |
| 19 | /// the dip extreme (at least 1 ATR), target `reward` R, trailing exit on a close back through the |
| 20 | /// VWAP. Risk: 1 % per trade. |
| 21 | use "viz/premium" as pr |
| 22 | left = param.int(10, title = "Swing bars left", min = 2, max = 50, group = "Swings") |
| 23 | right = param.int(5, title = "Swing bars right", min = 1, max = 30, group = "Swings") |
| 24 | trend_n = param.int(200, title = "Trend EMA", min = 20, max = 1000, group = "Filter") |
| 25 | window = param.int(6, title = "Reclaim window (bars)", min = 1, max = 50, group = "Signals") |
| 26 | margin = param.float(0.15, title = "Reclaim margin (ATR)", min = 0, max = 2, step = 0.05, group = "Signals") |
| 27 | flush = param.float(0.3, title = "Flush depth (ATR)", min = 0, max = 3, step = 0.05, group = "Signals") |
| 28 | reward = param.float(2.5, title = "Target (R)", min = 0.5, max = 10, step = 0.1, group = "Risk") |
| 29 | pl = ta.pivot_low(left, right) |
| 30 | ph = ta.pivot_high(left, right) |
| 31 | pv = bar.typical * volume |
| 32 | persist lp = na |
| 33 | persist lv = na |
| 34 | persist hp = na |
| 35 | persist hv = na |
| 36 | lp := lp + pv |
| 37 | lv := lv + volume |
| 38 | hp := hp + pv |
| 39 | hv := hv + volume |
| 40 | sp = 0.0 |
| 41 | sv = 0.0 |
| 42 | if not math.is_na(pl) or not math.is_na(ph) { |
| 43 | for i in 0..=right { |
| 44 | sp := sp + pv[i] |
| 45 | sv := sv + volume[i] |
| 46 | } |
| 47 | } |
| 48 | if not math.is_na(pl) { |
| 49 | lp := sp |
| 50 | lv := sv |
| 51 | } |
| 52 | if not math.is_na(ph) { |
| 53 | hp := sp |
| 54 | hv := sv |
| 55 | } |
| 56 | vl = lp / lv |
| 57 | vh = hp / hv |
| 58 | ema = ta.ema(close, trend_n) |
| 59 | a = ta.atr(14) |
| 60 | slope = (ema - ema[20]) / math.max(a, 1e-12) |
| 61 | up = close > ema and slope > 0.5 |
| 62 | dn = close < ema and slope < -0.5 |
| 63 | below = close < vl - flush * a |
| 64 | above = close > vh + flush * a |
| 65 | since_below = ta.bars_since(below) |
| 66 | since_above = ta.bars_since(above) |
| 67 | dip_low = ta.lowest(low, window + 1) |
| 68 | pop_high = ta.highest(high, window + 1) |
| 69 | go_l = up and close > vl + margin * a and not below and math.coalesce(since_below, 1000000) <= window and since_below >= 1 |
| 70 | go_s = dn and close < vh - margin * a and not above and math.coalesce(since_above, 1000000) <= window and since_above >= 1 |
| 71 | // one trade per reclaim: re-arm once price trades through the line again |
| 72 | persist used_l = false |
| 73 | persist used_s = false |
| 74 | if below { used_l := false } |
| 75 | if above { used_s := false } |
| 76 | flat = position.size == 0 |
| 77 | if flat and go_l and not used_l { |
| 78 | stop = math.min(dip_low, close - a) |
| 79 | order.market("L", side.long) |
| 80 | exit.bracket("L exit", entry = "L", stop = stop, target = close + (close - stop) * reward) |
| 81 | used_l := true |
| 82 | } |
| 83 | if flat and go_s and not used_s { |
| 84 | stop = math.max(pop_high, close + a) |
| 85 | order.market("S", side.short) |
| 86 | exit.bracket("S exit", entry = "S", stop = stop, target = close - (stop - close) * reward) |
| 87 | used_s := true |
| 88 | } |
| 89 | if position.size > 0 and close < vl - a { exit.close("L") } |
| 90 | if position.size < 0 and close > vh + a { exit.close("S") } |
| 91 | risk.max_drawdown(25) |
| 92 | render.line(ema, "Trend EMA", color = color.translucent(color.slate.300, 50), width = 1) |
| 93 | render.line(vl, "Swing-low VWAP", color = color.emerald.300, width = 1.75) |
| 94 | render.line(vh, "Swing-high VWAP", color = color.rose.300, width = 1.75) |
| 95 | render.mark(go_l and flat and not used_l[1], shape = shape.triangle_up, at = anchor.below_bar, color = color.emerald.300, text = "Reclaim", title = "Long reclaim") |
| 96 | render.mark(go_s and flat and not used_s[1], shape = shape.triangle_down, at = anchor.above_bar, color = color.rose.300, text = "Reject", title = "Short rejection") |
| 97 | persist t = draw.table.create(anchor.top_right, 5, 2) |
| 98 | if bar.is_last { |
| 99 | pr.heading(t, 2, "Anchored VWAP Reclaim", "Strategy · swing-anchored VWAPs") |
| 100 | pr.row(t, 2, "Trend", up ? "Up" : "Down", up ? pr.BULL : pr.BEAR) |
| 101 | pr.row(t, 3, "Swing-low VWAP", str.format("{:.2f} ({:+.2%})", vl, close / vl - 1), close > vl ? pr.BULL : pr.BEAR) |
| 102 | pr.row(t, 4, "Swing-high VWAP", str.format("{:.2f} ({:+.2%})", vh, close / vh - 1), close > vh ? pr.BULL : pr.BEAR) |
| 103 | } |
| 104 |
Reviews
No reviews yet. Be the first to review this listing.