Repaints ZigZag High Low Stats for ThinkorSwim

Repaints
Here is something I did for the trend reversal indicator found in this thread that may interest you also https://usethinkscript.com/threads/...r-with-signals-for-thinkorswim.183/post-14256

Here is the code and an image of what it looks like on a chart
Is there a way to get the stop bubbles to plot under yesterday's candle when a Bull signal occurs and over yesterday's candle when a Bear signal occurs? Currently they are are plotting under/over today's candle, but the stops are based on yesterday's high/low.

I was able to figure this out by adding [-1] to the code below for the stop lines, but cannot figure out how to get the stop bubbles to plot like this.

plot bullstopplot = bullstop [-1];
bullstopplot.setdefaultColor(color.red);

plot bearstopplot = bearstop [-1];
bearstopplot.setdefaultColor(color.red);

(See Post # 87 on this thread for a picture of how the stop lines and stop bubbles plot in their current form)

Thank you very much in advance for any assistance with this!
 
Last edited:

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

Is there a way to get the stop bubbles to plot under yesterday's candle when a Bull signal occurs and over yesterday's candle when a Bear signal occurs? Currently they are are plotting under/over today's candle, but the stops are based on yesterday's high/low.

I was able to figure this out by adding [-1] to the code below for the stop lines, but cannot figure out how to get the stop bubbles to plot like this.

plot bullstopplot = bullstop [-1];
bullstopplot.setdefaultColor(color.red);

plot bearstopplot = bearstop [-1];
bearstopplot.setdefaultColor(color.red);

(See Post # 87 on this thread for a picture of how the stop lines and stop bubbles plot in their current form)

Thank you very much in advance for any assistance with this!

See if this is what you were looking to happen.

Capture.jpg
Ruby:
# Trend Reversal
# Dixon72 with modifications by tomsk
# 1.18.2020
# Scanner by https://usethinkscript.com/u/theelderwand

# V1.0 - 11.09.2019 - Dixon72 - Initial release of Trend Reversal Scanner
# V1.1 - 01.18.2020 - tomsk   - Modified to only display last bullish/bearish signal
# V1.2 - 01.18.2020 - tomsk   - Added user input selector displayBubblesOnly to display bubbles rather than arrows
# V1.3 - 01.19.2020 - BLT     - Modified bubble placement, added Stop Loss bubble and extended line

input displayBubblesOnly = yes;

def price = close;
def superfast_length = 9;
def fast_length = 14;
def slow_length = 21;
def displace = 0;

def mov_avg9 = ExpAverage(price[-displace], superfast_length);
def mov_avg14 = ExpAverage(price[-displace], fast_length);
def mov_avg21 = ExpAverage(price[-displace], slow_length);

#moving averages
def Superfast = mov_avg9;
def Fast = mov_avg14;
def Slow = mov_avg21;

def buy = mov_avg9 > mov_avg14 and mov_avg14 > mov_avg21 and low > mov_avg9;
def stopbuy = mov_avg9 <= mov_avg14;
def buynow = !buy[1] and buy;
def buysignal = CompoundValue(1, if buynow and !stopbuy then 1 else if buysignal[1] == 1 and stopbuy then 0 else buysignal[1], 0);

def Buy_Signal = buysignal[1] == 0 and buysignal == 1;
def Momentum_Down = buysignal[1] == 1 and buysignal == 0;

def sell = mov_avg9 < mov_avg14 and mov_avg14 < mov_avg21 and high < mov_avg9;
def stopsell = mov_avg9 >= mov_avg14;
def sellnow = !sell[1] and sell;
def sellsignal = CompoundValue(1, if sellnow and !stopsell then 1 else if sellsignal[1] == 1 and stopsell then 0 else sellsignal[1], 0);
def Sell_Signal = sellsignal[1] == 0 and sellsignal;


input method = {default average, high_low};
def bubbleoffset = .0005;
def percentamount = .01;
def revAmount = .05;
def atrreversal = 2.0;
def atrlength = 5;
def pricehigh = high;
def pricelow = low;
def averagelength = 5;
def averagetype = AverageType.EXPONENTIAL;
def mah = MovingAverage(averagetype, pricehigh, averagelength);
def mal = MovingAverage(averagetype, pricelow, averagelength);
def priceh = if method == method.high_low then pricehigh else mah;
def pricel = if method == method.high_low then pricelow else mal;
def EI = ZigZagHighLow("price h" = priceh, "price l" = pricel, "percentage reversal" = percentamount, "absolute reversal" = revAmount, "atr length" = atrlength, "atr reversal" = atrreversal);
rec EISave = if !IsNaN(EI) then EI else GetValue(EISave, 1);
def chg = (if EISave == priceh then priceh else pricel) - GetValue(EISave, 1);
def isUp = chg >= 0;
def EIL = if !IsNaN(EI) and !isUp then pricel else GetValue(EIL, 1);
def EIH = if !IsNaN(EI) and isUp then priceh else GetValue(EIH, 1);
def dir = CompoundValue(1, if EIL != EIL[1] or pricel == EIL[1] and pricel == EISave then 1 else if EIH != EIH[1] or priceh == EIH[1] and priceh == EISave then -1 else dir[1], 0);
def signal = CompoundValue(1, if dir > 0 and pricel > EIL then if signal[1] <= 0 then 1 else signal[1] else if dir < 0 and priceh < EIH then if signal[1] >= 0 then -1 else signal[1] else signal[1], 0);

def bullish2 = if signal > 0 and signal[1] <= 0 then barNumber() else 0;
plot upArrow = if !displayBubblesOnly and barNumber() == HighestAll(bullish2) then low * 0.994 else Double.NaN;
upArrow.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
upArrow.SetLineWeight(5);
upArrow.SetDefaultColor(Color.CYAN);

def bearish2 = if signal < 0 and signal[1] >= 0 then barNumber() else 0;
plot downArrow = if !displayBubblesOnly and barNumber() == HighestAll(bearish2) then high * 1.004 else Double.NaN;
downArrow.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
downArrow.SetLineWeight(5);
downArrow.SetDefaultColor(Color.YELLOW);

AddChartBubble(displayBubblesOnly and barNumber() == HighestAll(bullish2), low, "Bull " + astext(low), Color.Cyan, no);
AddChartBubble(displayBubblesOnly and barNumber() == HighestAll(bearish2), high, "Bear " + astext(high), Color.Yellow, yes);
def bullstop= if barNumber() == HighestAll(bullish2) then low[1] else if barnumber() < HighestAll(bullish2) then double.nan else bullstop[1];
plot bullstopplot = bullstop;
bullstopplot.setdefaultColor(color.red);
AddChartBubble(displayBubblesOnly and barNumber() == HighestAll(bullish2-1), low, "Stop " + astext(low[1]), Color.red, no);
def bearstop= if barNumber() == HighestAll(bearish2) then high[1] else if barnumber() < HighestAll(bearish2) then double.nan else bearstop[1];
plot bearstopplot = bearstop;
bearstopplot.setdefaultColor(color.red);
AddChartBubble(displayBubblesOnly and barNumber() == HighestAll(bearish2-1), high, "Stop " + astext(high[1]), Color.red, yes);
# End Trend Reversal
 
See if this is what you were looking to happen.
Yes! Exactly the way I wanted it to plot! Thank you so much! May I ask you one more question, is there anything that can be added to the code which will allow me to adjust the stop bubbles up or down? On some charts the stop bubbles overlap with the bull/bear bubbles so it would be great if I could adjust the stop bubbles up or down so that they don't overlap with each other. Thank you my friend!
 
Yes! Exactly the way I wanted it to plot! Thank you so much! May I ask you one more question, is there anything that can be added to the code which will allow me to adjust the stop bubbles up or down? On some charts the stop bubbles overlap with the bull/bear bubbles so it would be great if I could adjust the stop bubbles up or down so that they don't overlap with each other. Thank you my friend!

The input bubblemover_updown will move only the Stop bubbles the number of ticks entered there from their original plot position.

Capture.jpg

Ruby:
# Trend Reversal
# Dixon72 with modifications by tomsk
# 1.18.2020
# Scanner by https://usethinkscript.com/u/theelderwand

# V1.0 - 11.09.2019 - Dixon72 - Initial release of Trend Reversal Scanner
# V1.1 - 01.18.2020 - tomsk   - Modified to only display last bullish/bearish signal
# V1.2 - 01.18.2020 - tomsk   - Added user input selector displayBubblesOnly to display bubbles rather than arrows
# V1.3 - 01.19.2020 - BLT     - Modified bubble placement, added Stop Loss bubble and extended line

input displayBubblesOnly = yes;

def price = close;
def superfast_length = 9;
def fast_length = 14;
def slow_length = 21;
def displace = 0;

def mov_avg9 = ExpAverage(price[-displace], superfast_length);
def mov_avg14 = ExpAverage(price[-displace], fast_length);
def mov_avg21 = ExpAverage(price[-displace], slow_length);

#moving averages
def Superfast = mov_avg9;
def Fast = mov_avg14;
def Slow = mov_avg21;

def buy = mov_avg9 > mov_avg14 and mov_avg14 > mov_avg21 and low > mov_avg9;
def stopbuy = mov_avg9 <= mov_avg14;
def buynow = !buy[1] and buy;
def buysignal = CompoundValue(1, if buynow and !stopbuy then 1 else if buysignal[1] == 1 and stopbuy then 0 else buysignal[1], 0);

def Buy_Signal = buysignal[1] == 0 and buysignal == 1;
def Momentum_Down = buysignal[1] == 1 and buysignal == 0;

def sell = mov_avg9 < mov_avg14 and mov_avg14 < mov_avg21 and high < mov_avg9;
def stopsell = mov_avg9 >= mov_avg14;
def sellnow = !sell[1] and sell;
def sellsignal = CompoundValue(1, if sellnow and !stopsell then 1 else if sellsignal[1] == 1 and stopsell then 0 else sellsignal[1], 0);
def Sell_Signal = sellsignal[1] == 0 and sellsignal;


input method = {default average, high_low};
def bubbleoffset = .0005;
def percentamount = .01;
def revAmount = .05;
def atrreversal = 2.0;
def atrlength = 5;
def pricehigh = high;
def pricelow = low;
def averagelength = 5;
def averagetype = AverageType.EXPONENTIAL;
def mah = MovingAverage(averagetype, pricehigh, averagelength);
def mal = MovingAverage(averagetype, pricelow, averagelength);
def priceh = if method == method.high_low then pricehigh else mah;
def pricel = if method == method.high_low then pricelow else mal;
def EI = ZigZagHighLow("price h" = priceh, "price l" = pricel, "percentage reversal" = percentamount, "absolute reversal" = revAmount, "atr length" = atrlength, "atr reversal" = atrreversal);
rec EISave = if !IsNaN(EI) then EI else GetValue(EISave, 1);
def chg = (if EISave == priceh then priceh else pricel) - GetValue(EISave, 1);
def isUp = chg >= 0;
def EIL = if !IsNaN(EI) and !isUp then pricel else GetValue(EIL, 1);
def EIH = if !IsNaN(EI) and isUp then priceh else GetValue(EIH, 1);
def dir = CompoundValue(1, if EIL != EIL[1] or pricel == EIL[1] and pricel == EISave then 1 else if EIH != EIH[1] or priceh == EIH[1] and priceh == EISave then -1 else dir[1], 0);
def signal = CompoundValue(1, if dir > 0 and pricel > EIL then if signal[1] <= 0 then 1 else signal[1] else if dir < 0 and priceh < EIH then if signal[1] >= 0 then -1 else signal[1] else signal[1], 0);

def bullish2 = if signal > 0 and signal[1] <= 0 then barNumber() else 0;
plot upArrow = if !displayBubblesOnly and barNumber() == HighestAll(bullish2) then low * 0.994 else Double.NaN;
upArrow.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
upArrow.SetLineWeight(5);
upArrow.SetDefaultColor(Color.CYAN);

def bearish2 = if signal < 0 and signal[1] >= 0 then barNumber() else 0;
plot downArrow = if !displayBubblesOnly and barNumber() == HighestAll(bearish2) then high * 1.004 else Double.NaN;
downArrow.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
downArrow.SetLineWeight(5);
downArrow.SetDefaultColor(Color.YELLOW);

input bubblemover_updown = 3;

AddChartBubble(displayBubblesOnly and barNumber() == HighestAll(bullish2), low, "Bull " + astext(low), Color.Cyan, no);
AddChartBubble(displayBubblesOnly and barNumber() == HighestAll(bearish2), high, "Bear " + astext(high), Color.Yellow, yes);
def bullstop= if barNumber() == HighestAll(bullish2) then low[1] else if barnumber() < HighestAll(bullish2) then double.nan else bullstop[1];
plot bullstopplot = bullstop;
bullstopplot.setdefaultColor(color.red);
AddChartBubble(displayBubblesOnly and barNumber() == HighestAll(bullish2-1), low - ticksize() * bubblemover_updown, "Stop " + astext(low[1]), Color.red, no);
def bearstop= if barNumber() == HighestAll(bearish2) then high[1] else if barnumber() < HighestAll(bearish2) then double.nan else bearstop[1];
plot bearstopplot = bearstop;
bearstopplot.setdefaultColor(color.red);
AddChartBubble(displayBubblesOnly and barNumber() == HighestAll(bearish2-1), high + ticksize() * bubblemover_updown, "Stop " + astext(high[1]), Color.red, yes);
# End Trend Reversal
 
Last edited:
The input bubblemover_updown will move only the Stop bubbles the number of ticks entered there from their original plot position.
Wow this sounds like just what I need! Would you kindly provide some additional insight as to where I would add this piece of code to the rest of the code to be able to adjust the stop bubbles up and down? I just added "input bubblemover_updown" to the rest of the code but it didn't do anything so I must be missing something. Thank you again Sleepy!
 
Wow this sounds like just what I need! Would you kindly provide some additional insight as to where I would add this piece of code to the rest of the code to be able to adjust the stop bubbles up and down? I just added "input bubblemover_updown" to the rest of the code but it didn't do anything so I must be missing something. Thank you again Sleepy!

Sorry, I apparently did not correctly copy the code I used in the image above, so I have edited it to include the bubblemover_updown that I used.
 
Last edited:
@Madison If you haven't already done this, here is one way to use code to count the number of Highs and Lows displayed on the chart.
Do you know how the % calculated? Example: NVAX 5.27.2022 9:45am till 2:15pm , your indicator it shows % is 15.62% but IF I drag wit TD measurement, from bottom is 21.16% +$9? Can you also include the $net value change in the bubble?

 
Do you know how the % calculated? Example: NVAX 5.27.2022 9:45am till 2:15pm , your indicator it shows % is 15.62% but IF I drag wit TD measurement, from bottom is 21.16% +$9? Can you also include the $net value change in the bubble?


Here is the refernced code with additional data in the bubbles, including close of current zigzag, the close of the prior one and the net change.

Ruby:
# TD Ameritrade IP Company, Inc. (c) 2011-2021

#



input price = close;

input reversalAmount = 8.0;

input showBubbles = no;

input showLabel = no;



Assert(reversalAmount > 0, "'reversal amount' should be positive: " + reversalAmount);



plot "ZZ%" = reference ZigZagHighLow(price, price, reversalAmount, 0, 1, 0);



def zzSave = if !IsNaN("ZZ%") then price else GetValue(zzSave, 1);

def chg = (price / GetValue(zzSave, 1) - 1) * 100;

def isUp = chg >= 0;

def isConf = AbsValue(chg) >= reversalAmount or (IsNaN(GetValue("ZZ%", 1)) and GetValue(isConf, 1));



"ZZ%".EnableApproximation();

"ZZ%".DefineColor("Up Trend", Color.UPTICK);

"ZZ%".DefineColor("Down Trend", Color.DOWNTICK);

"ZZ%".DefineColor("Undefined", Color.DARK_ORANGE);

"ZZ%".AssignValueColor(if !isConf then "ZZ%".Color("Undefined") else if isUp then "ZZ%".Color("Up Trend") else "ZZ%".Color("Down Trend"));



DefineGlobalColor("Unconfirmed", Color.DARK_ORANGE);

DefineGlobalColor("Up", Color.UPTICK);

DefineGlobalColor("Down", Color.DOWNTICK);



def barNumber = BarNumber();



AddChartBubble(showBubbles and !IsNaN("ZZ%") and barNumber != 1,
               price,
               Round(chg) + "%\nC:    " +
               price + "\nC[1]: " +
               GetValue(zzSave, 1) +
               "\nChg:" + (price - GetValue(zzSave, 1)),
               if !isConf
                  then GlobalColor("Unconfirmed")
               else if isUp
                  then GlobalColor("Up")
                  else GlobalColor("Down"), isUp);

AddLabel(showLabel and barNumber != 1, (if isConf then "Confirmed " else "Unconfirmed ") + "ZigZag: " + Round(chg) + "%", if !isConf then GlobalColor("Unconfirmed") else if isUp then GlobalColor("Up") else GlobalColor("Down"));

input show_stats_labels = yes;
def xh = CompoundValue(1, if isUp and !IsNaN("ZZ%") then xh[1] + 1 else xh[1], 0);
AddLabel(show_stats_labels, "#Highs: " + xh, Color.GREEN);
def xl = CompoundValue(1, if !isUp and !IsNaN("ZZ%") then xl[1] + 1 else xl[1], 0);
AddLabel(show_stats_labels, "#Lows: " + xl, Color.RED);

input showbubbles_stats = yes;
AddChartBubble(showbubbles_stats and !IsNaN("ZZ%") and barNumber != 1 and isUp, price, "H: " + xh, Color.GREEN, isUp);
AddChartBubble(showbubbles_stats and !IsNaN("ZZ%") and barNumber != 1 and !isUp, price, "L: " + xl, Color.RED, isUp);
#
 
There are inputs for count to limit how many zigzags to plot, and show your candle coloring scheme.
@SleepyZ Would you kindly assist in making a few tweaks to this study?

1. The candles will only change color after a follow through day. For example, if today the signal changed from bullish to bearish, the candlestick color would not change from green to red unless tomorrow's signal also remained bearish on a closing basis. At that time (tomorrow after the close), the candlestick would change from green to red and also the red down arrow would plot tomorrow after the close. The same would happen when the signal changes from bearish to bullish.

2. Option to replace the up and down arrows with bubbles that say "bullish" and "bearish".

My attempts to make these tweaks have resulted in either all the candles painting gray or the bubbles not plotting at all so I am obviously doing something wrong. Thank you for any assistance!

# ZigZag High Low Stats
# tomsk
# 11.16.2019

# V1.0 - 11.16.2019 - tomsk - Initial release of ZigZag High Low Stats

# Extracted idea from RDMercer's post #369 of a variant of a massive
# Zig Zag High Low Supply Demand study that comprises many different
# components
#
# https://usethinkscript.com/threads/...-signals-for-thinkorswim.183/page-19#post-369
#
# I heavily modified, cleaned up and extracted some interesting Zig Zag statistical information resulting in this study called Zig Zag High
# Low Stats. It displays the following information represented via bubbles at each of the Zig zag turning points
#
# Label for Confirmed/Unconfirmed Status of Current Zigzag
# Price Change between Zigzags
# Price at Zigzag High/Low
# Bar Count between Zigzags
# Volume at Zigzag Reversals

input showBubblesChange = no; # Price Change between Zigzags
input showBubblesPrice = no; # Price at Zigzag High/Low
input showBubblesBarCount = no; # Bar Count between Zigzags
input showBubblesVolume = no; # Volume at Zigzag Reversals

input BubbleOffset = .0005;
input PercentAmount = .01;
input RevAmount = .05;
input ATRreversal = 3.0;
input ATRlength = 5;

def zz = ZigZagHighLow("price h" = high, "price l" = low, "percentage reversal" = PercentAmount,
"absolute reversal" = RevAmount, "atr length" = ATRlength, "atr reversal" = ATRreversal);

def ReversalAmount = if (close * PercentAmount / 100) > Max(RevAmount < ATRreversal * reference ATR(ATRlength), RevAmount)
then (close * PercentAmount / 100)
else if RevAmount < ATRreversal * reference ATR(ATRlength)
then ATRreversal * reference ATR(ATRlength)
else RevAmount;
# Zig Zag Specific Data

def zzSave = if !IsNaN(zz) then zz else GetValue(zzSave, 1);
def chg = (if zzSave == high then high else low) - GetValue(zzSave, 1);
def isUp = chg >= 0;
def isConf = AbsValue(chg) >= ReversalAmount or (IsNaN(GetValue(zz, 1)) and GetValue(isConf, 1));

# Price Change Specific Data

def xxHigh = if zzSave == high then high else xxHigh[1];
def chgHigh = high - xxHigh[1];
def xxLow = if zzSave == low then low else xxLow[1];
def chgLow = low - xxLow[1];

# Bar Count Specific Data

def zzCount = if zzSave[1] != zzSave then 1 else if zzSave[1] == zzSave then zzCount[1] + 1 else 0;
def zzCountHiLo = if zzCountHiLo[1] == 0 and (zzSave == high or zzSave == low) then 1
else if zzSave == high or zzSave == low then zzCountHiLo[1] + 1
else zzCountHiLo[1];
def zzHiLo = if zzSave == high or zzSave == low then zzCountHiLo else zzCountHiLo + 1;
def zzCountHigh = if zzSave == high then zzCount[1] else Double.NaN;
def zzCountLow = if zzSave == low then zzCount[1] else Double.NaN;

# Volume Specific Data

def vol = if BarNumber() == 0 then 0 else volume + vol[1];
def vol1 = if BarNumber() == 1 then volume else vol1[1];
def xxVol = if zzSave == high or zzSave == low then TotalSum(volume) else xxVol[1];
def chgVol = if xxVol - xxVol[1] + vol1 == vol then vol else xxVol - xxVol[1];

# Zigzag Status Label

AddLabel(BarNumber() != 1, (if isConf then "Confirmed " else "Unconfirmed ") + "ZigZag: " + chg + " ATRrev " + Round(reference ATR(ATRlength) * ATRreversal, 2) + " RevAmt " + Round(ReversalAmount, 2), if !isConf then Color.DARK_ORANGE else if isUp then Color.GREEN else Color.RED);

# Zig Zag Plot

plot zzp = if isUp <= 1 then zz else Double.NaN;
zzp.AssignValueColor(if isUp then Color.DARK_GREEN else if !isUp then Color.RED else Color.DARK_ORANGE);
zzp.SetStyle(Curve.FIRM);
zzp.EnableApproximation();
zzp.HideBubble();

# Bubbles

# Price Change between Zigzags

AddChartBubble(showBubblesChange and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + BubbleOffset) else low * (1 - BubbleOffset), "$" + Round(chg, 2), if isUp and chgHigh > 0 then Color.GREEN else if isUp and chgHigh < 0 then Color.RED else if isUp then Color.YELLOW else if !isUp and chgLow > 0 then Color.GREEN else if !isUp and chgLow < 0 then Color.RED else Color.YELLOW, isUp);

# Price at Zigzag High/Low

AddChartBubble(showBubblesPrice and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + BubbleOffset) else low * (1 - BubbleOffset), if isUp then "$" + high else "$" + low, if isUp and chgHigh > 0 then Color.GREEN else if isUp and chgHigh < 0 then Color.RED else if isUp then Color.YELLOW else if !isUp and chgLow > 0 then Color.GREEN else if !isUp and chgLow < 0 then Color.RED else Color.YELLOW, isUp);

