ZigCycleBarCount [MsF]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Trader_Morry

//@version=4

////////
// Title 
study("ZigCycleBarCount", "ZigCyclBarCnt", true, format.price, max_labels_count=51, max_lines_count=50)


////////
// Input values 
// [
Depth       = input(12, "Depth", input.integer, minval=1, step=1)
Deviation   = input(5, "Deviation", input.integer, minval=1, step=1)
Backstep    = input(3, "Backstep", input.integer, minval=2, step=1)
line_thick  = input(2, "Line Thickness", input.integer, minval=1, maxval=4)
upcolor     = input(color.aqua, "Bull Color")
dncolor     = input(color.red, "Bear Color")
repaint     = input(true, "Repaint Levels")
price       = input(true, "Price Values")
Label_Style = input(title="Label Style", type=input.string, defval="TEXT", options=["BALLOON", "TEXT"])
// ]

////////
// Hidden input values
// [
// ]

//////// 
// Making
// [
var last_h = 1, last_h := last_h + 1
var last_l = 1, last_l := last_l + 1
var lw = 1, var hg = 1
lw := lw + 1, hg := hg + 1
p_lw = -lowestbars(Depth), p_hg = -highestbars(Depth)
lowing = lw == p_lw or low - low[p_lw] > Deviation*syminfo.mintick
highing = hg == p_hg or high[p_hg] - high > Deviation*syminfo.mintick
lh = barssince(not highing[1]), ll = barssince(not lowing[1])
down = barssince(not (lh > ll)) >= Backstep, lower = low[lw] > low[p_lw], higher = high[hg] < high[p_hg]
if lw != p_lw and (not down[1] or lower)
    lw := p_lw < hg ? p_lw : 0
if hg != p_hg and (down[1] or higher)
    hg := p_hg < lw ? p_hg : 0

line zz = na
label point = na
x1 = down ? lw : hg
y1 = down ? low[lw] : high[hg]

var zigBarCount = 0 // once at init
var t_zigBarCount = 0 // once at init

if down == down[1]
    if repaint
        label.delete(point[1])
        line.delete(zz[1])
    down
if down != down[1]
    if down
        last_h := hg
    else
        last_l := lw
    if not repaint
        nx = down?last_h:last_l
        zigBarCount := (bar_index-nx) - (bar_index-(down?last_l:last_h))
        zz := line.new(bar_index-nx, down ? high[nx] : low[nx], bar_index-(down?last_l:last_h), down ? low[last_l] : high[last_h], width=line_thick, color=down?upcolor:dncolor)
        if price
            if Label_Style == "BALLOON"
                point := label.new(bar_index-nx, down ? high[nx] : low[nx], down ? tostring(high[nx])+"\n"+"C="+tostring(zigBarCount) : tostring(low[nx])+"\n"+"C="+tostring(zigBarCount), style=down?label.style_label_down:label.style_label_up, size=size.normal, color=down?upcolor:dncolor, textcolor=color.black, tooltip = down ? (high[nx] > high[last_h[1]]?"Higher High":"Lower High") : (low[nx] < low[last_l[1]] ? "Lower Low" : "Higher Low"))
            else
                point := label.new(bar_index-nx, na, down ? tostring(high[nx])+"\n"+"C="+tostring(zigBarCount) : tostring(low[nx])+"\n"+"C="+tostring(zigBarCount), style=label.style_none, yloc=down?yloc.abovebar:yloc.belowbar, size=size.normal, color=down?upcolor:dncolor, textcolor=color.blue, tooltip = down ? (high[nx] > high[last_h[1]]?"Higher High":"Lower High") : (low[nx] < low[last_l[1]] ? "Lower Low" : "Higher Low"))
        else
            if Label_Style == "BALLOON"
                point := label.new(bar_index-nx, down ? high[nx] : low[nx], tostring(zigBarCount), style=down?label.style_label_down:label.style_label_up, size=size.normal, color=down?upcolor:dncolor, textcolor=color.black, tooltip = down ? (high[nx] > high[last_h[1]]?"Higher High":"Lower High") : (low[nx] < low[last_l[1]] ? "Lower Low" : "Higher Low"))
            else
                point := label.new(bar_index-nx, na, tostring(zigBarCount), style=label.style_none, yloc=down?yloc.abovebar:yloc.belowbar, size=size.normal, color=down?upcolor:dncolor, textcolor=color.blue, tooltip = down ? (high[nx] > high[last_h[1]]?"Higher High":"Lower High") : (low[nx] < low[last_l[1]] ? "Lower Low" : "Higher Low"))
    down
