OPEN-SOURCE SCRIPT

EMA + SuperTrend Signals (Customized Subham) - FIXED

36
//version=5
indicator("EMA + SuperTrend Signals (modes + filters) - FIXED firstClose", overlay=true, shorttitle="EMA×ST Modes", max_labels_count=500)

// ====== USER INPUTS ======
useHeikin = input.bool(false, "Use Heikin Ashi price (set true if chart is Heikin Ashi)")
srcType = input.string("Close", "Price source for EMA/SuperTrend", options=["Close", "HL2", "Typical (H+L+C)/3"])
emaFastLen = input.int(10, "Fast EMA Length", minval=1)
emaSlowLen = input.int(50, "Slow EMA Length", minval=1)
useEMAFilter = input.bool(true, "Require EMA filter for signals (Fast EMA > Slow EMA)")
atrLen = input.int(10, "SuperTrend ATR Length", minval=1)
atrMult = input.float(3.0, "SuperTrend ATR Multiplier", step=0.1)

showArrows = input.bool(true, "Show buy/sell arrows")
showBands = input.bool(true, "Show final upper/lower bands")
showST = input.bool(true, "Show SuperTrend line")
showEMA = input.bool(true, "Plot EMAs")
showBg = input.bool(true, "Color background by ST")
alertsEnabled = input.bool(true, "Enable alertcondition()s")

// ====== SIGNAL MODE / BEHAVIOR ======
signalMode = input.string("Flip only", "Signal Mode", options=["Flip only", "First close in trend", "EMA crossover in trend"])
allowOnTrendNotOnlyFlip = input.bool(true, "Allow signals based on Signal Mode (in addition to flips)")

// ====== SIDEWAYS / NOISE FILTER INPUTS ======
useAdxFilter = input.bool(true, "Use ADX filter (require trend strength)")
adxLen = input.int(14, "ADX length", minval=1)
adxThreshold = input.int(20, "ADX threshold (lower = more signals)")

useVolFilter = input.bool(true, "Use ATR% volatility filter (require sufficient movement)")
volPctThreshold = input.float(0.002, "ATR / Price threshold (e.g. 0.002 = 0.2%)", step=0.0001)

useRsiFilter = input.bool(true, "Use RSI filter")
rsiLen = input.int(14, "RSI length", minval=1)
rsiBuyThreshold = input.int(50, "RSI buy threshold (require RSI > this for buys)", minval=1, maxval=99)
rsiSellThreshold = input.int(50, "RSI sell threshold (require RSI < this for sells)", minval=1, maxval=99)

// ====== HEIKIN ASHI VALUES (optional) ======
var float haOpen = na
var float haClose = na
var float haHigh = na
var float haLow = na

if useHeikin
haClose := (open + high + low + close) / 4.0
haOpen := na(haOpen[1]) ? (open + close) / 2.0 : (haOpen[1] + haClose[1]) / 2.0
haHigh := math.max(high, math.max(haOpen, haClose))
haLow := math.min(low, math.min(haOpen, haClose))

// ====== PRICE SOURCE FUNCTION ======
_getSrc(_choice) =>
float _result = na
if useHeikin
if _choice == "Close"
_result := haClose
else if _choice == "HL2"
_result := (haHigh + haLow) * 0.5
else
_result := (haHigh + haLow + haClose) / 3.0
else
if _choice == "Close"
_result := close
else if _choice == "HL2"
_result := (high + low) * 0.5
else
_result := (high + low + close) / 3.0
_result

priceSrc = _getSrc(srcType)
priceHigh = useHeikin ? haHigh : high
priceLow = useHeikin ? haLow : low
priceClose = nz(priceSrc, close)

// ====== EMA CALC ======
emaFast = ta.ema(priceSrc, emaFastLen)
emaSlow = ta.ema(priceSrc, emaSlowLen)

// ====== SUPER TREND CALC (finalUpper / finalLower) ======
hl2_local = (priceHigh + priceLow) * 0.5
atr = ta.atr(atrLen)

upperBasic = hl2_local + atrMult * atr
lowerBasic = hl2_local - atrMult * atr

