# https://www.tradingview.com/v/YcKrOcXe/
#// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
#// © HoanGhetti
# rsi types from @loxx - https://www.tradingview.com/v/iKTE0aCF/
#indicator("RSI Trendlines with Breakouts [HG]", precision = 2, max_labels_count = 500, max_lines_count = 500)
# Converted and mod by Sam4Cok@Samer800 - 07/2023 - Result may not be typical
declare lower;
input colorBreakoutBar = yes;
input useChartTimeframe = {default"Yes", "No"};
input manualTimeframe = AggregationPeriod.FIFTEEN_MIN;
input selectRSI = {default Regular, Slow, Rapid, Harris, "Ehlers Smoothed", RSX};
input LookbackRange = 4; # 'How many bars to determine when a swing high/low is detected.'
input repaint = yes;
input rsiSource = close;
input rsiLength = 14;
input overbought = 70;
input oversold = 30;
input rsiDifference = 3; # 'The difference between the current RSI value and the breakout value'
input ShowBrakouts = yes;
input alerts = yes;
input alertType = Alert.BAR;
input sound = Sound.NoSound;
#-- MTF
def c; def h; def l;
Switch (useChartTimeframe) {
case "Yes" :
c = rsiSource;
h = high;
l = low;
case "No" :
c = close(Period=manualTimeframe);
h = high(Period=manualTimeframe);
l = low(Period=manualTimeframe);
}
# //Regular RSI, same as ta.rsi(src, per)
script rsi_rsi {
input src = close;
input per = 14;
def alpha = 1.0 / Max(per, 1);
def change = src - src[1];
def _change = _change[1] + alpha * (change - _change[1]);
def _changa = _changa[1] + alpha * (AbsValue(change) - _changa[1]);
def out = if _changa != 0 then 50 * (_change / _changa + 1) else 50;
plot rsi_rsi = out;
}
#// rsx RSI
script rsi_rsx {
input src = close;
input len = 14;
def nRSI = RSI(Price = src, Length = len);
def src_out = 100 * src;
def mom0 = (src_out - src_out[1]);
def moa0 = AbsValue(mom0);
def Kg = 3 / (len + 2.0);
def Hg = 1 - Kg;
def f28 = CompoundValue(1, Kg * mom0 + Hg * f28[1], nRSI);
def f30 = CompoundValue(1, Hg * f30[1] + Kg * f28, nRSI);
def mom1 = f28 * 1.5 - f30 * 0.5;
def f38 = CompoundValue(1, Hg * f38[1] + Kg * mom1, nRSI);
def f40 = CompoundValue(1, Kg * f38 + Hg * f40[1], nRSI);
def mom2 = f38 * 1.5 - f40 * 0.5;
def f48 = CompoundValue(1, Hg * f48[1] + Kg * mom2, nRSI);
def f50 = CompoundValue(1, Kg * f48 + Hg * f50[1], nRSI);
def mom_out = f48 * 1.5 - f50 * 0.5;
def f58 = CompoundValue(1, Hg * f58[1] + Kg * moa0, nRSI);
def f60 = CompoundValue(1, Kg * f58 + Hg * f60[1], nRSI);
def moa1 = f58 * 1.5 - f60 * 0.5;
def f68 = CompoundValue(1, Hg * f68[1] + Kg * moa1, nRSI);
def f70 = CompoundValue(1, Kg * f68 + Hg * f70[1], nRSI);
def moa2 = f68 * 1.5 - f70 * 0.5;
def f78 = CompoundValue(1, Hg * f78[1] + Kg * moa2, nRSI);
def f80 = CompoundValue(1, Kg * f78 + Hg * f80[1], nRSI);
def moa_out = f78 * 1.5 - f80 * 0.5;
def rsiout = Max(Min((mom_out / moa_out + 1.0) * 50.0, 100), 0);
plot rsx = rsiout;
}
#// Slow RSI
script rsi_slo {
input src = close;
input per = 14;
def _rsival;
def nRSI = RSI(Price = src, Length = per);
def up = fold k = 0 to per with p do
if (src[k] - GetValue(src, k + 1)) > 0 then p + (src[k] - GetValue(src, k + 1)) else p;
def dn = fold i = 0 to per with q do
if (src[i] - GetValue(src, i + 1)) > 0 then q else q - (src[i] - GetValue(src, i + 1));
if (up + dn == 0) {
_rsival = CompoundValue(1, _rsival[1] + (1 / Max(per, 1)) * (50 - _rsival[1]), nRSI);
} else {
_rsival = CompoundValue(1, _rsival[1] + (1 / Max(per, 1)) * (100 * up / (up + dn) - _rsival[1]), nRSI);
}
plot out = _rsival;
}
#// Rapid RSI, same as Cuttlers RSI
script rsi_rap {
input src = close;
input per = 14;
def up = fold k = 0 to per with p do
if (src[k] - GetValue(src, k + 1)) > 0 then p + (src[k] - GetValue(src, k + 1)) else p;
def dn = fold i = 0 to per with q do
if (src[i] - GetValue(src, i + 1)) > 0 then q else q - (src[i] - GetValue(src, i + 1));
def out = if (up + dn) == 0 then 50 else 100 * up / (up + dn);
plot rsi_rap = out;
}
#// Harris RSI
script rsi_har {
input src = close;
input per = 14;
def avUp = fold k = 0 to per with p do
if (src[k] - GetValue(src, k + 1)) > 0 then p + (src[k] - GetValue(src, k + 1)) else p;
def avDn = fold i = 0 to per with q do
if (src[i] - GetValue(src, i + 1)) > 0 then q else q - (src[i] - GetValue(src, i + 1));
def Up = fold k1 = 0 to per with p1 do
if (src[k1] - GetValue(src, k1 + 1)) > 0 then p1 + 1 else p1;
def Dn = fold i1 = 0 to per with q1 do
if (src[i1] - GetValue(src, i1 + 1)) > 0 then q1 else q1 + 1;
def avgUp = if (Up != 0) then avUp / Up else avgUp[1];
def avgDn = if (Dn != 0) then avDn / Dn else avgDn[1];
def rs = if rs[1] == 0 then 1 else
if avgDn != 0 then avgUp / avgDn else rs[1];
def out = 100 - 100 / (1.0 + rs);
plot rsi_har = out;
}
# //Ehlers' Smoothed RSI
script rsi_ehl {
input src = close;
input per = 14;
def bar_index = if IsNaN(close) then bar_index[1] else bar_index[1] + 1;
def _src = if (bar_index > 2) then (src + 2 * src[1] + src[2]) / 4.0 else src;
def Up = fold k = 0 to per with p do
if (_src[k] - GetValue(_src, k + 1)) > 0 then p + (_src[k] - GetValue(_src, k + 1)) else p;
def Dn = fold i = 0 to per with q do
if (_src[i] - GetValue(_src, i + 1)) > 0 then q else q - (_src[i] - GetValue(_src, i + 1));
def out = 50 * (Up - Dn) / (Up + Dn) + 50;
plot rsi_ehl = out;
}
def Regular = rsi_rsi(c, rsiLength);
def Slow = rsi_slo(c, rsiLength);
def Rapid = rsi_rap(c, rsiLength);
def Harris = rsi_har(c, rsiLength);
def Ehlers = rsi_ehl(c, rsiLength);
def RSX = rsi_rsx(c, rsiLength);
def nRSI;
switch (selectRSI) {
case Regular :
nRSI = Regular;
case Slow :
nRSI = Slow;
case Rapid :
nRSI = Rapid;
case Harris :
nRSI = Harris;
case "Ehlers Smoothed" :
nRSI = Ehlers;
case RSX :
nRSI = RSX;
}
plot rsiLine = nRSI;
rsiLine.SetLineWeight(2);
rsiLine.SetDefaultColor(Color.WHITE);
def na = Double.NaN;
def last = IsNaN(close);
def pos = Double.POSITIVE_INFINITY;
def neg = Double.NEGATIVE_INFINITY;
plot OB = if last then na else overbought; # 'OVERBOUGHT'
plot OS = if last then na else oversold; # 'OVERSOLD'
plot midLine = if last then na else 50; # "Middle Line"
midLine.SetStyle(Curve.SHORT_DASH);
midLine.SetDefaultColor(Color.DARK_GRAY);
ob.SetDefaultColor(Color.DARK_GRAY);
os.SetDefaultColor(Color.DARK_GRAY);
AddCloud(OB, OS, CreateColor(76,10,127));
#----------------------------
#//----
script fixnan {
input source = close;
def fix = if !IsNaN(source) then source else fix[1];
plot result = fix;
}
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 = 1; # 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 = CompoundValue(1, BarNumber(), 0);
_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;
}
def ph = fixnan(findpivots(nRSI, 1, 1, LookbackRange));
def pl = fixnan(findpivots(nRSI, -1, 1, LookbackRange));
script pivot {
input rsi = close;
input LookbackPeriod = 4;
input pType = 1;
input ph = close;
input pl = close;
input rsiDiff = 3;
input repaint = yes;
def na = Double.NaN;
def bar_index = CompoundValue(1, BarNumber(), 0);
def pvtL = pType < 0;
def pivot = if pvtL then pl else ph;
def change = pivot != pivot[1];
def xAxis0 = if change then bar_index else xAxis0[1];
def xAxis1 = if xAxis0 != xAxis0[1] then xAxis0[1] else xAxis1[1];
def xAxis = xAxis0 - xAxis1;
def prevPivot0 = if change then pivot[1] else prevPivot0[1];
def prevPivot = if prevPivot0 != prevPivot0[1] then prevPivot0[1] else prevPivot[1];
def pivotCond = change and (if pvtL then pivot > prevPivot else pivot < prevPivot);
def slopePre;
def validElements;
def y1;
def y2;
def Slope;
if pivotCond {
slopePre = (pivot - prevPivot) / xAxis;
validElements = fold i = 0 to LookbackPeriod with p=1 while p do
if pvtL then GetValue(rsi, LookbackPeriod - i) >= (pivot + (slopePre * i))
else GetValue(rsi, LookbackPeriod - i) <= (pivot + (slopePre * i));
if validElements {
y1 = prevPivot;
y2 = pivot;
Slope = (y2 - y1) / xAxis;
} else {
y1 = y1[1];
y2 = y2[1];
Slope = Slope[1];
}
} else {
slopePre = na;#slope[1];
validElements = na;#validElements[1];
y1 = y1[1];
y2 = y2[1];
Slope = Slope[1];
}
def y1Change = (y1 != y1[1]);
def changeInX = if y1Change then 0 else changeInX[1] + 1;
def trendLine;
def label;
def Crossed;
def hasCrossed;
if y1Change {
Crossed = no;
} else {
Crossed = hasCrossed[1];
}
def data = if !Crossed then y2 + (Slope * changeInX) else data[1];
def condType = (if pvtL then rsi < (data - rsiDiff) else rsi > (data + rsiDiff)) and !Crossed;
def condition = if repaint then condType else (condType and !IsNaN(close));
if condition {
hasCrossed = yes;
trendLine = y2;
label = yes;
} else {
hasCrossed = Crossed;
trendLine = data;
label = na;
}
plot pData = if trendLine == rsi or trendLine >= 100 or trendLine <= 0 or hasCrossed then na else trendLine;
plot breakout = if label then data else na;
}
def UpValue = pivot(nRSI, LookbackRange, 1, ph, pl, rsiDifference, repaint).pData;
def DnValue = pivot(nRSI, LookbackRange, -1, ph, pl, rsiDifference, repaint).pData;
def BreakUp = pivot(nRSI, LookbackRange, 1, ph, pl, rsiDifference, repaint).breakout;
def BreakDn = pivot(nRSI, LookbackRange, -1, ph, pl, rsiDifference, repaint).breakout;
def UpPH = UpValue;
def LoLH = DnValue;
def UpBreak = BreakUp;
def LoBreak = BreakDn;
#-------- Breakout Bubbles
AddChartBubble(ShowBrakouts and UpBreak, UpBreak, "Break", Color.CYAN, no);
AddChartBubble(ShowBrakouts and LoBreak, LoBreak, "Break", Color.MAGENTA, yes);
AssignPriceColor(if !colorBreakoutBar then Color.CURRENT else
if !IsNaN(UpBreak) then Color.CYAN else
if !IsNaN(LoBreak) then Color.MAGENTA else Color.CURRENT);
#//----
plot upperPH = UpPH;
upperPH.SetDefaultColor(Color.GREEN);
plot LowerLH = LoLH;
LowerLH.SetDefaultColor(Color.RED);
#---- Alerts
Alert(alerts and UpBreak, "Break Up!", alertType, sound);
Alert(alerts and LoBreak, "Break Down!", alertType, sound);
#----Div-----------
input MaxLookback = 60; # "Max of Lookback Range"
input DivBull = no; # "Plot Bullish"
input DivHiddenBull = no; # "Plot Hidden Bullish"
input DivBear = no; # "Plot Bearish"
input DivHiddenBear = no; # "Plot Hidden Bearish"
def divSrc = nRSI;
#_inRange(cond) =>
script _inRange {
input cond = yes;
input rangeUpper = 60;
input rangeLower = 5;
def bars = if cond then 0 else bars[1] + 1;
def inrange = (rangeLower <= bars) and (bars <= rangeUpper);
plot retrun = inRange;
}
def pld = findpivots(divSrc,-1, LookbackRange, LookbackRange);
def phd = findpivots(divSrc, 1, LookbackRange, LookbackRange);
def plFound = if !isNaN(pld) then 1 else 0;
def phFound = if !isNaN(phd) then 1 else 0;
def lFound = if plFound then divSrc else lFound[1];
def vlFound = if lFound!=lFound[1] then lFound[1] else vlFound[1];
def hFound = if phFound then divSrc else hFound[1];
def vhFound = if hFound!=hFound[1] then hFound[1] else vhFound[1];
def lPrice = if plFound then l else lPrice[1];
def plPrice = if lPrice!=lPrice[1] then lPrice[1] else plPrice[1];
def hPrice = if phFound then h else hPrice[1];
def phPrice = if hPrice!=hPrice[1] then hPrice[1] else phPrice[1];
#// Regular Bullish
def oscHL = divSrc > vlFound and _inRange(plFound[1],MaxLookback,LookbackRange);
def priceLL = l < plPrice;
def bullCond = DivBull and plFound and oscHL and priceLL;
#// Hidden Bullish
def oscLL = divSrc < vlFound and _inRange(plFound[1],MaxLookback,LookbackRange);
def priceHL = l > plPrice;
def hiddenBullCond = DivHiddenBull and plFound and oscLL and priceHL;
#// Regular Bearish
def oscLH = divSrc < vhFound and _inRange(phFound[1],MaxLookback,LookbackRange);
def priceHH = h > phPrice;
def bearCond = DivBear and phFound and oscLH and priceHH;
#// Hidden Bearish
def oscHH = divSrc > vhFound and _inRange(phFound[1],MaxLookback,LookbackRange);
def priceLH = h < phPrice;
def hiddenBearCond = DivHiddenBear and phFound and oscHH and priceLH;
#------ Bubbles
addchartbubble(bullCond, divSrc, "R", color.GREEN, no);
addchartbubble(bearCond, divSrc, "R", Color.RED, yes);
addchartbubble(hiddenBullCond, divSrc, "H", color.DARK_green, no);
addchartbubble(hiddenBearCond, divSrc, "H", color.DARK_red, yes);
#----End of Code