//@version=5
indicator("Reversal Algo", overlay=true)
// Input parameters
alertLong = input.bool(true, title="Long Alert", group="Alerts")
alertShort = input.bool(true, title="Short Alert", group="Alerts")
signalFilter = input.bool(false, title="Show Buy/Sell Dots When Close >
DonchianUpper", group="Dots", inline="21")
showDots = input.bool(true, title="Show Buy/Sell Dots When Not Filtered",
group="Dots", inline="21")
macd_fast = input.int(20, title="Fast Length", group="MACD Settings", inline="1")
macd_slow = input.int(50, title="Slow Length", group="MACD Settings", inline="1")
macd_src = input.source(close, title="Source", group="MACD Settings")
macd_signal_ema = input.int(12, title="Signal Smoothing", group="MACD Settings")
// Calculate MACD
[macd, signal, hist] = ta.macd(macd_src, macd_fast, macd_slow, macd_signal_ema)
cross_UP = ta.crossover(macd, signal)
cross_DN = ta.crossunder(macd, signal)
// RSI
rsiPeriod = input.int(14, "RSI Length", group="RSI Settings")
rsisrc = input.source(close, "RSI Source", group="RSI Settings")
rsi = ta.rsi(rsisrc, rsiPeriod)
rsisignal = rsi - 50
// Volatility for support and resistance zones
volatilityPeriod = input.int(10, title="Volatility Period", minval=1,
group="Support/Resistance Cloud")
multiplier = input.float(5.0, title="Multiplier", minval=1, step=0.5,
group="Support/Resistance Cloud")
// Color Settings
gradientRange = input.int(2000, title="Gradient Range", minval=500, step=500,
group="Colors")
// Calculate volatility
atr = ta.atr(volatilityPeriod)
upperBand = (high + low) / 2 + atr * multiplier
lowerBand = (high + low) / 2 - atr * multiplier
// Determine support and resistance zones with more precise levels
supportLevel = ta.lowest(low, 20)
resistanceLevel = ta.highest(high, 20)
preciseSupportZoneStart = math.max(supportLevel, ta.lowest(lowerBand, 20))
preciseSupportZoneEnd = math.min(supportLevel, ta.highest(lowerBand, 20))
preciseResistanceZoneStart = math.max(resistanceLevel, ta.lowest(upperBand, 20))
preciseResistanceZoneEnd = math.min(resistanceLevel, ta.highest(upperBand, 20))
// Kalman filter function
kalmanFilter(input, kf_q, kf_r) =>
var kf_x = 0.0
var kf_p = 1.0
kf_k = kf_p / (kf_p + kf_r)
kf_x := kf_k * input + (1 - kf_k) * nz(kf_x[1])
kf_p := (1 - kf_k) * kf_p + kf_q
kf_x
// Smooth the support and resistance zone levels using Kalman filter
kf_q = 0.01
kf_r = 0.1
smoothedSupportZoneStart = kalmanFilter(preciseSupportZoneStart, kf_q, kf_r)
smoothedSupportZoneEnd = kalmanFilter(preciseSupportZoneEnd, kf_q, kf_r)
smoothedResistanceZoneStart = kalmanFilter(preciseResistanceZoneStart, kf_q, kf_r)
smoothedResistanceZoneEnd = kalmanFilter(preciseResistanceZoneEnd, kf_q, kf_r)
// Determine trend based on MACD histogram and RSI signal
histPower = math.abs(hist)
rsiPower = math.abs(rsisignal)
bullishTrend = hist > 0 and hist > hist[1] and rsisignal > 0
bearishTrend = hist < 0 and hist < hist[1] and rsisignal < 0
consolidatingTrend = not bullishTrend and not bearishTrend
// Change bar color based on MACD histogram power and RSI signal
barcolor(na(histPower) ? color.purple :
bullishTrend ? color.from_gradient(histPower, 0, gradientRange,
color.rgb(0, 255, 0), color.rgb(0, 150, 0)) :
bearishTrend ? color.from_gradient(histPower, 0, gradientRange,
color.rgb(255, 0, 0), color.rgb(150, 0, 0)) :
color.from_gradient(histPower, 0, gradientRange, color.rgb(150, 0 , 0),
color.rgb(0, 150, 0)))
// Display histPower value and rsiPower value for debug
//label.new(bar_index, high, str.tostring(histPower, format.mintick),
style=label.style_none, yloc=yloc.abovebar, color=color.white)
//label.new(bar_index, high, str.tostring(rsiPower, format.mintick),
style=label.style_none, yloc=yloc.belowbar, color=color.white)
// Plot Buy and Sell Signals
plotshape(showDots and cross_UP and rsisignal > 0 and (not signalFilter or close >
smoothedSupportZoneEnd), title="Strong Buy", color=color.rgb(0, 255, 0),
style=shape.triangleup, location=location.belowbar, size=size.small, text="Strong",
textcolor=color.white)
plotshape(showDots and cross_DN and rsisignal < 0 and (not signalFilter or close <
smoothedResistanceZoneStart), title="Strong Sell", color=color.rgb(255, 0, 0),
style=shape.triangledown, location=location.abovebar, size=size.small,
text="Strong", textcolor=color.white)
plotshape(showDots and cross_UP and rsisignal <= 0 and (not signalFilter or close >
smoothedSupportZoneEnd), title="Buy", color=color.rgb(0, 255, 0),
style=shape.triangleup, location=location.belowbar, size=size.tiny, text="Buy",
textcolor=color.white)
plotshape(showDots and cross_DN and rsisignal >= 0 and (not signalFilter or close <
smoothedResistanceZoneStart), title="Sell", color=color.rgb(255, 0, 0),
style=shape.triangledown, location=location.abovebar, size=size.tiny, text="Sell",
textcolor=color.white)
// Plot the dynamic support and resistance zones
supportZone = smoothedSupportZoneStart
resistanceZone = smoothedResistanceZoneEnd
fill(plot(supportZone, title="Support Zone", style=plot.style_linebr, linewidth=1,
color=color.new(color.blue, 70)), plot(smoothedSupportZoneEnd,
style=plot.style_linebr, linewidth=1, color=color.new(color.blue, 70)),
color=color.new(color.blue, 80))
fill(plot(smoothedResistanceZoneStart, title="Resistance Zone",
style=plot.style_linebr, linewidth=1, color=color.new(color.red, 70)),
plot(smoothedResistanceZoneEnd, style=plot.style_linebr, linewidth=1,
color=color.new(color.red, 70)), color=color.new(color.red, 80))
// Function to generate alert message
alertMessage(msg) =>
"Symbol = " + syminfo.tickerid + " | TimeFrame = " + timeframe.period + " |
Price = " + str.tostring(close) + " | Reversal Algo " + msg
// Alerts
if alertLong and cross_UP and (not signalFilter or close > smoothedSupportZoneEnd)
alert(alertMessage("Buy"), alert.freq_once_per_bar_close)
if alertShort and cross_DN and (not signalFilter or close <
smoothedResistanceZoneStart)
alert(alertMessage("Sell"), alert.freq_once_per_bar_close)