1Copy the scriptPress Copy script above, or the copy button on the code below.
2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.
Source Code
377 lines of Pine Script v6 from GemHunter/gemhunter.pine, published under MPL-2.0. Keep the author's credit and licence lines when you reuse it.
gemhunter.pine
//@version=6
// ════════════════════════════════════════════════════════════════════════════════
// GemHunter v4 — EMA + RSI + MACD + ADX trend-regime detector
// Anti-chop filters · non-repainting higher-timeframe confirmation · alerts
// https://github.com/Finland93/GemHunter
// Educational tool, not financial advice. Backtest before using.
// ════════════════════════════════════════════════════════════════════════════════
indicator("GemHunter v4 (EMA+RSI+MACD+ADX+S/R, Anti-Chop, MTF-Confirmed)", shorttitle="GemHunter v4", overlay=true, max_bars_back=5000, max_boxes_count=500, max_labels_count=500)
// ════════════════════════════════════════════════════════════════════════════════
// INPUTS
// ════════════════════════════════════════════════════════════════════════════════
grp_trend = "Trend Engine (EMA + MACD + RSI)"
emaFastLen = input.int(50, "EMA Fast", minval=2, group=grp_trend, tooltip="Fast trend EMA. Lower = more responsive, more flips.")
emaSlowLen = input.int(200, "EMA Slow", minval=5, group=grp_trend, tooltip="Slow trend EMA. Defines the macro bias.")
rsiLen = input.int(14, "RSI Length", minval=2, group=grp_trend)
rsiBullTh = input.int(55, "RSI Bull Threshold", minval=1, maxval=99, group=grp_trend)
rsiBearTh = input.int(45, "RSI Bear Threshold", minval=1, maxval=99, group=grp_trend)
macdFast = input.int(12, "MACD Fast", minval=1, group=grp_trend)
macdSlow = input.int(26, "MACD Slow", minval=1, group=grp_trend)
macdSignal = input.int(9, "MACD Signal", minval=1, group=grp_trend)
votesNeeded = input.int(2, "Votes Needed (of 3)", minval=1, maxval=3, group=grp_trend, tooltip="How many of EMA / MACD / RSI must agree. 3 = strictest, fewest signals.")
confirmBars = input.int(3, "Bars to Confirm Regime", minval=1, group=grp_trend, tooltip="A raw signal must persist this many bars before it counts (debounce).")
grp_filters = "Noise Filters (Anti-Chop / Hysteresis)"
emaAtrMult = input.float(0.5, "Min EMA Separation (x ATR)", minval=0.0, step=0.05, group=grp_filters, tooltip="EMAs must be this far apart (in ATRs) to count as trending. Higher = fewer chop flips.")
slopeLb = input.int(20, "EMA Slow Slope Lookback", minval=1, group=grp_filters)
slopeMinRoc = input.float(0.05,"Min EMA Slow ROC % (abs)", minval=0.0, step=0.01, group=grp_filters, tooltip="Slow EMA must be sloping at least this much. Filters flat/sideways markets.")
rsiHyst = input.int(2, "RSI Hysteresis (+/-)", minval=0, maxval=10, group=grp_filters, tooltip="Widens the RSI bands so price has to commit before flipping.")
macdStdLen = input.int(100, "MACD Hist Strength Window", minval=5, group=grp_filters)
macdStdMult = input.float(0.5, "MACD Hist Strength (x StDev)", minval=0.0, step=0.1, group=grp_filters, tooltip="MACD histogram must exceed this many std-devs to count. Filters weak momentum.")
useADX = input.bool(true, "Require ADX Trend Strength", group=grp_filters, tooltip="Blocks signals when ADX is weak or +DI/-DI disagree with the trade side. Excellent for cutting range/chop. Turn OFF to revert to pure voting.")
adxLen = input.int(14, "ADX / DI Length", minval=1, group=grp_filters)
adxSmooth = input.int(14, "ADX Smoothing", minval=1, group=grp_filters)
adxMinTh = input.float(18.0,"ADX Min Threshold", minval=0.0, step=0.5, group=grp_filters, tooltip="Typical 18-25. Higher = only strong trends pass.")
grp_htf = "Higher Timeframe Confirmation"
useHTF = input.bool(true, "Enable HTF Confirmation", group=grp_htf)
htfTF = input.timeframe("240", "HTF (e.g. 60, 240, D, W)", group=grp_htf)
htfMode = input.string("Filter", "HTF Mode", options=["Display Only","Filter","Strict"], group=grp_htf, tooltip="Display Only = info only. Filter = block counter-trend signals. Strict = require full LTF+HTF agreement.")
grp_bg = "Background Controls"
bgSource = input.string("Gated", "Background Uses", options=["LTF","Gated","HTF"], group=grp_bg, tooltip="LTF = chart signal only. Gated = chart signal after HTF gating. HTF = higher-timeframe only.")
minHoldBars = input.int(5, "Min Bars to Hold Trend", minval=0, group=grp_bg, tooltip="Regime cannot flip again until this many bars pass since the last flip.")
grp_sig = "Signals & Alerts"
showSignals = input.bool(true, "Show Flip Markers", group=grp_sig)
grp_style = "Style"
showBG = input.bool(true, "Background Tint", group=grp_style)
showTable = input.bool(true, "Show Tables", group=grp_style)
showEMAs = input.bool(true, "Plot EMAs", group=grp_style)
showMACDZero= input.bool(false, "Show MACD Zero Dots", group=grp_style)
grp_sr = "Support & Resistance"
showSR = input.bool(true, "Show S/R Zones", group=grp_sr)
srLeft = input.int(15, "Pivot Left", minval=1, group=grp_sr)
srRight = input.int(15, "Pivot Right", minval=1, group=grp_sr, tooltip="Bars required AFTER a swing before it's confirmed as a pivot. Larger = stronger, fewer levels, but each level appears later. This delay is confirmation lag, not repainting.")
srMaxLevels = input.int(8, "Max Levels Kept", minval=1, maxval=30, group=grp_sr, tooltip="Once this many zones exist, the oldest un-retested one is removed to keep the chart clean.")
srZoneAtr = input.float(0.25, "Zone Half-Width (x ATR)", minval=0.0, step=0.05, group=grp_sr, tooltip="Half-thickness of each zone as a multiple of ATR(14).")
srMergeAtr = input.float(0.5, "Merge Distance (x ATR)", minval=0.0, step=0.05, group=grp_sr, tooltip="A new pivot within this many ATRs of an existing zone reinforces it (touch count +1) instead of drawing a duplicate.")
srExtend = input.int(10, "Extend Right (bars)", minval=0, group=grp_sr)
srShowStrength = input.bool(true, "Show Touch Count", group=grp_sr)
// ════════════════════════════════════════════════════════════════════════════════
// CORE (LTF / chart timeframe)
// ════════════════════════════════════════════════════════════════════════════════
emaFast = ta.ema(close, emaFastLen)
emaSlow = ta.ema(close, emaSlowLen)
rsiVal = ta.rsi(close, rsiLen)
macdLine = ta.ema(close, macdFast) - ta.ema(close, macdSlow)
signalLine = ta.ema(macdLine, macdSignal)
macdHist = macdLine - signalLine
atr14 = ta.atr(14)
[diPlus, diMinus, adxVal] = ta.dmi(adxLen, adxSmooth)
// Filter sub-conditions
emaSepOK = not na(atr14) and math.abs(emaFast - emaSlow) > atr14 * emaAtrMult
rocSlow = ta.roc(emaSlow, slopeLb)
slopeOKU = not na(rocSlow) and rocSlow > slopeMinRoc
slopeOKD = not na(rocSlow) and rocSlow < -slopeMinRoc
macdStdev = ta.stdev(macdHist, macdStdLen)
macdStr = not na(macdStdev) and math.abs(macdHist) > macdStdev * macdStdMult
// ADX strength + directional alignment (DMI). When disabled, always passes.
adxStrong = not na(adxVal) and adxVal >= adxMinTh
adxBullOK = not useADX or (adxStrong and diPlus >= diMinus)
adxBearOK = not useADX or (adxStrong and diMinus >= diPlus)
// Per-engine votes
bullEMA = close > emaFast and emaFast > emaSlow and emaSepOK and slopeOKU
bearEMA = close < emaFast and emaFast < emaSlow and emaSepOK and slopeOKD
bullMACD = macdLine > 0 and macdLine > signalLine and macdStr
bearMACD = macdLine < 0 and macdLine < signalLine and macdStr
bullRSI = rsiVal >= (rsiBullTh + rsiHyst)
bearRSI = rsiVal <= (rsiBearTh - rsiHyst)
bullVotes = (bullEMA ? 1 : 0) + (bullMACD ? 1 : 0) + (bullRSI ? 1 : 0)
bearVotes = (bearEMA ? 1 : 0) + (bearMACD ? 1 : 0) + (bearRSI ? 1 : 0)
rawBull = bullVotes >= votesNeeded and adxBullOK
rawBear = bearVotes >= votesNeeded and adxBearOK
// Debounce N consecutive bars
var int bullRun = 0
var int bearRun = 0
bullRun := rawBull ? bullRun + 1 : 0
bearRun := rawBear ? bearRun + 1 : 0
ltfBull = bullRun >= confirmBars
ltfBear = bearRun >= confirmBars
// ════════════════════════════════════════════════════════════════════════════════
// HTF CONFIRMATION — one bundled, non-repainting request.security call
// • All slope / stdev maths run inside the HTF context (correct bar spacing)
// • A var-held "confirmed only" gate prevents intra-HTF-bar repainting
// ════════════════════════════════════════════════════════════════════════════════
htfEval() =>
_emaF = ta.ema(close, emaFastLen)
_emaS = ta.ema(close, emaSlowLen)
_rsi = ta.rsi(close, rsiLen)
_mL = ta.ema(close, macdFast) - ta.ema(close, macdSlow)
_sL = ta.ema(_mL, macdSignal)
_hist = _mL - _sL
_atr = ta.atr(14)
_sepOK = not na(_atr) and math.abs(_emaF - _emaS) > _atr * emaAtrMult
_roc = ta.roc(_emaS, slopeLb)
_sU = not na(_roc) and _roc > slopeMinRoc
_sD = not na(_roc) and _roc < -slopeMinRoc
_hStd = ta.stdev(_hist, macdStdLen)
_hStr = not na(_hStd) and math.abs(_hist) > _hStd * macdStdMult
_bE = _emaF > _emaS and _sepOK and _sU
_rE = _emaF < _emaS and _sepOK and _sD
_bM = _mL > 0 and _mL > _sL and _hStr
_rM = _mL < 0 and _mL < _sL and _hStr
_bR = _rsi >= (rsiBullTh + rsiHyst)
_rR = _rsi <= (rsiBearTh - rsiHyst)
_bull = ((_bE ? 1 : 0) + (_bM ? 1 : 0) + (_bR ? 1 : 0)) >= votesNeeded
_bear = ((_rE ? 1 : 0) + (_rM ? 1 : 0) + (_rR ? 1 : 0)) >= votesNeeded
var bool _bullHold = false
var bool _bearHold = false
if barstate.isconfirmed
_bullHold := _bull
_bearHold := _bear
[_bullHold, _bearHold]
[htfBullRaw, htfBearRaw] = request.security(syminfo.tickerid, htfTF, htfEval(), barmerge.gaps_off, barmerge.lookahead_off)
htfBull = useHTF and htfBullRaw
htfBear = useHTF and htfBearRaw
// Gate LTF by HTF mode
bool gatedBull = ltfBull
bool gatedBear = ltfBear
if useHTF
if htfMode == "Filter"
gatedBull := ltfBull and not htfBear
gatedBear := ltfBear and not htfBull
else if htfMode == "Strict"
gatedBull := ltfBull and htfBull
gatedBear := ltfBear and htfBear
// ════════════════════════════════════════════════════════════════════════════════
// REGIME with flip guard + duration stats
// ════════════════════════════════════════════════════════════════════════════════
var string regime = "Neutral"
var int startBarIx = na
var int lastFlip = na
var int upDur = 0
var int downDur = 0
var float avgUp = na
var float avgDown = na
var int upCount = 0
var int dnCount = 0
canFlip = na(lastFlip) ? true : (bar_index - lastFlip) >= minHoldBars
wantBull = gatedBull and regime != "Uptrend" and canFlip
wantBear = gatedBear and regime != "Downtrend" and canFlip
if wantBull
if regime == "Downtrend" and not na(startBarIx)
downDur := bar_index - startBarIx
dnCount += 1
avgDown := na(avgDown) ? downDur : (avgDown * (dnCount - 1) + downDur) / dnCount
regime := "Uptrend"
startBarIx := bar_index
lastFlip := bar_index
upDur := 0
if wantBear
if regime == "Uptrend" and not na(startBarIx)
upDur := bar_index - startBarIx
upCount += 1
avgUp := na(avgUp) ? upDur : (avgUp * (upCount - 1) + upDur) / upCount
regime := "Downtrend"
startBarIx := bar_index
lastFlip := bar_index
downDur := 0
if regime == "Uptrend" and not na(startBarIx)
upDur := bar_index - startBarIx
if regime == "Downtrend" and not na(startBarIx)
downDur := bar_index - startBarIx
flipUp = regime == "Uptrend" and regime[1] != "Uptrend"
flipDown = regime == "Downtrend" and regime[1] != "Downtrend"
// ════════════════════════════════════════════════════════════════════════════════
// TABLES
// ════════════════════════════════════════════════════════════════════════════════
var table tblTopRight = table.new(position.top_right, 2, 3, bgcolor=color.new(color.white, 88), frame_color=color.new(color.black, 75), frame_width=1)
var table tblBotLeft = table.new(position.bottom_left, 2, 2, bgcolor=color.new(color.white, 88), frame_color=color.new(color.black, 75), frame_width=1)
var table tblBotRight = table.new(position.bottom_right, 2, 2, bgcolor=color.new(color.white, 88), frame_color=color.new(color.black, 75), frame_width=1)
ltfStatusTxt = gatedBull ? "Bullish" : gatedBear ? "Bearish" : "Neutral"
ltfStatusCol = gatedBull ? color.green : gatedBear ? color.red : color.gray
htfStatusTxt = useHTF ? (htfBull ? "Bullish" : htfBear ? "Bearish" : "Neutral") : "—"
htfStatusCol = useHTF ? (htfBull ? color.green : htfBear ? color.red : color.gray) : color.gray
adxTxt = na(adxVal) ? "—" : str.tostring(math.round(adxVal))
adxCol = na(adxVal) ? color.gray : (adxVal >= adxMinTh ? color.green : color.orange)
barsNow = regime == "Uptrend" ? upDur : regime == "Downtrend" ? downDur : 0
if showTable and barstate.islast
table.cell(tblTopRight, 0, 0, "HTF:", text_color=color.white, bgcolor=color.new(color.blue, 0))
table.cell(tblTopRight, 1, 0, htfStatusTxt, text_color=htfStatusCol, bgcolor=color.white)
table.cell(tblTopRight, 0, 1, "LTF:", text_color=color.white, bgcolor=color.new(color.blue, 0))
table.cell(tblTopRight, 1, 1, ltfStatusTxt, text_color=ltfStatusCol, bgcolor=color.white)
table.cell(tblTopRight, 0, 2, "ADX:", text_color=color.white, bgcolor=color.new(color.blue, 0))
table.cell(tblTopRight, 1, 2, adxTxt, text_color=adxCol, bgcolor=color.white)
table.cell(tblBotLeft, 0, 0, "AVG UP:", text_color=color.white, bgcolor=color.new(color.blue, 0))
table.cell(tblBotLeft, 1, 0, na(avgUp) ? "—" : str.tostring(math.round(avgUp)), text_color=color.green, bgcolor=color.white)
table.cell(tblBotLeft, 0, 1, "AVG DOWN:", text_color=color.white, bgcolor=color.new(color.blue, 0))
table.cell(tblBotLeft, 1, 1, na(avgDown) ? "—" : str.tostring(math.round(avgDown)), text_color=color.red, bgcolor=color.white)
table.cell(tblBotRight, 0, 0, "Trend:", text_color=color.white, bgcolor=color.new(color.blue, 0))
table.cell(tblBotRight, 1, 0, regime, text_color=color.black, bgcolor=color.white)
table.cell(tblBotRight, 0, 1, "Bars:", text_color=color.white, bgcolor=color.new(color.blue, 0))
table.cell(tblBotRight, 1, 1, str.tostring(barsNow), text_color=color.black, bgcolor=color.white)
// ════════════════════════════════════════════════════════════════════════════════
// BACKGROUND
// ════════════════════════════════════════════════════════════════════════════════
bgBull = color.new(color.green, 85)
bgBear = color.new(color.red, 85)
bgNeu = color.new(color.gray, 90)
bgBullSig = bgSource == "LTF" ? ltfBull : bgSource == "HTF" ? htfBull : gatedBull
bgBearSig = bgSource == "LTF" ? ltfBear : bgSource == "HTF" ? htfBear : gatedBear
bgColor = bgBullSig ? bgBull : bgBearSig ? bgBear : bgNeu
bgcolor(showBG ? bgColor : na, title="Regime Tint")
// ════════════════════════════════════════════════════════════════════════════════
// PLOTS
// ════════════════════════════════════════════════════════════════════════════════
plot(showEMAs ? emaFast : na, "EMA Fast", color=color.new(color.teal, 0), linewidth=2)
plot(showEMAs ? emaSlow : na, "EMA Slow", color=color.new(color.orange, 0), linewidth=2)
plotshape(showSignals and flipUp, title="Flip Up", style=shape.triangleup, location=location.belowbar, color=color.new(color.green, 0), size=size.tiny, text="Bull")
plotshape(showSignals and flipDown, title="Flip Down", style=shape.triangledown, location=location.abovebar, color=color.new(color.red, 0), size=size.tiny, text="Bear")
plotshape(showMACDZero and macdLine > 0, title="MACD>0", style=shape.circle, location=location.belowbar, color=color.new(color.green, 0), size=size.tiny)
plotshape(showMACDZero and macdLine < 0, title="MACD<0", style=shape.circle, location=location.abovebar, color=color.new(color.red, 0), size=size.tiny)
// ════════════════════════════════════════════════════════════════════════════════
// SUPPORT & RESISTANCE — confirmed-pivot zones with touch-count strength
// • Levels come from confirmed swing pivots, so they DO NOT repaint. A zone simply
// appears srRight bars after its pivot (confirmation lag, not repainting).
// • A new pivot within "Merge Distance" of an existing zone reinforces it
// (touch count +1) instead of cluttering the chart with a duplicate.
// • Each zone is colored by its CURRENT role: green support while price trades
// above it, red resistance while price trades below — a broken level flips role.
// • The oldest un-retested zones are pruned so only the most relevant ones remain.
// ════════════════════════════════════════════════════════════════════════════════
phSR = ta.pivothigh(high, srLeft, srRight)
plSR = ta.pivotlow(low, srLeft, srRight)
var array<float> srPx = array.new<float>()
var array<float> srHalf = array.new<float>()
var array<int> srHits = array.new<int>()
var array<int> srBar = array.new<int>()
var array<box> srBx = array.new<box>()
var array<label> srLb = array.new<label>()
srBrokeUp = false
srBrokeDn = false
if showSR and not na(atr14)
float half = atr14 * srZoneAtr
float mDist = atr14 * srMergeAtr
// 1) register this bar's confirmed pivot(s): reinforce a nearby zone, else add one
candPx = array.new<float>()
if not na(phSR)
array.push(candPx, phSR)
if not na(plSR)
array.push(candPx, plSR)
if array.size(candPx) > 0
for c = 0 to array.size(candPx) - 1
px = array.get(candPx, c)
nearIdx = -1
float nearDst = na
if array.size(srPx) > 0
for i = 0 to array.size(srPx) - 1
d = math.abs(array.get(srPx, i) - px)
if d <= mDist and (na(nearDst) or d < nearDst)
nearDst := d
nearIdx := i
if nearIdx >= 0
array.set(srHits, nearIdx, array.get(srHits, nearIdx) + 1)
array.set(srBar, nearIdx, bar_index)
else
box nb = box.new(bar_index - srRight, px + half, bar_index, px - half, border_color=color.new(color.gray, 45), bgcolor=color.new(color.gray, 82))
label nl = label.new(bar_index, px, "", style=label.style_label_left, textcolor=color.white, color=color.new(color.gray, 100), size=size.small)
array.push(srPx, px)
array.push(srHalf, half)
array.push(srHits, 1)
array.push(srBar, bar_index)
array.push(srBx, nb)
array.push(srLb, nl)
// 2) prune the oldest un-retested zone(s) beyond the cap
while array.size(srPx) > srMaxLevels
oldIdx = 0
oldBar = array.get(srBar, 0)
for i = 1 to array.size(srPx) - 1
if array.get(srBar, i) < oldBar
oldBar := array.get(srBar, i)
oldIdx := i
box.delete(array.get(srBx, oldIdx))
label.delete(array.get(srLb, oldIdx))
array.remove(srPx, oldIdx)
array.remove(srHalf, oldIdx)
array.remove(srHits, oldIdx)
array.remove(srBar, oldIdx)
array.remove(srBx, oldIdx)
array.remove(srLb, oldIdx)
// 3) restyle + extend every active zone; flag a break when price closes through one
if array.size(srPx) > 0
for i = 0 to array.size(srPx) - 1
px = array.get(srPx, i)
hf = array.get(srHalf, i)
isSup = close >= px
col = isSup ? color.green : color.red
bx = array.get(srBx, i)
box.set_top(bx, px + hf)
box.set_bottom(bx, px - hf)
box.set_right(bx, bar_index + srExtend)
box.set_bgcolor(bx, color.new(col, 82))
box.set_border_color(bx, color.new(col, 45))
lb = array.get(srLb, i)
if srShowStrength
label.set_xy(lb, bar_index + srExtend, px)
label.set_text(lb, str.tostring(array.get(srHits, i)))
label.set_textcolor(lb, color.new(col, 0))
label.set_color(lb, color.new(col, 85))
label.set_style(lb, label.style_label_left)
else
label.set_text(lb, "")
label.set_color(lb, color.new(color.gray, 100))
if not na(close[1])
if close > px and close[1] <= px
srBrokeUp := true
if close < px and close[1] >= px
srBrokeDn := true
// ════════════════════════════════════════════════════════════════════════════════
// ALERTS (create these in TradingView via Alerts → Condition: GemHunter v4)
// ════════════════════════════════════════════════════════════════════════════════
alertcondition(flipUp, title="GemHunter ▲ Flip to Uptrend", message="GemHunter: trend flipped to UPTREND — {{ticker}} {{interval}}")
alertcondition(flipDown, title="GemHunter ▼ Flip to Downtrend", message="GemHunter: trend flipped to DOWNTREND — {{ticker}} {{interval}}")
alertcondition(gatedBull and not gatedBull[1], title="GemHunter • LTF Bullish (gated)", message="GemHunter: gated BULLISH signal — {{ticker}} {{interval}}")
alertcondition(gatedBear and not gatedBear[1], title="GemHunter • LTF Bearish (gated)", message="GemHunter: gated BEARISH signal — {{ticker}} {{interval}}")
alertcondition(useHTF and htfBull and not htfBull[1], title="GemHunter • HTF turned Bullish", message="GemHunter: higher timeframe BULLISH — {{ticker}} {{interval}}")
alertcondition(useHTF and htfBear and not htfBear[1], title="GemHunter • HTF turned Bearish", message="GemHunter: higher timeframe BEARISH — {{ticker}} {{interval}}")
alertcondition(srBrokeUp, title="GemHunter • Broke a Level (up)", message="GemHunter: price closed UP through an S/R level — {{ticker}} {{interval}}")
alertcondition(srBrokeDn, title="GemHunter • Broke a Level (down)", message="GemHunter: price closed DOWN through an S/R level — {{ticker}} {{interval}}")
Overview
GemHunter v4 combines exponential moving average alignment, MACD momentum, and RSI strength, optionally gated by ADX trend strength and higher-timeframe confirmation. Filters such as ATR-based EMA separation, slow EMA slope, and RSI hysteresis suppress sideways chop. The indicator overlays regime background tints, reversal markers, EMA lines, dynamic support and resistance zones from swing pivots, and informational dashboard tables directly onto the price chart.
Multi-indicator voting engine combining EMA, MACD, and RSI
Anti-chop filtering via ATR separation, slope threshold, and hysteresis
Higher-timeframe regime confirmation
Dynamic support and resistance zones with touch counts
On-chart dashboard tables for regime status and trend duration
The inputs you can change from the gear icon on the chart. Defaults are the author's.
Setting
Type
Default
Variable
EMA Fast
int
50
emaFastLen
EMA Slow
int
200
emaSlowLen
RSI Length
int
14
rsiLen
RSI Bull Threshold
int
55
rsiBullTh
RSI Bear Threshold
int
45
rsiBearTh
MACD Fast
int
12
macdFast
MACD Slow
int
26
macdSlow
MACD Signal
int
9
macdSignal
Votes Needed (of 3)
int
2
votesNeeded
Bars to Confirm Regime
int
3
confirmBars
Min EMA Separation (x ATR)
float
0.5
emaAtrMult
EMA Slow Slope Lookback
int
20
slopeLb
Show all 38 settings
Setting
Type
Default
Variable
Min EMA Slow ROC % (abs)
float
0.05
slopeMinRoc
RSI Hysteresis (+/-)
int
2
rsiHyst
MACD Hist Strength Window
int
100
macdStdLen
MACD Hist Strength (x StDev)
float
0.5
macdStdMult
Require ADX Trend Strength
bool
true
useADX
ADX / DI Length
int
14
adxLen
ADX Smoothing
int
14
adxSmooth
ADX Min Threshold
float
18.0
adxMinTh
Enable HTF Confirmation
bool
true
useHTF
HTF (e.g. 60, 240, D, W)
timeframe
240
htfTF
HTF Mode
string
Filter
htfMode
Background Uses
string
Gated
bgSource
Min Bars to Hold Trend
int
5
minHoldBars
Show Flip Markers
bool
true
showSignals
Background Tint
bool
true
showBG
Show Tables
bool
true
showTable
Plot EMAs
bool
true
showEMAs
Show MACD Zero Dots
bool
false
showMACDZero
Show S/R Zones
bool
true
showSR
Pivot Left
int
15
srLeft
Pivot Right
int
15
srRight
Max Levels Kept
int
8
srMaxLevels
Zone Half-Width (x ATR)
float
0.25
srZoneAtr
Merge Distance (x ATR)
float
0.5
srMergeAtr
Extend Right (bars)
int
10
srExtend
Show Touch Count
bool
true
srShowStrength
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 script provides an indicator-based backtesting engine framework that simulates trade entries, exits, and filtering directly on the price chart. It evaluates selected entry rules and multi-layered filters, including moving average trends, volume increases,
This indicator combines pivot-based support and resistance levels with multi-timeframe MACD crossovers and a higher-timeframe exponential moving average trend filter. It identifies support and resistance touches using pivot highs and lows within a user-defined
This overlay indicator plots Central Pivot Range levels and bands across yearly, quarterly, monthly, weekly, daily, and six-hour periods. Each timeframe can be shown or hidden, and pivot and band colors are set separately. It also marks MACD momentum and EMA t
The Moving Confluence Overlay indicator identifies confluence trading setups on the price chart by combining an exponential moving average ribbon, StochRSI crossovers, MACD momentum, and ATR volatility spike detection. When conditions align, it triggers trade
Xiaotang System V5.0 is a price-chart overlay indicator that identifies momentum breakouts across moving averages and session VWAP. It computes Heikin-Ashi price data, 50-period and 200-period SMAs, and intraday VWAP while monitoring 5-minute higher-timeframe
Icarus is an overlay indicator that projects momentum and level indicators directly onto the price chart. It calculates higher-timeframe equivalents for moving averages, computes Supertrend, and constructs price-equivalent RSI upper and lower bands based on La