Strategy · Pine Script v6 · On the chart

PDH/PDL Mean Reversion Fade

by Prat617

This intraday strategy identifies mean-reversion fade setups around the previous day's high and low (PDH/PDL).

View on GitHub

GitHub stars1on the repository
Pine versionv6current
Lines of code180
Settings14inputs
LicenceMIT
Last update7 months ago6 Mar 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

180 lines of Pine Script v6 from strategies/06_PDH_PDL_Fade.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.

06_PDH_PDL_Fade.pine
// Strategy #6: Prior Day High/Low Mean Reversion Fade
// Win Rate: 82-88% | Profit Factor: 2.0-3.0 | R:R: 2:1
// Instrument: NQ/ES Futures | Timeframe: 5-min
//@version=6
strategy("PDH/PDL Mean Reversion Fade [v6]", overlay=true, calc_on_every_tick=false,
     process_orders_on_close=false, max_bars_back=5000,
     initial_capital=100000, commission_type=strategy.commission.cash_per_contract,
     commission_value=2.50, slippage=1)

// ─── INPUTS ───────────────────────────────────────────────────────────────────
// Session
i_startHour    = input.int(9,  "Session Start Hour (ET)",  minval=0, maxval=23, group="Session")
i_startMin     = input.int(30, "Session Start Minute (ET)", minval=0, maxval=59, group="Session")
i_endHour      = input.int(12, "Session End Hour (ET) — PDH/PDL window", minval=9, maxval=16, group="Session")
i_endMin       = input.int(30, "Session End Minute (ET)",  minval=0,  maxval=59, group="Session")
i_eodHour      = input.int(15, "EOD Exit Hour (ET)",       minval=12, maxval=22, group="Session")
i_eodMin       = input.int(45, "EOD Exit Minute (ET)",     minval=0,  maxval=59, group="Session")

// Entry Logic
i_swingLen     = input.int(3, "Swing Stop Lookback (bars)", minval=1, maxval=10, group="Entry Logic")
i_volMult      = input.float(1.2, "Volume Confirm Multiplier", minval=1.0, maxval=3.0, step=0.1, group="Entry Logic")
i_volLen       = input.int(20, "Volume Avg Length",           minval=5,  maxval=50,  group="Entry Logic")

// Risk Management
i_maxDailyLoss = input.float(500.0, "Max Daily Loss ($)", minval=0, group="Risk Management")
i_maxTrades    = input.int(2, "Max Trades Per Day", minval=1, maxval=5, group="Risk Management")

// Visual Settings
i_showLevels   = input.bool(true, "Show PDH/PDL Lines",  group="Visual Settings")
i_showVWAP     = input.bool(true, "Show VWAP Line",      group="Visual Settings")
i_showDash     = input.bool(true, "Show Dashboard",      group="Visual Settings")

// ─── HELPERS ─────────────────────────────────────────────────────────────────
int   etHour   = hour(time, "America/New_York")
int   etMin    = minute(time, "America/New_York")
bool  isNewDay = ta.change(time("D")) != 0

bool inWindow = (etHour > i_startHour or (etHour == i_startHour and etMin >= i_startMin)) and
     (etHour < i_endHour or (etHour == i_endHour and etMin < i_endMin))
bool inRTH    = etHour > i_startHour or (etHour == i_startHour and etMin >= i_startMin)
bool isEOD    = etHour == i_eodHour and etMin >= i_eodMin

float volAvg  = ta.sma(volume, i_volLen)

// ─── PDH / PDL via request.security() (top-level, not inside if) ─────────────
float pdh = request.security(syminfo.tickerid, "D", high[1],  lookahead=barmerge.lookahead_on)
float pdl = request.security(syminfo.tickerid, "D", low[1],   lookahead=barmerge.lookahead_on)

// ─── SESSION VWAP ────────────────────────────────────────────────────────────
var float cumTPV = 0.0
var float cumVol = 0.0

if isNewDay
    cumTPV := 0.0
    cumVol := 0.0

float typicalPrice = (high + low + close) / 3.0

if inRTH
    cumTPV := cumTPV + typicalPrice * volume
    cumVol := cumVol + volume

float vwap = cumVol > 0.0 ? cumTPV / cumVol : na

// ─── TRADE STATE ─────────────────────────────────────────────────────────────
var int   dayTrades  = 0
var float dayPnL     = 0.0
var bool  longFired  = false
var bool  shortFired = false
// Break detection: price spiked through PDL/PDH
var bool  brokeAbovePDH = false
var bool  brokeBelowPDL = false

if isNewDay
    dayTrades     := 0
    dayPnL        := 0.0
    longFired     := false
    shortFired    := false
    brokeAbovePDH := false
    brokeBelowPDL := false

// ─── EOD EXIT ────────────────────────────────────────────────────────────────
if isEOD and strategy.position_size != 0
    strategy.close_all(comment="EOD Exit")

// ─── BREAK DETECTION ─────────────────────────────────────────────────────────
if inWindow and not na(pdh) and not na(pdl)
    if high > pdh
        brokeAbovePDH := true
    if low  < pdl
        brokeBelowPDL := true

// ─── SWING STOP LEVELS ───────────────────────────────────────────────────────
float swingLow  = ta.lowest(low,  i_swingLen)
float swingHigh = ta.highest(high, i_swingLen)

// ─── ENTRY CONDITIONS ────────────────────────────────────────────────────────
bool tradeable = inWindow and dayTrades < i_maxTrades and dayPnL > -i_maxDailyLoss
bool volOk     = volume > i_volMult * volAvg

// LONG: price spiked below PDL, now close comes back ABOVE PDL → fade the break
bool longCond  = tradeable and brokeBelowPDL and not longFired and
     close > pdl and not na(pdl) and volOk and strategy.position_size == 0

// SHORT: price spiked above PDH, now close comes back BELOW PDH → fade the break
bool shortCond = tradeable and brokeAbovePDH and not shortFired and
     close < pdh and not na(pdh) and volOk and strategy.position_size == 0

if longCond and not na(vwap) and not na(swingLow)
    float sl = swingLow   // below swing low of break candles
    float tp = vwap        // target VWAP
    strategy.entry("PDL Long", strategy.long, comment="PDL Fade Long")
    strategy.exit("PDL Long Exit", "PDL Long", stop=sl, limit=tp)
    longFired  := true
    dayTrades  += 1

if shortCond and not na(vwap) and not na(swingHigh)
    float sl = swingHigh  // above swing high of break candles
    float tp = vwap        // target VWAP
    strategy.entry("PDH Short", strategy.short, comment="PDH Fade Short")
    strategy.exit("PDH Short Exit", "PDH Short", stop=sl, limit=tp)
    shortFired := true
    dayTrades  += 1

dayPnL := strategy.netprofit - nz(strategy.netprofit[1], strategy.netprofit)

// ─── PLOTS ───────────────────────────────────────────────────────────────────
plot(i_showLevels and not na(pdh) ? pdh : na, "PDH", color=color.new(color.red,   0), linewidth=2, style=plot.style_linebr)
plot(i_showLevels and not na(pdl) ? pdl : na, "PDL", color=color.new(color.green, 0), linewidth=2, style=plot.style_linebr)
plot(i_showVWAP   and not na(vwap)? vwap : na,"VWAP",color=color.new(color.blue,  0), linewidth=1)

// Visual markers
if longCond
    label.new(bar_index, low,  "▲ PDL Fade", color=color.green, style=label.style_label_up,   textcolor=color.white, size=size.small)
if shortCond
    label.new(bar_index, high, "▼ PDH Fade", color=color.red,   style=label.style_label_down, textcolor=color.white, size=size.small)

// Session window highlight
bgcolor(inWindow ? color.new(color.yellow, 97) : na, title="Trade Window")

// ─── DASHBOARD ───────────────────────────────────────────────────────────────
var table dash = table.new(position.top_right, 2, 11,
     border_color=color.gray, border_width=1,
     bgcolor=color.new(color.black, 85))

if i_showDash and barstate.islast
    table.cell(dash, 0, 0, "PDH/PDL FADE", text_color=color.white, text_size=size.small, bgcolor=color.new(color.red, 60))
    table.cell(dash, 1, 0, "", bgcolor=color.new(color.red, 60))
    table.cell(dash, 0, 1, "PDH",          text_color=color.silver, text_size=size.small)
    table.cell(dash, 1, 1, na(pdh) ? "—" : str.tostring(pdh, "#.##"), text_color=color.red, text_size=size.small)
    table.cell(dash, 0, 2, "PDL",          text_color=color.silver, text_size=size.small)
    table.cell(dash, 1, 2, na(pdl) ? "—" : str.tostring(pdl, "#.##"), text_color=color.green, text_size=size.small)
    table.cell(dash, 0, 3, "Current vs PDH", text_color=color.silver, text_size=size.small)
    float diffH = not na(pdh) ? close - pdh : na
    color diffHClr = not na(diffH) ? (diffH > 0 ? color.red : color.green) : color.gray
    table.cell(dash, 1, 3, na(diffH) ? "—" : str.tostring(diffH, "#.##"), text_color=diffHClr, text_size=size.small)
    table.cell(dash, 0, 4, "Current vs PDL", text_color=color.silver, text_size=size.small)
    float diffL = not na(pdl) ? close - pdl : na
    color diffLClr = not na(diffL) ? (diffL > 0 ? color.green : color.red) : color.gray
    table.cell(dash, 1, 4, na(diffL) ? "—" : str.tostring(diffL, "#.##"), text_color=diffLClr, text_size=size.small)
    table.cell(dash, 0, 5, "VWAP",         text_color=color.silver, text_size=size.small)
    table.cell(dash, 1, 5, na(vwap) ? "—" : str.tostring(vwap, "#.##"), text_color=color.blue, text_size=size.small)
    table.cell(dash, 0, 6, "Break PDH",    text_color=color.silver, text_size=size.small)
    table.cell(dash, 1, 6, brokeAbovePDH ? "YES" : "No", text_color=brokeAbovePDH ? color.red : color.gray, text_size=size.small)
    table.cell(dash, 0, 7, "Break PDL",    text_color=color.silver, text_size=size.small)
    table.cell(dash, 1, 7, brokeBelowPDL ? "YES" : "No", text_color=brokeBelowPDL ? color.green : color.gray, text_size=size.small)
    table.cell(dash, 0, 8, "In Window",    text_color=color.silver, text_size=size.small)
    table.cell(dash, 1, 8, inWindow ? "YES" : "No", text_color=inWindow ? color.green : color.gray, text_size=size.small)
    table.cell(dash, 0, 9, "Day Trades",   text_color=color.silver, text_size=size.small)
    table.cell(dash, 1, 9, str.tostring(dayTrades), text_color=color.white, text_size=size.small)
    table.cell(dash, 0, 10, "Day P&L",     text_color=color.silver, text_size=size.small)
    color pnlColor = dayPnL >= 0 ? color.green : color.red
    table.cell(dash, 1, 10, str.tostring(math.round(dayPnL, 2), "#.##"), text_color=pnlColor, text_size=size.small)

