Skip to content

Instantly share code, notes, and snippets.

@niquedegraaff
Last active July 7, 2025 13:24
Show Gist options
  • Save niquedegraaff/4428558435f74cd30de1d9b95895af01 to your computer and use it in GitHub Desktop.
Save niquedegraaff/4428558435f74cd30de1d9b95895af01 to your computer and use it in GitHub Desktop.
Enhanced version 3 of built-in ZigZagLib library. This version supports HH LH / LL HL labels to be shown, it also exports a prevPivot function that allows the user to retrieve the previous privot with same isHigh value as latest pivot. It also stores a isHigher field in the Pivot type. This can come in handy if user wants to calculate a trend (o…
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © niquedegraaff
//@version=6
library("Absolute_ZigZag_Lib", overlay = true)
// @type The source to use
// @param high (float) The high value for the pivot lows.
// @param low (float) The low value for the pivot highs.
// @param priority (string) Which source has higher priority ("high" or "low"). Default is "high"
export type Source
float high = high
float low = low
string priority = "high"
// @type Features to enable
// @param closeBreaksClose (bool) Check if current (highest/lowest) pivot close broke previous pivot close.
// @param closeBreaksPivot (bool) Check if current (highest/lowest) pivot close broke previous pivot (high or low).
export type Features
bool closeBreaksClose = false
bool closeBreaksPivot = false
// @type Tooltips to show
// @param name (bool) Show the pivot's name in the tooltip?
// @param price (bool) Show the pivot's price in the tooltip?
// @param close (bool) Show the pivot's close price in the tooltip?
// @param closeBreaksClose (bool) Show if current (highest/lowest) pivot close broke previous pivot close (Only effective if feature is enabled).
// @param closeBreaksPivot (bool) Show if current (highest/lowest) pivot close broke previous pivot (high/low) (Only effective if feature is enabled).
export type Tooltips
bool name = true
bool price = true
bool close = true
bool closeBreaksClose = false
bool closeBreaksPivot = false
// @type Theme
// @desc Used to define a ZigZag theme with customizable styling options for lines, labels, and tooltips.
// @param enabled (bool) Enable built-in ZigZag rendering, including lines and labels. Set to false to fully customize rendering externally.
// @param colorDefault (color) The fallback color used when no specific direction is detected.
// @param colorNeutral (color) Color used for neutral moves (e.g., equal highs/lows).
// @param colorBullish (color) Color used for bullish moves (price going up).
// @param colorBearish (color) Color used for bearish moves (price going down).
// @param lineWidth (int) Width of the ZigZag lines (1–4).
// @param labelSize (string) Size of the label text (e.g., size.small, size.normal, size.large).
// @param showLabelL (bool) Show label for regular low pivot ('L').
// @param showLabelLL (bool) Show label for Lower Low pivot ('LL').
// @param showLabelHL (bool) Show label for Higher Low pivot ('HL').
// @param showLabelH (bool) Show label for regular high pivot ('H').
// @param showLabelLH (bool) Show label for Lower High pivot ('LH').
// @param showLabelHH (bool) Show label for Higher High pivot ('HH').
// @param coloredLines (bool) If true, ZigZag lines are colored according to trend direction (bullish/bearish/neutral).
// @param showCloseInfo (bool) Show additional price information related to closing values in labels.
// @param showTooltips (bool) Enable mouse-over tooltips with additional pivot information.
// @param tooltips (Tooltips) Tooltip configuration (e.g., formatting or content rules).
export type Theme
bool enabled = false
color colorDefault = color.gray
color colorNeutral = color.yellow
color colorBullish = color.green
color colorBearish = color.red
int lineWidth = 2
string labelSize = size.normal
bool showLabelL = true
bool showLabelLL = true
bool showLabelHL = true
bool showLabelH = true
bool showLabelLH = true
bool showLabelHH = true
bool coloredLines = false
bool showCloseInfo = false
bool showTooltips = true
Tooltips tooltips
// @type All settings for the indicator
// @param source (Source) The source to be used.
// @param features (Features) The features to be used.
// @param theme (Theme) The theme to be used.
// @param limit (int) The max number of pivots to be shown
export type Settings
Source source
Features features
Theme theme
int limit // Default to a reasonable integer instead of na
// @type Used to determine a coordination on the chart
// @param x (int) The time
// @param y (float) The price
export type Point
int x // time
float y // price
// @type Used to determine pivots on the chart.
// @param point (Point) The current coordination on the chart
// @param isHigh (bool) Whether this Pivot is a pivot high or low.
// @param isHigher (bool) Whether this Pivot is higher than the previous paired pivot (not last pivot, but 2 back). Defaults to false instead of na.
// @param name (string) The name of the pivot.
// @param abbr (string) The abbreviation of the name of the pivot.
// @param close (float) The highest/lowest close price of the swing to this pivot.
// @param comulativeVolume (float) The cumulative volume for this pivot (optional).
// @param closeBreaksClose (bool) Whether the pivot (highest/lowest) close breaks the previous pivot (highest/lowest) close. Defaults to false.
// @param closeBreaksPivot (bool) Whether the pivot (highest/lowest) close breaks the previous pivot (high/low). Defaults to false.
// @param isLast (bool) Whether this pivot is the most recent one.
// @param ln (line) Line to draw (optional)
// @param lb (label) Label to draw (optional)
export type Pivot
Point point
bool isHigh
bool isHigher = false // Changed from na to false
string name = ""
string abbr = ""
float close = close
float comulativeVolume = 0.0 // Changed from na to 0.0
bool closeBreaksPivot = false // Changed from na to false
bool closeBreaksClose = false // Changed from na to false
bool isLast = true
line ln = na
label lb = na
// @function Gets the first Pivot
// @param this (array<Pivot>) The object to work with.
// @return (Pivot) The first Pivot in the array or NA if not available.
export method getFirst(array<Pivot> this) =>
this.size() > 0 ? this.get(0) : na
// @function Gets the latest Pivot
// @param this (array<Pivot>) The object to work with.
// @return (Pivot) The last Pivot in the array or NA if not available.
export method getLast(array<Pivot> this) =>
int size = this.size(), size > 0 ? this.get(size - 1) : na
// @function Gets previous Pivot by index number.
// @param this (array<Pivot>) The object to work with.
// @param index (int) The index number (optional, default is 1)
// @return (Pivot) The previous Pivot or NA if not available.
export method getPrev(array<Pivot> this, int index = 1) =>
int size = this.size(), size > index ? this.get(size - 1 - index) : na
// @function Checks if current pivot is higher than the previous paired pivot (2 back).
// @param this (Pivot) The object to work with.
// @param pivots (array<Pivot>) The array of pivots.
// @return (bool) Whether the pivot is higher or not. Returns false if array is too small (instead of na).
method isHigher(Pivot this, Pivot[] pivots) =>
int size = pivots.size()
if size > 2
this.point.y > pivots.get(size - 3).point.y
else
false // Changed from na to false
// @function Checks if the current pivot is at the current bar
// @param this (Pivot) The object to work with.
// @return (bool) Whether the current pivot is at the current bar or not.
export method isAtCurrentBar(Pivot this) =>
this.point.x >= last_bar_time
// @function Checks if current pivot is a higher high
// @param this (Pivot) The object to work with.
// @return (bool) True if the pivot is a higher high, false if not.
export method isHigherHigh(Pivot this) =>
bool r = this.isHigh and this.isHigher
// @function Checks if current pivot is a lower high
// @param this (Pivot) The object to work with.
// @return (bool) True if the pivot is a lower high, false if not.
export method isLowerHigh(Pivot this) =>
bool r = this.isHigh and not this.isHigher
// @function Checks if current pivot is a higher low
// @param this (Pivot) The object to work with.
// @return (bool) True if the pivot is a higher low, false if not.
export method isHigherLow(Pivot this) =>
bool r = not this.isHigh and this.isHigher
// @function Checks if current pivot is a lower low
// @param this (Pivot) The object to work with.
// @return (bool) True if the pivot is a lower low, false if not.
export method isLowerLow(Pivot this) =>
bool r = not this.isHigh and not this.isHigher
// @function Gets the latest Pivot High based on previous number of Pivot highs back. Default is the latest.
// @param this (array<Pivot>) The object to work with.
// @param prev (int) Number of previous pivot highs back (1 = latest, >1 is earlier ones).
// @return (Pivot) The latest Pivot High or NA if not available.
export method getHigh(array<Pivot> this, int prev = 1) =>
int size = this.size()
int n = math.max(1, prev)
Pivot lastPivot = this.getLast()
Pivot returnPivot = na
if not na(lastPivot)
if n == 1 and lastPivot.isHigh
returnPivot := lastPivot
else
n := n * (lastPivot.isHigh ? 2 : 1)
if size > n
returnPivot := this.get(size - 1 - n)
returnPivot
// @function Gets the latest pivot high
// @param this (array<Pivot>) The object to work with.
// @return (Pivot) The latest Pivot high in the array or NA if not available.
export method getLastHigh(array<Pivot> this) =>
this.getHigh(1)
// @function Gets the previous pivot high
// @param this (array<Pivot>) The object to work with.
// @return (Pivot) The previous Pivot high in the array or NA if not available.
export method getPrevHigh(array<Pivot> this) =>
this.getHigh(2)
// @function Gets the Pivot Low
// @param this (array<Pivot>) The object to work with.
// @param prev (int) Number of previous pivot lows back (1 = latest, >1 is earlier ones).
// @return (Pivot) The latest Pivot Low or NA if not available.
export method getLow(array<Pivot> this, int prev = 1) =>
int size = this.size()
int n = math.max(1, prev)
Pivot lastPivot = this.getLast()
Pivot returnPivot = na
if not na(lastPivot)
if n == 1 and not lastPivot.isHigh
returnPivot := lastPivot
else
n := n * (lastPivot.isHigh ? 1 : 2)
if size > n
returnPivot := this.get(size - 1 - n)
returnPivot
// @function Gets the latest pivot low
// @param this (array<Pivot>) The object to work with.
// @return (Pivot) The latest Pivot low in the array or NA if not available.
export method getLastLow(array<Pivot> this) =>
this.getLow(1)
// @function Gets the previous pivot low
// @param this (array<Pivot>) The object to work with.
// @return (Pivot) The previous Pivot low in the array or NA if not available.
export method getPrevLow(array<Pivot> this) =>
this.getLow(2)
// @function Builds name (and abbreviation) string for current pivot
// @param this (Pivot) The object to work with.
// @return (string) The name for this pivot.
// @return (string) Abbreviation of the name for this pivot.
method buildNameString(Pivot this) =>
string highLowAbbr = this.isHigh ? "H" : "L"
string highLow = highLowAbbr + (this.isHigh ? "igh" : "ow")
string higherLowerAbbr = ""
string higherLower = ""
// Only append higher/lower if isHigher has been set (not default false)
if this.isHigher != Pivot.new(this.point, this.isHigh).isHigher // Check against default value
higherLowerAbbr := this.isHigher ? "H" : "L"
higherLower := higherLowerAbbr + (this.isHigher ? "igher " : "ower ")
string name = str.format("{0}{1}", higherLower, highLow)
string abbr = str.format("{0}{1}", higherLowerAbbr, highLowAbbr)
[name, abbr]
// @function Builds the string for the CloseBreaksClose feature
// @param this (Pivot) The object to work with.
// @return (string) The string indicating if close breaks previous close.
method buildCloseBreaksCloseString(Pivot this) =>
string str = this.closeBreaksClose ? (this.isHigh ? "꜀" : "ᶜ") : ""
// @function Builds the string for the CloseBreaksPivot feature
// @param this (Pivot) The object to work with.
// @return (string) The string indicating if close breaks previous pivot.
method buildCloseBreaksPivotString(Pivot this) =>
string str = this.closeBreaksPivot ? (this.isHigh ? "ₚ" : "ᵖ") : ""
// @function Generates the text for the label of the Pivot
// @param this (Pivot) The object to work with.
// @param settings (Settings) The global settings for the indicator.
// @return (string) Text: HH for higher high, LH for lower high, HL for higher low, LL for lower low
method buildLabelTextString(Pivot this, Settings settings) =>
string str = ""
if settings.theme.showCloseInfo
str := settings.features.closeBreaksClose ? this.buildCloseBreaksCloseString() : str
str += settings.features.closeBreaksPivot ? this.buildCloseBreaksPivotString() : ""
// If isHigher is still default (false) and hasn't been set, show only abbr
if this.isHigher == Pivot.new(this.point, this.isHigh).isHigher
str := this.abbr
else
str := this.isHigh ? str + "\n" + this.abbr : this.abbr + "\n" + str
// @function Creates a color based on current pivot conditions.
// @param this (Pivot) The object to work with.
// @param prev (Pivot) The previous pivot
// @param theme (Theme) The theme settings
// @returns (color) The color for this pivot
method generateColor(Pivot this, Pivot prev, Theme theme) =>
color c = theme.colorDefault
if this.isHigherLow()
c := not prev.isHigher ? theme.colorNeutral : theme.colorBullish
if this.isLowerLow()
c := theme.colorBearish
if this.isHigherHigh()
c := theme.colorBullish
if this.isLowerHigh()
c := prev.isHigher ? theme.colorNeutral : theme.colorBearish
c
// @function Checks if current close broke previous pivot value
// @param this (Pivot) The object to work with.
// @return (bool) Whether the current close broke the previous pivot value
method closeBrokePrevPivot(Pivot this) =>
this.isHigh ? this.closeBreaksPivot : not this.closeBreaksPivot
// @function Checks if current close broke previous pivot close
// @param this (Pivot) The object to work with.
// @return (bool) Whether the current close broke the previous pivot close
method closeBrokePrevPivotClose(Pivot this) =>
this.isHigh ? this.closeBreaksClose : not this.closeBreaksClose
// @function Calculates the cumulative volume from previous pivot to current pivot
method calculateComulativeVolume(Pivot this) =>
this.comulativeVolume + volume
// @function Builds a tooltip string
// @param this (Pivot) The object to work with.
// @param settings (Settings) The global settings.
// @return (string) The tooltip
method buildTooltipString(Pivot this, Settings settings) =>
array<string> tooltips = array.new<string>()
string strName = this.name
string strHighOrLow = this.isHigh ? "high" : "low"
string strAboveOrBelow = this.isHigh ? "above" : "below"
string strHighestOrLowest = this.isHigh ? "highest" : "lowest"
if settings.theme.tooltips.name
tooltips.push("name\t\t\t: " + strName)
if settings.theme.tooltips.price
tooltips.push("price\t\t\t: " + str.tostring(this.point.y))
if settings.theme.tooltips.close
tooltips.push(strHighestOrLowest + " close\t\t: " + str.tostring(this.close))
if settings.theme.tooltips.closeBreaksPivot
tooltips.push(str.format("close {0} pivot\t: {1}", this.isAtCurrentBar() or this.isLast ? "breaks" : "broke", this.closeBrokePrevPivot()))
if settings.theme.tooltips.closeBreaksClose
tooltips.push(str.format("close {0} close\t: {1}", this.isAtCurrentBar() or this.isLast ? "breaks" : "broke", this.closeBrokePrevPivotClose()))
// Return the joined string
string str = array.join(tooltips, "\n")
// @function Adds a new pivot to the pivots array.
// @param this (array<Pivot>) The object to work with.
// @param point (Point) The point coordinates of the new pivot.
// @param isHigh (bool) Whether the pivot is a high or not (then it is a low).
// @param settings (Settings) The global settings.
// @return (Pivot) The latest Pivot.
export method add(array<Pivot> this, Point point, bool isHigh, Settings settings) =>
Theme theme = settings.theme
Pivot lastPivot = this.getLast()
Pivot prevPivot = this.getPrev()
Pivot pivot = Pivot.new(point, isHigh)
pivot.close := (isHigh ? math.max(close, close[1]) : math.min(close, close[1]))
pivot.close := (isHigh and close > pivot.close) or (not isHigh and close < pivot.close) ? close : pivot.close
if not na(lastPivot)
color pivotColor = pivot.generateColor(lastPivot, theme)
// If we have a previous Pivot...
if not na(prevPivot)
pivot.closeBreaksPivot := pivot.isHigh ? close > prevPivot.point.y : close < prevPivot.point.y
pivot.closeBreaksClose := pivot.isHigh ? close > prevPivot.close : close < prevPivot.close
pivot.isHigher := point.y > prevPivot.point.y
[name, abbr] = pivot.buildNameString()
pivot.name := name
pivot.abbr := abbr
pivotColor := pivot.generateColor(lastPivot, theme)
// Create the line for the new Pivot
if theme.enabled
pivot.ln := line.new(
x1 = lastPivot.point.x,
y1 = lastPivot.point.y,
x2 = pivot.point.x,
y2 = pivot.point.y,
xloc = xloc.bar_time,
extend = extend.none,
color = theme.coloredLines ? pivotColor : theme.colorDefault,
style = line.style_solid,
width = theme.lineWidth)
// Create label for the new Pivot
if theme.enabled
pivot.lb := label.new(
x = pivot.point.x,
y = pivot.point.y,
text = pivot.buildLabelTextString(settings),
xloc = xloc.bar_time,
yloc = isHigh ? yloc.abovebar : yloc.belowbar,
color = color.rgb(0, 0, 0, 100),
style = label.style_none,
textcolor = (pivot.abbr == "L" and theme.showLabelL) or (pivot.abbr == "LL" and theme.showLabelLL) or (pivot.abbr == "HL" and theme.showLabelHL) or (pivot.abbr == "H" and theme.showLabelH) or (pivot.abbr == "LH" and theme.showLabelLH) or (pivot.abbr == "HH" and theme.showLabelHH) ? pivotColor : #00000000,
size = theme.labelSize,
textalign = text.align_center,
text_font_family = font.family_default,
tooltip = theme.showTooltips ? pivot.buildTooltipString(settings) : "")
// Last pivot is no longer the last pivot
lastPivot.isLast := false
this.set(this.size() - 1, lastPivot)
// Remove old pivot when max number of pivots is reached
if this.size() >= settings.limit
Pivot oldestPivot = this.shift()
oldestPivot.ln.delete()
oldestPivot.lb.delete()
oldestPivot := this.first()
oldestPivot.ln.delete()
// Push the new pivot to the end of the array
this.push(pivot)
// Return the new Pivot
pivot
// @function Updates pivot in array
// @param this (array<Pivot>) The object to work with.
// @param pivot (Pivot) The pivot to update.
// @param point (Point) The new point coordinates.
// @param settings (Settings) The global settings.
// @return (Pivot) The updated Pivot
method update(array<Pivot> this, Pivot pivot, Point point, Settings settings) =>
Theme theme = settings.theme
Pivot prevPivot = na
pivot.point.x := point.x
pivot.point.y := point.y
pivot.ln.set_xy2(point.x, point.y)
pivot.lb.set_xy(point.x, point.y)
pivot.close := (pivot.isHigh ? math.max(close, close[1]) : math.min(close, close[1]))
if not na(this)
prevPivot := this.getPrev(2)
pivot.close := (pivot.isHigh and close > pivot.close) or (not pivot.isHigh and close < pivot.close) ? close : pivot.close
if not na(prevPivot)
Pivot lastPivot = this.getLast()
pivot.isHigher := point.y > prevPivot.point.y
// Check if close is higher/lower than previous pivot and pivot's bar close value.
pivot.closeBreaksPivot := pivot.isHigh ? close > prevPivot.point.y : close < prevPivot.point.y
pivot.closeBreaksClose := pivot.isHigh ? close > prevPivot.close : close < prevPivot.close
// Rebuild name string
[name, abbr] = pivot.buildNameString()
pivot.name := name
pivot.abbr := abbr
if theme.enabled
color pivotColor = pivot.generateColor(lastPivot, theme)
color lineColor = pivotColor
pivotColor := (pivot.abbr == "L" and theme.showLabelL) or (pivot.abbr == "LL" and theme.showLabelLL) or (pivot.abbr == "HL" and theme.showLabelHL) or (pivot.abbr == "H" and theme.showLabelH) or (pivot.abbr == "LH" and theme.showLabelLH) or (pivot.abbr == "HH" and theme.showLabelHH) ? pivotColor : #00000000
pivot.lb.set_text(pivot.buildLabelTextString(settings))
pivot.lb.set_textcolor(pivotColor)
if theme.showTooltips
pivot.lb.set_tooltip(pivot.buildTooltipString(settings))
pivot.ln.set_color(theme.coloredLines ? lineColor : theme.colorDefault)
this.set(this.size() - 1, pivot)
pivot
// @function Scans for new pivot
// @param this (array<Pivot>) The object to work with.
// @param source (float) The source value to scan.
// @param isHigh (bool) Whether we look for a pivot high or not.
// @param settings (Settings) The settings.
method scan(array<Pivot> this, float source, bool isHigh, Settings settings) =>
Point point = Point.new(time, source)
Pivot lastPivot = this.getLast()
if not na(lastPivot)
if lastPivot.isHigh
if point.y > lastPivot.point.y
this.update(lastPivot, point, settings)
if not isHigh
this.add(point, isHigh, settings)
else
if point.y < lastPivot.point.y
this.update(lastPivot, point, settings)
if isHigh
this.add(point, isHigh, settings)
else
this.add(point, isHigh, settings)
// @function Creates a new ZigZag Instance
// @param customSettings (Settings) The settings for this instance.
// @return (array<Pivot>) The array of pivots.
export new(Settings customSettings) =>
Settings settings = customSettings
// Ensure all settings components are initialized
if na(settings.source)
settings.source := Source.new()
if na(settings.theme)
settings.theme := Theme.new()
if na(settings.features)
settings.features := Features.new()
// Change settings based on enabled/disabled features
if settings.features.closeBreaksClose == false
settings.theme.tooltips.closeBreaksClose := false
if settings.features.closeBreaksPivot == false
settings.theme.tooltips.closeBreaksPivot := false
// Create pivots
var Pivot[] pivots = array.new<Pivot>()
float srcLow = settings.source.low
float srcHigh = settings.source.high
if srcHigh != srcLow and srcLow < srcLow[1] and srcHigh > srcHigh[1]
if settings.source.priority == "high" // IF HIGH CAME FIRST
pivots.scan(srcHigh, true, settings) // HIGH
pivots.scan(srcLow, false, settings) // LOW
else
pivots.scan(srcLow, false, settings) // LOW
pivots.scan(srcHigh, true, settings) // HIGH
else
if srcHigh > srcHigh[1]
if srcLow >= srcLow[1]
pivots.scan(srcHigh, true, settings) // HIGH
if srcLow < srcLow[1]
if srcHigh <= srcHigh[1]
pivots.scan(srcLow, false, settings) // LOW
// Return the pivots array
pivots
export method barIsPivot(array<Pivot> pivots) =>
var lastPivot = pivots.getLast()
// @function Helper function to generate a lower timeframe period (string) for current timeframe period.
// You can use this in conjunction with request.security_lower_tf() to figure out if current high
// of this bar was created before the low of this bar.
// @return (string) Timeframe period for lower timeframe.
export getLowerTimeframePeriod() =>
int tf = timeframe.in_seconds(timeframe.period)
string ltf = switch true
tf <= 60 => '10S'
tf <= 300 => '1' // 5 minutes => 1 minute
tf <= 600 => '2' // 10 minutes => 2 minutes
tf <= 1800 => '3' // 30 minutes => 3 minutes
tf <= 3600 => '5' // 1 hour => 5 minutes
tf <= 14400 => '15' // 4 hour => 15 minutes
tf <= 86400 => '30' // 1 day => 30 minutes
tf <= 172800 => '60' // 2 days => 1 hour
tf <= 259200 => '240' // 3 days => 4 hours
tf <= 432000 => '360' // 5 days => 6 hours
tf <= 604800 => '720' // 1 week => 12 hours
tf <= 1209600 => 'D' // 2 weeks => 1 day
tf <= 2628000 => '2D' // 1 month => 2 days
tf <= 5256000 => '5D' // 2 months => 5 days
tf <= 7884000 => 'W' // 3 months => 1 week
tf <= 15768000 => '2W' // 6 months => 2 weeks
tf <= 31536000 => '1M' // 1 year => 1 month
=> timeframe.period
// ---------------------------------------------------------------------------------------------------------------------
// USAGE EXAMPLE AREA
// ---------------------------------------------------------------------------------------------------------------------
// Input: General options
int iPivotLimit = input.int(
title = "Limit",
defval = 1000,
minval = 1,
step = 1,
tooltip = "The maximum amount of pivots to be shown.",
group = "S O U R C E")
string iSource = input.string(
title = "Source",
defval = "high/low",
options = ["high/low", "custom"],
group = "S O U R C E")
float iSourceHigh = input.source(
title = "Custom High",
defval = close,
group = "S O U R C E")
float iSourceLow = input.source(
title = "Custom Low",
defval = close,
group = "S O U R C E")
string iSourcePriority = input.string(
title = "Prioritize",
defval = "auto",
options = ["auto", "high", "low"],
tooltip = "In the case if we have both a higher high and a lower low, which is prioritized? If set to automatic, the indicator will look at lower timeframe.",
group = "S O U R C E")
// Input: Features
bool iFeatureCloseBreaksClose = input.bool(
title = "Close Breaks Close",
defval = true,
tooltip = "Check if current pivot (highest/lowest) close broke previous paired pivot (highest/lowest) close.",
group = "F E A T U R E S")
bool iFeatureCloseBreaksPivot = input.bool(
title = "Close Breaks Pivot",
defval = true,
tooltip = "Check if current pivot (highest/lowest) close broke previous paired pivot (high/low).",
group = "F E A T U R E S")
// Input: Set theming options
bool iThemeHide = input.bool(
title = "Hide",
defval = false,
tooltip = "You can hide or show everything at once with this setting.",
group = "T H E M I N G")
bool iThemeShowCloseInfo = input.bool(
title = "Show close info",
defval = true,
tooltip = "Show extra close info above and below pivot labels?\nC = Close is higher than previous paired pivot close. \nCP = Close is higher than previous paired pivot.",
group = "T H E M I N G")
color iThemeColorDefault = input.color(
title = "Default",
defval = color.rgb(120, 123, 134, 0),
group = "T H E M I N G")
color iThemeColorNeutral = input.color(
title = "Neutral",
defval = color.rgb(200, 200, 000, 0),
group = "T H E M I N G")
color iThemeColorBullish = input.color(
title = "Bullish",
defval = color.rgb(000, 200, 000, 0),
group = "T H E M I N G")
color iThemeColorBearish = input.color(
title = "Bearish",
defval = color.rgb(200, 000, 000, 0),
group = "T H E M I N G")
string iThemeStyle = input.string(
title = "Style",
defval = "labels & lines",
options = ["labels & lines", "labels", "none"],
tooltip = "If \"none\" is selected, the default color will be used for all drawings.",
group = "T H E M I N G")
int iThemeLineWidth = input.int(
title = "Line width",
defval = 2,
minval = 1,
maxval = 50,
tooltip = "Width in pixels",
group = "T H E M I N G")
string iThemeLabelSize = input.string(
title = "Label size",
defval = "normal",
options = ["huge", "large", "normal", "small", "tiny"],
group = "T H E M I N G")
bool iThemeShowLabelL = input.bool(
title = "Show label L",
defval = true,
group = "T H E M I N G")
bool iThemeShowLabelLL = input.bool(
title = "Show label LL",
defval = true,
group = "T H E M I N G")
bool iThemeShowLabelHL = input.bool(
title = "Show label HL",
defval = true,
group = "T H E M I N G")
bool iThemeShowLabelH = input.bool(
title = "Show label H",
defval = true,
group = "T H E M I N G")
bool iThemeShowLabelLH = input.bool(
title = "Show label LH",
defval = true,
group = "T H E M I N G")
bool iThemeShowLabelHH = input.bool(
title = "Show label HH",
defval = true,
group = "T H E M I N G")
// Input: Set Tooltip Options
bool iTooltipDisable = input.bool(
title = "Disable",
defval = false,
tooltip = "This setting overrides all below tooltip settings.",
group = "T O O L T I P S")
bool iTooltipName = input.bool(
title = "Show name",
defval = true,
group = "T O O L T I P S")
bool iTooltipPrice = input.bool(
title = "Show price",
defval = true,
group = "T O O L T I P S")
bool iTooltipClose = input.bool(
title = "Show close",
defval = true,
group = "T O O L T I P S")
bool iTooltipCloseBreaksClose = input.bool(
title = "Show close breaks close",
defval = true,
group = "T O O L T I P S")
bool iTooltipCloseBreaksPivot = input.bool(
title = "Show close breaks pivot",
defval = true,
group = "T O O L T I P S")
// Setup the highFirst value for the ZigZag indicator
ltf = getLowerTimeframePeriod()
[ltf_high, ltf_low] = request.security_lower_tf(syminfo.tickerid, ltf, [iSourceHigh, iSourceLow])
string sourcePriorityAuto = (ltf == timeframe.period ? false : ltf_high.lastindexof(ltf_high.max()) <= ltf_low.lastindexof(ltf_low.min())) ? "high" : "low"
// Setup the source for the ZigZag indicator
Source sourceSettings = Source.new(
high = iSource == "high/low" ? high : iSourceHigh,
low = iSource == "high/low" ? low : iSourceLow,
priority = iSourcePriority == "auto" ? sourcePriorityAuto : iSourcePriority)
// Setup to be used features for the ZigZag indicator
Features featuresSettings = Features.new(
closeBreaksClose = iFeatureCloseBreaksClose,
closeBreaksPivot = iFeatureCloseBreaksPivot)
// Setup the theme for the ZigZag indicator
Theme themeSettings = Theme.new(
enabled = not iThemeHide,
colorDefault = iThemeColorDefault,
colorNeutral = iThemeStyle == "none" ? iThemeColorDefault : iThemeColorNeutral,
colorBullish = iThemeStyle == "none" ? iThemeColorDefault : iThemeColorBullish,
colorBearish = iThemeStyle == "none" ? iThemeColorDefault : iThemeColorBearish,
coloredLines = iThemeStyle == "labels & lines" ? true : false,
lineWidth = iThemeLineWidth,
labelSize = iThemeLabelSize,
showLabelL = iThemeShowLabelL,
showLabelHL = iThemeShowLabelHL,
showLabelLL = iThemeShowLabelLL,
showLabelH = iThemeShowLabelH,
showLabelLH = iThemeShowLabelLH,
showLabelHH = iThemeShowLabelHH,
showCloseInfo = iThemeShowCloseInfo,
showTooltips = not iTooltipDisable,
tooltips = Tooltips.new(iTooltipName, iTooltipPrice, iTooltipClose, iTooltipCloseBreaksClose, iTooltipCloseBreaksPivot))
// All settings for the ZigZag indicator
settings = Settings.new(sourceSettings, featuresSettings, themeSettings, iPivotLimit)
// Create the ZigZag indicator
array<Pivot> pivots = new(settings)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment