#/@seoco
#indicator('CryptoSignalScanner - RSI Overbought/Oversold + Divergence Indicator',
# Converted by [email protected] -02/2023
declare lower;
input rsiAgg1 = AggregationPeriod.FIFTEEN_MIN;
input rsiAgg2 = AggregationPeriod.HOUR;
input rsiAgg3 = AggregationPeriod.FOUR_HOURS;
input rsiAgg4 = AggregationPeriod.DAY;
input ShowCurrenttimeStoch = yes;
input rsiShowInput = yes; # 'Show RSI', group='Show/Hide Settings')
input maShowInput = no; # 'Show MA', group='Show/Hide Settings')
input showRSIMAInput = yes; # 'Show RSIMA Cloud'
input rsiBandShowInput = yes; # 'Show Oversold/Overbought Lines'
input rsiBandExtShowInput = yes; # 'Show Oversold/Overbought Extended Lines'
input rsiHighlightShowInput = yes; # 'Show Oversold/Overbought Highlight Lines'
input DivergenceShowInput = yes; # 'Show RSI Divergence Labels'
#//--- RSI Input Settings
input rsiSourceInput = close; # 'Source'
input rsiLengthInput = 14; # 'RSI Length'
input rsiUpperBandExtInput = 80; # 'RSI Overbought Extended Line'
input rsiUpperBandInput = 70; # 'RSI Overbought Line'
input rsiLowerBandInput = 30; # 'RSI Oversold Line'
input rsiLowerBandExtInput = 20; # 'RSI Oversold Extended Line'
#//--- MA Input Settings
input maTypeInput = {"SMA", "Bollinger Bands", default "EMA", "SMMA (RMA)", "WMA", "VWMA"}; # "MA Type"
input maLengthInput = 14; # "MA Length"
#//--- Divergence Input Settings
input lbrInput = 2; # "Pivot Lookback Right"
input lblInput = 2; # "Pivot Lookback Left"
input lbRangeMaxInput = 10; # "Max of Lookback Range"
input lbRangeMinInput = 2; # "Min of Lookback Range"
input plotBullInput = yes; # "Plot Bullish"
input plotHiddenBullInput = yes; # "Plot Hidden Bullish"
input plotBearInput = yes; # "Plot Bearish"
input plotHiddenBearInput = yes; # "Plot Hidden Bearish"
#//--- Stoch RSI Settings + Calculation
input showStochRSI = no; # "Show Stochastic RSI"
input smoothK = 3; # "Stochastic K"
input smoothD = 4; # "Stochastic D"
input lengthRSI = 14; # "Stochastic RSI Lenght"
input lengthStoch = 14; # "Stochastic Lenght"
def na = Double.NaN;
def pos = Double.POSITIVE_INFINITY;
def neg = Double.NEGATIVE_INFINITY;
def isBB = maTypeInput == maTypeInput."Bollinger Bands";
#--- Color
DefineGlobalColor("Green" , CreateColor(38,166,154));
DefineGlobalColor("Red" , CreateColor(239,83,79));
DefineGlobalColor("Gray" , CreateColor(42,42,42));
#//--- RSI Calculation
def close15 = close(Period = rsiAgg1);
def close1h = close(Period = rsiAgg2);
def close4h = close(Period = rsiAgg3);
def close1d = close(Period = rsiAgg4);
def rsi = RSI(PRICE = rsiSourceInput, LENGTH = rsiLengthInput);
def up15 = WildersAverage(Max((close15 - close15[1]), 0), rsiLengthInput);
def down15 = WildersAverage(-Min((close15 - close15[1]), 0), rsiLengthInput);
def rsi15 = if down15 == 0 then 100 else if up15 == 0 then 0 else 100 - (100 / (1 + up15 / down15));
def up1h = WildersAverage(Max((close1h - close1h[1]), 0), rsiLengthInput);
def down1h = WildersAverage(-Min((close1h - close1h[1]), 0), rsiLengthInput);
def rsi1h = if down1h == 0 then 100 else if up1h == 0 then 0 else 100 - (100 / (1 + up1h / down1h));
def up4h = WildersAverage(Max((close4h - close4h[1]), 0), rsiLengthInput);
def down4h = WildersAverage(-Min((close4h - close4h[1]), 0), rsiLengthInput);
def rsi4h = if down4h == 0 then 100 else if up4h == 0 then 0 else 100 - (100 / (1 + up4h / down4h));
def up1d = WildersAverage(Max((close1d - close1d[1]), 0), rsiLengthInput);
def down1d = WildersAverage(-Min((close1d - close1d[1]), 0), rsiLengthInput);
def rsi1d = if down1d == 0 then 100 else if up1d == 0 then 0 else 100 - (100 / (1 + up1d / down1d));
#//--- MA Calculation
# stoch(source, high, low, length) =>
script stoch {
input src = close;
input h = high;
input l = low;
input len = 0;
def stoch = 100 * (src - lowest(l, len)) / (highest(h, len) - lowest(l, len));
plot return = stoch;
}
#ma(source, length, type) =>
script ma {
input source = close;
input length = 14;
input type = "EMA";
def ma =
if type == "SMA" then SimpleMovingAvg(source, length) else
if type == "Bollinger Bands" then SimpleMovingAvg(source, length) else
if type == "EMA" then ExpAverage(source, length) else
if type == "SMMA (RMA)" then WildersAverage(source, length) else
if type == "WMA" then WMA(source, length) else
if type == "VWMA" then SimpleMovingAvg(source * volume, length) / SimpleMovingAvg(volume, length) else source;
plot return = ma;
}
def rsiMA = ma(rsi, maLengthInput, maTypeInput);
def rsi1 = RSI(Price=close15, LENGTH=lengthRSI);
def k = SimpleMovingAvg(stoch(rsi1, rsi1, rsi1, lengthStoch), smoothK);
def d = SimpleMovingAvg(k, smoothD);
def osc = rsi;
def rsiColor = rsi >= rsiMA;
plot kTf = if !ShowCurrenttimeStoch then na else SimpleMovingAvg(stoch(rsi, rsi, rsi, lengthStoch), smoothK);
plot dTf = if !ShowCurrenttimeStoch then na else SimpleMovingAvg(kTf, smoothD);
kTf.SetDefaultColor(Color.CYAN);
dTf.SetDefaultColor(Color.YELLOW);
#//--- Plot Lines
plot maPlot = if maShowInput then rsiMA else na;
maPlot.SetDefaultColor(Color.YELLOW);
def rsiMAPlot = if showRSIMAInput then rsiMA else na;
plot rsiPlot = if rsiShowInput then rsi else na;
rsiPlot.AssignValueColor(if rsiColor then GlobalColor("Green") else GlobalColor("Red"));
AddCloud(rsiPlot, rsiMAPlot, GlobalColor("Green"), GlobalColor("Red"));
plot StochK = if showStochRSI then k else na;
StochK.SetDefaultColor(Color.WHITE);
plot StockD = if showStochRSI then d else na;
StockD.SetDefaultColor(Color.MAGENTA);
plot bbUpperBand = if isBB then rsiMA + stdev(rsi, maLengthInput) * 2 else na; # "Upper Bollinger Band"
bbUpperBand.SetDefaultColor(Color.GRAY);
plot bbLowerBand = if isBB then rsiMA - stdev(rsi, maLengthInput) * 2 else na; # "Lower Bollinger Band"
bbLowerBand.SetDefaultColor(Color.GRAY);
AddCloud(bbUpperBand, bbLowerBand, GlobalColor("Gray"));
plot midLine = 50;
midLine.SetDefaultColor(Color.DARK_GRAY);
plot rsiUpBandExt = if rsiBandExtShowInput then rsiUpperBandExtInput else na;
rsiUpBandExt.SetStyle(Curve.SHORT_DASH);
rsiUpBandExt.SetDefaultColor(Color.RED);
plot rsiUpBand = if rsiBandShowInput then rsiUpperBandInput else na;
rsiUpBand.SetStyle(Curve.SHORT_DASH);
rsiUpBand.SetDefaultColor(Color.DARK_RED);
plot rsiLoBand = if rsiBandShowInput then rsiLowerBandInput else na;
rsiLoBand.SetStyle(Curve.SHORT_DASH);
rsiLoBand.SetDefaultColor(Color.DARK_GREEN);
plot rsiLoBandExt = if rsiBandExtShowInput then rsiLowerBandExtInput else na;
rsiLoBandExt.SetStyle(Curve.SHORT_DASH);
rsiLoBandExt.SetDefaultColor(Color.GREEN);
AddCloud(if rsiHighlightShowInput then if rsi >= rsiUpperBandExtInput then pos else na else na, neg, Color.GREEN);
AddCloud(if rsiHighlightShowInput then if rsi >= rsiUpperBandInput then if rsi < rsiUpperBandExtInput then pos else na else na else na, neg, Color.DARK_GREEN);
AddCloud(if rsiHighlightShowInput then if rsi <= rsiLowerBandExtInput then pos else na else na, neg, Color.RED);
AddCloud(if rsiHighlightShowInput then if rsi <= rsiLowerBandInput then if rsi > rsiLowerBandExtInput then pos else na else na else na, neg, Color.DARK_RED);
script FindPivots {
input dat = close; # default data or study being evaluated
input HL = 0; # default high or low pivot designation, -1 low, +1 high
input lbL = 5; # default Pivot Lookback Left
input lbR = 1; # default Pivot Lookback Right
##############
def _nan; # used for non-number returns
def _BN; # the current barnumber
def _VStop; # confirms that the lookforward period continues the pivot trend
def _V; # the Value at the actual pivot point
##############
_BN = BarNumber();
_nan = Double.NaN;
_VStop = if !isNaN(dat) and lbr > 0 and lbl > 0 then
fold a = 1 to lbR + 1 with b=1 while b do
if HL > 0 then dat > GetValue(dat,-a) else dat < GetValue(dat,-a) else _nan;
if (HL > 0) {
_V = if _BN > lbL and dat == Highest(dat, lbL+1) and _VStop
then dat else _nan;
} else {
_V = if _BN > lbL and dat == Lowest(dat, lbL+1) and _VStop
then dat else _nan;
}
plot result = if !IsNaN(_V) and _VStop then _V else _nan;
}
#valuewhen (Cond, source, lbr, occurrence)
script valuewhen {
input cond = 0;
input src = close;
input MinLookback = 2;
input MaxLookback = 10;
input occurrence = 0;
def n = occurrence + 1;
def offset = fold j = 0 to MinLookback + MaxLookback + 1 with p=1 while p < n + 1
do p + ( if p == n then j - n else if cond[j]==yes then 1 else 0 );
plot price = GetValue(src, offset-1);
}
#_inRange(cond) =>
script _inRange {
input cond = yes;
input rangeUpper = 10;
input rangeLower = 2;
def bars = if cond then 0 else bars[1] + 1;
def inrange = (rangeLower <= bars) and (bars <= rangeUpper);
plot retrun = inRange;
}
#//--- Plot Divergence
#// Regular Bullish
#// Osc: Higher Low
def pl = findpivots(osc,-1, lblInput, lbrInput);
def ph = findpivots(osc, 1, lblInput, lbrInput);
def plFound = if isNaN(pl) then 0 else 1;
def phFound = if isNaN(ph) then 0 else 1;
def vlFound = valuewhen(plFound, osc, lbRangeMinInput, lbRangeMaxInput, 1);
def vhFound = valuewhen(phFound, osc, lbRangeMinInput, lbRangeMaxInput, 1);
def plPrice = valuewhen(plFound, low, lbRangeMinInput, lbRangeMaxInput, 1);
def phPrice = valuewhen(phFound, high, lbRangeMinInput, lbRangeMaxInput, 1);
#// Regular Bullish
def oscHL = osc > vlFound and _inRange(plFound[1],lbRangeMaxInput,lbRangeMinInput);
def priceLL = low < plPrice;
def bullCond = DivergenceShowInput and plotBullInput and plFound and oscHL and priceLL;
#// Hidden Bullish
def oscLL = osc < vlFound and _inRange(plFound[1],lbRangeMaxInput,lbRangeMinInput);
def priceHL = low > plPrice;
def hiddenBullCond = DivergenceShowInput and plotHiddenBullInput and plFound and oscLL and priceHL;
#// Regular Bearish
def oscLH = osc < vhFound and _inRange(phFound[1],lbRangeMaxInput,lbRangeMinInput);
def priceHH = high > phPrice;
def bearCond = DivergenceShowInput and plotBearInput and phFound and oscLH and priceHH;
#// Hidden Bearish
def oscHH = osc > vhFound and _inRange(phFound[1],lbRangeMaxInput,lbRangeMinInput);
def priceLH = high < phPrice;
def hiddenBearCond = DivergenceShowInput and plotHiddenBearInput and phFound and oscHH and priceLH;
#------ Bubbles
addchartbubble(bullCond, osc, "R", color.GREEN, no);
addchartbubble(bearCond, osc, "R", Color.RED, yes);
addchartbubble(hiddenBullCond, osc, "H", color.DARK_green, no);
addchartbubble(hiddenBearCond, osc, "H", color.DARK_red, yes);
#--- Labels
AddLabel(rsiShowInput, "RSI Current: " + ROUND(rsi,2), if rsi<50 then Color.RED else Color.GREEN);
AddLabel(rsiShowInput, "RSI 15m: " + ROUND(rsi15,2), if rsi15<50 then Color.PINK else Color.LIGHT_GREEN);
AddLabel(rsiShowInput, "RSI 1h: " + ROUND(rsi1h,2), if rsi1h<50 then Color.PINK else Color.LIGHT_GREEN);
AddLabel(rsiShowInput, "RSI 4h: " + ROUND(rsi4h,2), if rsi4h<50 then Color.PINK else Color.LIGHT_GREEN);
AddLabel(rsiShowInput, "RSI 1d: " + ROUND(rsi1d,2), if rsi1d<50 then Color.PINK else Color.LIGHT_GREEN);
#--- END CODE