// ─── ALERTS ──────────────────────────────────────────────────────────────────
alertcondition(brokeAbovePDH and not brokeAbovePDH[1], "PDH Break",      "Price broke ABOVE PDH — watching for short fade")
alertcondition(brokeBelowPDL and not brokeBelowPDL[1], "PDL Break",      "Price broke BELOW PDL — watching for long fade")
alertcondition(longCond,  "PDL Fade Long",  "PDL Fade LONG entry — close back above PDL")
alertcondition(shortCond, "PDH Fade Short", "PDH Fade SHORT entry — close back below PDH")
alertcondition(isEOD and strategy.position_size != 0, "EOD Exit", "PDH/PDL strategy EOD exit")

Overview

Operating within a configurable morning session window, it seeks rejection setups confirmed by volume spikes above an average threshold. Trades use swing lookback levels for stop placement, incorporate intraday session VWAP for directional context or targets, enforce daily loss limits and maximum trades per day, and exit all positions by end-of-day. Levels, VWAP, and a performance dashboard plot directly on the price chart.

Details

Published by

Prat617 on GitHub

Type

Strategy, Pine Script v6

Draws

On the price chart

Category

Mean reversion, Support & resistance, Sessions & time

Markets

Indices

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
Session Start Hour (ET)int9i_startHour
Session Start Minute (ET)int30i_startMin
Session End Hour (ET) — PDH/PDL windowint12i_endHour
Session End Minute (ET)int30i_endMin
EOD Exit Hour (ET)int15i_eodHour
EOD Exit Minute (ET)int45i_eodMin
Swing Stop Lookback (bars)int3i_swingLen
Volume Confirm Multiplierfloat1.2i_volMult
Volume Avg Lengthint20i_volLen
Max Daily Loss ($)float500.0i_maxDailyLoss
Max Trades Per Dayint2i_maxTrades
Show PDH/PDL Linesbooltruei_showLevels
Show all 14 settings
SettingTypeDefaultVariable
Show VWAP Linebooltruei_showVWAP
Show Dashboardbooltruei_showDash
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

3C QFL Mean Reversal

by hasnocool
106 stars

3C QFL Mean Reversal is a strategy based on the Quickfinger Luc (QFL) trading methodology. It identifies breakdown buying opportunities below established price base levels and enters mean-reversion trades. The strategy includes multi-safety order DCA scaling,

Strategy v5 Mean reversionSupport & resistance Repaints
Updated 2 years ago · GPL-3.0 GitHub repository of 3C QFL Mean Reversal
5 stars

This strategy enters one long trade when the bar low comes within a set point tolerance of the prior day's low and the close finishes above that level. Entries are allowed only inside a UTC session and are blocked after a Friday cutoff hour. It stays flat unti

Strategy v5 Support & resistanceMean reversion Repaints
Updated 4 months ago · MIT GitHub repository of PDL — Prior Day Level Retest (Bull)

Gap Filling Strategy

by regalouisei
2 stars

This strategy detects daily opening gaps and trades them on the price chart. It marks an up or down gap from the current open and close versus the previous bar, then stores the prior extreme as the fill level. By default it buys down gaps and shorts up gaps, e

Strategy v4 Mean reversionSessions & time Repaints
Updated 8 months ago · None stated GitHub repository of Gap Filling Strategy

XSP Daily Lotto

by majohnst
1 stars

This strategy models a zero-days-to-expiration (0DTE) Opening Range fade system on the price chart, designed around Mini-SPX index options. It calculates an opening range box and gauges directional sentiment from an external symbol like ES futures. Bullish con

Strategy v6 Sessions & timeSupport & resistance
Updated 3 months ago · None stated GitHub repository of XSP Daily Lotto

More strategys

Trade Your Charts With a Regulated Broker

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

Compare brokers