Appearance
Personalize your experience
Pressure Divergence Reversal
Admin's ChoiceFreeFades swings that volume pressure did not confirm
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
Fades exhausted swings that volume pressure did not confirm. Signed volume pressure (buy minus sell volume over total volume, from exchange order flow or a bulk-volume estimate) is averaged into a wave. A new swing low below the previous one, with the wave higher than it was at the previous low, means sellers pushed price further with less force. The entry waits for the wave to cross back over its slower tide line, the sign that buyers have taken over. Entry: bullish pressure divergence at a confirmed swing low, then wave crossing above the tide within `window` bars (mirror for shorts at swing highs). Exit: stop beyond the divergence swing (at least 1 ATR), target `reward` R, or time stop. Risk: 1 % per trade.
Settings
Wave length: 8
Tide length: 34
Swing bars: 5
Divergence reach (bars): 60
Confirmation window (bars): 10
Target (R): 2
Maximum bars held: 72
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
- ▸ bullish pressure divergence at a confirmed swing low, then wave crossing above the tide within `window` bars (mirror for shorts at swing highs)
Exit Conditions
- ▸ stop beyond the divergence swing (at least 1 ATR), target `reward` R, or time stop
Measured backtest
BTCUSDT 1h (Binance), 2025-11-01 to 2026-11-01 · backtest engine, script costs included
2.7%
Return
0.29
Sharpe
-8.0%
Max DD
41.8%
Win Rate
98
Trades
| Market | Trades | Return | Sharpe | Max DD | Win rate | Profit factor |
|---|---|---|---|---|---|---|
| BTCUSDT 1h | 98 | 2.7% | 0.29 | -8.0% | 41.8% | 1.05 |
| ETHUSDT 1h | 95 | -22.4% | -2.04 | -24.9% | 28.4% | 0.61 |
Past results on historical data do not predict future returns.
Source Code
Edit in IDE| 1 | strategy "Pressure Divergence Reversal" { |
| 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 | /// Fades exhausted swings that volume pressure did not confirm. Signed volume pressure (buy minus |
| 12 | /// sell volume over total volume, from exchange order flow or a bulk-volume estimate) is averaged |
| 13 | /// into a wave. A new swing low below the previous one, with the wave higher than it was at the |
| 14 | /// previous low, means sellers pushed price further with less force. The entry waits for the wave |
| 15 | /// to cross back over its slower tide line, the sign that buyers have taken over. |
| 16 | /// Entry: bullish pressure divergence at a confirmed swing low, then wave crossing above the tide |
| 17 | /// within `window` bars (mirror for shorts at swing highs). Exit: stop beyond the divergence swing |
| 18 | /// (at least 1 ATR), target `reward` R, or time stop. Risk: 1 % per trade. |
| 19 | use "viz/premium" as pr |
| 20 | fast = param.int(8, title = "Wave length", min = 2, max = 200, group = "Pressure") |
| 21 | slow = param.int(34, title = "Tide length", min = 5, max = 500, group = "Pressure") |
| 22 | swing = param.int(5, title = "Swing bars", min = 2, max = 30, group = "Divergence") |
| 23 | reach = param.int(60, title = "Divergence reach (bars)", min = 10, max = 500, group = "Divergence") |
| 24 | window = param.int(10, title = "Confirmation window (bars)", min = 1, max = 50, group = "Signals") |
| 25 | reward = param.float(2.0, title = "Target (R)", min = 0.5, max = 10, step = 0.1, group = "Risk") |
| 26 | hold = param.int(72, title = "Maximum bars held", min = 2, max = 1000, group = "Risk") |
| 27 | (buy, sell, _) = hft.flow(fast) |
| 28 | signed = buy - sell |
| 29 | wave = ta.ema(signed, fast) / math.max(ta.ema(volume, fast), 1e-12) |
| 30 | tide = ta.ema(signed, slow) / math.max(ta.ema(volume, slow), 1e-12) |
| 31 | ph = ta.pivot_high(swing, swing) |
| 32 | pl = ta.pivot_low(swing, swing) |
| 33 | wave_at = wave[swing] |
| 34 | persist ph_p = na |
| 35 | persist ph_w = na |
| 36 | persist ph_x = 0 |
| 37 | persist pl_p = na |
| 38 | persist pl_w = na |
| 39 | persist pl_x = 0 |
| 40 | persist bull_x = -1 |
| 41 | persist bear_x = -1 |
| 42 | persist bull_stop = na |
| 43 | persist bear_stop = na |
| 44 | if not math.is_na(pl) { |
| 45 | if not math.is_na(pl_p) and bar.index - pl_x <= reach and pl < pl_p and wave_at > pl_w and pl_w < 0 { |
| 46 | bull_x := bar.index |
| 47 | bull_stop := pl |
| 48 | } |
| 49 | pl_p := pl |
| 50 | pl_w := wave_at |
| 51 | pl_x := bar.index |
| 52 | } |
| 53 | if not math.is_na(ph) { |
| 54 | if not math.is_na(ph_p) and bar.index - ph_x <= reach and ph > ph_p and wave_at < ph_w and ph_w > 0 { |
| 55 | bear_x := bar.index |
| 56 | bear_stop := ph |
| 57 | } |
| 58 | ph_p := ph |
| 59 | ph_w := wave_at |
| 60 | ph_x := bar.index |
| 61 | } |
| 62 | a = ta.atr(14) |
| 63 | x_up = ta.cross_up(wave, tide) |
| 64 | x_dn = ta.cross_down(wave, tide) |
| 65 | go_l = bull_x >= 0 and bar.index - bull_x <= window and x_up |
| 66 | go_s = bear_x >= 0 and bar.index - bear_x <= window and x_dn |
| 67 | flat = position.size == 0 |
| 68 | if flat and go_l { |
| 69 | stop = math.min(bull_stop - 0.2 * a, close - a) |
| 70 | order.market("L", side.long) |
| 71 | exit.bracket("L exit", entry = "L", stop = stop, target = close + (close - stop) * reward) |
| 72 | bull_x := -1 |
| 73 | } |
| 74 | if flat and go_s { |
| 75 | stop = math.max(bear_stop + 0.2 * a, close + a) |
| 76 | order.market("S", side.short) |
| 77 | exit.bracket("S exit", entry = "S", stop = stop, target = close - (stop - close) * reward) |
| 78 | bear_x := -1 |
| 79 | } |
| 80 | if position.size != 0 and position.bars_held >= hold { exit.close_all() } |
| 81 | risk.max_drawdown(25) |
| 82 | render.mark(not math.is_na(pl) and bull_x == bar.index, shape = shape.circle, at = anchor.below_bar, color = color.emerald.200, size = 0.5, title = "Bullish divergence") |
| 83 | render.mark(not math.is_na(ph) and bear_x == bar.index, shape = shape.circle, at = anchor.above_bar, color = color.rose.200, size = 0.5, title = "Bearish divergence") |
| 84 | render.mark(go_l and flat, shape = shape.triangle_up, at = anchor.below_bar, color = color.emerald.300, text = "Div", title = "Long entry") |
| 85 | render.mark(go_s and flat, shape = shape.triangle_down, at = anchor.above_bar, color = color.rose.300, text = "Div", title = "Short entry") |
| 86 | render.candle_color(color.ramp(math.clamp(wave, -0.5, 0.5), -0.5, 0.5, "pnl")) |
| 87 | persist t = draw.table.create(anchor.top_right, 5, 2) |
| 88 | if bar.is_last { |
| 89 | pr.heading(t, 2, "Pressure Divergence Reversal", "Strategy · signed volume pressure") |
| 90 | pr.row(t, 2, "Wave / tide", str.format("{:+.2f} / {:+.2f}", wave, tide), wave > tide ? pr.BULL : pr.BEAR) |
| 91 | pr.row(t, 3, "Bullish setup", bull_x >= 0 and bar.index - bull_x <= window ? "Armed" : "No", pr.BULL) |
| 92 | pr.row(t, 4, "Bearish setup", bear_x >= 0 and bar.index - bear_x <= window ? "Armed" : "No", pr.BEAR) |
| 93 | } |
| 94 |
Reviews
No reviews yet. Be the first to review this listing.