var float finalUpper = na
var float finalLower = na

finalUpper := nz(finalUpper[1], upperBasic)
finalLower := nz(finalLower[1], lowerBasic)

finalUpper := (upperBasic < finalUpper or priceClose[1] > finalUpper) ? upperBasic : finalUpper
finalLower := (lowerBasic > finalLower or priceClose[1] < finalLower) ? lowerBasic : finalLower

var int trend = 1
trend := nz(trend[1], 1)
if (priceClose > nz(finalUpper[1], finalUpper))
trend := 1
else if (priceClose < nz(finalLower[1], finalLower))
trend := -1

superTrend = trend == 1 ? finalLower : finalUpper
isBull = trend == 1
isBear = trend == -1

// ====== SIGNAL RULE BASE (flips) ======
prevTrend = nz(trend[1], trend)
bullFlip = (trend == 1 and prevTrend == -1)
bearFlip = (trend == -1 and prevTrend == 1)

// EMA crossover signals (series)
emaXoverBuy = ta.crossover(emaFast, emaSlow)
emaXoverSell = ta.crossunder(emaFast, emaSlow)

// price vs superTrend confirmation
priceAboveST = priceClose > superTrend
priceBelowST = priceClose < superTrend

// Basic EMA filters
emaFilterBuy = (emaFast > emaSlow) and (priceClose > emaFast)
emaFilterSell = (emaFast < emaSlow) and (priceClose < emaFast)

// Build raw candidates depending on mode
flipBuy = bullFlip
flipSell = bearFlip

// firstClose: first bar where trend flipped and price confirms on that bar's close
firstCloseBuy = (trend == 1) and (prevTrend == -1) and (priceClose > superTrend)
firstCloseSell = (trend == -1) and (prevTrend == 1) and (priceClose < superTrend)

// emaCrossoverCandidate: EMA cross while trend confirms
emaCandidateBuy = emaXoverBuy and (trend == 1)
emaCandidateSell = emaXoverSell and (trend == -1)

// Compose the raw buy/sell depending on chosen Signal Mode
var bool buySignal_raw = false
var bool sellSignal_raw = false
if signalMode == "Flip only"
buySignal_raw := flipBuy
sellSignal_raw := flipSell
else if signalMode == "First close in trend"
buySignal_raw := firstCloseBuy or (allowOnTrendNotOnlyFlip and flipBuy)
sellSignal_raw := firstCloseSell or (allowOnTrendNotOnlyFlip and flipSell)
else // "EMA crossover in trend"
buySignal_raw := emaCandidateBuy or (allowOnTrendNotOnlyFlip and flipBuy)
sellSignal_raw := emaCandidateSell or (allowOnTrendNotOnlyFlip and flipSell)

// Apply EMA filter option (if enabled)
if useEMAFilter
buySignal_raw := buySignal_raw and emaFilterBuy
sellSignal_raw := sellSignal_raw and emaFilterSell

// ====== SIDEWAYS FILTERS IMPLEMENTATION ======
// Manual ADX implementation (Wilder smoothing)
up = priceHigh - priceHigh[1]
down = priceLow[1] - priceLow
plusDM = (up > down and up > 0) ? up : 0.0
minusDM = (down > up and down > 0) ? down : 0.0

tr1 = priceHigh - priceLow
tr2 = math.abs(priceHigh - nz(priceClose[1], priceClose))
tr3 = math.abs(priceLow - nz(priceClose[1], priceClose))
trueRange = math.max(tr1, math.max(tr2, tr3))

smoothedTR = ta.rma(trueRange, adxLen)
smoothedPlusDM = ta.rma(plusDM, adxLen)
smoothedMinusDM = ta.rma(minusDM, adxLen)

plusDI = smoothedTR == 0 ? 0.0 : (100.0 * smoothedPlusDM / smoothedTR)
minusDI = smoothedTR == 0 ? 0.0 : (100.0 * smoothedMinusDM / smoothedTR)