# Bar Count between Zigzags

AddChartBubble(showBubblesBarCount and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + BubbleOffset) else low * (1 - BubbleOffset), if zzSave == high then zzCountHigh else zzCountLow, if isUp and chgHigh > 0 then Color.GREEN else if isUp and chgHigh < 0 then Color.RED else if isUp then Color.YELLOW else if !isUp and chgLow > 0 then Color.GREEN else if !isUp and chgLow < 0 then Color.RED else Color.YELLOW, if isUp then yes else no);

# Volume at Zigzag Reversals

AddChartBubble(showBubblesVolume and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + BubbleOffset) else low * (1 - BubbleOffset), chgVol, if isUp and chgHigh > 0 then Color.GREEN else if isUp and chgHigh < 0 then Color.RED else if isUp then Color.YELLOW else if !isUp and chgLow > 0 then Color.GREEN else if !isUp and chgLow < 0 then Color.RED else Color.YELLOW, if isUp then yes else no);

#Arrows
def zzL = if !IsNaN(zz) and !isUp then low else GetValue(zzL, 1);
def zzH = if !IsNaN(zz) and isUp then high else GetValue(zzH, 1);
def dir = CompoundValue(1, if zzL != zzL[1] or low == zzL[1] and low == zzSave then 1 else if zzH != zzH[1] or high == zzH[1] and high == zzSave then -1 else dir[1], 0);
def signal = CompoundValue(1, if dir > 0 and low > zzL then if signal[1] <= 0 then 1 else signal[1] else if dir < 0 and high < zzH then if signal[1] >= 0 then -1 else signal[1] else signal[1], 0);

