ZigZagHighLow with look back and look forward bars?

SubZer0

New member
Hello,
I'm currently using the inbuilt ZigZagHighLow indicator in ToS. It is designed to detect swing points using price change %. It works for some stocks but doesn't work for others. I am looking for any similar indicators that connect the swing high/low with trend lines and also support looking back n number of bars forward and backward. The closest i came across were these threads

https://usethinkscript.com/threads/...i-retracement-indicator-for-thinkorswim.8091/
https://usethinkscript.com/threads/improving-swing-high-low-indicator.10983/

I got it working (don't need the fib code) but am stuck at the point where i am trying to have the code automatically draw trend lines to connect the swing highs and swing lows to generate the market structure plot instead of the chart bubbles.

Appreciate any advise and pointers to achieve an indicator that is very close to the ZigZagHighLow indicator, draws the market structure plot and accepts lookback and lookforward of n number of bars.

Thanks!!
 
Last edited:
Solution
OK. Took me a bit of digging but i found the root cause. If ShowHorizontals is turned off, the %change value shows as N/A. Works fine when turning it back on. I can reproduce this on the charts and flexible grid you shared.

Looking at the code, RLo and RHi are set to NaN when horizontals are turned off. These values feed into downstream calculations for showing labels and also for the bubbles.

This fixes that problem by using sethiding(). Thank you.

Ruby:
def h = high;
def l = low;
def c = close;
def o = open;
def v = volume;

# Simple Fractal Recon
input length = 5;


def HH1 = h >= Highest(h, length) and h >= Highest(h, length)[-length];
def  High1 = if HH1 then h else Double.NaN;
def LL1 = l <= Lowest(l, length) and l <=...

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Good day sleepyz any way of just getting value insted of bubble?

Yes, but you can only have a dollar value or percent as both are needing a boolean, which only plots at one place, either high or low. So set either input show_values_dollars or input show_values_percents to NO.

Ruby:
def h = high;
def l = low;
def c = close;
def o = open;
def v = volume;

# Simple Fractal Recon
input length = 5;


def HH1 = h >= Highest(h, length) and h >= Highest(h, length)[-length];
def  High1 = if HH1 then h else Double.NaN;
def LL1 = l <= Lowest(l, length) and l <= Lowest(l, length)[-length];
def Low1 = if LL1 then l else Double.NaN;
def PointCount = if BarNumber() == 1 then 0 else
                 if IsNaN(c) then PointCount[1] else
                 if !IsNaN(High1) then Max(1, PointCount[1] + 1) else
                 if !IsNaN(Low1) then Min(-1, PointCount[1] - 1)
                 else PointCount[1];

input showhorizontals = no;
def RangeHI = if !IsNaN(High1) and PointCount == 1
then h else RangeHI[1];
plot Rhi = RangeHI;
Rhi.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Rhi.SetLineWeight(1);
Rhi.SetDefaultColor(Color.RED);
rhi.sethiding(!showhorizontals);

def RangeLO = if !IsNaN(Low1) and PointCount == -1
then l else RangeLO[1];
plot Rlo =  RangeLO;
Rlo.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Rlo.SetLineWeight(1);
Rlo.SetDefaultColor(Color.GREEN);
Rlo.sethiding(!showhorizontals);

#Harndog
input HHLLlabels = yes;

def rh1 = if !IsNaN(Rhi) then Rhi else rh1[1];
def rh2 = if rh1 != rh1[1] then rh1[1] else rh2[1];

AddLabel(HHLLlabels, if rh1 > rh2
              then "Higher Highs"
              else "Lower Highs",
              if rh1 > rh2
              then Color.GREEN
              else Color.RED);

def rl1 = if !IsNaN(Rlo) then Rlo else rl1[1];
def rl2 = if rl1 != rl1[1] then rl1[1] else rl2[1];
AddLabel(HHLLlabels, if  rl1 > rl2
              then "Higher Lows"
              else "Lower Lows",
              if rl1 > rl2
              then Color.GREEN
              else Color.RED);

#ZigZags
def zHI;
def zLO;

zHI = if !IsNaN(High1) and PointCount == 1 then h else Double.NaN;
zLO = if !IsNaN(Low1) and PointCount == -1 then l else Double.NaN;

def bn = BarNumber();
def lastzhi = if !IsNaN(zHI) then bn else lastzhi[1];
def lastzlo = if !IsNaN(zLO) then bn else lastzlo[1];


plot hilowline = if !IsNaN(zHI) then zHI else zLO;
hilowline.EnableApproximation();
hilowline.SetLineWeight(3);
hilowline.SetDefaultColor(Color.WHITE);

def last = if IsNaN(close[-1]) and !IsNaN(close) then BarNumber() else Double.NaN;
def lastbar   = if BarNumber() == HighestAll(last) then 1 else 0;
def lastvalue = if lastbar then close else Double.NaN;

plot hilowline1 = if bn < Max(lastzhi, lastzlo)
                  then Double.NaN
                  else if lastzlo > lastzhi and !IsNaN(zLO)
                  then zLO
                  else if lastzlo < lastzhi and !IsNaN(zHI)
                  then zHI else lastvalue;
hilowline1.EnableApproximation();
hilowline1.SetLineWeight(3);
hilowline1.SetDefaultColor(Color.WHITE);

def xxhigh  = if rh1 == high then high else xxhigh[1];
def xxlow   = if rl1 == low then low else xxlow[1];
def chghigh = (rh1 - xxlow[1]) / xxlow[1] * 100;
def chglow  = (rl1 - xxhigh[1]) / xxhigh[1] * 100;

input showbubbles = no;
AddChartBubble(showbubbles and !IsNaN(High1) and PointCount == 1, high, "H\n" + AsText(high) + " \n" +  Round(chghigh) + "%", if xxhigh > xxhigh[1] then Color.GREEN else Color.RED);
AddChartBubble(showbubbles and !IsNaN(Low1) and PointCount == -1, low, "L\n" + AsText(low) + " \n" +  Round(chglow) + "%", if xxlow > xxlow[1] then Color.GREEN else Color.RED, no);

input showvalues_dollars = yes;
plot hvalue = if showvalues_dollars and !IsNaN(High1) and PointCount == 1 then high else double.nan;
hvalue.setpaintingStrategy(paintingStrategy.VALUES_ABOVE);
hvalue.setdefaultColor(color.green);
plot lvalue = if showvalues_dollars and !IsNaN(Low1) and PointCount == -1 then low else double.nan;
lvalue.setpaintingStrategy(paintingStrategy.VALUES_BELOW);
lvalue.setdefaultColor(color.red);

input showvalues_percents = no;
plot hpercent = if showvalues_percents and !IsNaN(High1) and PointCount == 1 then round(chghigh) else double.nan;
hpercent.setpaintingStrategy(paintingStrategy.VALUES_ABOVE);
hpercent.setdefaultColor(color.green);
plot lpercent = if showvalues_percents and !IsNaN(Low1) and PointCount == -1 then round(chglow) else double.nan;
lpercent.setpaintingStrategy(paintingStrategy.VALUES_BELOW);
lpercent.setdefaultColor(color.red);
#
 
Hi SleepyZ,
I got some time to learn the code and made some changes to get close to what i need. Almost there but i'm a bit stuck and could use your expertise.

Following up on our last discussion from post #12 of this thread, i made the following changes :
#2: The last zigzag leg now attempts to identify if it should connect to the top of the last bar or bottom. It does that by checking if the last swing point that was detected was a swing high or a swing low. This seems to be working, for now

#3: Instead of connecting the last zigzag leg to the highest or lowest of the "last bar", i am now able to get the highest or lowest between the last swing point and the last bar. Although i am getting the price right, i am unable to figure out how to connect the last leg to the correct candle. Below is a screenshot from MRK today:
As you see, the third candle from right is the one i am trying to connect the last leg of zigzag to. I know the original code is designed to only connect to the last candle but i am hitting the limits of my skillset in working with thinkscript code to figure this out.

Would you be able to, please, advise how to connect the last zigzag leg to the candle that has the highest or lowest price (Ticker: MRK in this case from my screenshot where the correct candle is third from right)? My changes are below, i've marked the sections i have modified


Please note: I'm still grappling with ThinkScript and my changes might not be clean enough. Appreciate input if this can be done differently.

Ruby:
def h = high;
def l = low;
def c = close;
def o = open;
def v = volume;

# Simple Fractal Recon
input length = 3;
input showSwingPointBubbles = no;

def HH1 = h >= Highest(h, length) and h >= Highest(h, length)[-length];
def  High1 = if HH1 then h else Double.NaN;
def LL1 = l <= Lowest(l, length) and l <= Lowest(l, length)[-length];
def Low1 = if LL1 then l else Double.NaN;
def PointCount = if BarNumber() == 1 then 0 else
                 if IsNaN(c) then PointCount[1] else
                 if !IsNaN(High1) then Max(1, PointCount[1] + 1) else
                 if !IsNaN(Low1) then Min(-1, PointCount[1] - 1)
                 else PointCount[1];

input showhorizontals = no;
def RangeHI = if !IsNaN(High1) and PointCount == 1
then h else RangeHI[1];
plot Rhi = RangeHI;
Rhi.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Rhi.SetLineWeight(1);
Rhi.SetDefaultColor(Color.RED);
rhi.sethiding(!showhorizontals);

def RangeLO = if !IsNaN(Low1) and PointCount == -1
then l else RangeLO[1];
plot Rlo =  RangeLO;
Rlo.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Rlo.SetLineWeight(1);
Rlo.SetDefaultColor(Color.GREEN);
Rlo.sethiding(!showhorizontals);

#Harndog
input HHLLlabels = no;

def rh1 = if !IsNaN(Rhi) then Rhi else rh1[1];
def rh2 = if rh1 != rh1[1] then rh1[1] else rh2[1];

AddLabel(HHLLlabels, if rh1 > rh2
              then "Higher Highs"
              else "Lower Highs",
              if rh1 > rh2
              then Color.GREEN
              else Color.RED);

def rl1 = if !IsNaN(Rlo) then Rlo else rl1[1];
def rl2 = if rl1 != rl1[1] then rl1[1] else rl2[1];
AddLabel(HHLLlabels, if  rl1 > rl2
              then "Higher Lows"
              else "Lower Lows",
              if rl1 > rl2
              then Color.GREEN
              else Color.RED);

#ZigZags
def zHI;
def zLO;

zHI = if !IsNaN(High1) and PointCount == 1 then h else Double.NaN;
zLO = if !IsNaN(Low1) and PointCount == -1 then l else Double.NaN;

def bn = BarNumber();
def lastzhi = if !IsNaN(zHI) then bn else lastzhi[1];
def lastzlo = if !IsNaN(zLO) then bn else lastzlo[1];


plot hilowline = if !IsNaN(zHI) then zHI else zLO;
hilowline.EnableApproximation();
hilowline.SetLineWeight(1);
hilowline.SetDefaultColor(Color.LIGHT_GRAY);

#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#SubZer0 changes start here
def highestFromLastSwingLow;
def lowestFromLastSwingHigh;

#Get the highest price after the most recent swing low
if ( rl1[1] == low[1])
{
    #This is the bar immediately after the latest swing low bar was detected.
    #Use the high values from this bar as a baseline
    highestFromLastSwingLow = high;
}
else
{
    #Keep finding the highest point after the last swing low
    highestFromLastSwingLow = if (high > highestFromLastSwingLow[1] ) then high else highestFromLastSwingLow[1];
}

#Get the lowest price after the most recent swing high
if( rh1[1] == high[1] )
{
    #This is the bar immediately after the latest swing high bar was detected.
    #Use the low values from this bar as a baseline
    lowestFromLastSwingHigh = low;
}
else
{
    #Keep finding the lowest point after the last swing high
    lowestFromLastSwingHigh = if (low < lowestFromLastSwingHigh[1] ) then low else lowestFromLastSwingHigh[1];
}

def last = if IsNaN(close[-1]) and !IsNaN(close) then BarNumber() else Double.NaN;
def lastbar   = if BarNumber() == HighestAll(last) then 1 else 0;
def lastvalue;

#determine if the last zigzag leg should be connected to the top of the last candle or the bottom
if lastBar
{
    if lastZLo > lastZhi
    {
        #The most recent swing point was a swing low.
        #Plot to the highest point found after the last swing low
        lastValue = highestFromLastSwingLow;
    }
    else
    {
        #The most recent swing point was a swing high
        #Plot to the lowest point found after the last swing high
        lastValue = lowestFromLastSwingHigh;
    }
}
else
{
    lastvalue = Double.NaN;
}

#SubZer0 changes end here
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

plot hilowline1 = if bn < Max(lastzhi, lastzlo)
                  then Double.NaN
                  else if lastzlo > lastzhi and !IsNaN(zLO)
                  then zLO
                  else if lastzlo < lastzhi and !IsNaN(zHI)
                  then zHI else lastvalue;
hilowline1.EnableApproximation();
hilowline1.SetLineWeight(1);
hilowline1.SetDefaultColor(Color.LIGHT_GRAY);

def xxhigh  = if rh1 == high then high else xxhigh[1];
def xxlow   = if rl1 == low then low else xxlow[1];
def chghigh = (rh1 - xxlow[1]) / xxlow[1] * 100;
def chglow  = (rl1 - xxhigh[1]) / xxhigh[1] * 100;


AddChartBubble(showSwingPointBubbles and !IsNaN(High1) and PointCount == 1, high, "H\n" + AsText(high) + " \n" +  Round(chghigh) + "%", if xxhigh > xxhigh[1] then Color.GREEN else Color.RED);
AddChartBubble(showSwingPointBubbles and !IsNaN(Low1) and PointCount == -1, low, "L\n" + AsText(low) + " \n" +  Round(chglow) + "%", if xxlow > xxlow[1] then Color.GREEN else Color.RED, no);
 
Last edited:
Hi SleepyZ,
I corrected these two lines in my code above. I changed index from -1 to +1

if ( rl1[-1] == low[-1])
if( rh1[-1] == high[-1])

Thanks. I like your idea. I had already changed the code as the lastvalues reached back before the last zz. I think this does what you wanted.

Screenshot-2022-10-21-095320.png
Ruby:
def h = high;
def l = low;
def c = close;
def o = open;
def v = volume;

# Simple Fractal Recon
input length = 3;
input showSwingPointBubbles = no;

def HH1 = h >= Highest(h, length) and h >= Highest(h, length)[-length];
def  High1 = if HH1 then h else Double.NaN;
def LL1 = l <= Lowest(l, length) and l <= Lowest(l, length)[-length];
def Low1 = if LL1 then l else Double.NaN;
def PointCount = if BarNumber() == 1 then 0 else
                 if IsNaN(c) then PointCount[1] else
                 if !IsNaN(High1) then Max(1, PointCount[1] + 1) else
                 if !IsNaN(Low1) then Min(-1, PointCount[1] - 1)
                 else PointCount[1];

input showhorizontals = no;
def RangeHI = if !IsNaN(High1) and PointCount == 1
then h else RangeHI[1];
plot Rhi = RangeHI;
Rhi.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Rhi.SetLineWeight(1);
Rhi.SetDefaultColor(Color.RED);
Rhi.SetHiding(!showhorizontals);

def RangeLO = if !IsNaN(Low1) and PointCount == -1
then l else RangeLO[1];
plot Rlo =  RangeLO;
Rlo.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Rlo.SetLineWeight(1);
Rlo.SetDefaultColor(Color.GREEN);
Rlo.SetHiding(!showhorizontals);

#Harndog
input HHLLlabels = no;

def rh1 = if !IsNaN(Rhi) then Rhi else rh1[1];
def rh2 = if rh1 != rh1[1] then rh1[1] else rh2[1];

AddLabel(HHLLlabels, if rh1 > rh2
              then "Higher Highs"
              else "Lower Highs",
              if rh1 > rh2
              then Color.GREEN
              else Color.RED);

def rl1 = if !IsNaN(Rlo) then Rlo else rl1[1];
def rl2 = if rl1 != rl1[1] then rl1[1] else rl2[1];
AddLabel(HHLLlabels, if  rl1 > rl2
              then "Higher Lows"
              else "Lower Lows",
              if rl1 > rl2
              then Color.GREEN
              else Color.RED);

#ZigZags
def zHI;
def zLO;

zHI = if !IsNaN(High1) and PointCount == 1 then h else Double.NaN;
zLO = if !IsNaN(Low1) and PointCount == -1 then l else Double.NaN;

def bn = BarNumber();
def lastzhi = if !IsNaN(zHI) then bn else lastzhi[1];
def lastzlo = if !IsNaN(zLO) then bn else lastzlo[1];


plot hilowline = if !IsNaN(zHI) then zHI else zLO;
hilowline.EnableApproximation();
hilowline.SetLineWeight(1);
hilowline.SetDefaultColor(Color.LIGHT_GRAY);

#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

def lastbar = if IsNaN(close[-1]) and !IsNaN(close) then bn else Double.NaN;
def range =  Between(bn, Max(HighestAll(lastzhi+1), HighestAll(lastzlo+1)), HighestAll(lastbar));

def hhi     = if bn == HighestAll(lastzlo+1)
              then high
              else if range and high > hhi[1]
              then high
              else hhi[1];
def hhibar  = if high == hhi then bn else Double.NaN;
def lasthhi = if bn == HighestAll(hhibar) then hhi else Double.NaN;

def llo     = if bn == HighestAll(lastzhi+1)
              then low
              else if range and low < llo[1]
              then low
              else llo[1];
def llobar  = if range and  low == llo then bn else Double.NaN;
def lastllo = if range and bn == highestAll(llobar) then (llo) else Double.NaN;


plot hilowline1 = if bn < Max(lastzhi, lastzlo)
                  then Double.NaN
                  else if lastzlo > lastzhi and !IsNaN(zLO)
                  then zLO
                  else if lastzlo < lastzhi and !IsNaN(zHI)
                  then zHI
                  else if highestall(lastzhi)<highestall(lastzlo)
                  then lasthhi
                  else lastllo;
hilowline1.EnableApproximation();
hilowline1.SetLineWeight(1);
hilowline1.SetDefaultColor(Color.LIGHT_GRAY);

def xxhigh  = if rh1 == high then high else xxhigh[1];
def xxlow   = if rl1 == low then low else xxlow[1];
def chghigh = (rh1 - xxlow[1]) / xxlow[1] * 100;
def chglow  = (rl1 - xxhigh[1]) / xxhigh[1] * 100;


AddChartBubble(showSwingPointBubbles and !IsNaN(High1) and PointCount == 1, high, "H\n" + AsText(high) + " \n" +  Round(chghigh) + "%", if xxhigh > xxhigh[1] then Color.GREEN else Color.RED);
AddChartBubble(showSwingPointBubbles and !IsNaN(Low1) and PointCount == -1, low, "L\n" + AsText(low) + " \n" +  Round(chglow) + "%", if xxlow > xxlow[1] then Color.GREEN else Color.RED, no);
#
 
Thank you SleepyZ. I will test this code in a few minutes. Your code looks a whole lot cleaner than mine. :)

