//@version=6
indicator("zaBor RSI+AO+Stoch chart", overlay=true, max_labels_count=200)
//================== SYNC INPUTS ==================
rsiLen = input.int(14, "RSI Length", minval=2)
stochKLen = input.int(14, "Stoch K Length", minval=2)
stochDLen = input.int(3, "Stoch D Length", minval=1)
stochSmooth = input.int(3, "Stoch Smooth", minval=1)
signalMode = input.string("Divergence+Momentum", "Entry Mode", options=["Divergence+Momentum", "Momentum Only", "Divergence Only"])
useHiddenDiv = input.bool(true, "Enable Hidden Divergences (for trends)")
pivLeft = input.int(5, "Pivot Left Bars", minval=1)
pivRight = input.int(5, "Pivot Right Bars", minval=1)
maxPivDist = input.int(40, "Max Pivot Distance", minval=5)
validBars = input.int(50, "Divergence Valid Window", minval=1)
minPriceDiff = input.float(0.6, "Min Price Divergence %", minval=0, step=0.1)
minRsiDiff = input.float(3.5, "Min RSI Divergence Points", minval=0, step=0.5)
buyRsiMax = input.float(35.0, "BUY: Max RSI Level", step=0.5)
sellRsiMin = input.float(65.0, "SELL: Min RSI Level", step=0.5)
buyRsiRebound = input.float(50.0, "BUY: RSI Rebound to Mid", step=0.5)
sellRsiRebound = input.float(50.0, "SELL: RSI Rebound to Mid", step=0.5)
useAO = input.bool(false, "Enable AO Filter")
aoMode = input.string("Slope", "AO Mode", options=["Slope","ZeroCross"])
aoWindowN = input.int(20, "Zero-Cross Window (bars)", minval=1)
buyKmax = input.float(35.0, "BUY: Max Stoch K", step=0.5)
sellKmin = input.float(65.0, "SELL: Min Stoch K", step=0.5)
cooldownBars = input.int(15, "Cooldown After Signal", minval=0)
//================== DUPLICATE LOGIC ==================
rsi = ta.rsi(close, rsiLen)
ll = ta.lowest(low, stochKLen)
hh = ta.highest(high, stochKLen)
kRaw = (hh - ll) != 0 ? 100.0 * (close - ll) / (hh - ll) : 50.0
k = ta.sma(kRaw, stochSmooth)
d = ta.sma(k, stochDLen)
ao = ta.sma(hl2, 5) - ta.sma(hl2, 34)
ema20 = ta.ema(close, 20)
ema50 = ta.ema(close, 50)
uptrend = ema20 > ema50
downtrend = ema20 < ema50
pLowPrice = ta.pivotlow(low, pivLeft, pivRight)
pHighPrice = ta.pivothigh(high, pivLeft, pivRight)
pLowRSI = ta.pivotlow(rsi, pivLeft, pivRight)
pHighRSI = ta.pivothigh(rsi, pivLeft, pivRight)
pivotCenterIndex = bar_index - pivRight
var float prevLowPrice = na
var float prevLowRSI = na
var int prevLowIdx = na
var float lastLowPrice = na
var float lastLowRSI = na
var int lastLowIdx = na
var float prevHighPrice = na
var float prevHighRSI = na
var int prevHighIdx = na
var float lastHighPrice = na
var float lastHighRSI = na
var int lastHighIdx = na
if not na(pLowPrice) and not na(pLowRSI)
prevLowPrice := lastLowPrice
prevLowRSI := lastLowRSI
prevLowIdx := lastLowIdx
lastLowPrice := pLowPrice
lastLowRSI := pLowRSI
lastLowIdx := pivotCenterIndex
if not na(pHighPrice) and not na(pHighRSI)
prevHighPrice := lastHighPrice
prevHighRSI := lastHighRSI
prevHighIdx := lastHighIdx
lastHighPrice := pHighPrice
lastHighRSI := pHighRSI
lastHighIdx := pivotCenterIndex
haveLow2 = not na(prevLowPrice) and not na(lastLowIdx) and lastLowIdx > prevLowIdx
haveHigh2 = not na(prevHighPrice) and not na(lastHighIdx) and lastHighIdx > prevHighIdx
lowDistOk = haveLow2 and (lastLowIdx - prevLowIdx <= maxPivDist)
highDistOk = haveHigh2 and (lastHighIdx - prevHighIdx <= maxPivDist)
priceDownPct = lowDistOk ? math.abs(lastLowPrice - prevLowPrice) / prevLowPrice * 100 : 0
rsiUpDiff = lowDistOk ? (lastLowRSI - prevLowRSI) : 0
priceUpPct = highDistOk ? math.abs(lastHighPrice - prevHighPrice) / prevHighPrice * 100 : 0
rsiDownDiff = highDistOk ? (prevHighRSI - lastHighRSI) : 0
bullDiv = lowDistOk and (lastLowPrice < prevLowPrice) and (lastLowRSI > prevLowRSI) and priceDownPct >= minPriceDiff and rsiUpDiff >= minRsiDiff and lastLowRSI <= buyRsiMax
bearDiv = highDistOk and (lastHighPrice > prevHighPrice) and (lastHighRSI < prevHighRSI) and priceUpPct >= minPriceDiff and rsiDownDiff >= minRsiDiff and lastHighRSI >= sellRsiMin
hiddenBullDiv = lowDistOk and (lastLowPrice > prevLowPrice) and (lastLowRSI < prevLowRSI) and priceDownPct >= minPriceDiff and rsiUpDiff >= minRsiDiff
hiddenBearDiv = highDistOk and (lastHighPrice < prevHighPrice) and (lastHighRSI > prevHighRSI) and priceUpPct >= minPriceDiff and rsiDownDiff >= minRsiDiff
rsiOversold = rsi <= buyRsiMax
rsiOverbought = rsi >= sellRsiMin
rsiLow20 = ta.lowest(rsi, 20)
rsiHigh20 = ta.highest(rsi, 20)
rsiReboundSell = rsi >= sellRsiRebound and rsiLow20 < 40
rsiReboundBuy = rsi <= buyRsiRebound and rsiHigh20 > 60
var int setupBuyStart = na
var int setupBuyExpiry = na
var bool aoSeenBuy = false
var int setupSellStart = na
var int setupSellExpiry = na
var bool aoSeenSell = false
var int lastBuyBar = na
var int lastSellBar = na
canBuy = na(lastBuyBar) or (bar_index - lastBuyBar >= cooldownBars)
canSell = na(lastSellBar) or (bar_index - lastSellBar >= cooldownBars)
buyDivTrigger = bullDiv or (useHiddenDiv and hiddenBullDiv and uptrend)
sellDivTrigger = bearDiv or (useHiddenDiv and hiddenBearDiv and downtrend)
buyMomentumTrigger = rsiOversold or rsiReboundBuy
sellMomentumTrigger = rsiOverbought or rsiReboundSell
buySetupTrigger = (signalMode == "Divergence Only" and buyDivTrigger) or (signalMode == "Momentum Only" and buyMomentumTrigger) or (signalMode == "Divergence+Momentum" and (buyDivTrigger or buyMomentumTrigger))
sellSetupTrigger = (signalMode == "Divergence Only" and sellDivTrigger) or (signalMode == "Momentum Only" and sellMomentumTrigger) or (signalMode == "Divergence+Momentum" and (sellDivTrigger or sellMomentumTrigger))
if buySetupTrigger
setupBuyStart := bar_index
setupBuyExpiry := bar_index + validBars
aoSeenBuy := false
if sellSetupTrigger
setupSellStart := bar_index
setupSellExpiry := bar_index + validBars
aoSeenSell := false
if not na(setupBuyExpiry) and bar_index > setupBuyExpiry
setupBuyStart := na
setupBuyExpiry := na
aoSeenBuy := false
if not na(setupSellExpiry) and bar_index > setupSellExpiry
setupSellStart := na
setupSellExpiry := na
aoSeenSell := false
aoSlopeUp = ao > ao[1]
aoSlopeDn = ao < ao[1]
aoCrossUp = ta.crossover(ao, 0.0)
aoCrossDn = ta.crossunder(ao, 0.0)
if not na(setupBuyStart) and aoMode == "ZeroCross" and aoCrossUp
if (bar_index - setupBuyStart <= aoWindowN)
aoSeenBuy := true
if not na(setupSellStart) and aoMode == "ZeroCross" and aoCrossDn
if (bar_index - setupSellStart <= aoWindowN)
aoSeenSell := true
aoOkBuy = not useAO or (aoMode == "Slope" ? aoSlopeUp : aoSeenBuy)
aoOkSell = not useAO or (aoMode == "Slope" ? aoSlopeDn : aoSeenSell)
//================== STOCH TRIGGERS ==================
// v20: Added direction confirmation (k rising/falling after crossover)
stochBuyTrig = ta.crossover(k, d) and k < buyKmax and k > k[1]
stochSellTrig = ta.crossunder(k, d) and k > sellKmin and k < k[1]
//================== v20 REVERSAL CONFIRMATION FILTERS ==================
// Filter #1: RSI Momentum Confirmation (moderate - allows 1-2 bar hesitation)
rsiConfirmBuy = rsi > rsi[1] or rsi > rsi[2]
rsiConfirmSell = rsi < rsi[1] or rsi < rsi[2]
// Filter #2: Price Action Confirmation (for momentum-only signals)
// Ensures bullish/bearish candle structure when no divergence present
priceConfirmBuy = close > open or low > low[1]
priceConfirmSell = close < open or high < high[1]
// Filter #3: Determine if signal is divergence-based or momentum-only
isDivergenceBuy = buyDivTrigger and not na(setupBuyStart)
isDivergenceSell = sellDivTrigger and not na(setupSellStart)
isMomentumOnlyBuy = not isDivergenceBuy and buyMomentumTrigger and not na(setupBuyStart)
isMomentumOnlySell = not isDivergenceSell and sellMomentumTrigger and not na(setupSellStart)
// Apply confirmations based on signal type
confirmBuy = isDivergenceBuy ? rsiConfirmBuy : (isMomentumOnlyBuy ? (rsiConfirmBuy and priceConfirmBuy) : rsiConfirmBuy)
confirmSell = isDivergenceSell ? rsiConfirmSell : (isMomentumOnlySell ? (rsiConfirmSell and priceConfirmSell) : rsiConfirmSell)
//================== FINAL SIGNALS ==================
buySignal = not na(setupBuyStart) and aoOkBuy and stochBuyTrig and canBuy and confirmBuy
sellSignal = not na(setupSellStart) and aoOkSell and stochSellTrig and canSell and confirmSell
if buySignal
lastBuyBar := bar_index
setupBuyStart := na
setupBuyExpiry := na
aoSeenBuy := false
if sellSignal
lastSellBar := bar_index
setupSellStart := na
setupSellExpiry := na
aoSeenSell := false
//================== CHART VISUALIZATION ==================
if buySignal
label.new(bar_index, low, "BUY", style=label.style_label_up, color=color.new(color.green, 0), textcolor=color.white, size=size.small)
if sellSignal
label.new(bar_index, high, "SELL", style=label.style_label_down, color=color.new(color.red, 0), textcolor=color.white, size=size.small)
Overview
zaBor RSI+AO+Stoch chart compares recent price and RSI pivots for regular divergences and, when enabled, hidden divergences, then combines those checks with RSI level or rebound rules and stochastic K thresholds. Entry mode can require divergence, momentum, or both. Optional AO slope or zero-cross filters and a cooldown limit repeat signals. EMA 20 and EMA 50 supply trend context. It is not a strategy and has no exit, stop, or position-size rules.
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
rsiLen
Stoch K Length
int
14
stochKLen
Stoch D Length
int
3
stochDLen
Stoch Smooth
int
3
stochSmooth
Entry Mode
string
Divergence+Momentum
signalMode
Enable Hidden Divergences (for trends)
bool
true
useHiddenDiv
Pivot Left Bars
int
5
pivLeft
Pivot Right Bars
int
5
pivRight
Max Pivot Distance
int
40
maxPivDist
Divergence Valid Window
int
50
validBars
Min Price Divergence %
float
0.6
minPriceDiff
Min RSI Divergence Points
float
3.5
minRsiDiff
Show all 22 settings
Setting
Type
Default
Variable
BUY: Max RSI Level
float
35.0
buyRsiMax
SELL: Min RSI Level
float
65.0
sellRsiMin
BUY: RSI Rebound to Mid
float
50.0
buyRsiRebound
SELL: RSI Rebound to Mid
float
50.0
sellRsiRebound
Enable AO Filter
bool
false
useAO
AO Mode
string
Slope
aoMode
Zero-Cross Window (bars)
int
20
aoWindowN
BUY: Max Stoch K
float
35.0
buyKmax
SELL: Min Stoch K
float
65.0
sellKmin
Cooldown After Signal
int
15
cooldownBars
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 scans multiple tickers simultaneously to detect regular bullish and bearish MACD divergences filtered by long-term trend direction (150 EMA versus 600 EMA). It evaluates pivot highs and lows in the MACD line against price action across configura
This overlay indicator looks for regular price divergences against a set of oscillators, using pivot highs and lows. It compares those pivots with RSI, MACD and its histogram, stochastic, CCI, momentum, OBV, a directional oscillator, volume-weighted MACD, Chai
The RSI Divergence Scanner calculates the Relative Strength Index and identifies regular and hidden bullish or bearish divergences against price using pivot high and low points. It plots divergence lines and customizable labels directly on the price chart. Inp
This indicator detects regular and hidden divergences across multiple technical factors plotted directly on the price chart. It evaluates price highs and lows against peaks and troughs identified by a five-bar fractal mechanism on RSI, RSI Stochastic, MACD, re
This indicator marks RSI divergences only when price trades beyond daily VWAP standard-deviation bands. It compares recent RSI extremes with price highs and lows over a lookback window, and it treats a divergence as valid only while RSI stays beyond overbought
This indicator builds a momentum score from the rate of change of close, using a lookback that expands or contracts with ATR relative to its standard deviation. It divides that rate of change by price standard deviation, scales the result, and weights it by vo