#Count to limit plot of arrows-------------------------------------------------
input Count = 2;
def cond = if signal > 0 and signal[1] <= 0 or
signal < 0 and signal[1] >= 0
then 1
else 0 ;
def dataCount = CompoundValue(1, if cond then dataCount[1] + 1 else dataCount[1], 0);
def limitplot = HighestAll(dataCount) - dataCount <= Count - 1;
#-------------------------------------------------------------------------------

input showarrows = yes;
plot U1 = showarrows and signal > 0 and signal[1] <= 0 and limitplot;
U1.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
U1.SetDefaultColor(Color.GREEN);
U1.SetLineWeight(4);
plot D1 = showarrows and signal < 0 and signal[1] >= 0 and limitplot;
D1.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
D1.SetDefaultColor(Color.RED);
D1.SetLineWeight(4);

#Color Candles based upon Last X Arrows------------------------------------------
input price_color = yes;
def colorup = if U1 then 1 else if colorup[1] and !D1 then 1 else 0;
def colordn = if D1 then 1 else if colordn[1] and !U1 then 1 else 0;
AssignPriceColor(if !price_color then Color.CURRENT
else if colorup == 1 then Color.GREEN
else if colordn == 1 then Color.RED
else Color.GRAY);
#--------------------------------------------------------------------------------
 
Last edited:
@SleepyZ Would you kindly assist in making a few tweaks to this study?

1. The candles will only change color after a follow through day. For example, if today the signal changed from bullish to bearish, the candlestick color would not change from green to red unless tomorrow's signal also remained bearish on a closing basis. At that time (tomorrow after the close), the candlestick would change from green to red and also the red down arrow would plot tomorrow after the close. The same would happen when the signal changes from bearish to bullish.

2. Option to replace the up and down arrows with bubbles that say "bullish" and "bearish".

My attempts to make these tweaks have resulted in either all the candles painting gray or the bubbles not plotting at all so I am obviously doing something wrong. Thank you for any assistance!

# ZigZag High Low Stats
# tomsk
# 11.16.2019

# V1.0 - 11.16.2019 - tomsk - Initial release of ZigZag High Low Stats

# Extracted idea from RDMercer's post #369 of a variant of a massive
# Zig Zag High Low Supply Demand study that comprises many different
# components
#
# https://usethinkscript.com/threads/...-signals-for-thinkorswim.183/page-19#post-369
#
# I heavily modified, cleaned up and extracted some interesting Zig Zag statistical information resulting in this study called Zig Zag High
# Low Stats. It displays the following information represented via bubbles at each of the Zig zag turning points
#
# Label for Confirmed/Unconfirmed Status of Current Zigzag
# Price Change between Zigzags
# Price at Zigzag High/Low
# Bar Count between Zigzags
# Volume at Zigzag Reversals

input showBubblesChange = no; # Price Change between Zigzags
input showBubblesPrice = no; # Price at Zigzag High/Low
input showBubblesBarCount = no; # Bar Count between Zigzags
input showBubblesVolume = no; # Volume at Zigzag Reversals

input BubbleOffset = .0005;
input PercentAmount = .01;
input RevAmount = .05;
input ATRreversal = 3.0;
input ATRlength = 5;

def zz = ZigZagHighLow("price h" = high, "price l" = low, "percentage reversal" = PercentAmount,
"absolute reversal" = RevAmount, "atr length" = ATRlength, "atr reversal" = ATRreversal);

def ReversalAmount = if (close * PercentAmount / 100) > Max(RevAmount < ATRreversal * reference ATR(ATRlength), RevAmount)
then (close * PercentAmount / 100)
else if RevAmount < ATRreversal * reference ATR(ATRlength)
then ATRreversal * reference ATR(ATRlength)
else RevAmount;
# Zig Zag Specific Data

def zzSave = if !IsNaN(zz) then zz else GetValue(zzSave, 1);
def chg = (if zzSave == high then high else low) - GetValue(zzSave, 1);
def isUp = chg >= 0;
def isConf = AbsValue(chg) >= ReversalAmount or (IsNaN(GetValue(zz, 1)) and GetValue(isConf, 1));

# Price Change Specific Data

def xxHigh = if zzSave == high then high else xxHigh[1];
def chgHigh = high - xxHigh[1];
def xxLow = if zzSave == low then low else xxLow[1];
def chgLow = low - xxLow[1];

# Bar Count Specific Data

def zzCount = if zzSave[1] != zzSave then 1 else if zzSave[1] == zzSave then zzCount[1] + 1 else 0;
def zzCountHiLo = if zzCountHiLo[1] == 0 and (zzSave == high or zzSave == low) then 1
else if zzSave == high or zzSave == low then zzCountHiLo[1] + 1
else zzCountHiLo[1];
def zzHiLo = if zzSave == high or zzSave == low then zzCountHiLo else zzCountHiLo + 1;
def zzCountHigh = if zzSave == high then zzCount[1] else Double.NaN;
def zzCountLow = if zzSave == low then zzCount[1] else Double.NaN;

# Volume Specific Data

def vol = if BarNumber() == 0 then 0 else volume + vol[1];
def vol1 = if BarNumber() == 1 then volume else vol1[1];
def xxVol = if zzSave == high or zzSave == low then TotalSum(volume) else xxVol[1];
def chgVol = if xxVol - xxVol[1] + vol1 == vol then vol else xxVol - xxVol[1];

# Zigzag Status Label

AddLabel(BarNumber() != 1, (if isConf then "Confirmed " else "Unconfirmed ") + "ZigZag: " + chg + " ATRrev " + Round(reference ATR(ATRlength) * ATRreversal, 2) + " RevAmt " + Round(ReversalAmount, 2), if !isConf then Color.DARK_ORANGE else if isUp then Color.GREEN else Color.RED);

# Zig Zag Plot

plot zzp = if isUp <= 1 then zz else Double.NaN;
zzp.AssignValueColor(if isUp then Color.DARK_GREEN else if !isUp then Color.RED else Color.DARK_ORANGE);
zzp.SetStyle(Curve.FIRM);
zzp.EnableApproximation();
zzp.HideBubble();

# Bubbles

# Price Change between Zigzags

AddChartBubble(showBubblesChange and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + BubbleOffset) else low * (1 - BubbleOffset), "$" + Round(chg, 2), if isUp and chgHigh > 0 then Color.GREEN else if isUp and chgHigh < 0 then Color.RED else if isUp then Color.YELLOW else if !isUp and chgLow > 0 then Color.GREEN else if !isUp and chgLow < 0 then Color.RED else Color.YELLOW, isUp);