Meanwhile, i wanted to ask if there is a way to show the %change or the $change on the last leg.
 
Thanks! You da best. It does exactly what i've been breaking my head to do, and you've done this in a very clean way. (y)

So issues #2 and #3 from post #12 are resolved

I now bumped into issue #1
- CLR
- FTI

PS: I use length=3 for this indicator as i only look at two bars before and after the current bar.

I was wondering if you were able to get any traction on this. I tried fiddling with the code to see if there were two consecutive highs without a low in between (and vice versa) but it went way over my head and i ended up breaking the code.

Thanks in advance if you can provide any guidance on #1 and also showing %change value on the last leg.
 
Thanks! You da best. It does exactly what i've been breaking my head to do, and you've done this in a very clean way. (y)

So issues #2 and #3 from post #12 are resolved

I now bumped into issue #1
- CLR
- FTI

PS: I use length=3 for this indicator as i only look at two bars before and after the current bar.

I was wondering if you were able to get any traction on this. I tried fiddling with the code to see if there were two consecutive highs without a low in between (and vice versa) but it went way over my head and i ended up breaking the code.

Thanks in advance if you can provide any guidance on #1 and also showing %change value on the last leg.

Here is the value or percent change on last leg.

Ruby:
def h = high;
def l = low;
def c = close;
def o = open;
def v = volume;