if repaint
    // last_h:last_lのどちらかが0なら縦に線を引くように変更する
//    if (last_h==0) or (last_l==0)
//        zigBarCount := (bar_index-x1) - (bar_index-(down?last_h:last_l))-1
//        if zigBarCount < 0
//            zz := line.new(bar_index-(down?last_h:last_l)-1, down ? high[last_h]-1 : low[last_l]-1, bar_index-x1, y1, width=line_thick, color=down?dncolor:upcolor)
//            t_zigBarCount := 0
//        else
//            zz := line.new(bar_index-(down?last_h:last_l), down ? high[last_h]-1 : low[last_l]-1, bar_index-x1, y1, width=line_thick, color=down?dncolor:upcolor)
//            t_zigBarCount := zigBarCount
//    else
    zigBarCount := (bar_index-x1) - (bar_index-(down?last_h:last_l))
    if zigBarCount < 0
        zz := line.new(bar_index-(down?last_h:last_l)-1, down ? high[last_h] : low[last_l], bar_index-x1, y1, width=line_thick, color=down?dncolor:upcolor)
        t_zigBarCount := 0
    else
        zz := line.new(bar_index-(down?last_h:last_l), down ? high[last_h] : low[last_l], bar_index-x1, y1, width=line_thick, color=down?dncolor:upcolor)
        t_zigBarCount := zigBarCount

    zigBarCount := t_zigBarCount
    if price
        if Label_Style == "BALLOON"
            point := label.new(bar_index-x1, y1, down ? tostring(low[x1])+"\n"+"C="+tostring(zigBarCount) : tostring(high[x1])+"\n"+"C="+tostring(zigBarCount), style=down?label.style_label_up:label.style_label_down, size=size.normal, color=down?dncolor:upcolor, textcolor=color.black, tooltip = down ? (low[x1] < low[last_l] ? "Lower Low" : "Higher Low") : (high[x1] > high[last_h]?"Higher High":"Lower High"))
        else
            point := label.new(bar_index-x1, na, down ? tostring(low[x1])+"\n"+"C="+tostring(zigBarCount) : tostring(high[x1])+"\n"+"C="+tostring(zigBarCount), style=label.style_none, yloc=down?yloc.belowbar:yloc.abovebar, size=size.normal, color=down?dncolor:upcolor, textcolor=color.blue, tooltip = down ? (low[x1] < low[last_l] ? "Lower Low" : "Higher Low") : (high[x1] > high[last_h]?"Higher High":"Lower High"))
    else
        if Label_Style == "BALLOON"
            point := label.new(bar_index-x1, y1, tostring(zigBarCount), style=down?label.style_label_up:label.style_label_down, size=size.normal, color=down?dncolor:upcolor, textcolor=color.black, tooltip = down ? (low[x1] < low[last_l] ? "Lower Low" : "Higher Low") : (high[x1] > high[last_h]?"Higher High":"Lower High"))
        else
            point := label.new(bar_index-x1, na, tostring(zigBarCount), style=label.style_none, yloc=down?yloc.belowbar:yloc.abovebar, size=size.normal, color=down?dncolor:upcolor, textcolor=color.blue, tooltip = down ? (low[x1] < low[last_l] ? "Lower Low" : "Higher Low") : (high[x1] > high[last_h]?"Higher High":"Lower High"))
// ]


////////
// Bull or Bear notifications
// [
bear = down
//bgcolor(bear?color.red:color.lime, title="Scanning Direction")

alertcondition(bear!=bear[1], "Direction Changed", 'Zigzag on {{ticker}} direction changed at {{time}}')
alertcondition(bear!=bear[1] and not bear, "Bullish Direction", 'Zigzag on {{ticker}} bullish direction at {{time}}')
alertcondition(bear!=bear[1] and bear, "Bearish Direction", 'Zigzag on {{ticker}} bearish direction at {{time}}')
// ]
