# Difference Between Two Zigzag High Pivot Points

#### british43

##### Member
VIP
I'm working on a script to find the different between two Zigzag high pivot points (would also like to do this for the low side also). Please see image. The bubble at "1" would green with the value of "93.74 and 43.01 (difference between previous high and current value of the Zigzag). If flip the scenario the bubble at "1" would red. Any help would be great.

This is the line of code I think I'm messing up.

def ATRSave = if !IsNaN(ZZ) then SMI1 else GetValue(ATRSave, 1);
def ATRchg = round(SMI1 - GetValue(ATRSave, 1));
plot ATRisUp = ATRchg >= 0;
ATRisUp.Hide();
def ATRisDown = ATRchg <= 0;
def isConf = AbsValue(ATRchg) >= reversalAmount or (IsNaN(getValue(ZZ, 1)) and getValue(isConf, 1));

plot ATRDiff= ATRchg;
ATRDiff.hide();

AddChartBubble(1, ZZ, SMI1+" "+ATRchg, if ATRisUp then Color.GREEN else if ATRisDown then Color.RED else Color.RED, ATRisUp);
[/CODE]

Ruby:
declare lower;

input length = 14;
input averageType1 = AverageType.WILDERS;

input KPeriod = 8;
input n3 = 5;
input priceHl = high;
input priceLl = low;
input priceCl = close;
input slowing_period = 3;
input averageType = AverageType.SIMPLE;
input showBreakoutSignals = {default "No", "On FullK", "On FullD", "On FullK & FullD"};
input showlabels = yes;

def lowest_k = Lowest(priceLl, KPeriod);
def c1 = priceCl - lowest_k;
def c2 = Highest(priceHl, KPeriod) - lowest_k;
def FastK = if c2 != 0 then c1 / c2 * 100 else 0;

plot SMI1 = round(MovingAverage(averageType, FastK, slowing_period));

def o = open;
def h = high;
def l = low;
def c = close;
def priceH = SMI1;
def priceL = SMI1;
def priceC = SMI1;

input percentageReversal = 5.0;
input absoluteReversal = 0.0;
input atrLength = 5;
input atrReversal = 1;
input tickReversal = 0;

Assert(percentageReversal >= 0, "'percentage reversal' must not be negative: " + percentageReversal);
Assert(absoluteReversal >= 0, "'absolute reversal' must not be negative: " + absoluteReversal);
Assert(atrReversal >= 0, "'atr reversal' must not be negative: " + atrReversal);
Assert(tickReversal >= 0, "'ticks' must not be negative: " + tickReversal);
Assert(percentageReversal != 0 or absoluteReversal != 0 or atrReversal != 0 or tickReversal != 0, "Either 'percentage reversal' or 'absolute reversal' or 'atr reversal' or 'tick reversal' must not be zero");

def absReversal;
if (absoluteReversal != 0) {
absReversal = absoluteReversal;
} else {
absReversal =  tickReversal * TickSize();
}

def hlPivot;
if (atrReversal != 0) {
hlPivot = percentageReversal / 100 + WildersAverage(TrueRange(SMI1, SMI1, SMI1), atrLength) / SMI1 * atrReversal;
} else {
hlPivot = percentageReversal / 100;
}
def state = {default init, undefined, uptrend, downtrend};
def maxPriceH;
def minPriceL;
def newMax;
def newMin;
def prevMaxH = GetValue(maxPriceH, 1);
def prevMinL = GetValue(minPriceL, 1);

if GetValue(state, 1) == GetValue(state.init, 0) {
maxPriceH = priceH;
minPriceL = priceL;
newMax = yes;
newMin = yes;
state = state.undefined;
} else if GetValue(state, 1) == GetValue(state.undefined, 0) {
if priceH >= prevMaxH {
state = state.uptrend;
maxPriceH = priceH;
minPriceL = prevMinL;
newMax = yes;
newMin = no;
} else if priceL <= prevMinL {
state = state.downtrend;
maxPriceH = prevMaxH;
minPriceL = priceL;
newMax = no;
newMin = yes;
} else {
state = state.undefined;
maxPriceH = prevMaxH;
minPriceL = prevMinL;
newMax = no;
newMin = no;
}
} else if GetValue(state, 1) == GetValue(state.uptrend, 0) {
if priceL <= prevMaxH - prevMaxH * hlPivot - absReversal {
state = state.downtrend;
maxPriceH = prevMaxH;
minPriceL = priceL;
newMax = no;
newMin = yes;
} else {
state = state.uptrend;
if (priceH >= prevMaxH) {
maxPriceH = priceH;
newMax = yes;
} else {
maxPriceH = prevMaxH;
newMax = no;
}
minPriceL = prevMinL;
newMin = no;
}
} else {
if priceH >= prevMinL + prevMinL * hlPivot + absReversal {
state = state.uptrend;
maxPriceH = priceH;
minPriceL = prevMinL;
newMax = yes;
newMin = no;
} else {
state = state.downtrend;
maxPriceH = prevMaxH;
newMax = no;
if (priceL <= prevMinL) {
minPriceL = priceL;
newMin = yes;
} else {
minPriceL = prevMinL;
newMin = no;
}
}
}

def barNumber = BarNumber();
def barCount = HighestAll(If(IsNaN(priceH), 0, barNumber));
def newState = GetValue(state, 0) != GetValue(state, 1);
def offset = barCount - barNumber + 1;
def highPoint = state == state.uptrend and priceH == maxPriceH;
def lowPoint = state == state.downtrend and priceL == minPriceL;

def lastH;
if highPoint and offset > 1 {
lastH = fold iH = 1 to offset with tH = priceH while !IsNaN(tH) and !GetValue(newState, -iH) do if GetValue(newMax, -iH) or iH == offset - 1 and GetValue(priceH, -iH) == tH then Double.NaN else tH;
} else {
lastH = Double.NaN;
}

