# Pivot High/Low ZigZag Indicator
# Detects pivot highs/lows with N bars confirmation
# Draws zigzag lines between consecutive confirmed pivots
# Shows bubbles with bar count at confirmed pivots
#
# Free for use for non commercial. Header credits must be included when any form of the code included in this package is used.
# User assumes all risk. Author not responsible for errors or use of tool.
# b4indicators.com
declare upper;
# User input for confirmation bars
input N = 50;
# Variables to track pivot highs
def isPivotHigh = high == Highest(high, 2 * N + 1) and high == GetValue(high, N);
def pivotHighPrice = if isPivotHigh then high else Double.NaN;
def pivotHighBar = if isPivotHigh then BarNumber() else pivotHighBar[1];
# Variables to track pivot lows
def isPivotLow = low == Lowest(low, 2 * N + 1) and low == GetValue(low, N);
def pivotLowPrice = if isPivotLow then low else Double.NaN;
def pivotLowBar = if isPivotLow then BarNumber() else pivotLowBar[1];
# Track the last confirmed pivot type (1 = high, -1 = low)
def lastPivotType = if isPivotHigh then 1
else if isPivotLow then -1
else lastPivotType[1];
# Track last pivot values
def lastPivotPrice = if isPivotHigh then high
else if isPivotLow then low
else lastPivotPrice[1];
def lastPivotBarNum = if isPivotHigh or isPivotLow then BarNumber()
else lastPivotBarNum[1];
# Track previous confirmed pivot
def prevPivotPrice = if isPivotHigh or isPivotLow then lastPivotPrice[1]
else prevPivotPrice[1];
def prevPivotBarNum = if isPivotHigh or isPivotLow then lastPivotBarNum[1]
else prevPivotBarNum[1];
# Calculate bars between pivots
def barsBetween = if isPivotHigh or isPivotLow then BarNumber() - prevPivotBarNum
else Double.NaN;
# Plot pivot points (for reference, can be hidden)
plot PivotHigh = pivotHighPrice;
PivotHigh.SetPaintingStrategy(PaintingStrategy.BOOLEAN_POINTS);
PivotHigh.SetDefaultColor(Color.GREEN);
PivotHigh.SetLineWeight(3);
PivotHigh.Hide();
plot PivotLow = pivotLowPrice;
PivotLow.SetPaintingStrategy(PaintingStrategy.BOOLEAN_POINTS);
PivotLow.SetDefaultColor(Color.RED);
PivotLow.SetLineWeight(3);
PivotLow.Hide();
# Draw zigzag line between consecutive confirmed pivots
def linePrice = if BarNumber() >= prevPivotBarNum and BarNumber() <= lastPivotBarNum
then prevPivotPrice + (lastPivotPrice - prevPivotPrice) *
(BarNumber() - prevPivotBarNum) / (lastPivotBarNum - prevPivotBarNum)
else Double.NaN;
plot ZigZag = linePrice;
ZigZag.SetDefaultColor(Color.MAGENTA);
ZigZag.SetLineWeight(2);
ZigZag.SetStyle(Curve.FIRM);
# Add bubbles at confirmed pivots showing bar count
AddChartBubble(isPivotHigh and !IsNaN(barsBetween), high, barsBetween,
Color.BLACK, yes);
AddChartBubble(isPivotLow and !IsNaN(barsBetween), low, barsBetween,
Color.BLACK, no);
# Color the bubbles
DefineGlobalColor("PivotHighBubble", Color.GREEN);
DefineGlobalColor("PivotLowBubble", Color.RED);