# Simple Fractal Recon
input length = 3;
input showSwingPointBubbles = no;

def HH1 = h >= Highest(h, length) and h >= Highest(h, length)[-length];
def  High1 = if HH1 then h else Double.NaN;
def LL1 = l <= Lowest(l, length) and l <= Lowest(l, length)[-length];
def Low1 = if LL1 then l else Double.NaN;
def PointCount = if BarNumber() == 1 then 0 else
                 if IsNaN(c) then PointCount[1] else
                 if !IsNaN(High1) then Max(1, PointCount[1] + 1) else
                 if !IsNaN(Low1) then Min(-1, PointCount[1] - 1)
                 else PointCount[1];

input showhorizontals = no;
def RangeHI = if !IsNaN(High1) and PointCount == 1
then h else RangeHI[1];
plot Rhi = RangeHI;
Rhi.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Rhi.SetLineWeight(1);
Rhi.SetDefaultColor(Color.RED);
Rhi.SetHiding(!showhorizontals);

def RangeLO = if !IsNaN(Low1) and PointCount == -1
then l else RangeLO[1];
plot Rlo =  RangeLO;
Rlo.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Rlo.SetLineWeight(1);
Rlo.SetDefaultColor(Color.GREEN);
Rlo.SetHiding(!showhorizontals);