# Price at Zigzag High/Low

AddChartBubble(showBubblesPrice and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + BubbleOffset) else low * (1 - BubbleOffset), if isUp then "$" + high else "$" + low, if isUp and chgHigh > 0 then Color.GREEN else if isUp and chgHigh < 0 then Color.RED else if isUp then Color.YELLOW else if !isUp and chgLow > 0 then Color.GREEN else if !isUp and chgLow < 0 then Color.RED else Color.YELLOW, isUp);

# Bar Count between Zigzags

AddChartBubble(showBubblesBarCount and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + BubbleOffset) else low * (1 - BubbleOffset), if zzSave == high then zzCountHigh else zzCountLow, if isUp and chgHigh > 0 then Color.GREEN else if isUp and chgHigh < 0 then Color.RED else if isUp then Color.YELLOW else if !isUp and chgLow > 0 then Color.GREEN else if !isUp and chgLow < 0 then Color.RED else Color.YELLOW, if isUp then yes else no);

# Volume at Zigzag Reversals

AddChartBubble(showBubblesVolume and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + BubbleOffset) else low * (1 - BubbleOffset), chgVol, if isUp and chgHigh > 0 then Color.GREEN else if isUp and chgHigh < 0 then Color.RED else if isUp then Color.YELLOW else if !isUp and chgLow > 0 then Color.GREEN else if !isUp and chgLow < 0 then Color.RED else Color.YELLOW, if isUp then yes else no);

#Arrows
def zzL = if !IsNaN(zz) and !isUp then low else GetValue(zzL, 1);
def zzH = if !IsNaN(zz) and isUp then high else GetValue(zzH, 1);
def dir = CompoundValue(1, if zzL != zzL[1] or low == zzL[1] and low == zzSave then 1 else if zzH != zzH[1] or high == zzH[1] and high == zzSave then -1 else dir[1], 0);
def signal = CompoundValue(1, if dir > 0 and low > zzL then if signal[1] <= 0 then 1 else signal[1] else if dir < 0 and high < zzH then if signal[1] >= 0 then -1 else signal[1] else signal[1], 0);

#Count to limit plot of arrows-------------------------------------------------
input Count = 2;
def cond = if signal > 0 and signal[1] <= 0 or
signal < 0 and signal[1] >= 0
then 1
else 0 ;
def dataCount = CompoundValue(1, if cond then dataCount[1] + 1 else dataCount[1], 0);
def limitplot = HighestAll(dataCount) - dataCount <= Count - 1;
#-------------------------------------------------------------------------------

input showarrows = yes;
plot U1 = showarrows and signal > 0 and signal[1] <= 0 and limitplot;
U1.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
U1.SetDefaultColor(Color.GREEN);
U1.SetLineWeight(4);
plot D1 = showarrows and signal < 0 and signal[1] >= 0 and limitplot;
D1.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
D1.SetDefaultColor(Color.RED);
D1.SetLineWeight(4);

#Color Candles based upon Last X Arrows------------------------------------------
input price_color = yes;
def colorup = if U1 then 1 else if colorup[1] and !D1 then 1 else 0;
def colordn = if D1 then 1 else if colordn[1] and !U1 then 1 else 0;
AssignPriceColor(if !price_color then Color.CURRENT
else if colorup == 1 then Color.GREEN
else if colordn == 1 then Color.RED
else Color.GRAY);
#--------------------------------------------------------------------------------

I changed the color candles code slightly and added bubbles as an option for arrows. The bubbles can be moved up/down.

The arrows and/or bubbles should plot after the bar signaling them closes. The zigzag code can produce many false signals and as it repaints if you are not watching the chart, you would never know. So the waiting for the bar to close where the plots occurs is meant to lessen the repainting. However, if you see the plotting or coloring waiting for the bar after these close, then let me know all the chart details at that time so I can test what happened. Otherwise, while watching this today and OnDemand, it looks to be acting correctly.

Ruby:
# ZigZag High Low Stats
# tomsk
# 11.16.2019

# V1.0 - 11.16.2019 - tomsk - Initial release of ZigZag High Low Stats

# Extracted idea from RDMercer's post #369 of a variant of a massive
# Zig Zag High Low Supply Demand study that comprises many different
# components
#
# https://usethinkscript.com/threads/...-signals-for-thinkorswim.183/page-19#post-369
#
# I heavily modified, cleaned up and extracted some interesting Zig Zag statistical information resulting in this study called Zig Zag High
# Low Stats. It displays the following information represented via bubbles at each of the Zig zag turning points
#
# Label for Confirmed/Unconfirmed Status of Current Zigzag
# Price Change between Zigzags
# Price at Zigzag High/Low
# Bar Count between Zigzags
# Volume at Zigzag Reversals

input showBubblesChange = no; # Price Change between Zigzags
input showBubblesPrice = no; # Price at Zigzag High/Low
input showBubblesBarCount = no; # Bar Count between Zigzags
input showBubblesVolume = no; # Volume at Zigzag Reversals

input BubbleOffset = .0005;
input PercentAmount = .01;
input RevAmount = .05;
input ATRreversal = 3.0;
input ATRlength = 5;

def zz = ZigZagHighLow("price h" = high, "price l" = low, "percentage reversal" = PercentAmount,
"absolute reversal" = RevAmount, "atr length" = ATRlength, "atr reversal" = ATRreversal);

def ReversalAmount = if (close * PercentAmount / 100) > Max(RevAmount < ATRreversal * reference ATR(ATRlength), RevAmount)
then (close * PercentAmount / 100)
else if RevAmount < ATRreversal * reference ATR(ATRlength)
then ATRreversal * reference ATR(ATRlength)
else RevAmount;
# Zig Zag Specific Data

def zzSave = if !IsNaN(zz) then zz else GetValue(zzSave, 1);
def chg = (if zzSave == high then high else low) - GetValue(zzSave, 1);
def isUp = chg >= 0;
def isConf = AbsValue(chg) >= ReversalAmount or (IsNaN(GetValue(zz, 1)) and GetValue(isConf, 1));

# Price Change Specific Data

def xxHigh = if zzSave == high then high else xxHigh[1];
def chgHigh = high - xxHigh[1];
def xxLow = if zzSave == low then low else xxLow[1];
def chgLow = low - xxLow[1];

# Bar Count Specific Data

def zzCount = if zzSave[1] != zzSave then 1 else if zzSave[1] == zzSave then zzCount[1] + 1 else 0;
def zzCountHiLo = if zzCountHiLo[1] == 0 and (zzSave == high or zzSave == low) then 1
else if zzSave == high or zzSave == low then zzCountHiLo[1] + 1
else zzCountHiLo[1];
def zzHiLo = if zzSave == high or zzSave == low then zzCountHiLo else zzCountHiLo + 1;
def zzCountHigh = if zzSave == high then zzCount[1] else Double.NaN;
def zzCountLow = if zzSave == low then zzCount[1] else Double.NaN;

# Volume Specific Data

def vol = if BarNumber() == 0 then 0 else volume + vol[1];
def vol1 = if BarNumber() == 1 then volume else vol1[1];
def xxVol = if zzSave == high or zzSave == low then TotalSum(volume) else xxVol[1];
def chgVol = if xxVol - xxVol[1] + vol1 == vol then vol else xxVol - xxVol[1];

# Zigzag Status Label

AddLabel(BarNumber() != 1, (if isConf then "Confirmed " else "Unconfirmed ") + "ZigZag: " + chg + " ATRrev " + Round(reference ATR(ATRlength) * ATRreversal, 2) + " RevAmt " + Round(ReversalAmount, 2), if !isConf then Color.DARK_ORANGE else if isUp then Color.GREEN else Color.RED);

# Zig Zag Plot

plot zzp = if isUp <= 1 then zz else Double.NaN;
zzp.AssignValueColor(if isUp then Color.DARK_GREEN else if !isUp then Color.RED else Color.DARK_ORANGE);
zzp.SetStyle(Curve.FIRM);
zzp.EnableApproximation();
zzp.HideBubble();

# Bubbles

# Price Change between Zigzags

AddChartBubble(showBubblesChange and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + BubbleOffset) else low * (1 - BubbleOffset), "$" + Round(chg, 2), if isUp and chgHigh > 0 then Color.GREEN else if isUp and chgHigh < 0 then Color.RED else if isUp then Color.YELLOW else if !isUp and chgLow > 0 then Color.GREEN else if !isUp and chgLow < 0 then Color.RED else Color.YELLOW, isUp);

# Price at Zigzag High/Low

AddChartBubble(showBubblesPrice and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + BubbleOffset) else low * (1 - BubbleOffset), if isUp then "$" + high else "$" + low, if isUp and chgHigh > 0 then Color.GREEN else if isUp and chgHigh < 0 then Color.RED else if isUp then Color.YELLOW else if !isUp and chgLow > 0 then Color.GREEN else if !isUp and chgLow < 0 then Color.RED else Color.YELLOW, isUp);

# Bar Count between Zigzags

AddChartBubble(showBubblesBarCount and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + BubbleOffset) else low * (1 - BubbleOffset), if zzSave == high then zzCountHigh else zzCountLow, if isUp and chgHigh > 0 then Color.GREEN else if isUp and chgHigh < 0 then Color.RED else if isUp then Color.YELLOW else if !isUp and chgLow > 0 then Color.GREEN else if !isUp and chgLow < 0 then Color.RED else Color.YELLOW, if isUp then yes else no);

# Volume at Zigzag Reversals

AddChartBubble(showBubblesVolume and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + BubbleOffset) else low * (1 - BubbleOffset), chgVol, if isUp and chgHigh > 0 then Color.GREEN else if isUp and chgHigh < 0 then Color.RED else if isUp then Color.YELLOW else if !isUp and chgLow > 0 then Color.GREEN else if !isUp and chgLow < 0 then Color.RED else Color.YELLOW, if isUp then yes else no);

#Arrows
def zzL = if !IsNaN(zz) and !isUp then low else GetValue(zzL, 1);
def zzH = if !IsNaN(zz) and isUp then high else GetValue(zzH, 1);
def dir = CompoundValue(1, if zzL != zzL[1] or low == zzL[1] and low == zzSave then 1 else if zzH != zzH[1] or high == zzH[1] and high == zzSave then -1 else dir[1], 0);
def signal = CompoundValue(1, if dir > 0 and low > zzL then if signal[1] <= 0 then 1 else signal[1] else if dir < 0 and high < zzH then if signal[1] >= 0 then -1 else signal[1] else signal[1], 0);