def lastL;
if lowPoint and offset > 1 {
lastL = fold iL = 1 to offset with tL = priceL while !IsNaN(tL) and !GetValue(newState, -iL) do if GetValue(newMin, -iL) or iL == offset - 1 and GetValue(priceL, -iL) == tL then Double.NaN else tL;
} else {
lastL = Double.NaN;
}

plot ZZ;
if barNumber == 1 {
ZZ = fold iF = 1 to offset with tP = Double.NaN while IsNaN(tP) do if GetValue(state, -iF) == GetValue(state.uptrend, 0) then priceL else if GetValue(state, -iF) == GetValue(state.downtrend, 0) then priceH else Double.NaN;
} else if barNumber == barCount {
ZZ = if highPoint or state == state.downtrend and priceL > minPriceL then priceH else if lowPoint or state == state.uptrend and priceH < maxPriceH then priceL else Double.NaN;
} else {
ZZ = if !IsNaN(lastH) then lastH else if !IsNaN(lastL) then lastL else Double.NaN;
}
ZZ.SetDefaultColor(GetColor(1));
ZZ.EnableApproximation();

#ZZ.hide();

def bar = BarNumber();

input n = 10;
def CurrMACDh = if SMI1 > 0
then fold i = 1 to n + 1
with p = 1
while p
do SMI1 > GetValue(SMI1, -i)
else 0;
def CurrMACDPivotH = if (bar > n and
SMI1 == Highest(SMI1, n) and
CurrMACDh)
then SMI1
else Double.NaN;
def CurrMACDl = if SMI1 > 0
then fold j = 1 to n + 1
with q = 1
while q
do SMI1 < GetValue(SMI1, -j)
else 0;
def CurrMACDPivotL = if (bar > n and
SMI1 == Lowest(SMI1, n) and
CurrMACDl)
then SMI1
else Double.NaN;
def CurrPHBar = if !IsNaN(CurrMACDPivotH)
then bar
else CurrPHBar[1];
def CurrPLBar = if !IsNaN(CurrMACDPivotL)
then bar
else CurrPLBar[1];
def PHpoint = if !IsNaN(CurrMACDPivotH)
then CurrMACDPivotH
else PHpoint[1];
def priorPHBar = if PHpoint != PHpoint[1]
then CurrPHBar[1]
else priorPHBar[1];
def PLpoint = if !IsNaN(CurrMACDPivotL)
then CurrMACDPivotL
else PLpoint[1];
def priorPLBar = if PLpoint != PLpoint[1]
then CurrPLBar[1]
else priorPLBar[1];
def HighPivots = bar >= HighestAll(priorPHBar);
def LowPivots = bar >= HighestAll(priorPLBar);
def pivotHigh = if HighPivots
then CurrMACDPivotH
else Double.NaN;
plot PlotHline = pivotHigh;
PlotHline.EnableApproximation();
PlotHline.SetDefaultColor(GetColor(7));
PlotHline.SetStyle(Curve.SHORT_DASH);
plot pivotLow = if LowPivots
then CurrMACDPivotL
else Double.NaN;
pivotLow.EnableApproximation();
pivotLow.SetDefaultColor(GetColor(7));
pivotLow.SetStyle(Curve.SHORT_DASH);
plot PivotDot = if !IsNaN(pivotHigh)
then pivotHigh
else if !IsNaN(pivotLow)
then pivotLow
else Double.NaN;
PivotDot.SetDefaultColor(GetColor(7));
PivotDot.SetPaintingStrategy(PaintingStrategy.POINTS);
PivotDot.SetLineWeight(3);

input reversalamount =8.0;

[B]def ATRSave = if  !IsNaN(ZZ) then SMI1 else GetValue(ATRSave, 1);
def ATRchg = round(SMI1 - GetValue(ATRSave, 1));
plot ATRisUp = ATRchg >= 0;
ATRisUp.Hide();
def ATRisDown = ATRchg <= 0;
def isConf = AbsValue(ATRchg) >= reversalAmount or (IsNaN(getValue(ZZ, 1)) and getValue(isConf, 1));

plot ATRDiff= ATRchg;
ATRDiff.hide();

AddChartBubble(1, ZZ, SMI1+" "+ATRchg, if ATRisUp then Color.GREEN else if ATRisDown then Color.RED else Color.RED, ATRisUp);
[/B]

Last edited by a moderator:
I'm working on a script to find the different between two Zigzag high pivot points (would also like to do this for the low side also). Please see image. The bubble at "1" would green with the value of "93.74 and 43.01 (difference between previous high and current value of the Zigzag). If flip the scenario the bubble at "1" would red. Any help would be great.

This is the line of code I think I'm messing up.

def ATRSave = if !IsNaN(ZZ) then SMI1 else GetValue(ATRSave, 1);
def ATRchg = round(SMI1 - GetValue(ATRSave, 1));
plot ATRisUp = ATRchg >= 0;
ATRisUp.Hide();
def ATRisDown = ATRchg <= 0;
def isConf = AbsValue(ATRchg) >= reversalAmount or (IsNaN(getValue(ZZ, 1)) and getValue(isConf, 1));

plot ATRDiff= ATRchg;
ATRDiff.hide();

AddChartBubble(1, ZZ, SMI1+" "+ATRchg, if ATRisUp then Color.GREEN else if ATRisDown then Color.RED else Color.RED, ATRisUp);
[/CODE]

Added a bubble on the top/bottom of the current green/red bubbles that has the difference between the high/previous high and low/previous low. Astext() was used to present uniform looking rounded 2 digit numbers in the bubbles.