#Harndog
input HHLLlabels = no;

def rh1 = if !IsNaN(Rhi) then Rhi else rh1[1];
def rh2 = if rh1 != rh1[1] then rh1[1] else rh2[1];

AddLabel(HHLLlabels, if rh1 > rh2
              then "Higher Highs"
              else "Lower Highs",
              if rh1 > rh2
              then Color.GREEN
              else Color.RED);

def rl1 = if !IsNaN(Rlo) then Rlo else rl1[1];
def rl2 = if rl1 != rl1[1] then rl1[1] else rl2[1];
AddLabel(HHLLlabels, if  rl1 > rl2
              then "Higher Lows"
              else "Lower Lows",
              if rl1 > rl2
              then Color.GREEN
              else Color.RED);

#ZigZags
def zHI;
def zLO;

zHI = if !IsNaN(High1) and PointCount == 1 then h else Double.NaN;
zLO = if !IsNaN(Low1) and PointCount == -1 then l else Double.NaN;

def bn = BarNumber();
def lastzhi = if !IsNaN(zHI) then bn else lastzhi[1];
def lastzlo = if !IsNaN(zLO) then bn else lastzlo[1];


plot hilowline = if !IsNaN(zHI) then zHI else zLO;
hilowline.EnableApproximation();
hilowline.SetLineWeight(1);
hilowline.SetDefaultColor(Color.LIGHT_GRAY);