#Count to limit plot of arrows-------------------------------------------------
input Count   = 2;
def cond      = if signal > 0 and signal[1] <= 0 or
                   signal < 0 and signal[1] >= 0
                then 1
                else 0 ;
def dataCount = CompoundValue(1, if cond then dataCount[1] + 1 else dataCount[1], 0);
def limitplot = HighestAll(dataCount) - dataCount <= Count - 1;
#-------------------------------------------------------------------------------

input showarrows = yes;
plot U1 = showarrows and signal > 0 and signal[1] <= 0 and limitplot;
U1.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
U1.SetDefaultColor(Color.GREEN);
U1.SetLineWeight(4);
plot D1 = showarrows and signal < 0 and signal[1] >= 0 and limitplot;
D1.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
D1.SetDefaultColor(Color.RED);
D1.SetLineWeight(4);

#--------------------------------------------------------------------------------
input showbubbles = yes;
input bubbleupdn  = 2;#Number of ticks
addchartBubble(showbubbles and signal > 0 and signal[1] <= 0 and limitplot, low - ticksize() * bubbleupdn, "Bull", color.green, no);
addchartBubble(showbubbles and signal < 0 and signal[1] >= 0 and limitplot, high + ticksize() * bubbleupdn, "Bear", color.red);

#Color Candles based upon Last X Arrows------------------------------------------
input price_color = yes;
def colorup = if U1 then 1 else if D1 then 0
else colorup[1];
def colordn = if D1 then 1 else if U1 then 0
else colordn[1];
AssignPriceColor(if !price_color then Color.CURRENT   
                 else if colorup == 1 then Color.GREEN
                 else if colordn == 1 then Color.RED
                 else Color.GRAY);
#--------------------------------------------------------------------------------
 
I changed the color candles code slightly and added bubbles as an option for arrows. The bubbles can be moved up/down.

The arrows and/or bubbles should plot after the bar signaling them closes. The zigzag code can produce many false signals and as it repaints if you are not watching the chart, you would never know. So the waiting for the bar to close where the plots occurs is meant to lessen the repainting. However, if you see the plotting or coloring waiting for the bar after these close, then let me know all the chart details at that time so I can test what happened. Otherwise, while watching this today and OnDemand, it looks to be acting correctly.
@SleepyZ Sorry for all of the updates to this reply! The more I looked at the chart with your updated code I think this is exactly what I was trying to achieve. I was a bit confused as to whether the "signal" is based on the candlesticks changing color or the zzp plot changing color. But it seems as though it's based on the zzp plot.

Thank you for your never ending generosity and willingness to help others Sleepyz!
 
Last edited:
Cambié ligeramente el código de las velas de color y agregué burbujas como una opción para las flechas. Las burbujas se pueden mover hacia arriba/abajo.

Las flechas y/o burbujas deben trazarse después de que la barra que las señala se cierre. El código en zigzag puede producir muchas señales falsas y, como se vuelve a pintar, si no está mirando el gráfico, nunca lo sabrá. Entonces, la espera de que la barra cierre donde ocurren las tramas está destinada a disminuir el repintado. Sin embargo, si ve el trazado o el color esperando la barra después de que se cierren, infórmeme todos los detalles del gráfico en ese momento para que pueda probar qué sucedió. De lo contrario, mientras ve esto hoy y OnDemand, parece estar actuando correctamente.
Could you help me draw the last zigzag line? I tried several ways, I didn't succeed

[CÓDIGO]# Oscilación alta y Oscilación baja
# tomsk
# 11.18.2019
# Según lo solicitado por chillc15, he modificado el código @RobertPayne para incluir SwingHigh
# puntos que ahora están trazados en CYAN con los puntos altos de oscilación pintados en ROSA.

# BALANCE BAJO
# definir puntos bajos de swing
longitud de entrada = 7;
def bn = NúmeroBarra();
def lastBar = HighestAll(if IsNaN(close) then 0 else bn);
def offset = Min(longitud - 1, lastBar - bn);

def swingLow = low < Lowest(low[1], length - 1) and low == GetValue(Lowest(low, length), -offset);


# COLUMPIO ALTO
# definir puntos altos de swing
def swingHigh = high > Highest(high[1], length - 1) and high == GetValue(Highest(high, length), -offset);


plot HighArrow = swingHigh;
HighArrow.SetLineWeight(3);
HighArrow.SetDefaultColor(Color.RED);
HighArrow.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);

plot LowArrow = swingLow;
LowArrow.SetLineWeight(3);
LowArrow.SetDefaultColor(Color.VERDE);
LowArrow.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);

# Fin de oscilación alta y oscilación baja
def h = alto;
def l = bajo;
def c = cerrar;
def HH1 =h >= Mayor(h, longitud)[-longitud];
#def HH1 = h >= Mayor(h, longitud) y h >= Mayor(h, longitud)[-longitud];
def Hi1 = si HH1 entonces h sino Double.NaN;
def LL1 = l <= Más bajo(l, longitud)[-longitud];
#def LL1 = l <= Más bajo(l, longitud) y l <= Más bajo(l, longitud)[-longitud];
def Lo1 = si LL1 entonces l sino Double.NaN;
def PointCount = if BarNumber() == 1 then 0 else
si IsNaN(c) entonces PointCount[1] else
si !IsNaN(Hi1) entonces Max(1, PointCount[1] + 1) else
si !IsNaN(Lo1) entonces Min(-1, PointCount[1] - 1)
else CuentaPuntos[1];

#zigzags
#plot "ZZ%" = referencia ZigZagHighLow(high, low, reversalAmount, 0, 1, 0);
def zHI;
def zLO;
zHI = si !IsNaN(Hi1) y PointCount == 1 entonces h else Double.NaN;
#zHI = CuentaPuntos == 1 ;
zLO = si !IsNaN(Lo1) y PointCount == -1 entonces l else Double.NaN;
#plot hilowline = si zHI else zLO;;
plot hilowline = if !IsNaN(zHI) then zHI else zLO;
hilowline.EnableApproximation();
hilowline.SetLineWeight(1);
hilowline.SetDefaultColor(Color.AMARILLO);[/CÓDIGO]
 
View attachment 1045
Extracted idea from RDMercer's post #369 of a variant of a massive Zig Zag High Low Supply Demand study that comprises many different components

https://usethinkscript.com/threads/...-signals-for-thinkorswim.183/page-19#post-369
I heavily modified, cleaned up and extracted some interesting Zig Zag statistical information resulting in this study called Zig Zag High Low Stats. It displays the following information represented via bubbles at each of the Zig zag turning points

Label for Confirmed/Unconfirmed Status of Current Zigzag
Price Change between Zigzags
Price at Zigzag High/Low
Bar Count between Zigzags
Volume at Zigzag Reversals

Here's the study - you might like to load this study on a Daily chart of AAPL, AMZN or your favorite ticker
You can turn off any information you don't want via the user interface

Code:
# ZigZag High Low Stats
# tomsk
# 11.16.2019

# V1.0 - 11.16.2019 - tomsk - Initial release of ZigZag High Low Stats

# Extracted idea from RDMercer's post #369 of a variant of a massive
# Zig Zag High Low Supply Demand study that comprises many different
# components
#
# https://usethinkscript.com/threads/trend-reversal-indicator-with-signals-for-thinkorswim.183/page-19#post-369
#
# I heavily modified, cleaned up and extracted some interesting Zig Zag statistical information resulting in this study called Zig Zag High
# Low Stats. It displays the following information represented via bubbles at each of the Zig zag turning points
#
# Label for Confirmed/Unconfirmed Status of Current Zigzag
# Price Change between Zigzags
# Price at Zigzag High/Low
# Bar Count between Zigzags
# Volume at Zigzag Reversals

input showBubblesChange = no;   # Price Change between Zigzags
input showBubblesPrice = no;    # Price at Zigzag High/Low
input showBubblesBarCount = no; # Bar Count between Zigzags
input showBubblesVolume = no;   # Volume at Zigzag Reversals

input BubbleOffset = .0005;
input PercentAmount = .01;
input RevAmount = .05;
input ATRreversal = 3.0;
input ATRlength = 5;

def zz = ZigZagHighLow("price h" = high, "price l" = low, "percentage reversal" = PercentAmount,
"absolute reversal" = RevAmount, "atr length" = ATRlength, "atr reversal" = ATRreversal);

def ReversalAmount = if (close * PercentAmount / 100) > Max(RevAmount < ATRreversal * reference ATR(ATRlength), RevAmount)
                     then (close * PercentAmount / 100)
                     else if RevAmount < ATRreversal * reference ATR(ATRlength)
                          then ATRreversal * reference ATR(ATRlength)
                          else RevAmount;
# Zig Zag Specific Data

def zzSave = if !IsNaN(zz) then zz else GetValue(zzSave, 1);
def chg = (if zzSave == high then high else low) - GetValue(zzSave, 1);
def isUp = chg >= 0;
def isConf = AbsValue(chg) >= ReversalAmount or (IsNaN(GetValue(zz, 1)) and GetValue(isConf, 1));

# Price Change Specific Data

def xxHigh = if zzSave == high then high else xxHigh[1];
def chgHigh = high - xxHigh[1];
def xxLow = if zzSave == low then low else xxLow[1];
def chgLow = low - xxLow[1];

# Bar Count Specific Data

def zzCount = if zzSave[1] != zzSave then 1 else if zzSave[1] == zzSave then zzCount[1] + 1 else 0;
def zzCountHiLo = if zzCountHiLo[1] == 0 and (zzSave == high or zzSave == low) then 1
                  else if zzSave == high or zzSave == low then zzCountHiLo[1] + 1
                  else zzCountHiLo[1];
def zzHiLo = if zzSave == high or zzSave == low then zzCountHiLo else zzCountHiLo + 1;
def zzCountHigh = if zzSave == high then zzCount[1] else Double.NaN;
def zzCountLow  = if zzSave == low then zzCount[1] else Double.NaN;

# Volume Specific Data

def vol = if BarNumber() == 0 then 0 else volume + vol[1];
def vol1 = if BarNumber() == 1 then volume else vol1[1];
def xxVol = if zzSave == high or zzSave == low then TotalSum(volume) else xxVol[1];
def chgVol =  if xxvol - xxVol[1] + vol1 == vol then vol else xxVol - xxVol[1];

# Zigzag Status Label