This is the area of the code where these changes were based upon. Not all of these were needed, but shows how you can capture past data.
#---------------------------------------------------------------------------------------------------------------------------------
def ATRSave = if !IsNaN(ZZ) then SMI1 else GetValue(ATRSave, 1);
def ATRSave1 = if ATRSave != ATRSave[1] then ATRSave[1] else GetValue(ATRSave1, 1);
def ATRSave2 = if ATRSave1 != ATRSave1[1] then ATRSave1[1] else GetValue(ATRSave2, 1);
def ATRSave3 = if ATRSave2 != ATRSave2[1] then ATRSave2[1] else GetValue(ATRSave3, 1);
#---------------------------------------------------------------------------------------------------------------------------------

Ruby:
declare lower;

input length = 14;
input averageType1 = AverageType.WILDERS;

input KPeriod = 8;
input n3 = 5;
input priceHl = high;
input priceLl = low;
input priceCl = close;
input slowing_period = 3;
input averageType = AverageType.SIMPLE;
input showBreakoutSignals = {default "No", "On FullK", "On FullD", "On FullK & FullD"};
input showlabels = yes;

def lowest_k = Lowest(priceLl, KPeriod);
def c1 = priceCl - lowest_k;
def c2 = Highest(priceHl, KPeriod) - lowest_k;
def FastK = if c2 != 0 then c1 / c2 * 100 else 0;

plot SMI1 = Round(MovingAverage(averageType, FastK, slowing_period));

def o = open;
def h = high;
def l = low;
def c = close;
def priceH = SMI1;
def priceL = SMI1;
def priceC = SMI1;

input percentageReversal = 5.0;
input absoluteReversal = 0.0;
input atrLength = 5;
input atrReversal = 1;
input tickReversal = 0;

Assert(percentageReversal >= 0, "'percentage reversal' must not be negative: " + percentageReversal);
Assert(absoluteReversal >= 0, "'absolute reversal' must not be negative: " + absoluteReversal);
Assert(atrReversal >= 0, "'atr reversal' must not be negative: " + atrReversal);
Assert(tickReversal >= 0, "'ticks' must not be negative: " + tickReversal);
Assert(percentageReversal != 0 or absoluteReversal != 0 or atrReversal != 0 or tickReversal != 0, "Either 'percentage reversal' or 'absolute reversal' or 'atr reversal' or 'tick reversal' must not be zero");

def absReversal;
if (absoluteReversal != 0) {
absReversal = absoluteReversal;
} else {
absReversal =  tickReversal * TickSize();
}

def hlPivot;
if (atrReversal != 0) {
hlPivot = percentageReversal / 100 + WildersAverage(TrueRange(SMI1, SMI1, SMI1), atrLength) / SMI1 * atrReversal;
} else {
hlPivot = percentageReversal / 100;
}
def state = {default init, undefined, uptrend, downtrend};
def maxPriceH;
def minPriceL;
def newMax;
def newMin;
def prevMaxH = GetValue(maxPriceH, 1);
def prevMinL = GetValue(minPriceL, 1);

if GetValue(state, 1) == GetValue(state.init, 0) {
maxPriceH = priceH;
minPriceL = priceL;
newMax = yes;
newMin = yes;
state = state.undefined;
} else if GetValue(state, 1) == GetValue(state.undefined, 0) {
if priceH >= prevMaxH {
state = state.uptrend;
maxPriceH = priceH;
minPriceL = prevMinL;
newMax = yes;
newMin = no;
} else if priceL <= prevMinL {
state = state.downtrend;
maxPriceH = prevMaxH;
minPriceL = priceL;
newMax = no;
newMin = yes;
} else {
state = state.undefined;
maxPriceH = prevMaxH;
minPriceL = prevMinL;
newMax = no;
newMin = no;
}
} else if GetValue(state, 1) == GetValue(state.uptrend, 0) {
if priceL <= prevMaxH - prevMaxH * hlPivot - absReversal {
state = state.downtrend;
maxPriceH = prevMaxH;
minPriceL = priceL;
newMax = no;
newMin = yes;
} else {
state = state.uptrend;
if (priceH >= prevMaxH) {
maxPriceH = priceH;
newMax = yes;
} else {
maxPriceH = prevMaxH;
newMax = no;
}
minPriceL = prevMinL;
newMin = no;
}
} else {
if priceH >= prevMinL + prevMinL * hlPivot + absReversal {
state = state.uptrend;
maxPriceH = priceH;
minPriceL = prevMinL;
newMax = yes;
newMin = no;
} else {
state = state.downtrend;
maxPriceH = prevMaxH;
newMax = no;
if (priceL <= prevMinL) {
minPriceL = priceL;
newMin = yes;
} else {
minPriceL = prevMinL;
newMin = no;
}
}
}

def barNumber = BarNumber();
def barCount = HighestAll(If(IsNaN(priceH), 0, barNumber));
def newState = GetValue(state, 0) != GetValue(state, 1);
def offset = barCount - barNumber + 1;
def highPoint = state == state.uptrend and priceH == maxPriceH;
def lowPoint = state == state.downtrend and priceL == minPriceL;

def lastH;
if highPoint and offset > 1 {
lastH = fold iH = 1 to offset with tH = priceH while !IsNaN(tH) and !GetValue(newState, -iH) do if GetValue(newMax, -iH) or iH == offset - 1 and GetValue(priceH, -iH) == tH then Double.NaN else tH;
} else {
lastH = Double.NaN;
}

def lastL;
if lowPoint and offset > 1 {
lastL = fold iL = 1 to offset with tL = priceL while !IsNaN(tL) and !GetValue(newState, -iL) do if GetValue(newMin, -iL) or iL == offset - 1 and GetValue(priceL, -iL) == tL then Double.NaN else tL;
} else {
lastL = Double.NaN;
}

