//@version=6
// ============================================================================
// Commodity Heat Reversal [WavesUnchained]
// Version: 1.5.0
// Author: WavesUnchained
// Build: 2026-10-02 00:00:00
// ============================================================================
// Score-based mean-reversion reversal and pullback-continuation signals for commodity futures (4H).
//
// Features:
// ✓ Dual Heat Score (long / short, 0–7 points)
// ✓ ATR-distance, ATR-expansion, RSI extremes, wick pressure, BB breach
// ✓ Optional MA-200 trend filter with extreme-score override
// ✓ Optional HTF EMA bias and trend-following pullback continuation signals
// ✓ Swing-high / swing-low stops + MA20 mean-reversion TP
// ✓ Selectable MA smoothing (EMA / RMA / SMA / WMA / HMA / JMA)
// ✓ Score dashboard table
// ✓ Alert conditions for long / short signals
//
// ============================================================================
indicator("Commodity Heat Reversal [WavesUnchained]",
shorttitle="CHR",
overlay=true)
// ── Inputs ────────────────────────────────────────────────────────────────────
var string GRP_SMOOTH = "Smoothing"
var string GRP_FILTER = "Trend Filter"
var string GRP_LEN = "Lengths"
var string GRP_SCORE = "Score"
var string GRP_QUALITY = "Quality"
var string GRP_CONT = "Continuation"
var string GRP_RISK = "Risk"
var string GRP_VIS = "Display"
maType = input.string("HMA", "MA Type", options=["EMA","RMA","SMA","WMA","HMA","JMA"], group=GRP_SMOOTH)
jmaPhase = input.int(50, " JMA Phase", minval=-100, maxval=100, group=GRP_SMOOTH)
jmaPower = input.float(2.0," JMA Power", minval=1.0, maxval=4.0, step=0.25, group=GRP_SMOOTH)
useTrendFilter = input.bool(false, "Enable Trend Filter", group=GRP_FILTER)
allowCounterTrendExtreme = input.bool(true, "Allow Counter-Trend at Extreme", group=GRP_FILTER)
useHTFBias = input.bool(true, "Use HTF Bias", group=GRP_FILTER)
htfTF = input.timeframe("D", "HTF Bias Timeframe", group=GRP_FILTER)
maFastLen = input.int(20, "MA Fast (TP)", group=GRP_LEN)
maMeanLen = input.int(50, "MA Mean", group=GRP_LEN)
maTrendLen = input.int(200, "MA Trend", group=GRP_LEN)
htfTrendLen = input.int(50, "HTF EMA Trend", group=GRP_LEN)
atrFastLen = input.int(14, "ATR Fast", group=GRP_LEN)
atrSlowLen = input.int(50, "ATR Slow (SMA)",group=GRP_LEN)
rsiLen = input.int(14, "RSI", group=GRP_LEN)
reversalHeatThreshold = input.int(1, "Reversal Heat Threshold", minval=1, maxval=2, group=GRP_SCORE, tooltip="Stretch evidence a reversal signal needs on top of the mandatory exhaustion (RSI/BB extreme) and wick-rejection gates: 1 = ATR distance to MA50 OR ATR expansion, 2 = both.")
extremeHeatThreshold = input.int(2, "Extreme Heat Threshold", minval=1, maxval=2, group=GRP_SCORE, tooltip="Stretch evidence (ATR distance + ATR expansion) at which the trend filter may be overridden and a reversal no longer counts as counter-trend.")
confirmationMode = input.string("Balanced", "Confirmation Mode", options=["Early","Balanced","Strict"], group=GRP_QUALITY)
signalCooldownBars = input.int(3, "Same-Direction Cooldown Bars", minval=0, maxval=50, group=GRP_QUALITY)
counterTrendDisplay = input.string("Hide", "Counter-Trend Reversals", options=["Show","Mark","Hide"], group=GRP_QUALITY)
showContinuationSignals = input.bool(false, "Show Pullback Continuation Signals", group=GRP_CONT,
tooltip="Optional visual context only. Default OFF keeps this indicator focused on reversal signals.")
continuationScore = input.int(2, "Pullback Heat Score", minval=1, maxval=7, group=GRP_CONT)
pullbackLookback = input.int(12, "Pullback Lookback Bars", minval=1, maxval=50, group=GRP_CONT)
continuationCooldownBars = input.int(8, "Pullback Signal Cooldown Bars", minval=0, maxval=50, group=GRP_CONT)
atrDistanceMult = input.float(2.5, "ATR Distance to MA50", step=0.1, group=GRP_RISK)
atrExpansionMult = input.float(1.5, "ATR Expansion Mult", step=0.1, group=GRP_RISK)
slAtrMult = input.float(1.2, "SL ATR Multiplier", step=0.1, group=GRP_RISK)
showTable = input.bool(true, "Show Score Table", group=GRP_VIS)
tablePos = input.string("Top Right", "Table Position",
options=["Top Right","Top Left","Bottom Right","Bottom Left"], group=GRP_VIS)
// ── Smoothing ─────────────────────────────────────────────────────────────────
f_jma(src, length, phase, power) =>
var float jma = na
var float e0 = na
var float e1 = na
var float e2 = na
_pr = phase < -100 ? 0.5 : phase > 100 ? 2.5 : phase / 100.0 + 1.5
_beta = 0.45 * (length - 1) / (0.45 * (length - 1) + 2)
_alpha = math.pow(_beta, power)
e0 := (1 - _alpha) * src + _alpha * nz(e0[1], src)
e1 := (src - e0) * (1 - _beta) + _beta * nz(e1[1], 0)
e2 := (e0 + _pr * e1 - nz(jma[1], src)) * math.pow(1 - _alpha, 2) + math.pow(_alpha, 2) * nz(e2[1], 0)
jma := nz(jma[1], src) + e2
jma
f_smooth(src, length, mode) =>
switch mode
'SMA' => ta.sma(src, length)
'RMA' => ta.rma(src, length)
'HMA' => ta.hma(src, length)
'WMA' => ta.wma(src, length)
'JMA' => f_jma(src, length, jmaPhase, jmaPower)
=> ta.ema(src, length)
// ── Indicators ───────────────────────────────────────────────────────────────
ma20 = f_smooth(close, maFastLen, maType)
ma50 = f_smooth(close, maMeanLen, maType)
ma200 = f_smooth(close, maTrendLen, maType)
ma9 = f_smooth(close, 9, maType)
atr14 = ta.atr(atrFastLen)
atr50 = ta.sma(atr14, atrSlowLen)
rsi = ta.rsi(close, rsiLen)
bbBasis = ta.sma(close, 20)
bbDev = ta.stdev(close, 20)
bbUpper = bbBasis + bbDev * 2
bbLower = bbBasis - bbDev * 2
// ── Higher timeframe bias ───────────────────────────────────────────────────
htfClose = request.security(syminfo.tickerid, htfTF, close, lookahead=barmerge.lookahead_off)
htfEma = request.security(syminfo.tickerid, htfTF, ta.ema(close, htfTrendLen), lookahead=barmerge.lookahead_off)
htfEmaSlope = request.security(syminfo.tickerid, htfTF, ta.ema(close, htfTrendLen) - ta.ema(close, htfTrendLen)[1], lookahead=barmerge.lookahead_off)
htfUpTrend = not useHTFBias or htfClose > htfEma or htfEmaSlope > 0
htfDownTrend = not useHTFBias or htfClose < htfEma or htfEmaSlope < 0
// ── Candle anatomy ───────────────────────────────────────────────────────────
candleRange = high - low
upperWick = high - math.max(open, close)
lowerWick = math.min(open, close) - low
upperWickPct = candleRange > 0 ? upperWick / candleRange : 0.0
lowerWickPct = candleRange > 0 ? lowerWick / candleRange : 0.0
// Reversal heat: only the stretch components that are not already mandatory gates
// (RSI/BB extreme and wick rejection are required separately) - 0..2
shortReversalHeat = (close > ma50 + atrDistanceMult * atr14 ? 1 : 0) + (atr14 > atr50 * atrExpansionMult ? 1 : 0)
longReversalHeat = (close < ma50 - atrDistanceMult * atr14 ? 1 : 0) + (atr14 > atr50 * atrExpansionMult ? 1 : 0)
// ── Heat Scores ──────────────────────────────────────────────────────────────
shortScore = 0
shortScore += close > ma50 + atrDistanceMult * atr14 ? 2 : 0
shortScore += atr14 > atr50 * atrExpansionMult ? 2 : 0
shortScore += rsi > 72 ? 1 : 0
shortScore += upperWickPct > 0.35 ? 1 : 0
shortScore += close > bbUpper ? 1 : 0
longScore = 0
longScore += close < ma50 - atrDistanceMult * atr14 ? 2 : 0
longScore += atr14 > atr50 * atrExpansionMult ? 2 : 0
longScore += rsi < 28 ? 1 : 0
longScore += lowerWickPct > 0.35 ? 1 : 0
longScore += close < bbLower ? 1 : 0
// ── Trend filter ─────────────────────────────────────────────────────────────
upTrend = close > ma200
downTrend = close < ma200
ma50Slope = ma50 - ma50[3]
localUpContext = close > ma50 and ma50Slope >= 0
localDownContext = close < ma50 and ma50Slope <= 0
longCounterTrend = not localUpContext or close < ma200
shortCounterTrend = not localDownContext or close > ma200
// ── Confirmation ─────────────────────────────────────────────────────────────
shortBaseConfirm = close < low[1] or close < ma9
longBaseConfirm = close > high[1] or close > ma9
shortStrictConfirm = close < open and close < ma9 and close < low[1] and upperWickPct > 0.20
longStrictConfirm = close > open and close > ma9 and close > high[1] and lowerWickPct > 0.20
shortBalancedConfirm = close < ma9 and (close < low[1] or upperWickPct > 0.30)
longBalancedConfirm = close > ma9 and (close > high[1] or lowerWickPct > 0.30)
shortCounterConfirm = confirmationMode == "Strict" ? shortStrictConfirm : confirmationMode == "Balanced" ? shortBalancedConfirm : shortBaseConfirm
longCounterConfirm = confirmationMode == "Strict" ? longStrictConfirm : confirmationMode == "Balanced" ? longBalancedConfirm : longBaseConfirm
shortConfirm = shortCounterTrend ? shortCounterConfirm : shortBaseConfirm
longConfirm = longCounterTrend ? longCounterConfirm : longBaseConfirm
shortAllowed = not useTrendFilter or (downTrend and htfDownTrend) or (allowCounterTrendExtreme and shortReversalHeat >= extremeHeatThreshold)
longAllowed = not useTrendFilter or (upTrend and htfUpTrend) or (allowCounterTrendExtreme and longReversalHeat >= extremeHeatThreshold)
// ── Signals (enforcing mandatory exhaustion & wick rejection gates) ───────────
hasExhaustionShort = (rsi > 72 or close > bbUpper)
hasRejectionShort = (upperWickPct > 0.35)
hasExhaustionLong = (rsi < 28 or close < bbLower)
hasRejectionLong = (lowerWickPct > 0.35)
shortSignalRaw = shortReversalHeat >= reversalHeatThreshold and shortConfirm and shortAllowed and hasExhaustionShort and hasRejectionShort
longSignalRaw = longReversalHeat >= reversalHeatThreshold and longConfirm and longAllowed and hasExhaustionLong and hasRejectionLong
barsSincePrevShortSignal = ta.barssince(shortSignalRaw[1])
barsSincePrevLongSignal = ta.barssince(longSignalRaw[1])
recentShortSignal = signalCooldownBars > 0 and not na(barsSincePrevShortSignal) and barsSincePrevShortSignal <= signalCooldownBars
recentLongSignal = signalCooldownBars > 0 and not na(barsSincePrevLongSignal) and barsSincePrevLongSignal <= signalCooldownBars
shortSignal = shortSignalRaw and not recentShortSignal
longSignal = longSignalRaw and not recentLongSignal
shortCounterTrendSignal = shortSignal and close > ma50 and ma50Slope >= 0 and shortReversalHeat < extremeHeatThreshold
longCounterTrendSignal = longSignal and close < ma50 and ma50Slope <= 0 and longReversalHeat < extremeHeatThreshold
showCounterTrend = counterTrendDisplay == "Show"
markCounterTrend = counterTrendDisplay == "Mark"
shortReversalSignal = shortSignal and (showCounterTrend or not shortCounterTrendSignal)
longReversalSignal = longSignal and (showCounterTrend or not longCounterTrendSignal)
shortCounterTrendMarker = markCounterTrend and shortCounterTrendSignal
longCounterTrendMarker = markCounterTrend and longCounterTrendSignal
// ── Pullback continuation signals ────────────────────────────────────────────
longPullbackTouched = low <= ma20 or low <= ma50 or close <= ma20
shortPullbackTouched = high >= ma20 or high >= ma50 or close >= ma20
longPullbackHeat = longScore >= continuationScore or rsi < 45
shortPullbackHeat = shortScore >= continuationScore or rsi > 55
localContinuationUp = close > ma50 and ma20 > ma50 and ma50Slope > 0
localContinuationDown = close < ma50 and ma20 < ma50 and ma50Slope < 0
longPullbackSetup = localContinuationUp and htfUpTrend and longPullbackTouched and longPullbackHeat
shortPullbackSetup = localContinuationDown and htfDownTrend and shortPullbackTouched and shortPullbackHeat
barsSinceLongPullback = ta.barssince(longPullbackSetup)
barsSinceShortPullback = ta.barssince(shortPullbackSetup)
recentLongPullback = not na(barsSinceLongPullback) and barsSinceLongPullback <= pullbackLookback
recentShortPullback = not na(barsSinceShortPullback) and barsSinceShortPullback <= pullbackLookback
longContinuationConfirm = barsSinceLongPullback > 0 and close > open and close > ma9 and close > high[1]
shortContinuationConfirm = barsSinceShortPullback > 0 and close < open and close < ma9 and close < low[1]
longContinuationRaw = showContinuationSignals and recentLongPullback and longContinuationConfirm and not longSignal
shortContinuationRaw = showContinuationSignals and recentShortPullback and shortContinuationConfirm and not shortSignal
barsSincePrevLongContinuation = ta.barssince(longContinuationRaw[1])
barsSincePrevShortContinuation = ta.barssince(shortContinuationRaw[1])
recentLongContinuation = continuationCooldownBars > 0 and not na(barsSincePrevLongContinuation) and barsSincePrevLongContinuation <= continuationCooldownBars
recentShortContinuation = continuationCooldownBars > 0 and not na(barsSincePrevShortContinuation) and barsSincePrevShortContinuation <= continuationCooldownBars
longContinuationSignal = longContinuationRaw and not recentLongContinuation
shortContinuationSignal = shortContinuationRaw and not recentShortContinuation
// ── SL / TP levels ───────────────────────────────────────────────────────────
swingHigh = ta.highest(high, 10)
swingLow = ta.lowest(low, 10)
shortSL = swingHigh + slAtrMult * atr14
longSL = swingLow - slAtrMult * atr14
// ── Plots ─────────────────────────────────────────────────────────────────────
plot(ma20, "MA 20", color=color.new(color.blue, 0), linewidth=1)
plot(ma50, "MA 50", color=color.new(color.orange, 0), linewidth=1)
plot(ma200, "MA 200", color=color.new(color.gray, 0), linewidth=1)
plot(shortReversalSignal ? shortSL : na, "Short SL", color=color.new(#d50000, 60), style=plot.style_linebr, linewidth=1)
plot(longReversalSignal ? longSL : na, "Long SL", color=color.new(#d50000, 60), style=plot.style_linebr, linewidth=1)
plot(shortReversalSignal ? ma20 : na, "Short TP", color=color.new(#00c853, 60), style=plot.style_linebr, linewidth=1)
plot(longReversalSignal ? ma20 : na, "Long TP", color=color.new(#00c853, 60), style=plot.style_linebr, linewidth=1)
plotshape(shortReversalSignal, title="Short Signal", style=shape.triangledown, location=location.abovebar,
color=#d50000, size=size.small)
plotshape(longReversalSignal, title="Long Signal", style=shape.triangleup, location=location.belowbar,
color=#00c853, size=size.small)
plotshape(shortCounterTrendMarker, title="Short Counter-Trend Reversal", style=shape.xcross, location=location.abovebar,
color=color.new(#d50000, 20), size=size.tiny)
plotshape(longCounterTrendMarker, title="Long Counter-Trend Reversal", style=shape.xcross, location=location.belowbar,
color=color.new(#00c853, 20), size=size.tiny)
plotshape(shortContinuationSignal, title="Short Pullback Continuation", style=shape.diamond, location=location.abovebar,
color=#ff9800, size=size.tiny)
plotshape(longContinuationSignal, title="Long Pullback Continuation", style=shape.diamond, location=location.belowbar,
color=#2962ff, size=size.tiny)
// ── Score table ──────────────────────────────────────────────────────────────
if showTable
tpos = switch tablePos
"Top Left" => position.top_left
"Bottom Right" => position.bottom_right
"Bottom Left" => position.bottom_left
=> position.top_right
color tc = color.new(color.gray, 20)
color hd = color.new(color.gray, 90)
var table t = table.new(tpos, 3, 6,
bgcolor=color.new(color.white, 5),
border_color=color.new(color.gray, 60),
border_width=1,
frame_color=color.new(color.gray, 40),
frame_width=1)
table.cell(t, 0, 0, "CHR", text_color=tc, bgcolor=hd, text_size=size.small)
table.cell(t, 1, 0, "Score", text_color=tc, bgcolor=hd, text_size=size.small)
table.cell(t, 2, 0, "Signal", text_color=tc, bgcolor=hd, text_size=size.small)
shortActive = shortReversalSignal or shortCounterTrendMarker or shortContinuationSignal
longActive = longReversalSignal or longCounterTrendMarker or longContinuationSignal
shortBg = shortReversalSignal ? color.new(#d50000, 20) : shortCounterTrendMarker ? color.new(#d50000, 65) : shortContinuationSignal ? color.new(#ff9800, 20) : color.new(color.gray, 80)
longBg = longReversalSignal ? color.new(#00c853, 20) : longCounterTrendMarker ? color.new(#00c853, 65) : longContinuationSignal ? color.new(#2962ff, 20) : color.new(color.gray, 80)
shortTc = shortActive ? color.white : tc
longTc = longActive ? color.white : tc
shortLabel = shortReversalSignal ? "▼ SHORT" : shortCounterTrendMarker ? "CT SHORT" : shortContinuationSignal ? "◆ PB SHORT" : "–"
longLabel = longReversalSignal ? "▲ LONG" : longCounterTrendMarker ? "CT LONG" : longContinuationSignal ? "◆ PB LONG" : "–"
table.cell(t, 0, 1, "Short", text_color=tc, text_size=size.small)
table.cell(t, 1, 1, str.tostring(shortScore) + " / 7", text_color=tc, text_size=size.small)
table.cell(t, 2, 1, shortLabel, bgcolor=shortBg, text_color=shortTc, text_size=size.small)
table.cell(t, 0, 2, "Long", text_color=tc, text_size=size.small)
table.cell(t, 1, 2, str.tostring(longScore) + " / 7", text_color=tc, text_size=size.small)
table.cell(t, 2, 2, longLabel, bgcolor=longBg, text_color=longTc, text_size=size.small)
table.cell(t, 0, 3, "", bgcolor=color.new(color.gray, 80), text_size=size.small)
table.cell(t, 1, 3, "", bgcolor=color.new(color.gray, 80), text_size=size.small)
table.cell(t, 2, 3, "", bgcolor=color.new(color.gray, 80), text_size=size.small)
trendLabel = not useTrendFilter ? "Off" : upTrend ? "Up" : "Down"
htfLabel = not useHTFBias ? "Off" : htfUpTrend ? "Up" : htfDownTrend ? "Down" : "Neutral"
table.cell(t, 0, 4, "Trend", text_color=tc, text_size=size.small)
table.cell(t, 1, 4, trendLabel, text_color=tc, text_size=size.small)
table.cell(t, 2, 4, "RSI " + str.tostring(math.round(rsi, 1)), text_color=tc, text_size=size.small)
table.cell(t, 0, 5, "HTF", text_color=tc, text_size=size.small)
table.cell(t, 1, 5, htfTF, text_color=tc, text_size=size.small)
table.cell(t, 2, 5, htfLabel, text_color=tc, text_size=size.small)
// ── Alerts ───────────────────────────────────────────────────────────────────
bool alertsOnBarClose = input.bool(true, "Alerts only on bar close (confirmed)", group="Alerts")
bool alertOk = not alertsOnBarClose or barstate.isconfirmed
alertcondition(alertOk and (longReversalSignal), "CHR Long Signal", "CHR · LONG · {{ticker}} {{interval}}")
alertcondition(alertOk and (shortReversalSignal), "CHR Short Signal", "CHR · SHORT · {{ticker}} {{interval}}")
alertcondition(alertOk and (longCounterTrendMarker), "CHR Long Counter-Trend Reversal", "CHR · COUNTER-TREND LONG · {{ticker}} {{interval}}")
alertcondition(alertOk and (shortCounterTrendMarker), "CHR Short Counter-Trend Reversal", "CHR · COUNTER-TREND SHORT · {{ticker}} {{interval}}")
alertcondition(alertOk and (longContinuationSignal), "CHR Long Pullback Continuation", "CHR · PULLBACK CONTINUATION LONG · {{ticker}} {{interval}}")
alertcondition(alertOk and (shortContinuationSignal), "CHR Short Pullback Continuation", "CHR · PULLBACK CONTINUATION SHORT · {{ticker}} {{interval}}")
alertcondition(alertOk and (longReversalSignal or shortReversalSignal), "CHR Any Reversal Signal", "CHR · REVERSAL SIGNAL · {{ticker}} {{interval}}")
alertcondition(alertOk and (longReversalSignal or shortReversalSignal or longContinuationSignal or shortContinuationSignal), "CHR Any Signal", "CHR · SIGNAL · {{ticker}} {{interval}}")
Overview
Commodity Heat Reversal [WavesUnchained] builds separate long and short heat scores from ATR distance to a mean moving average, ATR expansion, RSI extremes, wick pressure, and Bollinger Band breaches. Optional filters use a longer trend moving average and a higher-timeframe EMA bias. Confirmation mode, cooldown, and heat thresholds control when markers appear. Optional pullback-continuation signals and a score table can be shown. Suggested swing stops and a fast-moving-average target are displayed; the script does not place trades.
The inputs you can change from the gear icon on the chart. Defaults are the author's.
Setting
Type
Default
Variable
MA Type
string
HMA
maType
JMA Phase
int
50
jmaPhase
JMA Power
float
2.0
jmaPower
Enable Trend Filter
bool
false
useTrendFilter
Allow Counter-Trend at Extreme
bool
true
allowCounterTrendExtreme
Use HTF Bias
bool
true
useHTFBias
HTF Bias Timeframe
timeframe
D
htfTF
MA Fast (TP)
int
20
maFastLen
MA Mean
int
50
maMeanLen
MA Trend
int
200
maTrendLen
HTF EMA Trend
int
50
htfTrendLen
ATR Fast
int
14
atrFastLen
Show all 29 settings
Setting
Type
Default
Variable
ATR Slow (SMA)
int
50
atrSlowLen
RSI
int
14
rsiLen
Reversal Heat Threshold
int
1
reversalHeatThreshold
Extreme Heat Threshold
int
2
extremeHeatThreshold
Confirmation Mode
string
Balanced
confirmationMode
Same-Direction Cooldown Bars
int
3
signalCooldownBars
Counter-Trend Reversals
string
Hide
counterTrendDisplay
Show Pullback Continuation Signals
bool
false
showContinuationSignals
Pullback Heat Score
int
2
continuationScore
Pullback Lookback Bars
int
12
pullbackLookback
Pullback Signal Cooldown Bars
int
8
continuationCooldownBars
ATR Distance to MA50
float
2.5
atrDistanceMult
ATR Expansion Mult
float
1.5
atrExpansionMult
SL ATR Multiplier
float
1.2
slAtrMult
Show Score Table
bool
true
showTable
Table Position
string
Top Right
tablePos
Alerts only on bar close (confirmed)
bool
true
alertsOnBarClose
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 overlay indicator recreates short-setup conditions and audits their later outcomes on the price chart. It scores optional percent-surge, RSI overbought rollover, Bollinger exhaustion, volume spike, and EMA trend filters, then marks BASE or STRONG signals
This overlay indicator plots a 20-period Bollinger Band envelope with a two-standard-deviation width on the price chart. It marks a long bounce when price reclaims the lower band, 14-period RSI is between 30 and 70, 14-period ADX is above 25, and Binance BTCUS
This overlay indicator plots a Supertrend from an ATR length and factor, four exponential moving averages, and a selectable VWAP or TWAP taken from a chosen timeframe on the price chart. It also shows MACD and stochastic with adjustable lengths, smoothing, ver
This indicator plots trade entry and exit signals on the price chart by combining Bollinger Bands with optional filter conditions. It calculates standard Bollinger Bands along with RSI, Aroon, and moving average filters. Reversal signals trigger when price bre
This indicator identifies mean-reversion setups by combining Bollinger Bands with Fair Value Gaps (FVGs). It tracks FVGs that print outside the upper or lower Bollinger Bands and counts them toward an alert threshold. Signals trigger upon gap mitigation (by to
This indicator combines Bollinger Bands, RSI, Stochastic RSI, and volume spike detection to identify mean-reversion conditions during range-bound market regimes. It calculates Bollinger Band width to identify low-volatility states and triggers buy or sell sign