AddLabel(BarNumber() != 1, (if isConf then "Confirmed " else "Unconfirmed ") + "ZigZag: " + chg + "  ATRrev " + Round(reference ATR(ATRlength) * ATRreversal, 2) + "  RevAmt " + Round(ReversalAmount, 2), if !isConf then Color.Dark_Orange else if isUp then Color.Green else Color.Red);

# Zig Zag Plot

plot zzp = if isUp <= 1 then zz else Double.NaN;
zzp.AssignValueColor(if isUp then Color.Green else if !isUp then Color.Red else Color.Dark_Orange);
zzp.SetStyle(Curve.FIRM);
zzp.EnableApproximation();
zzp.HideBubble();

# Bubbles

# Price Change between Zigzags

AddChartBubble(showBubblesChange and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + BubbleOffset) else low * (1 - BubbleOffset), "$" + Round(chg, 2), if isUp and chgHigh > 0 then Color.Green else if isUp and chgHigh < 0 then Color.Red else if isUp then Color.Yellow else if !isUp and chgLow > 0 then Color.Green else if !isUp and chgLow < 0 then Color.Red else Color.Yellow, isUp);

# Price at Zigzag High/Low

AddChartBubble(showBubblesPrice and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + BubbleOffset) else low * (1 - BubbleOffset), if isUp then "$" + high else "$" + low, if isUp and chgHigh > 0 then Color.Green else if isUp and chgHigh < 0 then Color.Red else if isUp then Color.Yellow else if !isUp and chgLow > 0 then Color.Green else if !isUp and chgLow < 0 then Color.Red else Color.Yellow, isUp);

# Bar Count between Zigzags

AddChartBubble(showBubblesBarCount and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + BubbleOffset) else low * (1 - BubbleOffset), if zzSave == high then zzCountHigh else zzCountLow, if isUp and chgHigh > 0 then Color.Green else if isUp and chgHigh < 0 then Color.Red else if isUp then Color.Yellow else if !isUp and chgLow > 0 then Color.Green else if !isUp and chgLow < 0 then Color.Red else Color.Yellow, if isUp then yes else no);

# Volume at Zigzag Reversals

AddChartBubble(showBubblesVolume and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + bubbleoffset) else low * (1 - bubbleoffset), chgVol, if isUp and chghigh > 0 then Color.Green else if isUp and chghigh < 0 then Color.Red else if isUp then Color.Yellow else if !isUp and chglow > 0 then Color.Green else if !isUp and chglow < 0 then Color.Red else Color.Yellow, if isUp then yes else no);

# End ZigZag High Low Stats
is it possible to modify the presentation, instead of showing bubbles, can make it just numbers like the presentation of sequencial indicator in TOS?
 
is it possible to modify the presentation, instead of showing bubbles, can make it just numbers like the presentation of sequencial indicator in TOS?

This might be what you want.

Capture.jpg
Ruby:
# ZigZag High Low Stats
# tomsk
# 11.16.2019

# V1.0 - 11.16.2019 - tomsk - Initial release of ZigZag High Low Stats

# Extracted idea from RDMercer's post #369 of a variant of a massive
# Zig Zag High Low Supply Demand study that comprises many different
# components
#
# https://usethinkscript.com/threads/trend-reversal-indicator-with-signals-for-thinkorswim.183/page-19#post-369
#
# I heavily modified, cleaned up and extracted some interesting Zig Zag statistical information resulting in this study called Zig Zag High
# Low Stats. It displays the following information represented via bubbles at each of the Zig zag turning points
#
# Label for Confirmed/Unconfirmed Status of Current Zigzag
# Price Change between Zigzags
# Price at Zigzag High/Low
# Bar Count between Zigzags
# Volume at Zigzag Reversals

input showBubblesChange = no;   # Price Change between Zigzags
input showBubblesPrice = no;    # Price at Zigzag High/Low
input showBubblesBarCount = no; # Bar Count between Zigzags
input showBubblesVolume = no;   # Volume at Zigzag Reversals

input BubbleOffset = .0005;
input PercentAmount = .01;
input RevAmount = .05;
input ATRreversal = 3.0;
input ATRlength = 5;

def zz = ZigZagHighLow("price h" = high, "price l" = low, "percentage reversal" = PercentAmount,
"absolute reversal" = RevAmount, "atr length" = ATRlength, "atr reversal" = ATRreversal);

def ReversalAmount = if (close * PercentAmount / 100) > Max(RevAmount < ATRreversal * reference ATR(ATRlength), RevAmount)
                     then (close * PercentAmount / 100)
                     else if RevAmount < ATRreversal * reference ATR(ATRlength)
                          then ATRreversal * reference ATR(ATRlength)
                          else RevAmount;
# Zig Zag Specific Data

def zzSave = if !IsNaN(zz) then zz else GetValue(zzSave, 1);
def chg = (if zzSave == high then high else low) - GetValue(zzSave, 1);
def isUp = chg >= 0;
def isConf = AbsValue(chg) >= ReversalAmount or (IsNaN(GetValue(zz, 1)) and GetValue(isConf, 1));

# Price Change Specific Data

def xxHigh = if zzSave == high then high else xxHigh[1];
def chgHigh = high - xxHigh[1];
def xxLow = if zzSave == low then low else xxLow[1];
def chgLow = low - xxLow[1];

# Bar Count Specific Data

def zzCount = if zzSave[1] != zzSave then 1 else if zzSave[1] == zzSave then zzCount[1] + 1 else 0;
def zzCountHiLo = if zzCountHiLo[1] == 0 and (zzSave == high or zzSave == low) then 1
                  else if zzSave == high or zzSave == low then zzCountHiLo[1] + 1
                  else zzCountHiLo[1];
def zzHiLo = if zzSave == high or zzSave == low then zzCountHiLo else zzCountHiLo + 1;
def zzCountHigh = if zzSave == high then zzCount[1] else Double.NaN;
def zzCountLow  = if zzSave == low then zzCount[1] else Double.NaN;

# Volume Specific Data

def vol = if BarNumber() == 0 then 0 else volume + vol[1];
def vol1 = if BarNumber() == 1 then volume else vol1[1];
def xxVol = if zzSave == high or zzSave == low then TotalSum(volume) else xxVol[1];
def chgVol =  if xxvol - xxVol[1] + vol1 == vol then vol else xxVol - xxVol[1];

# Zigzag Status Label

AddLabel(BarNumber() != 1, (if isConf then "Confirmed " else "Unconfirmed ") + "ZigZag: " + chg + "  ATRrev " + Round(reference ATR(ATRlength) * ATRreversal, 2) + "  RevAmt " + Round(ReversalAmount, 2), if !isConf then Color.Dark_Orange else if isUp then Color.Green else Color.Red);

# Zig Zag Plot

plot zzp = if isUp <= 1 then zz else Double.NaN;
zzp.AssignValueColor(if isUp then Color.Green else if !isUp then Color.Red else Color.Dark_Orange);
zzp.SetStyle(Curve.FIRM);
zzp.EnableApproximation();
zzp.HideBubble();

plot xdn = if !isnan(zz) and isup then zzcounthigh else double.nan;
xdn.setpaintingStrategy(PaintingStrategy.VALUES_ABOVE);
xdn.setdefaultColor(color.red);

plot xup = if !isnan(zz) and !isup then zzcountlow else double.nan;
xup.setpaintingStrategy(PaintingStrategy.VALUES_BELOW);
xup.setdefaultColor(color.green);


# Bubbles

# Price Change between Zigzags

AddChartBubble(showBubblesChange and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + BubbleOffset) else low * (1 - BubbleOffset), "$" + Round(chg, 2), if isUp and chgHigh > 0 then Color.Green else if isUp and chgHigh < 0 then Color.Red else if isUp then Color.Yellow else if !isUp and chgLow > 0 then Color.Green else if !isUp and chgLow < 0 then Color.Red else Color.Yellow, isUp);

# Price at Zigzag High/Low

AddChartBubble(showBubblesPrice and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + BubbleOffset) else low * (1 - BubbleOffset), if isUp then "$" + high else "$" + low, if isUp and chgHigh > 0 then Color.Green else if isUp and chgHigh < 0 then Color.Red else if isUp then Color.Yellow else if !isUp and chgLow > 0 then Color.Green else if !isUp and chgLow < 0 then Color.Red else Color.Yellow, isUp);

# Bar Count between Zigzags

AddChartBubble(showBubblesBarCount and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + BubbleOffset) else low * (1 - BubbleOffset), if zzSave == high then zzCountHigh else zzCountLow, if isUp and chgHigh > 0 then Color.Green else if isUp and chgHigh < 0 then Color.Red else if isUp then Color.Yellow else if !isUp and chgLow > 0 then Color.Green else if !isUp and chgLow < 0 then Color.Red else Color.Yellow, if isUp then yes else no);

# Volume at Zigzag Reversals

AddChartBubble(showBubblesVolume and !IsNaN(zz) and BarNumber() != 1, if isUp then high * (1 + bubbleoffset) else low * (1 - bubbleoffset), chgVol, if isUp and chghigh > 0 then Color.Green else if isUp and chghigh < 0 then Color.Red else if isUp then Color.Yellow else if !isUp and chglow > 0 then Color.Green else if !isUp and chglow < 0 then Color.Red else Color.Yellow, if isUp then yes else no);

# End ZigZag High Low Stats
 
hello, i got this code from here...
https://usethinkscript.com/threads/zigzag-high-low-stats-for-thinkorswim.1073/page-2#post-57956

i was inquirying to see if someone can help me add pivot lines on the swing high and lows of this zigzag indicator such as the ones i manually placed in the image below with the right extension on and price label. i looked at a few other similiar indicators that have the lines but i cannot seem to get them to work with this indicator. any assistance would be greatly appreciated.

SoK55js.png



Code:
## START CODE
## ZigZagSign TOMO modification, v0.2 written by Linus @Thinkscripter Lounge adapted from Thinkorswim ZigZagSign Script

input showBubbleschange = yes;
def price             = close;
def priceH            = high;    # swing high
def priceL            = low;     # swing low
def ATRreversalfactor = 3.2;
def ATR                 = reference ATR(length = 5);
def reversalAmount      = ATRreversalfactor * ATR;
def displace          = 1;



def barNumber = BarNumber();
def barCount = HighestAll(If(IsNaN(price), 0, barNumber));

rec state = {default init, undefined, uptrend, downtrend};
rec minMaxPrice;