#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

def lastbar = if IsNaN(close[-1]) and !IsNaN(close) then bn else Double.NaN;
def range =  Between(bn, Max(HighestAll(lastzhi+1), HighestAll(lastzlo+1)), HighestAll(lastbar));

def hhi     = if bn == HighestAll(lastzlo+1)
              then high
              else if range and high > hhi[1]
              then high
              else hhi[1];
def hhibar  = if high == hhi then bn else Double.NaN;
def lasthhi = if bn == HighestAll(hhibar) then hhi else Double.NaN;

def llo     = if bn == HighestAll(lastzhi+1)
              then low
              else if range and low < llo[1]
              then low
              else llo[1];
def llobar  = if range and  low == llo then bn else Double.NaN;
def lastllo = if range and bn == highestAll(llobar) then (llo) else Double.NaN;


plot hilowline1 = if bn < Max(lastzhi, lastzlo)
                  then Double.NaN
                  else if lastzlo > lastzhi and !IsNaN(zLO)
                  then zLO
                  else if lastzlo < lastzhi and !IsNaN(zHI)
                  then zHI
                  else if highestall(lastzhi)<highestall(lastzlo)
                  then lasthhi
                  else lastllo;
hilowline1.EnableApproximation();
hilowline1.SetLineWeight(1);
hilowline1.SetDefaultColor(Color.LIGHT_GRAY);