plot ZZ;
if barNumber == 1 {
ZZ = fold iF = 1 to offset with tP = Double.NaN while IsNaN(tP) do if GetValue(state, -iF) == GetValue(state.uptrend, 0) then priceL else if GetValue(state, -iF) == GetValue(state.downtrend, 0) then priceH else Double.NaN;
} else if barNumber == barCount {
ZZ = if highPoint or state == state.downtrend and priceL > minPriceL then priceH else if lowPoint or state == state.uptrend and priceH < maxPriceH then priceL else Double.NaN;
} else {
ZZ = if !IsNaN(lastH) then lastH else if !IsNaN(lastL) then lastL else Double.NaN;
}
ZZ.SetDefaultColor(GetColor(1));
ZZ.EnableApproximation();

#ZZ.hide();

def bar = BarNumber();

input n = 10;
def CurrMACDh = if SMI1 > 0
then fold i = 1 to n + 1
with p = 1
while p
do SMI1 > GetValue(SMI1, -i)
else 0;
def CurrMACDPivotH = if (bar > n and
SMI1 == Highest(SMI1, n) and
CurrMACDh)
then SMI1
else Double.NaN;
def CurrMACDl = if SMI1 > 0
then fold j = 1 to n + 1
with q = 1
while q
do SMI1 < GetValue(SMI1, -j)
else 0;
def CurrMACDPivotL = if (bar > n and
SMI1 == Lowest(SMI1, n) and
CurrMACDl)
then SMI1
else Double.NaN;
def CurrPHBar = if !IsNaN(CurrMACDPivotH)
then bar
else CurrPHBar[1];
def CurrPLBar = if !IsNaN(CurrMACDPivotL)
then bar
else CurrPLBar[1];
def PHpoint = if !IsNaN(CurrMACDPivotH)
then CurrMACDPivotH
else PHpoint[1];
def priorPHBar = if PHpoint != PHpoint[1]
then CurrPHBar[1]
else priorPHBar[1];
def PLpoint = if !IsNaN(CurrMACDPivotL)
then CurrMACDPivotL
else PLpoint[1];
def priorPLBar = if PLpoint != PLpoint[1]
then CurrPLBar[1]
else priorPLBar[1];
def HighPivots = bar >= HighestAll(priorPHBar);
def LowPivots = bar >= HighestAll(priorPLBar);
def pivotHigh = if HighPivots
then CurrMACDPivotH
else Double.NaN;
plot PlotHline = pivotHigh;
PlotHline.EnableApproximation();
PlotHline.SetDefaultColor(GetColor(7));
PlotHline.SetStyle(Curve.SHORT_DASH);
plot pivotLow = if LowPivots
then CurrMACDPivotL
else Double.NaN;
pivotLow.EnableApproximation();
pivotLow.SetDefaultColor(GetColor(7));
pivotLow.SetStyle(Curve.SHORT_DASH);
plot PivotDot = if !IsNaN(pivotHigh)
then pivotHigh
else if !IsNaN(pivotLow)
then pivotLow
else Double.NaN;
PivotDot.SetDefaultColor(GetColor(7));
PivotDot.SetPaintingStrategy(PaintingStrategy.POINTS);
PivotDot.SetLineWeight(3);

input reversalamount = 8.0;
#---------------------------------------------------------------------------------------------------------------------------------
def ATRSave = if  !IsNaN(ZZ) then SMI1 else GetValue(ATRSave, 1);
def ATRSave1 = if  ATRSave != ATRSave[1] then ATRSave[1] else GetValue(ATRSave1, 1);
def ATRSave2 = if  ATRSave1 != ATRSave1[1] then ATRSave1[1] else GetValue(ATRSave2, 1);
def ATRSave3 = if  ATRSave2 != ATRSave2[1] then ATRSave2[1] else GetValue(ATRSave3, 1);
#---------------------------------------------------------------------------------------------------------------------------------
def ATRchg = Round(SMI1 - GetValue(ATRSave, 1));
plot ATRisUp = ATRchg >= 0;
ATRisUp.Hide();
def ATRisDown = ATRchg <= 0;
def isConf = AbsValue(ATRchg) >= reversalamount or (IsNaN(GetValue(ZZ, 1)) and GetValue(isConf, 1));

plot ATRDiff = ATRchg;
ATRDiff.Hide();

AddChartBubble(1, ZZ, astext(SMI1) + " " + astext(ATRchg), if ATRisUp then Color.GREEN else if ATRisDown then Color.RED else Color.RED, ATRisUp);
AddChartBubble(1, ZZ, astext(ATRSave - atrsave2), if ATRisUp then Color.GREEN else if ATRisDown then Color.RED else Color.RED, ATRisUp);

@SleepyZ I have another questions: How would I go about flipping the bubble direction (i.e. top for high pivot and bottom for low pivot)?

@SleepyZ I have another questions: How would I go about flipping the bubble direction (i.e. top for high pivot and bottom for low pivot)?
How is that different than in the chart image I posted above. Otherwise, see if this is what you mean

Ruby:
AddChartBubble(1, ZZ, astext(ATRSave - atrsave2), if ATRisUp then Color.GREEN else if ATRisDown then Color.RED else Color.RED, ATRisUp);

AddChartBubble(1, ZZ, astext(SMI1) + " " + astext(ATRchg), if ATRisUp then Color.GREEN else if ATRisDown then Color.RED else Color.RED, ATRisUp);

@SleepyZ How can I change the bubble values to HH, HL, LL, LH? I've been trying but failed. Thanks.

@SleepyZ How can I change the bubble values to HH, HL, LL, LH? I've been trying but failed. Thanks.
The following has options to display, for the now 3 types of bubbles.

Ruby:
declare lower;

input length = 14;
input averageType1 = AverageType.WILDERS;