if (GetValue(state, 1) == GetValue(state.init, 0)) {
    minMaxPrice = price;
    state = state.undefined;
} else if (GetValue(state, 1) == GetValue(state.undefined, 0)) {
    if (price <= GetValue(minMaxPrice, 1) - reversalAmount) {
        state = state.downtrend;
        minMaxPrice = priceL;
    } else if (price >= GetValue(minMaxPrice, 1) + reversalAmount) {
        state = state.uptrend;
        minMaxPrice = priceH;
    } else {
        state = state.undefined;
        minMaxPrice = GetValue(minMaxPrice, 1);
    }
} else if (GetValue(state, 1) == GetValue(state.uptrend, 0)) {
    if (price <= GetValue(minMaxPrice, 1) - reversalAmount) {
        state = state.downtrend;
        minMaxPrice = priceL;
    } else {
        state = state.uptrend;
        minMaxPrice = Max(priceH, GetValue(minMaxPrice, 1));
    }
} else {
    if (price >= GetValue(minMaxPrice, 1) + reversalAmount) {
        state = state.uptrend;
        minMaxPrice = priceH;
    } else {
        state = state.downtrend;
        minMaxPrice = Min(priceL, GetValue(minMaxPrice, 1));
    }
}

def isCalculated = GetValue(state, 0) != GetValue(state, 1) and barNumber >= 1;
def futureDepth =  barCount - barNumber;
def tmpLastPeriodBar;
if (isCalculated) {
    if (futureDepth >= 1 and GetValue(state, 0) == GetValue(state, -1)) {
        tmpLastPeriodBar = fold lastPeriodBarI = 2 to futureDepth + 1 with lastPeriodBarAcc = 1
            while lastPeriodBarAcc > 0
            do if (GetValue(state, 0) != GetValue(state, -lastPeriodBarI))
                then -lastPeriodBarAcc
                else lastPeriodBarAcc + 1;
    } else {
        tmpLastPeriodBar = 0;
    }
} else {
    tmpLastPeriodBar = Double.NaN;
}

def lastPeriodBar = if (!IsNaN(tmpLastPeriodBar)) then -AbsValue(tmpLastPeriodBar) else -futureDepth;

rec currentPriceLevel;
rec currentPoints;
if (state == state.uptrend and isCalculated) {
    currentPriceLevel =
        fold barWithMaxOnPeriodI = lastPeriodBar to 1 with barWithMaxOnPeriodAcc = minMaxPrice
            do Max(barWithMaxOnPeriodAcc, GetValue(minMaxPrice, barWithMaxOnPeriodI));
    currentPoints =
        fold maxPointOnPeriodI = lastPeriodBar to 1 with maxPointOnPeriodAcc = Double.NaN
            while IsNaN(maxPointOnPeriodAcc)
            do if (GetValue(priceH, maxPointOnPeriodI) == currentPriceLevel)
                then maxPointOnPeriodI
                else maxPointOnPeriodAcc;
} else if (state == state.downtrend and isCalculated) {
    currentPriceLevel =
        fold barWithMinOnPeriodI = lastPeriodBar to 1 with barWithMinOnPeriodAcc = minMaxPrice
            do Min(barWithMinOnPeriodAcc, GetValue(minMaxPrice, barWithMinOnPeriodI));
    currentPoints =
        fold minPointOnPeriodI = lastPeriodBar to 1 with minPointOnPeriodAcc = Double.NaN
            while IsNaN(minPointOnPeriodAcc)
            do if (GetValue(priceL, minPointOnPeriodI) == currentPriceLevel)
                then minPointOnPeriodI
                else minPointOnPeriodAcc;
} else if (!isCalculated and (state == state.uptrend or state == state.downtrend)) {
    currentPriceLevel = GetValue(currentPriceLevel, 1);
    currentPoints = GetValue(currentPoints, 1) + 1;
} else {
    currentPoints = 1;
    currentPriceLevel = GetValue(price, currentPoints);
}

def data = if (barNumber == barCount or barNumber == 1) then if state == state.uptrend then priceH else priceL else if (currentPoints == 0) then currentPriceLevel else Double.NaN;

rec zzSave =  if !IsNaN(data) then if (barNumber == barCount or barNumber == 1) then if IsNaN(barNumber[-1]) and  state == state.uptrend then priceH else priceL else currentPriceLevel else GetValue(zzSave, 1);

def chg = (if barNumber == barCount and currentPoints < 0 then priceH else if barNumber == barCount and currentPoints > 0 then priceL else currentPriceLevel) - GetValue(zzSave, 1);

def isUp = chg >= 0;

#Higher/Lower/Equal High, Higher/Lower/Equal Low
def xxhigh = if zzSave == priceH then Round(high, 2) else Round(xxhigh[1], 2);
def chghigh = Round(Round(high, 2) - Round(xxhigh[1], 2), 2);
def xxlow = if zzSave == priceL then Round(low, 2) else Round(xxlow[1], 2);
def chglow = Round(Round(low, 2) - Round(xxlow[1], 2), 2);


rec isConf = AbsValue(chg) >= reversalAmount or (IsNaN(GetValue(data, 1)) and GetValue(isConf, 1));


plot "ZZ$" = if isConf then data else Double.NaN;
"ZZ$".EnableApproximation();
"ZZ$".SetDefaultColor(Color.CYAN);

DefineGlobalColor("Unconfirmed", Color.WHITE);
DefineGlobalColor("Up", Color.UPTICK);
DefineGlobalColor("Down", Color.DOWNTICK);

AddChartBubble(showBubbleschange and !IsNaN("ZZ$" ) and barNumber != 1, if isUp then high else low , Round(chg, 2) , if barCount == barNumber or !isConf then GlobalColor("Unconfirmed" ) else if isUp then GlobalColor("Up" ) else GlobalColor("Down" ), isUp);

## END CODE
 
Last edited by a moderator:
ive looked everywhere for just a simple label that can determine if price action is currently making HHs or LLs,

ive tried coding myself one and using other scripts that determine HHLLs with bubbles on the chart but ive got to many dam indicators...lol and cant see anything if i add another. so with that has anyone seen what im looking for or have some kind of start to code that i can try to tweak. i would greatly appreciate you. thanks for your time and effort.
 
@Madison If you haven't already done this, here is one way to use code to count the number of Highs and Lows displayed on the chart.

This will show labelsHHLL for whether zigzag pivots are HH/LH or HL/LL. The most recent of each is shown 1st.

There are options to show testlabels and testbubbles to show the basis for the labelsHHLL. There is a count for consecutive HH/LH and HL/LL which are shown in the testbubbles.

Screenshot-2023-02-22-084446.png
Code:
#HHLL_ZigZag_Labels_Bubbles_Count
## START CODE
## ZigZagSign TOMO modification, v0.2 written by Linus @Thinkscripter Lounge adapted from Thinkorswim ZigZagSign Script

input showBubbleschange = yes;
def price             = close;
def priceH            = high;    # swing high
def priceL            = low;     # swing low
input ATRreversalfactor = 3.2;
input ATRLength = 5;
def ATR                 = reference ATR(ATRlength);
def reversalAmount      = ATRreversalfactor * ATR;
def displace          = 1;



def barNumber = BarNumber();
def barCount = HighestAll(If(IsNaN(price), 0, barNumber));

rec state = {default init, undefined, uptrend, downtrend};
rec minMaxPrice;

if (GetValue(state, 1) == GetValue(state.init, 0)) {
    minMaxPrice = price;
    state = state.undefined;
} else if (GetValue(state, 1) == GetValue(state.undefined, 0)) {
    if (price <= GetValue(minMaxPrice, 1) - reversalAmount) {
        state = state.downtrend;
        minMaxPrice = priceL;
    } else if (price >= GetValue(minMaxPrice, 1) + reversalAmount) {
        state = state.uptrend;
        minMaxPrice = priceH;
    } else {
        state = state.undefined;
        minMaxPrice = GetValue(minMaxPrice, 1);
    }
} else if (GetValue(state, 1) == GetValue(state.uptrend, 0)) {
    if (price <= GetValue(minMaxPrice, 1) - reversalAmount) {
        state = state.downtrend;
        minMaxPrice = priceL;
    } else {
        state = state.uptrend;
        minMaxPrice = Max(priceH, GetValue(minMaxPrice, 1));
    }
} else {
    if (price >= GetValue(minMaxPrice, 1) + reversalAmount) {
        state = state.uptrend;
        minMaxPrice = priceH;
    } else {
        state = state.downtrend;
        minMaxPrice = Min(priceL, GetValue(minMaxPrice, 1));
    }
}

def isCalculated = GetValue(state, 0) != GetValue(state, 1) and barNumber >= 1;
def futureDepth =  barCount - barNumber;
def tmpLastPeriodBar;
if (isCalculated) {
    if (futureDepth >= 1 and GetValue(state, 0) == GetValue(state, -1)) {
        tmpLastPeriodBar = fold lastPeriodBarI = 2 to futureDepth + 1 with lastPeriodBarAcc = 1
            while lastPeriodBarAcc > 0
            do if (GetValue(state, 0) != GetValue(state, -lastPeriodBarI))
                then -lastPeriodBarAcc
                else lastPeriodBarAcc + 1;
    } else {
        tmpLastPeriodBar = 0;
    }
} else {
    tmpLastPeriodBar = Double.NaN;
}

def lastPeriodBar = if (!IsNaN(tmpLastPeriodBar)) then -AbsValue(tmpLastPeriodBar) else -futureDepth;

rec currentPriceLevel;
rec currentPoints;
if (state == state.uptrend and isCalculated) {
    currentPriceLevel =
        fold barWithMaxOnPeriodI = lastPeriodBar to 1 with barWithMaxOnPeriodAcc = minMaxPrice
            do Max(barWithMaxOnPeriodAcc, GetValue(minMaxPrice, barWithMaxOnPeriodI));
    currentPoints =
        fold maxPointOnPeriodI = lastPeriodBar to 1 with maxPointOnPeriodAcc = Double.NaN
            while IsNaN(maxPointOnPeriodAcc)
            do if (GetValue(priceH, maxPointOnPeriodI) == currentPriceLevel)
                then maxPointOnPeriodI
                else maxPointOnPeriodAcc;
} else if (state == state.downtrend and isCalculated) {
    currentPriceLevel =
        fold barWithMinOnPeriodI = lastPeriodBar to 1 with barWithMinOnPeriodAcc = minMaxPrice
            do Min(barWithMinOnPeriodAcc, GetValue(minMaxPrice, barWithMinOnPeriodI));
    currentPoints =
        fold minPointOnPeriodI = lastPeriodBar to 1 with minPointOnPeriodAcc = Double.NaN
            while IsNaN(minPointOnPeriodAcc)
            do if (GetValue(priceL, minPointOnPeriodI) == currentPriceLevel)
                then minPointOnPeriodI
                else minPointOnPeriodAcc;
} else if (!isCalculated and (state == state.uptrend or state == state.downtrend)) {
    currentPriceLevel = GetValue(currentPriceLevel, 1);
    currentPoints = GetValue(currentPoints, 1) + 1;
} else {
    currentPoints = 1;
    currentPriceLevel = GetValue(price, currentPoints);
}