dx = (plusDI + minusDI == 0) ? 0.0 : (100.0 * math.abs(plusDI - minusDI) / (plusDI + minusDI))
adxValue = ta.rma(dx, adxLen)

adxOk = useAdxFilter ? (adxValue > adxThreshold) : true

// ATR% check
safePrice = priceClose == 0.0 ? nz(close) : priceClose
atrPct = atr / math.abs(safePrice)
volOk = useVolFilter ? (atrPct > volPctThreshold) : true

// RSI checks
rsiValue = ta.rsi(priceSrc, rsiLen)
rsiOkBuy = useRsiFilter ? (rsiValue > rsiBuyThreshold) : true
rsiOkSell = useRsiFilter ? (rsiValue < rsiSellThreshold) : true

// Allow signal only when all enabled filters pass (separate for buy/sell)
allowBuy = adxOk and volOk and rsiOkBuy
allowSell = adxOk and volOk and rsiOkSell

// Final gated signals
buySignal = buySignal_raw and allowBuy
sellSignal = sellSignal_raw and allowSell

// Avoid both at once
if (buySignal and sellSignal)
buySignal := false
sellSignal := false

// ====== PLOTTING ======
plot(showEMA ? emaFast : na, title="EMA Fast", linewidth=2)
plot(showEMA ? emaSlow : na, title="EMA Slow", linewidth=2)

pUpper = plot(showBands ? finalUpper : na, title="Final Upper", linewidth=2, style=plot.style_line)
pLower = plot(showBands ? finalLower : na, title="Final Lower", linewidth=2, style=plot.style_line)
plot(showST ? superTrend : na, title="SuperTrend", linewidth=3, style=plot.style_line)
fill(pUpper, pLower, color = color.new(color.blue, 92))

plotshape(series = (showArrows and buySignal), title="Buy Arrow", style=shape.labelup, location=location.belowbar, color=color.green, text="BUY", textcolor=color.white, size=size.tiny)
plotshape(series = (showArrows and sellSignal), title="Sell Arrow", style=shape.labeldown, location=location.abovebar, color=color.red, text="SELL", textcolor=color.white, size=size.tiny)

// ====== BACKGROUND COLOR ======
var color bg_col = na
if showBg
if not (adxOk and volOk)
bg_col := color.new(color.gray, 85)
else
bg_col := isBull ? color.new(color.green, 90) : color.new(color.red, 90)
else
bg_col := na
bgcolor(bg_col)

// ====== ALERTS ======
alertcondition(alertsEnabled and buySignal, title="EMA+ST Buy", message="EMA+ST BUY — signal passed filters.")
alertcondition(alertsEnabled and sellSignal, title="EMA+ST Sell", message="EMA+ST SELL — signal passed filters.")
alertcondition(alertsEnabled and (buySignal or sellSignal), title="EMA+ST Any Signal", message="EMA+ST signal detected.")

// ====== DEBUG / LABELS ======
showDebug = input.bool(false, "Show debug label (mode, ADX, ATR%, RSI)")
if showDebug and barstate.islast
var label dbg = na
label.delete(dbg)
dbgText = "Mode:" + signalMode + " ADX:" + str.tostring(adxValue, "#.0") + " ATR%:" + str.tostring(atrPct*100, "#.2") + "% RSI:" + str.tostring(rsiValue, "#.1")
dbg := label.new(bar_index, high, dbgText, xloc=xloc.bar_index, yloc=yloc.abovebar, style=label.style_label_left, color=color.gray, textcolor=color.white)

var label lastLbl = na
if barstate.islast
label.delete(lastLbl)
lastLbl := label.new(bar_index, high, isBull ? "ST: Bull" : "ST: Bear", xloc=xloc.bar_index, yloc=yloc.abovebar, style=label.style_label_left, color=isBull ? color.green : color.red, textcolor=color.white)

Clause de non-responsabilité

Les informations et les publications ne sont pas destinées à être, et ne constituent pas, des conseils ou des recommandations en matière de finance, d'investissement, de trading ou d'autres types de conseils fournis ou approuvés par TradingView. Pour en savoir plus, consultez les Conditions d'utilisation.