input KPeriod = 8;
input n3 = 5;
input priceHl = high;
input priceLl = low;
input priceCl = close;
input slowing_period = 3;
input averageType = AverageType.SIMPLE;
input showBreakoutSignals = {default "No", "On FullK", "On FullD", "On FullK & FullD"};
input showlabels = yes;

def lowest_k = Lowest(priceLl, KPeriod);
def c1 = priceCl - lowest_k;
def c2 = Highest(priceHl, KPeriod) - lowest_k;
def FastK = if c2 != 0 then c1 / c2 * 100 else 0;

plot SMI1 = Round(MovingAverage(averageType, FastK, slowing_period));

def o = open;
def h = high;
def l = low;
def c = close;
def priceH = SMI1;
def priceL = SMI1;
def priceC = SMI1;

input percentageReversal = 5.0;
input absoluteReversal = 0.0;
input atrLength = 5;
input atrReversal = 1;
input tickReversal = 0;

Assert(percentageReversal >= 0, "'percentage reversal' must not be negative: " + percentageReversal);
Assert(absoluteReversal >= 0, "'absolute reversal' must not be negative: " + absoluteReversal);
Assert(atrReversal >= 0, "'atr reversal' must not be negative: " + atrReversal);
Assert(tickReversal >= 0, "'ticks' must not be negative: " + tickReversal);
Assert(percentageReversal != 0 or absoluteReversal != 0 or atrReversal != 0 or tickReversal != 0, "Either 'percentage reversal' or 'absolute reversal' or 'atr reversal' or 'tick reversal' must not be zero");

def absReversal;
if (absoluteReversal != 0) {
absReversal = absoluteReversal;
} else {
absReversal =  tickReversal * TickSize();
}

def hlPivot;
if (atrReversal != 0) {
hlPivot = percentageReversal / 100 + WildersAverage(TrueRange(SMI1, SMI1, SMI1), atrLength) / SMI1 * atrReversal;
} else {
hlPivot = percentageReversal / 100;
}
def state = {default init, undefined, uptrend, downtrend};
def maxPriceH;
def minPriceL;
def newMax;
def newMin;
def prevMaxH = GetValue(maxPriceH, 1);
def prevMinL = GetValue(minPriceL, 1);

if GetValue(state, 1) == GetValue(state.init, 0) {
maxPriceH = priceH;
minPriceL = priceL;
newMax = yes;
newMin = yes;
state = state.undefined;
} else if GetValue(state, 1) == GetValue(state.undefined, 0) {
if priceH >= prevMaxH {
state = state.uptrend;
maxPriceH = priceH;
minPriceL = prevMinL;
newMax = yes;
newMin = no;
} else if priceL <= prevMinL {
state = state.downtrend;
maxPriceH = prevMaxH;
minPriceL = priceL;
newMax = no;
newMin = yes;
} else {
state = state.undefined;
maxPriceH = prevMaxH;
minPriceL = prevMinL;
newMax = no;
newMin = no;
}
} else if GetValue(state, 1) == GetValue(state.uptrend, 0) {
if priceL <= prevMaxH - prevMaxH * hlPivot - absReversal {
state = state.downtrend;
maxPriceH = prevMaxH;
minPriceL = priceL;
newMax = no;
newMin = yes;
} else {
state = state.uptrend;
if (priceH >= prevMaxH) {
maxPriceH = priceH;
newMax = yes;
} else {
maxPriceH = prevMaxH;
newMax = no;
}
minPriceL = prevMinL;
newMin = no;
}
} else {
if priceH >= prevMinL + prevMinL * hlPivot + absReversal {
state = state.uptrend;
maxPriceH = priceH;
minPriceL = prevMinL;
newMax = yes;
newMin = no;
} else {
state = state.downtrend;
maxPriceH = prevMaxH;
newMax = no;
if (priceL <= prevMinL) {
minPriceL = priceL;
newMin = yes;
} else {
minPriceL = prevMinL;
newMin = no;
}
}
}

def barNumber = BarNumber();
def barCount = HighestAll(If(IsNaN(priceH), 0, barNumber));
def newState = GetValue(state, 0) != GetValue(state, 1);
def offset = barCount - barNumber + 1;
def highPoint = state == state.uptrend and priceH == maxPriceH;
def lowPoint = state == state.downtrend and priceL == minPriceL;

def lastH;
if highPoint and offset > 1 {
lastH = fold iH = 1 to offset with tH = priceH while !IsNaN(tH) and !GetValue(newState, -iH) do if GetValue(newMax, -iH) or iH == offset - 1 and GetValue(priceH, -iH) == tH then Double.NaN else tH;
} else {
lastH = Double.NaN;
}

def lastL;
if lowPoint and offset > 1 {
lastL = fold iL = 1 to offset with tL = priceL while !IsNaN(tL) and !GetValue(newState, -iL) do if GetValue(newMin, -iL) or iL == offset - 1 and GetValue(priceL, -iL) == tL then Double.NaN else tL;
} else {
lastL = Double.NaN;
}

plot ZZ;
if barNumber == 1 {
ZZ = fold iF = 1 to offset with tP = Double.NaN while IsNaN(tP) do if GetValue(state, -iF) == GetValue(state.uptrend, 0) then priceL else if GetValue(state, -iF) == GetValue(state.downtrend, 0) then priceH else Double.NaN;
} else if barNumber == barCount {
ZZ = if highPoint or state == state.downtrend and priceL > minPriceL then priceH else if lowPoint or state == state.uptrend and priceH < maxPriceH then priceL else Double.NaN;
} else {
ZZ = if !IsNaN(lastH) then lastH else if !IsNaN(lastL) then lastL else Double.NaN;
}
ZZ.SetDefaultColor(GetColor(1));
ZZ.EnableApproximation();