def data = if (barNumber == barCount or barNumber == 1) then if state == state.uptrend then priceH else priceL else if (currentPoints == 0) then currentPriceLevel else Double.NaN;

rec zzSave =  if !IsNaN(data) then if (barNumber == barCount or barNumber == 1) then if IsNaN(barNumber[-1]) and  state == state.uptrend then priceH else priceL else currentPriceLevel else GetValue(zzSave, 1);

def chg = (if barNumber == barCount and currentPoints < 0 then priceH else if barNumber == barCount and currentPoints > 0 then priceL else currentPriceLevel) - GetValue(zzSave, 1);

def isUp = chg >= 0;

#Higher/Lower/Equal High, Higher/Lower/Equal Low
def xxhigh = if zzSave == priceH then Round(high, 2) else Round(xxhigh[1], 2);
def chghigh = Round(Round(high, 2) - Round(xxhigh[1], 2), 2);
def xxlow = if zzSave == priceL then Round(low, 2) else Round(xxlow[1], 2);
def chglow = Round(Round(low, 2) - Round(xxlow[1], 2), 2);


rec isConf = AbsValue(chg) >= reversalAmount or (IsNaN(GetValue(data, 1)) and GetValue(isConf, 1));


plot "ZZ$" = if isConf then data else Double.NaN;
"ZZ$".EnableApproximation();
"ZZ$".SetDefaultColor(Color.CYAN);

DefineGlobalColor("Unconfirmed", Color.WHITE);
DefineGlobalColor("Up", Color.UPTICK);
DefineGlobalColor("Down", Color.DOWNTICK);

AddChartBubble(showBubbleschange and !IsNaN("ZZ$" ) and barNumber != 1, if isUp then high else low , Round(chg, 2) , if barCount == barNumber or !isConf then GlobalColor("Unconfirmed" ) else if isUp then GlobalColor("Up" ) else GlobalColor("Down" ), isUp);

## END CODE
#Label/Bubbles Addon

input labelsHHLL = yes;
input testlabels = yes;
input testbubbles = yes;

#Highs
def z = if isUp and !IsNaN("ZZ$") then zzSave else z[1];

#Highs = Last 5 Values
def z1 = if z != z[1] then z else z1[1];
def z2 = if z1 != z1[1] then z1[1] else z2[1];
def z3 = if z2 != z2[1] then z2[1] else z3[1];
def z4 = if z3 != z3[1] then z3[1] else z4[1];
def z5 = if z4 != z4[1] then z4[1] else z5[1];
AddLabel(testlabels, z1 + " " + z2 + " " + z3 + " " + z4 + " " + z5, Color.GREEN);

#Highs - Labels for HH/LH - Most Recent 1st
AddLabel(labelsHHLL, "HIGHS:", Color.WHITE);
AddLabel(labelsHHLL, if z1 > z2 then "HH" else "LH", if z1 > z2 then Color.GREEN else Color.RED);
AddLabel(labelsHHLL, if z2 > z3 then "HH" else "LH", if z2 > z3 then Color.GREEN else Color.RED);
AddLabel(labelsHHLL, if z3 > z4 then "HH" else "LH", if z3 > z4 then Color.GREEN else Color.RED);
AddLabel(labelsHHLL, if z4 > z5 then "HH" else "LH", if z4 > z5 then Color.GREEN else Color.RED);

#Count Highs
def hh = if isUp and !IsNaN("ZZ$") and z1 > z2 then hh[1] + 1 else if isUp and !IsNaN("ZZ$") and z1 < z2 then 0 else hh[1];
def lh = if isUp and !IsNaN("ZZ$") and z1 < z2 then lh[1] + 1 else if isUp and !IsNaN("ZZ$") and z1 > z2 then 0 else lh[1];
AddChartBubble(testbubbles and isUp and !IsNaN("ZZ$"), if isUp then high else low, if z1 < z2 then "LH:" + lh else "HH:" + hh, if z1 > z2 then Color.GREEN else Color.RED);

###########################################################
#Lows
def lz = if !isUp and !IsNaN("ZZ$") then zzSave else lz[1];
#Lows - Last 5 Values
def lz1 = if lz != lz[1] then lz else lz1[1];
def lz2 = if lz1 != lz1[1] then lz1[1] else lz2[1];
def lz3 = if lz2 != lz2[1] then lz2[1] else lz3[1];
def lz4 = if lz3 != lz3[1] then lz3[1] else lz4[1];
def lz5 = if lz4 != lz4[1] then lz4[1] else lz5[1];
AddLabel(testlabels, lz1 + " " + lz2 + " " + lz3 + " " + lz4 + " " + lz5);

#Lows - Labels for HL/LL - Most Recent 1st
AddLabel(labelsHHLL, "       ", Color.BLACK);#Spacer
AddLabel(labelsHHLL, "LOWS:", Color.WHITE);
AddLabel(labelsHHLL, if lz1 > lz2 then "HL" else "LL", if lz1 > lz2 then Color.GREEN else Color.RED);
AddLabel(labelsHHLL, if lz2 > lz3 then "HL" else "LL", if lz2 > lz3 then Color.GREEN else Color.RED);
AddLabel(labelsHHLL, if lz3 > lz4 then "HL" else "LL", if lz3 > lz4 then Color.GREEN else Color.RED);
AddLabel(labelsHHLL, if lz4 > lz5 then "HL" else "LL", if lz4 > lz5 then Color.GREEN else Color.RED);

#Count Lows
def hl = if !isUp and !IsNaN("ZZ$") and lz1 > lz2 then hl[1] + 1 else if !isUp and !IsNaN("ZZ$") and lz1 < lz2 then 0 else hl[1];
def ll = if !isUp and !IsNaN("ZZ$") and lz1 < lz2 then ll[1] + 1 else if !isUp and !IsNaN("ZZ$") and lz1 > lz2 then 0 else ll[1];
AddChartBubble(testbubbles and !isUp and !IsNaN("ZZ$"), if isUp then high else low, if lz1 > lz2 then "HL:" + hl else "LL:" + ll, if lz1 > lz2 then Color.GREEN else Color.RED, no);
;
 
ive looked everywhere for just a simple label that can determine if price action is currently making HHs or LLs,

ive tried coding myself one and using other scripts that determine HHLLs with bubbles on the chart but ive got to many dam indicators...lol and cant see anything if i add another. so with that has anyone seen what im looking for or have some kind of start to code that i can try to tweak. i would greatly appreciate you. thanks for your time and effort.

here is something to start with

it draws,
..wedges on peaks that are higher than the previous peak
..wedges on valleys that are lower than the previous valley.
..lines from peaks and valleys

can draw arrows on every peak and valley.

peaks and valleys are defined by a quantity of bars before and after the current bar. default is 5


Code:
# higher_highs_lower_lows_00

#https://usethinkscript.com/threads/hhll-label.14565/
#HHLL label ?
#ArmyScalper  2/21

#------------------------
#https://usethinkscript.com/threads/zigzag-high-low-with-supply-demand-zones-for-thinkorswim.172/#post-7048
# original code, bar qty includes current bar
# define swing low points , robert payne
# modifified by halcyonguy to ignore last bar , and bar qty does not include current bar
#------------------------
def bn = BarNumber();
def na = double.nan;
input peak_valley_bars = 5;
def length = peak_valley_bars;
def lastbn = HighestAll(if IsNaN(close) then 0 else bn);
def offset = Min(length - 1, lastbn - bn);
input ignore_last_bar = yes;
def ignorelast = if (ignore_last_bar and bn == lastbn) then 0 else 1;

# chg so 2+ price levels in a row won't be skipped. trigger on the last bar in set, >= prev bars
def peak = ignorelast and high >= highest(high[1], length) and high > GetValue(highest(high, length), -(offset+1));
def valley = ignorelast and low <= Lowest(low[1], length) and low < GetValue(Lowest(low, length), -(offset+1));

# hold value of recent peak/valley
def pklevel = if bn == 1 then na else if peak then high else pklevel[1];
def vallevel = if bn == 1 then na else if valley then low else vallevel[1];

input show_levels = yes;
plot zh = if show_levels then pklevel else na;
plot zv = if show_levels then vallevel else na;
zh.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
zv.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);

def hihi = (peak and high > pklevel[1]);
def lohi = (peak and high < pklevel[1]);
def hilo = (valley and low > vallevel[1]);
def lolo = (valley and low < vallevel[1]);

plot zhihi = if hihi then 1 else 0;
zhihi.SetPaintingStrategy(PaintingStrategy.boolean_wedge_up);
zhihi.SetDefaultColor(Color.cyan);
zhihi.setlineweight(3);
zhihi.hidebubble();

plot zlolo = if lolo then 1 else 0;
zlolo.SetPaintingStrategy(PaintingStrategy.boolean_wedge_down);
zlolo.SetDefaultColor(Color.yellow);
zlolo.setlineweight(3);
zlolo.hidebubble();

#-----------------------------

input show_arrows = no;
def vert = 0.001;
plot z1 = if show_arrows and peak then high*(1+vert) else na;
z1.SetPaintingStrategy(PaintingStrategy.arrow_down);
z1.SetDefaultColor(Color.cyan);
z1.setlineweight(1);
z1.hidebubble();

plot z2 = if show_arrows and valley then low*(1-vert) else na;
z2.SetPaintingStrategy(PaintingStrategy.arrow_up);
z2.SetDefaultColor(Color.cyan);
z2.setlineweight(1);
z2.hidebubble();
#

GBO6k8b.jpg
 
ive looked everywhere for just a simple label that can determine if price action is currently making HHs or LLs,

ive tried coding myself one and using other scripts that determine HHLLs with bubbles on the chart but ive got to many dam indicators...lol and cant see anything if i add another. so with that has anyone seen what im looking for or have some kind of start to code that i can try to tweak. i would greatly appreciate you. thanks for your time and effort.

Just noticed that you posed this same question that I responded on the same day as @halcyonguy did. Please only post your question in one thread. https://usethinkscript.com/threads/zigzag-high-low-stats-for-thinkorswim.1073/post-120429
 

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
441 Online
Create Post

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