def xxhigh  = if rh1 == high then high else xxhigh[1];
def xxlow   = if rl1 == low then low else xxlow[1];
def chghigh = (rh1 - xxlow[1]) / xxlow[1] * 100;
def chglow  = (rl1 - xxhigh[1]) / xxhigh[1] * 100;


AddChartBubble(showSwingPointBubbles and !IsNaN(High1) and PointCount == 1, high, "H\n" + AsText(high) + " \n" +  Round(chghigh) + "%", if xxhigh > xxhigh[1] then Color.GREEN else Color.RED);
AddChartBubble(showSwingPointBubbles and !IsNaN(Low1) and PointCount == -1, low, "L\n" + AsText(low) + " \n" +  Round(chglow) + "%", if xxlow > xxlow[1] then Color.GREEN else Color.RED, no);

input showvalues_dollars = yes;
plot hvalue = if showvalues_dollars and (!IsNaN(High1) and PointCount == 1)
              then high
              else if  showvalues_dollars and highestall(lastzhi)<highestall(lastzlo)
              then lasthhi
              else double.nan;
hvalue.setpaintingStrategy(paintingStrategy.VALUES_ABOVE);
hvalue.setdefaultColor(color.green);

plot lvalue = if showvalues_dollars and !IsNaN(Low1) and PointCount == -1
              then low
              else if showvalues_dollars and highestall(lastzhi)>highestall(lastzlo)
              then lastllo
              else double.nan;
lvalue.setpaintingStrategy(paintingStrategy.VALUES_BELOW);
lvalue.setdefaultColor(color.red);

input showvalues_percents = no;
plot hpercent = if showvalues_percents and !IsNaN(High1) and PointCount == 1
                then round(chghigh)
                else if showvalues_percents and highestall(lastzhi)<highestall(lastzlo)
                then round((lasthhi - xxlow) / xxlow * 100)
                else double.nan;
hpercent.setpaintingStrategy(paintingStrategy.VALUES_ABOVE);
hpercent.setdefaultColor(color.green);

plot lpercent = if showvalues_percents and !IsNaN(Low1) and PointCount == -1
                then round(chglow)
                else if showvalues_percents and highestall(lastzhi)>highestall(lastzlo)
                then round((lastllo - xxhigh) / xxhigh * 100)
                else double.nan;
lpercent.setpaintingStrategy(paintingStrategy.VALUES_BELOW);
lpercent.setdefaultColor(color.red);
#
 
Hi SleepyZ,
I had some time today and i played around with your code a little bit. On the end-points of the zig-zags, i wanted to make an option to show PercentChange, DollarChange, ActualPrice and Disabled. I refactored your code a little bit... not as neat and concise as yours but below is a snippet from just that change. Do you think it makes sense? I briefly tested it, seems okay. It also addresses showing values on the last leg.



Ruby:
input showEndPointLabel = {"PercentChange", "DollarChange", default "PriceValue", "Disabled"};

plot hvalue;
plot lvalue;

plot hvalueLastBar;
plot lvalueLastBar;

def chgLastBarHigh = (lasthhi - rl1)/rl1 * 100;
def chgLastBarLow = (lastllo - rh1)/rh1 * 100;