#ZZ.hide();

def bar = BarNumber();

input n = 10;
def CurrMACDh = if SMI1 > 0
then fold i = 1 to n + 1
with p = 1
while p
do SMI1 > GetValue(SMI1, -i)
else 0;
def CurrMACDPivotH = if (bar > n and
SMI1 == Highest(SMI1, n) and
CurrMACDh)
then SMI1
else Double.NaN;
def CurrMACDl = if SMI1 > 0
then fold j = 1 to n + 1
with q = 1
while q
do SMI1 < GetValue(SMI1, -j)
else 0;
def CurrMACDPivotL = if (bar > n and
SMI1 == Lowest(SMI1, n) and
CurrMACDl)
then SMI1
else Double.NaN;
def CurrPHBar = if !IsNaN(CurrMACDPivotH)
then bar
else CurrPHBar[1];
def CurrPLBar = if !IsNaN(CurrMACDPivotL)
then bar
else CurrPLBar[1];
def PHpoint = if !IsNaN(CurrMACDPivotH)
then CurrMACDPivotH
else PHpoint[1];
def priorPHBar = if PHpoint != PHpoint[1]
then CurrPHBar[1]
else priorPHBar[1];
def PLpoint = if !IsNaN(CurrMACDPivotL)
then CurrMACDPivotL
else PLpoint[1];
def priorPLBar = if PLpoint != PLpoint[1]
then CurrPLBar[1]
else priorPLBar[1];
def HighPivots = bar >= HighestAll(priorPHBar);
def LowPivots = bar >= HighestAll(priorPLBar);
def pivotHigh = if HighPivots
then CurrMACDPivotH
else Double.NaN;
plot PlotHline = pivotHigh;
PlotHline.EnableApproximation();
PlotHline.SetDefaultColor(GetColor(7));
PlotHline.SetStyle(Curve.SHORT_DASH);
plot pivotLow = if LowPivots
then CurrMACDPivotL
else Double.NaN;
pivotLow.EnableApproximation();
pivotLow.SetDefaultColor(GetColor(7));
pivotLow.SetStyle(Curve.SHORT_DASH);
plot PivotDot = if !IsNaN(pivotHigh)
then pivotHigh
else if !IsNaN(pivotLow)
then pivotLow
else Double.NaN;
PivotDot.SetDefaultColor(GetColor(7));
PivotDot.SetPaintingStrategy(PaintingStrategy.POINTS);
PivotDot.SetLineWeight(3);

input reversalamount = 8.0;
#---------------------------------------------------------------------------------------------------------------------------------
def ATRSave = if  !IsNaN(ZZ) then SMI1 else GetValue(ATRSave, 1);
def ATRSave1 = if  ATRSave != ATRSave[1] then ATRSave[1] else GetValue(ATRSave1, 1);
def ATRSave2 = if  ATRSave1 != ATRSave1[1] then ATRSave1[1] else GetValue(ATRSave2, 1);
def ATRSave3 = if  ATRSave2 != ATRSave2[1] then ATRSave2[1] else GetValue(ATRSave3, 1);
#---------------------------------------------------------------------------------------------------------------------------------
def ATRchg = Round(SMI1 - GetValue(ATRSave, 1));
plot ATRisUp = ATRchg >= 0;
ATRisUp.Hide();
def ATRisDown = ATRchg <= 0;
def isConf = AbsValue(ATRchg) >= reversalamount or (IsNaN(GetValue(ZZ, 1)) and GetValue(isConf, 1));

plot ATRDiff = ATRchg;
ATRDiff.Hide();

#Bubbles and spacers--------------------------------------------------------------------------
input show_smi_atrchange_bubble = yes;
ZZ,
AsText(SMI1) + " " + AsText(ATRchg),
if ATRisUp then Color.GREEN
else if ATRisDown then Color.RED
else Color.RED, ATRisUp);

input show_atr_change_bubble = yes;
ZZ,
AsText(ATRSave - ATRSave2),
if ATRisUp then Color.GREEN
else if ATRisDown then Color.RED
else Color.WHITE, ATRisUp);

input showHH_HL_LH_LL_bubble = yes;
ZZ,
if ATRisUp and (ATRSave - ATRSave2) > 0
then "HH"
else if ATRisUp
then "LH"
else if ATRisDown and (ATRSave - ATRSave2) > 0
then "HL"
else if ATRisDown and (ATRSave - ATRSave2) < 0
then "LL"
else "",
if ATRisUp then Color.GREEN
else if ATRisDown then Color.RED
else Color.WHITE, ATRisUp);

