#TOS version ZigZagHighLow modified in part by Linus' and Lar's code
input method = {default average, high_low};
input bubbleoffset = .001;
input percentamount = .01;
input revAmount = .05;
input atrreversal = 3.0;
input atrlength = 5;
input pricehigh = high;
input pricelow = low;
input averagelength = 5;
input 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 zz = ZigZagHighLow("price h" = priceh, "price l" = pricel, "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;
rec zzSave = if !IsNaN(zz) then zz else GetValue(zzSave, 1);
def chg = (if zzSave == priceh then priceh else pricel) - GetValue(zzSave, 1);
def isUp = chg >= 0;
rec isConf = AbsValue(chg) >= reversalAmount or (IsNaN(GetValue(zz, 1)) and GetValue(isConf, 1));
def zzd = if isUp then 1 else 0;
plot zzp = if zzd <= 1 then zz else Double.NaN;
zzp.AssignValueColor(if zzd == 1 then Color.GREEN else if zzd == 0 then Color.RED else Color.DARK_ORANGE);
zzp.SetStyle(Curve.FIRM);
zzp.EnableApproximation();
zzp.HideBubble();
#Price Change between zigzags
def xxhigh = if zzSave == priceh then priceh else xxhigh[1];
def chghigh = priceh - xxhigh[1];
def xxlow = if zzSave == pricel then pricel else xxlow[1];
def chglow = pricel - xxlow[1];
input showBubbleschange = no;
AddChartBubble(showBubbleschange and !IsNaN(zz) and BarNumber() != 1, if isUp then priceh * (1 + bubbleoffset) else pricel * (1 - bubbleoffset) , "$" + astext(chg) , 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 High/Low
input showBubblesprice = no;
AddChartBubble(showBubblesprice and !IsNaN(zz) and BarNumber() != 1, if isUp then priceh * (1 + bubbleoffset) else pricel * (1 - bubbleoffset) , if isUp then "$" + priceh else "$" + pricel , 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);
#Label for Confirmed/Unconfirmed Status of Current Zigzag
AddLabel(BarNumber() != 1, "ZZRev: " + chg + "Confirm@ " + Round(reversalAmount, 2), if !isConf then Color.DARK_ORANGE else if isUp then Color.GREEN else Color.RED);
#Daily ZigZag Range Total
rec counth = if GetDay() == GetLastDay() and SecondsFromTime(0930) >= 0 then CompoundValue(1, if counth[1] == 0 and !IsNaN(chghigh) and zzSave == pricehigh and zzSave != pricelow then AbsValue(chg) else if !IsNaN(chghigh) and (zzSave == pricehigh and zzSave != pricelow) then counth[1] + AbsValue(chg) else counth[1], 0) else 0;
rec countl = if GetDay() == GetLastDay() and SecondsFromTime(0930) >= 0 then CompoundValue(1, if countl[1] == 0 and !IsNaN(chglow) and zzSave != pricehigh and zzSave == pricelow then AbsValue(chg) else if !IsNaN(chglow) and (zzSave != pricehigh and zzSave == pricelow) then countl[1] + AbsValue(chg) else countl[1], 0) else 0;
AddLabel(yes, "ZZRange " + "$" + Round((counth + countl), 2), Color.GREEN);
#Bar Count between zigzags
def barnumber = BarNumber();
rec 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 == priceh or zzSave == pricel) then 1 else if zzSave == priceh or zzSave == pricel then zzcounthilo[1] + 1 else zzcounthilo[1];
def zzhilo = if zzSave == priceh or zzSave == pricel then zzcounthilo else zzcounthilo + 1;
def zzcounthigh = if zzSave == priceh then zzcount[1] else Double.NaN;
def zzcountlow = if zzSave == pricel then zzcount[1] else Double.NaN;
input showBubblesbarcount = no;
AddChartBubble(showBubblesbarcount and !IsNaN(zz) and BarNumber() != 1, if isUp then priceh * (1 + bubbleoffset) else pricel * (1 - bubbleoffset) , if zzSave == priceh 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 Reversals
input showvolumewave = no;
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 == priceh or zzSave == pricel then TotalSum(volume) else xxvol[1];
def chgvol = if xxvol - xxvol[1] + vol1 == vol then vol else xxvol - xxvol[1];
plot cvol = chgvol;
cvol.AssignValueColor( if isUp then Color.GREEN else Color.RED);
cvol.SetHiding(showvolumewave == no);
rec zzvol = if zzhilo[1] != zzhilo then 0 else zzvol[1] + volume;
plot zzvolupdn = if showvolumewave then zzvol else Double.NaN;
zzvolupdn.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
zzvolupdn.AssignValueColor(if isUp then Color.GREEN else Color.RED);
rec volup = if isUp then if close > open then volup[1] + volume else volup[1] else 0;
rec volup_ = if isUp then if close <= open then volup_[1] + volume else volup_[1] else 0;
def volup1 = if zzSave == priceh then volup - volup_ else Double.NaN;
rec voldn = if !isUp then if close > open then voldn[1] + volume else voldn[1] else 0;
rec voldn_ = if !isUp then if close <= open then voldn_[1] + volume else voldn_[1] else 0;
def voldn1 = if zzSave == pricel then voldn - voldn_ else Double.NaN;
input show_net_volume = yes;
AddChartBubble(show_net_volume and !IsNaN(zz) and BarNumber() != 1, if isUp then priceh * (1 + bubbleoffset) else pricel * (1 - bubbleoffset), "NV: " + if isUp then AbsValue(volup1) else AbsValue(voldn1), 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 );
plot zzt = if showvolumewave then if zzSave == priceh or zzSave == pricel then chgvol else Double.NaN else Double.NaN;
zzt.EnableApproximation();
zzt.AssignValueColor( if isUp then Color.GREEN else Color.RED);
zzt.SetLineWeight(2);
AddChartBubble(showvolumewave and !IsNaN(zz) and barnumber != 1, chgvol , chgvol, if isUp then Color.GREEN else Color.RED, yes);
AddChartBubble(showvolumewave and !IsNaN(zz) and barnumber != 1, chgvol , if zzSave == priceh 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.GREEN else if !isUp and chglow > 0 then Color.GREEN else if !isUp and chglow < 0 then Color.RED else Color.RED, yes );
input showBubblesVolume = no;
AddChartBubble(showBubblesVolume and !IsNaN(zz) and BarNumber() != 1, if isUp then priceh * (1 + bubbleoffset) else pricel * (1 - bubbleoffset), "ZV: " + 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 );