switch (showEndPointLabel)
{
    case "PercentChange":
        hvalue = if !IsNaN(High1) and PointCount == 1 then round(chghigh) else double.nan;
        lvalue = if !IsNaN(Low1) and PointCount == -1 then round(chglow) else double.nan;

        hvalueLastBar = if !IsNaN(lasthhi) and lastzlo > lastzhi then round(chgLastBarHigh) else double.nan;
        lvalueLastBar = if !IsNaN(lastllo) and lastzhi > lastzlo then round(chgLastBarLow) else double.nan;

    case "DollarChange":
        hvalue = if !IsNaN(High1) and PointCount == 1 then xxhigh - xxlow else double.nan;
        lvalue = if !IsNaN(Low1) and PointCount == -1 then xxlow - xxhigh else double.nan;

        hvalueLastBar = if !IsNaN(lasthhi) and lastzlo > lastzhi then lasthhi - rl1 else double.nan;
        lvalueLastBar = if !IsNaN(lastllo) and lastzhi > lastzlo then lastllo - rh1 else double.nan;
  

    case "PriceValue":
        hvalue = if !IsNaN(High1) and PointCount == 1 then xxhigh else double.nan;
        lvalue = if !IsNaN(Low1) and PointCount == -1 then xxlow else double.nan;

        hvalueLastBar = if !IsNaN(lasthhi) and  lastzlo > lastzhi then lasthhi else double.nan;
        lvalueLastBar = if !IsNaN(lastllo) and  lastzhi > lastzlo then lastllo else double.nan;
      

    case "Disabled":
        hvalue = Double.NaN;
        lValue = Double.NaN;
        hvaluelastBar = Double.NaN;
        lvaluelastBar = Double.NaN;
}

hvalue.setpaintingStrategy(paintingStrategy.VALUES_ABOVE);
hvalue.setdefaultColor(color.green);

lvalue.setpaintingStrategy(paintingStrategy.VALUES_BELOW);
lvalue.setdefaultColor(color.red);

hvaluelastBar.SetPaintingStrategy(paintingstrategy.VALUES_ABOVE);
hvaluelastBar.setdefaultColor(color.white);

lvaluelastBar.SetPaintingStrategy(paintingstrategy.VALUES_BELOW);
lvaluelastBar.setdefaultColor(color.white);
 
Hi SleepyZ,
Could you please help me understand the logic behind PointCount? Thanks so much and appreciate all the help you've provided.

It is just a way to limit the plot of the zzs in the same direction without another zz in the opposite direction to the first occurrence of the zz. It does this by counting the zz in each direction. The image shows 2 swing highs in the first group without a swing low in between. Only the first is chosen. There were 3 swing highs in the 2nd set of bubbles, again with the first chosen. There were 2 swing lows in the 3rd set without a swing high in between.

If we allow repainting as was done on the last leg, then we could try to use the higher counts on the swing highs as the new swing high instead of the first swing high and the first swing low in the case of last set of bubbles.

The TOS zigzaghighlow indicator repaints itself until it is perfect. If you were not watching the chart as it developed and only looked at it historically, you would likely miss all the repainting and think it catches the best swing every time. The swing highlow does not repaint as the zigzag does.

 
It is just a way to limit the plot of the zzs in the same direction without another zz in the opposite direction to the first occurrence of the zz. It does this by counting the zz in each direction. The image shows 2 swing highs in the first group without a swing low in between. Only the first is chosen. There were 3 swing highs in the 2nd set of bubbles, again with the first chosen. There were 2 swing lows in the 3rd set without a swing high in between.

If we allow repainting as was done on the last leg, then we could try to use the higher counts on the swing highs as the new swing high instead of the first swing high and the first swing low in the case of last set of bubbles.

The TOS zigzaghighlow indicator repaints itself until it is perfect. If you were not watching the chart as it developed and only looked at it historically, you would likely miss all the repainting and think it catches the best swing every time. The swing highlow does not repaint as the zigzag does.

Understood and thanks for the explanation. Very clear. I tried to mess with the PointCount logic and got it mostly working but i am stuck at one place. Here is the logic i am trying to use to decide which pointcount to use.

1. I track the bar number of all swing highs that were detected and also their respective price levels
2. If the bar number of previous swing high is higher than the latest swing low, it means two swing high points were detected without a low swing point in between
3. if #2 is true, i compare price of current swing high with previous swing high and only retain the swing high that is higher in price
3. I then set the point count of the swing high

If there are multiple swing highs detected (P1, P2, P3, P4) without a swing low in between, then my changes result in setting them as (P1, P1, P1, P1). It kinda works and picks the relevant swing point but also draws a line through the previous swing points which i am trying to avoid

Q: How do i reset the previous pointcount to zero when a new point is detected and matches above criteria?

PS: I am okay with the code repainting if it helps to know. I can't imagine how repainting would impact this indicator in a negative way... i mean the previous swing points are still going to be the same and the latest one will be redrawn based on new data. Do you see any concerns with repainting?

I have only made changes to swing high code below

Ruby:
def HH1 = h >= Highest(h, length) and h >= Highest(h, length)[-length];
def  High1 = if HH1 then h else Double.NaN;