This is great!!I wanted to do something like this but for RSI. Do you think something like this would be possible over RSI? I tried out a couple of things without success, but I didn't want to go too far down this path if it wasn't possible or if there is already a RSI ZigZag indicator (I wasn't able to find one on here or elsewhere online for for TOS).

This is great!!I wanted to do something like this but for RSI. Do you think something like this would be possible over RSI? I tried out a couple of things without success, but I didn't want to go too far down this path if it wasn't possible or if there is already a RSI ZigZag indicator (I wasn't able to find one on here or elsewhere online for for TOS).
I have one message eme back tomorrow ull send it your way

This is great!!I wanted to do something like this but for RSI. Do you think something like this would be possible over RSI? I tried out a couple of things without success, but I didn't want to go too far down this path if it wasn't possible or if there is already a RSI ZigZag indicator (I wasn't able to find one on here or elsewhere online for for TOS).
#Muathe: the moving average and its zig zag requested by Braum codede by zzz. cloud added by Paris. peak and valley added by Braum . The difference between Muathe rsi and regular rsi is the values of the ovb and ovs.and most important part of it is the line of 61.8. listen to him at youtube for the full explaination of this line. I changed the exp to wilders.
Ruby:
declare lower;

input length = 14;
input over_Bought = 69.10;
input over_Sold = 38.2;
input price = close;
input averageType = AverageType.WILDERS;

def NetChgAvg = MovingAverage(averageType, price - price[1], length);
def TotChgAvg = MovingAverage(averageType, AbsValue(price - price[1]), length);
def ChgRatio = if TotChgAvg != 0 then NetChgAvg / TotChgAvg else 0;

plot mid_point = 61.8;
plot RSI = 50 * (ChgRatio + 1);
RSI.DefineColor("OverBought", Color.RED); RSI.DefineColor("Normal", Color.gray); RSI.DefineColor("OverSold", Color.green); RSI.AssignValueColor(if RSI > over_Bought then RSI.Color("OverSOLD") else if RSI < over_Sold then RSI.Color("OverBOUGHT") else RSI.Color("normal"));
plot center_line = 50.10;

plot OverSold = over_Sold;
OverSold.SetDefaultColor(Color.green); OverSold.SetStyle(Curve.firm); OverSold.SetLineWeight(2);

plot OverBought = over_Bought; OverBought.SetDefaultColor(Color.red); OverBought.SetStyle(Curve.firm); OverBought.SetLineWeight(2);
RSI.DefineColor("OverBought", GetColor(5));
RSI.DefineColor("Normal", GetColor(7));
RSI.DefineColor("OverSold", GetColor(1));
RSI.AssignValueColor(if RSI > over_Bought then RSI.color("OverBought") else if RSI < over_Sold then RSI.color("OverSold") else RSI.color("Normal"));
OverSold.SetDefaultColor(GetColor(8));
OverBought.SetDefaultColor(GetColor(8));

input reversalAmount = 0.3;
input lengthzz = 1;
input avg = AverageType.EXPONENTIAL;
input rsiavglength = 3; #for 1M i use 9avg and for 5M use 5avg
def pricezz = average(rsi,rsiavglength);

def avgprice = MovingAverage(averagetype = avg, (pricezz), length);
Assert(reversalAmount > 0, "'reversal amount' should be positive: " + reversalAmount);
plot "ZZ\$" = reference ZigZagHighLow(avgprice, avgprice, 0, reversalAmount, 1, 0);
def zzSave = if !IsNaN("ZZ\$") then avgprice else GetValue(zzSave, 1);

def chg = avgprice - GetValue(zzSave, 1);
def isUp = if chg >= 0 then 1 else 0;
def isConf = AbsValue(chg) >= reversalAmount or (IsNaN(GetValue("ZZ\$", 1)) and GetValue(isConf, 1));
"ZZ\$".EnableApproximation();
"ZZ\$".AssignValueColor(if isUp then Color.green else Color.red);
AddCloud(if rsi >= over_Bought then rsi else Double.NaN, over_Bought, Color.green, Color.CURRENT);
AddCloud(over_Sold, if rsi <= over_Sold then rsi else Double.NaN, Color.red, Color.CURRENT);

AddChartBubble(!IsNaN("ZZ\$") and !isUp, "ZZ\$", "V", Color.GREEN, no);
AddChartBubble(!IsNaN("ZZ\$") and isUp, "ZZ\$", "P", Color.RED, yes);

Last edited by a moderator:
This is great! Thank you @germanburrito ! I really appreciate it.

@germanburrito I convert the study to RSI

Ruby:
declare lower;

plot Forecast = reference RSI;

def o = open;
def h = high;
def l = low;
def c = close;
def priceH = forecast;
def priceL = forecast;
def priceC = forecast;

input percentageReversal = 5.0;
input absoluteReversal = 0.0;
input atrLength = 5;
input atrReversal = 1;
input tickReversal = 0;

Assert(percentageReversal >= 0, "'percentage reversal' must not be negative: " + percentageReversal);
Assert(absoluteReversal >= 0, "'absolute reversal' must not be negative: " + absoluteReversal);
Assert(atrReversal >= 0, "'atr reversal' must not be negative: " + atrReversal);
Assert(tickReversal >= 0, "'ticks' must not be negative: " + tickReversal);
Assert(percentageReversal != 0 or absoluteReversal != 0 or atrReversal != 0 or tickReversal != 0, "Either 'percentage reversal' or 'absolute reversal' or 'atr reversal' or 'tick reversal' must not be zero");

def absReversal;
if (absoluteReversal != 0) {
absReversal = absoluteReversal;
} else {
absReversal =  tickReversal * TickSize();
}

def hlPivot;
if (atrReversal != 0) {
hlPivot = percentageReversal / 100 + WildersAverage(TrueRange(forecast, forecast, forecast), atrLength) / forecast * atrReversal;
} else {
hlPivot = percentageReversal / 100;
}
def state = {default init, undefined, uptrend, downtrend};
def maxPriceH;
def minPriceL;
def newMax;
def newMin;
def prevMaxH = GetValue(maxPriceH, 1);
def prevMinL = GetValue(minPriceL, 1);

if GetValue(state, 1) == GetValue(state.init, 0) {
maxPriceH = priceH;
minPriceL = priceL;
newMax = yes;
newMin = yes;
state = state.undefined;
} else if GetValue(state, 1) == GetValue(state.undefined, 0) {
if priceH >= prevMaxH {
state = state.uptrend;
maxPriceH = priceH;
minPriceL = prevMinL;
newMax = yes;
newMin = no;
} else if priceL <= prevMinL {
state = state.downtrend;
maxPriceH = prevMaxH;
minPriceL = priceL;
newMax = no;
newMin = yes;
} else {
state = state.undefined;
maxPriceH = prevMaxH;
minPriceL = prevMinL;
newMax = no;
newMin = no;
}
} else if GetValue(state, 1) == GetValue(state.uptrend, 0) {
if priceL <= prevMaxH - prevMaxH * hlPivot - absReversal {
state = state.downtrend;
maxPriceH = prevMaxH;
minPriceL = priceL;
newMax = no;
newMin = yes;
} else {
state = state.uptrend;
if (priceH >= prevMaxH) {
maxPriceH = priceH;
newMax = yes;
} else {
maxPriceH = prevMaxH;
newMax = no;
}
minPriceL = prevMinL;
newMin = no;
}
} else {
if priceH >= prevMinL + prevMinL * hlPivot + absReversal {
state = state.uptrend;
maxPriceH = priceH;
minPriceL = prevMinL;
newMax = yes;
newMin = no;
} else {
state = state.downtrend;
maxPriceH = prevMaxH;
newMax = no;
if (priceL <= prevMinL) {
minPriceL = priceL;
newMin = yes;
} else {
minPriceL = prevMinL;
newMin = no;
}
}
}

def barNumber = BarNumber();
def barCount = HighestAll(If(IsNaN(priceH), 0, barNumber));
def newState = GetValue(state, 0) != GetValue(state, 1);
def offset = barCount - barNumber + 1;
def highPoint = state == state.uptrend and priceH == maxPriceH;
def lowPoint = state == state.downtrend and priceL == minPriceL;

def lastH;
if highPoint and offset > 1 {
lastH = fold iH = 1 to offset with tH = priceH while !IsNaN(tH) and !GetValue(newState, -iH) do if GetValue(newMax, -iH) or iH == offset - 1 and GetValue(priceH, -iH) == tH then Double.NaN else tH;
} else {
lastH = Double.NaN;
}

def lastL;
if lowPoint and offset > 1 {
lastL = fold iL = 1 to offset with tL = priceL while !IsNaN(tL) and !GetValue(newState, -iL) do if GetValue(newMin, -iL) or iL == offset - 1 and GetValue(priceL, -iL) == tL then Double.NaN else tL;
} else {
lastL = Double.NaN;
}

plot ZZ;
if barNumber == 1 {
ZZ = fold iF = 1 to offset with tP = Double.NaN while IsNaN(tP) do if GetValue(state, -iF) == GetValue(state.uptrend, 0) then priceL else if GetValue(state, -iF) == GetValue(state.downtrend, 0) then priceH else Double.NaN;
} else if barNumber == barCount {
ZZ = if highPoint or state == state.downtrend and priceL > minPriceL then priceH else if lowPoint or state == state.uptrend and priceH < maxPriceH then priceL else Double.NaN;
} else {
ZZ = if !IsNaN(lastH) then lastH else if !IsNaN(lastL) then lastL else Double.NaN;
}
ZZ.SetDefaultColor(GetColor(1));
ZZ.EnableApproximation();

#ZZ.hide();

@SleepyZ The bubbles makes the chart really clutter is there is a way to the bubble SetPaintingStrategy(PaintingStrategy.VALUES_BELOW) or VALUES_ABOVE?

Last edited:
@SleepyZ The bubbles makes the chart really clutter is there is a way to the bubble SetPaintingStrategy(PaintingStrategy.VALUES_BELOW) or VALUES_ABOVE?

The values that would be plotted are numerical. So instead, red/green arrows may work better. Set the bubble inputs to 'NO" and add the following to the bottom of your script.

Ruby:
input showarrows = yes;
plot arrowh = if showarrows and highpoint then zz else double.nan;
arrowh.setpaintingStrategy(PaintingStrategy.ARROW_DOWN);
arrowh.assignValueColor(if ATRisUp and (ATRSave - ATRSave2) > 0 then color.green else color.red);
plot arrowl = if showarrows and lowpoint then zz else double.nan;
arrowl.setpaintingStrategy(PaintingStrategy.ARROW_up);
arrowl.assignValueColor(if ATRisDown and (ATRSave - ATRSave2) > 0 then color.green else color.red);

Last edited:
@SleepyZ I have been trying to script the image below. It is based off the feedback you provided in previous post. Any help is much appreciated.

The following has options to display, for the now 3 types of bubbles.
Hi! Is there away to have the bubbles show on the chart as an upper indicator?

Hi! Is there away to have the bubbles show on the chart as an upper indicator?
The easiest way is to just move the script to the upper panel and check left axis at the input screen. You can the uncheck the plots for any lines you do not want to appear.

Alternatively, you could uncheck (hide) all of the plots and add the following verticalline code to the bottom of the script. The colors of the lines have been reversed to more represent the potential future trend.

In the image is the verticalline option with the zz plot showing for clarity.

Ruby:
#Verticalline---------------------------------------------------------
input showverticalline = yes;
AddVerticalLine(showverticalline and ZZ, "                                                                                         " +
if ATRisUp and (ATRSave - ATRSave2) > 0
then "HH"
else if ATRisUp
then "LH"
else if ATRisDown and (ATRSave - ATRSave2) > 0
then "HL"
else if ATRisDown and (ATRSave - ATRSave2) < 0
then "LL"
else "",
if ATRisUp then Color.RED
else if ATRisDown
then Color.GREEN
else Color.WHITE,
Curve.FIRM);

The easiest way is to just move the script to the upper panel and check left axis at the input screen. You can the uncheck the plots for any lines you do not want to appear.

Alternatively, you could uncheck (hide) all of the plots and add the following verticalline code to the bottom of the script. The colors of the lines have been reversed to more represent the potential future trend.

In the image is the verticalline option with the zz plot showing for clarity.
Thanks @SleepyZ ! You always come through. How could I use this to scan for HL's or LH's?

87k+ Posts
295 Online

## The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
• Exclusive indicators
• Proven strategies & setups
• Private Discord community
• Exclusive members-only content
• 1 full year of unlimited support

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?