//@version=5
indicator("15m Reversal Detector [Momentum+Volume]", shorttitle="Rev Detector", overlay=false)
// ==========================================
// THEORY: Multi-Factor Reversal Detection
// ==========================================
// A true reversal requires 3 confirmations:
// 1. MOMENTUM Divergence: Price makes new extreme but momentum weakens (RSI/MACD divergence)
// 2. PRICE ACTION: Rejection candles (long wicks, engulfing, pin bars)
// 3. VOLUME Anomaly: Climax volume (exhaustion) or Volume Drying (loss of conviction)
// ==========================================
// 1. INPUTS
// ==========================================
grp_mom = "Momentum Settings"
rsi_len = input.int(14, "RSI Length", group=grp_mom)
macd_fast = input.int(12, "MACD Fast", group=grp_mom)
macd_slow = input.int(26, "MACD Slow", group=grp_mom)
macd_sig = input.int(9, "MACD Signal", group=grp_mom)
grp_vol = "Volume Settings"
vol_ma_len = input.int(20, "Volume MA Length", group=grp_vol)
vol_spike_mult = input.float(2.0, "Volume Spike Multiplier", group=grp_vol)
grp_price = "Price Action Settings"
wick_ratio = input.float(0.6, "Min Wick/Body Ratio for Rejection", group=grp_price, tooltip="0.6 means wick must be 60% of total candle range")
bb_len = input.int(20, "BB Length (for Extreme Detection)", group=grp_price)
bb_mult = input.float(2.0, "BB Mult", group=grp_price)
grp_div = "Divergence Settings"
lookback_div = input.int(5, "Pivot Lookback for Divergence", group=grp_div)
// ==========================================
// 2. MOMENTUM INDICATORS
// ==========================================
// RSI
rsi = ta.rsi(close, rsi_len)
// MACD
[macd_line, signal_line, hist] = ta.macd(close, macd_fast, macd_slow, macd_sig)
// Stochastic RSI (faster momentum)
stoch_k = ta.stoch(close, high, low, 14)
// ==========================================
// 3. VOLUME ANALYSIS
// ==========================================
// Volume MA
vol_ma = ta.sma(volume, vol_ma_len)
// Volume States
is_vol_spike = volume > vol_ma * vol_spike_mult // Climax volume (exhaustion)
is_vol_dry = volume < vol_ma * 0.5 // Drying up (no conviction)
// Volume Delta (Buying vs Selling Pressure Proxy)
// Using close vs open to estimate directional pressure
vol_delta = (close > open) ? volume : -volume
vol_delta_ma = ta.sma(vol_delta, 10)
// ==========================================
// 4. PRICE ACTION PATTERNS
// ==========================================
// Bollinger Bands (for extreme price detection)
basis = ta.sma(close, bb_len)
dev = ta.stdev(close, bb_len)
upper_bb = basis + dev * bb_mult
lower_bb = basis - dev * bb_mult
at_top = close >= upper_bb // Price at statistical extreme (top)
at_bottom = close <= lower_bb // Price at statistical extreme (bottom)
// Candle Anatomy
body = math.abs(close - open)
range_candle = high - low
upper_wick = high - math.max(close, open)
lower_wick = math.min(close, open) - low
// Rejection Patterns
bearish_rejection = upper_wick > body * wick_ratio and close < open // Long upper wick + red body
bullish_rejection = lower_wick > body * wick_ratio and close > open // Long lower wick + green body
// Engulfing (Strong reversal pattern)
bullish_engulf = close > open and close[1] < open[1] and close > open[1] and open < close[1]
bearish_engulf = close < open and close[1] > open[1] and close < open[1] and open > close[1]
// ==========================================
// 5. DIVERGENCE DETECTION
// ==========================================
// Find Recent Pivot Highs/Lows in PRICE
ph_price = ta.pivothigh(high, lookback_div, lookback_div)
pl_price = ta.pivotlow(low, lookback_div, lookback_div)
// Find Recent Pivot Highs/Lows in RSI
ph_rsi = ta.pivothigh(rsi, lookback_div, lookback_div)
pl_rsi = ta.pivotlow(rsi, lookback_div, lookback_div)
// Store last pivots
var float last_ph_price = na
var float last_pl_price = na
var float last_ph_rsi = na
var float last_pl_rsi = na
var int last_ph_bar = na
var int last_pl_bar = na
if not na(ph_price)
last_ph_price := ph_price
last_ph_rsi := rsi[lookback_div]
last_ph_bar := bar_index - lookback_div
if not na(pl_price)
last_pl_price := pl_price
last_pl_rsi := rsi[lookback_div]
last_pl_bar := bar_index - lookback_div
// Bearish Divergence: Price makes Higher High, but RSI makes Lower High
bearish_div = false
if not na(last_ph_price) and not na(last_ph_rsi)
if high > last_ph_price and rsi < last_ph_rsi and bar_index - last_ph_bar < 30
bearish_div := true
// Bullish Divergence: Price makes Lower Low, but RSI makes Higher Low
bullish_div = false
if not na(last_pl_price) and not na(last_pl_rsi)
if low < last_pl_price and rsi > last_pl_rsi and bar_index - last_pl_bar < 30
bullish_div := true
// ==========================================
// 6. REVERSAL CONFLUENCE SCORE
// ==========================================
// Bearish Reversal Score (0-10)
bear_score = 0
bear_score := bear_score + (at_top ? 2 : 0) // At overbought zone
bear_score := bear_score + (bearish_rejection or bearish_engulf ? 3 : 0) // Strong price rejection
bear_score := bear_score + (bearish_div ? 3 : 0) // Momentum divergence
bear_score := bear_score + (is_vol_spike ? 1 : 0) // Volume climax
bear_score := bear_score + (rsi > 70 ? 1 : 0) // RSI overbought
// Bullish Reversal Score (0-10)
bull_score = 0
bull_score := bull_score + (at_bottom ? 2 : 0) // At oversold zone
bull_score := bull_score + (bullish_rejection or bullish_engulf ? 3 : 0) // Strong price rejection
bull_score := bull_score + (bullish_div ? 3 : 0) // Momentum divergence
bull_score := bull_score + (is_vol_spike ? 1 : 0) // Volume climax
bull_score := bull_score + (rsi < 30 ? 1 : 0) // RSI oversold
// Net Signal (-10 to +10)
reversal_signal = bull_score - bear_score
// ==========================================
// 7. VISUALIZATION
// ==========================================
// A. Main Oscillator: Reversal Signal
plot(reversal_signal, "Reversal Signal", color=reversal_signal > 0 ? color.green : color.red, style=plot.style_columns, linewidth=3)
// B. Reference Lines
hline(5, "Strong Bull", color=color.green, linestyle=hline.style_dashed)
hline(-5, "Strong Bear", color=color.red, linestyle=hline.style_dashed)
hline(0, "Neutral", color=color.gray)
// C. RSI Subplot (for visual divergence confirmation)
plot(rsi - 50, "RSI (Centered)", color=color.new(color.blue, 50), linewidth=1)
// D. Volume Pressure Indicator
vol_pressure = (volume / vol_ma - 1) * 10 // Normalized volume deviation
plot(vol_pressure, "Volume Pressure", color=color.new(color.orange, 70), style=plot.style_area)
// E. Signal Markers
strong_bull_reversal = bull_score >= 7
strong_bear_reversal = bear_score >= 7
plotshape(strong_bull_reversal, "Strong Bullish Reversal", shape.triangleup, location.bottom, color.lime, size=size.normal, text="REV")
plotshape(strong_bear_reversal, "Strong Bearish Reversal", shape.triangledown, location.top, color.red, size=size.normal, text="REV")
// ==========================================
// 8. ALERTS
// ==========================================
alertcondition(strong_bull_reversal, "Bullish Reversal Confirmed", "15m BULLISH REVERSAL: Momentum+Price+Volume Confluence Detected")
alertcondition(strong_bear_reversal, "Bearish Reversal Confirmed", "15m BEARISH REVERSAL: Momentum+Price+Volume Confluence Detected")
// ==========================================
// 9. TABLE: Real-Time Score Breakdown
// ==========================================
var table score_table = table.new(position.top_right, 2, 6, bgcolor=color.new(color.black, 80), border_width=1)
if barstate.islast
table.cell(score_table, 0, 0, "Factor", text_color=color.white, text_size=size.small)
table.cell(score_table, 1, 0, "Status", text_color=color.white, text_size=size.small)
table.cell(score_table, 0, 1, "Price Extreme", text_color=color.gray, text_size=size.tiny)
table.cell(score_table, 1, 1, at_top ? "Top" : at_bottom ? "Bottom" : "Mid", text_color=at_top ? color.red : at_bottom ? color.green : color.gray, text_size=size.tiny)
table.cell(score_table, 0, 2, "Divergence", text_color=color.gray, text_size=size.tiny)
table.cell(score_table, 1, 2, bearish_div ? "Bear" : bullish_div ? "Bull" : "None", text_color=bearish_div ? color.red : bullish_div ? color.green : color.gray, text_size=size.tiny)
table.cell(score_table, 0, 3, "Rejection", text_color=color.gray, text_size=size.tiny)
table.cell(score_table, 1, 3, bearish_rejection or bearish_engulf ? "Bear" : bullish_rejection or bullish_engulf ? "Bull" : "None", text_color=bearish_rejection or bearish_engulf ? color.red : bullish_rejection or bullish_engulf ? color.green : color.gray, text_size=size.tiny)
table.cell(score_table, 0, 4, "Volume", text_color=color.gray, text_size=size.tiny)
table.cell(score_table, 1, 4, is_vol_spike ? "Climax" : is_vol_dry ? "Dry" : "Normal", text_color=is_vol_spike ? color.orange : color.gray, text_size=size.tiny)
table.cell(score_table, 0, 5, "Signal", text_color=color.white, text_size=size.small)
table.cell(score_table, 1, 5, str.tostring(reversal_signal), text_color=reversal_signal > 5 ? color.lime : reversal_signal < -5 ? color.red : color.gray, text_size=size.small)
Overview
15m Reversal Detector uses RSI, MACD and a stochastic reading for momentum, volume spikes and dry-ups against a volume average, Bollinger Band extremes, wick rejection and engulfing candles, and pivot-based divergence. Inputs set the lengths, volume multiplier, wick ratio and divergence pivot lookback. The text mentions 15-minute use, but the settings work on other timeframes. It marks setups and is not a full trading system.
The inputs you can change from the gear icon on the chart. Defaults are the author's.
Setting
Type
Default
Variable
RSI Length
int
14
rsi_len
MACD Fast
int
12
macd_fast
MACD Slow
int
26
macd_slow
MACD Signal
int
9
macd_sig
Volume MA Length
int
20
vol_ma_len
Volume Spike Multiplier
float
2.0
vol_spike_mult
Min Wick/Body Ratio for Rejection
float
0.6
wick_ratio
BB Length (for Extreme Detection)
int
20
bb_len
BB Mult
float
2.0
bb_mult
Pivot Lookback for Divergence
int
5
lookback_div
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.
This indicator measures directional momentum by evaluating candlestick body proportions and volume over a user-defined lookback window. It computes the ratio of candle body to total range, weights the cumulative value by volume and absolute body size, and dete
Oscillator Suite plots a normalised price oscillator in a separate pane and overlays a signal line that can use SMA, EMA, WMA, HMA, RMA, VWMA, T3, ZEMA, KAMA, or GKEMA. It marks bullish and bearish divergences, a smoothed money-flow series, confluence areas an
This indicator plots the Money Flow Index in a separate pane and marks regular and hidden bullish and bearish divergences between price pivots and the oscillator. It builds the index from positive and negative money flow, then finds pivot highs and lows using
This indicator plots a Cipher B-style oscillator in a separate pane and can source its calculations from Heikin Ashi candles when that option is on. It draws WaveTrend lines with optional buy, gold, sell, and divergence dots, plus overbought and oversold level
This indicator plots a smoothed Z-score of cumulative volume delta in a separate pane, showing whether buying or selling pressure is dominant and when the reading enters extreme zones. It marks spot accumulation, climax or exhaustion, and pivot-based price-vol
The Candle Pressure Index measures buying versus selling pressure from candle geometry and relative volume. Each bar combines close location, body ratio, and volume rank into a raw pressure value. An exponential moving average of that pressure forms the CPI os