ThinkScript: Bar-based ZigZag (N-bar confirmed) + one bubble after each pivot

samhanoh

New member
Platform
  1. Thinkorswim
Hi,
I need a ThinkScript study that:

  • Detects pivot highs/lows by bar confirmation: N bars to the right (default N = 50, user input).
  • Draws a ZigZag line only between consecutive confirmed pivots (no early lines / no repaint).
  • Shows exactly one bubble only when a pivot is confirmed (i.e., on bar t+N for a pivot at t):
    • Green bubble for confirmed pivot high, red for confirmed pivot low (black text).
    • Bubble text = bar count between the previous confirmed pivot and this pivot.
 

barbaros

Administrator
Staff member
Is this close to what you are looking for?


Code:
# 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);
 
Top