#---> Track bar number for all Swing High Points
def SwingPointHighBars = if HH1 then BarNumber() else SwingPointHighBars[1];
#---> Track all Swing High Points
def SwingPointHigh = if HH1 then h else SwingPointHigh[1];

def LL1 = l <= Lowest(l, length) and l <= Lowest(l, length)[-length];
def Low1 = if LL1 then l else Double.NaN;

#---> Track bar number for all Swing Low Points
def SwingPointLowBars = if LL1 then BarNumber() else SwingPointLowBars[1];
#---> Track all Swing Low Points
def SwingPointLow = if LL1 then l else SwingPointLow[1];

#def PointCount = if BarNumber() == 1 then 0 else
#                 if IsNaN(c) then PointCount[1] else
#                 if !IsNaN(High1) then Max(1, PointCount[1] + 1) else
#                 if !IsNaN(Low1) then Min(-1, PointCount[1] - 1)
#                 else PointCount[1];

  
#--->
def PointCount;

if( BarNumber() == 1 )
{
    PointCount = 0;
}
else
{
    if( IsNaN(c) )
    {
        PointCount = PointCount[1];
    }
    else
    {
        if( !IsNaN(High1) )
        {
            if( SwingPointHighBars[1] > SwingPointLowBars )
            {
                #A new swing high was detected and the previous swing point was also a high
                #In this case, a swing low is missing, so check to see if we should
                #use the new swing high or the previous swing high
                if( SwingPointHigh > SwingPointHigh[1] )
                {
                    #Price of current swing high is higher than previous swing high, use this one
                    #Reduce point count
                    PointCount = Max(1, PointCount[1] - 1 );
                  
                    ###How do i reset the pointcount of the previous swing high so it is reset to zero?
                }
                else
                {
                    #Price of previous swing high was already higher than current swing high. Keep as is
                    PointCount = PointCount[1];
                }
            }
            else
            {
                #Normal situation. There is a swing low between the current high and previous high
                PointCount = Max(1, PointCount[1] + 1 );
            }
        }
        else
        {
            #---> Original code here. Have not changed it yet
            if( !IsNaN(Low1) )
            {
                PointCount = Min(-1, PointCount[1] - 1);
            }
            else
            { 
                PointCount = PointCount[1];
            }
        }
    }
}
#--->
 
Last edited:
It is just a way to limit the plot of the zzs in the same direction without another zz in the opposite direction to the first occurrence of the zz. It does this by counting the zz in each direction. The image shows 2 swing highs in the first group without a swing low in between. Only the first is chosen. There were 3 swing highs in the 2nd set of bubbles, again with the first chosen. There were 2 swing lows in the 3rd set without a swing high in between.

If we allow repainting as was done on the last leg, then we could try to use the higher counts on the swing highs as the new swing high instead of the first swing high and the first swing low in the case of last set of bubbles.

The TOS zigzaghighlow indicator repaints itself until it is perfect. If you were not watching the chart as it developed and only looked at it historically, you would likely miss all the repainting and think it catches the best swing every time. The swing highlow does not repaint as the zigzag does.
@SleepyZ , hi bro, may I check with if possible to trigger the condition after the pivot high with the next candle close below the Pivot candle 's Low. Image here for explanation: .

Many thanks in advance.
 
@SleepyZ , hi bro, may I check with if possible to trigger the condition after the pivot high with the next candle close below the Pivot candle 's Low. Image here for explanation: .

Many thanks in advance.
@SleepyZ, Hi bro, I try the followings but it did not return anything.

def highPivotPt = if !IsNaN(High1) and PointCount == 1 then high else double.NaN;
plot highSignal = if highPivotPt and close < low[1] then 1 else double.nan;
plot highSignal = if highPivotPt then close < low[1] else double.nan;

Much appreciated your advice. Cheers
 
@SleepyZ, Hi bro, I try the followings but it did not return anything.

def highPivotPt = if !IsNaN(High1) and PointCount == 1 then high else double.NaN;
plot highSignal = if highPivotPt and close < low[1] then 1 else double.nan;
plot highSignal = if highPivotPt then close < low[1] else double.nan;

Much appreciated your advice. Cheers

Since the highpivotpt relies upon future bars, then it will not work how you want. The pivot looks back x bars and forward the same x bars to find a pivot.
 
@SleepyZ good day how can i get this to work? im trying to get an avrage of the low to high and high to low change

i tried this and just get last ligh and low
def chghigh = (rh1 - xxlow[1]) ;#/ xxlow[1] * 100;
def chglow = (rl1 - xxhigh[1]);# / xxhigh[1] * 100;
def avg_length = 10;
def change_avghigh = average(chghigh,avg_length);
def change_avglow = average(chglow,avg_length);
 

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
312 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

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?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top