TR_HighLow
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Tommy_Rich

//@version=5

// @description TODO: add library description here
library(title ="TR_HighLow",overlay =true)

//////                      //
//// local function group ////    **********ローカル関数群**********
//                      //////
SetHighLowArray(
  float[] _a_Price, int[]   _a_Index,
  int[]   _a_Flag,  float[] _a_Difference,
  float   _Price,   int     _Index,
  int     _Flag,    float   _Difference) =>

    if _Price >0
        // 配列の先頭から最も古いレベルを削除します
        array.shift(_a_Price)
        array.shift(_a_Index)
        array.shift(_a_Flag)
        array.shift(_a_Difference)
    
        // 配列の最後に新しいレベルを追加します
        array.push(_a_Price,      _Price)
        array.push(_a_Index,      _Index)
        array.push(_a_Flag,       _Flag)
        array.push(_a_Difference, _Difference)

    [_a_Price, _a_Index, _a_Flag, _a_Difference]

ChangeHighLowArray(
  float[] _a_Price,      int[]   _a_Index,
  float[] _a_Difference, float   _Price,
  int     _Index,        float   _Difference,
  int     _Histories) =>

    if _Price >0
        array.set(_a_Price,      _Histories-1, _Price)
        array.set(_a_Index,      _Histories-1, _Index)
        array.set(_a_Difference, _Histories-1, _Difference)

    [_a_Price, _a_Index, _a_Difference]

//////                       //
//// global function group ////    **********グローバル関数群**********
//                       //////

// @function TODO: Function to display labels
// @param _Text TODO: text (series string) Label text.
// @param _X TODO: x (series int) Bar index.
// @param _Y TODO: y (series int/float) Price of the label position.
// @param _Style TODO: style (series string) Label style.
// @param _Size TODO: size (series string) Label size.
// @param _Yloc TODO: yloc (series string) Possible values are yloc.price, yloc.abovebar, yloc.belowbar.
// @param _Color TODO: color (series color) Color of the label border and arrow
// @returns TODO: No return values
export ShowLabel(
  string _Text,
  int    _X,     float  _Y,
  string _Style, string _Size,
  string _Yloc,  color  _Color) =>

    var label lbl1 = na
    lbl1 := label.new(x =_X, y =_Y, text =_Text, yloc =_Yloc, style =_Style, size =_Size, textcolor =_Color, textalign =text.align_center)

// @function TODO: Function to take out 12 colors in order
// @param _Index TODO: color number.
// @returns TODO: color code
export GetColor(
  int _Index) =>

    int _count =_Index % 12
    color ret =switch _count
        0  =>#ffbf7f
        1  =>#bf7fff
        2  =>#7fffbf
        3  =>#ff7f7f
        4  =>#7f7fff
        5  =>#7fff7f
        6  =>#ff7fbf
        7  =>#7fbfff
        8  =>#bfff7f
        9  =>#ff7fff
        10 =>#7fffff
        11 =>#ffff7f

// @function TODO: Table display position function
// @param _Pos TODO: position.
// @returns TODO: Table position
export Tbl_position(
  string _Pos) =>

    string _result =switch _Pos
        "top_left" => position.top_left
        "top_center" => position.top_center
        "top_right" => position.top_right
        "middle_left" => position.middle_left
        "middle_center" => position.middle_center
        "middle_right" => position.middle_right
        "bottom_left" => position.bottom_left
        "bottom_center" => position.bottom_center
        "bottom_right" => position.bottom_right
    _result

// @function      TODO: Delete Line
// @param         TODO: No parameter
// @returns       TODO: No return value
export DeleteLine() =>

    for currentElement in line.all
        line.delete(currentElement)

// @function      TODO: Delete Label
// @param         TODO: No parameter
// @returns       TODO: No return value
export DeleteLabel() =>

    for currentElement in label.all
        label.delete(currentElement)


// @function                 TODO: Draw a zig-zag line.
// @param _a_PHiLo           TODO: High-Low price array
// @param _a_IHiLo           TODO: High-Low INDEX array
// @param _a_FHiLo           TODO: High-Low flag array sequence 1:High 2:Low
// @param _a_DHiLo           TODO: High-Low Price Differential Array
// @param _Histories         TODO: Array size (High-Low length)
// @param _Provisional_PHiLo TODO: Provisional High-Low Price
// @param _Provisional_IHiLo TODO: Provisional High-Low INDEX
// @param _Color1            TODO: Normal High-Low color
// @param _Width1            TODO: Normal High-Low width
// @param _Color2            TODO: Provisional High-Low color
// @param _Width2            TODO: Provisional High-Low width
// @param _ShowLabel         TODO: Label display flag True: Displayed False: Not displayed
// @param _ShowHighLowBar    TODO: High-Low bar display flag True:Show False:Hide
// @param _HighLowBarWidth   TODO: High-Low bar width
// @param _HighLow_LabelSize TODO: Label Size
// @returns                  TODO: No return value
export ZigZag(
  float[] _a_PHiLo,           int[]   _a_IHiLo,
  int[]   _a_FHiLo,           float[] _a_DHiLo,
  int     _Histories,
  float   _Provisional_PHiLo, int     _Provisional_IHiLo,
  color   _Color1,            int     _Width1,
  color   _Color2,            int     _Width2,
  bool    _ShowLabel,         string  _LabelSize,
  bool    _ShowHighLowBar,    int     _HighLowBarWidth) =>

    string info =""
    var line l   =na
    var line l_1 =na
    var line l_2 =na

    int    i_1 =bar_index - _Histories
    int    i_2 =i_1

    float  p_1 =0., p_2 =0.
    int    f_1 =0 , f_2 =0
    float  d_1 =0., d_2 =0.

    bool _ShowTrendLine  =true

    // for int i =_Histories - 1 to 0
    for int i =0 to _Histories - 1

        i_2 :=i_1
        p_2 :=p_1
        f_2 :=f_1
        d_2 :=d_1

        i_1 :=array.get(_a_IHiLo, i)
        p_1 :=array.get(_a_PHiLo, i)
        f_1 :=array.get(_a_FHiLo, i)
        d_1 :=array.get(_a_DHiLo, i)

        // if i !=_Histories - 1
        if i !=0
            l :=line.new(i_1, p_1, i_2, p_2, color =_Color1, width =_Width1)

        if _ShowHighLowBar
            l_1 :=line.new(i_1, p_1, i_1 + 50, p_1, color =color.new(GetColor(i),     40), width =_HighLowBarWidth, extend=extend.right)
            if p_2 != 0.
                l_2 :=line.new(i_2, p_2, i_2 + 50, p_2, color =color.new(GetColor(i + 1), 40), width =_HighLowBarWidth, extend=extend.right)

        if _ShowLabel
            string yloc1  =yloc.abovebar
            string yloc2  =yloc.belowbar
            string style1 =label.style_none
            string style2 =label.style_none
            color  color1 =color.blue
            color  color2 =color.red

            if f_1 == 2
                yloc1  :=yloc.belowbar
                yloc2  :=yloc.abovebar
                color1 :=color.red
                color2 :=color.blue

            // info :=str.tostring(p_1)
            info :=str.tostring(p_1) + "\n(" + str.tostring(d_1) + ")"
            ShowLabel(info, i_1, p_1, style1, _LabelSize, yloc1, color1)
            if p_2 != 0.
                // info :=str.tostring(p_2)
                info :=str.tostring(p_2) + "\n(" + str.tostring(d_2) + ")"
                ShowLabel(info, i_2, p_2, style2, _LabelSize, yloc2, color2)

    if not na(_Provisional_PHiLo)
        if _Provisional_IHiLo > i_1
            l :=line.new(i_1, p_1, _Provisional_IHiLo, _Provisional_PHiLo, color =_Color2, width =_Width2)

// @function             TODO: Draw a Trend Line
// @param _a_PHiLo       TODO: High-Low price array
// @param _a_IHiLo       TODO: High-Low INDEX array
// @param _Histories     TODO: Array size (High-Low length)
// @param _MultiLine     TODO: Draw a multiple Line.
// @param _StartWidth    TODO: Line width start value  
// @param _EndWidth      TODO: Line width end value
// @param _IncreWidth    TODO: Line width increment value
// @param _StartTrans    TODO: Transparent rate start value
// @param _EndTrans      TODO: Transparent rate finally
// @param _IncreTrans    TODO: Transparent rate increase value
// @param _ColorMode     TODO: 0:Nomal 1:Gradation
// @param _Color1_1      TODO: Gradation Color 1_1
// @param _Color1_2      TODO: Gradation Color 1_2
// @param _Color2_1      TODO: Gradation Color 2_1
// @param _Color2_2      TODO: Gradation Color 2_2
// @param _Top_High      TODO: _Top_High Value for Gradation
// @param _Top_Low       TODO: _Top_Low Value for Gradation
// @param _Bottom_High   TODO: _Bottom_High Value for Gradation
// @param _Bottom_Low    TODO: _Bottom_Low Value for Gradation
// @returns              TODO: No return value
export TrendLine(
  float[] _a_PHiLo,    int[]   _a_IHiLo,
  int     _Histories,  bool    _MultiLine,
  float   _StartWidth, float   _EndWidth,
  float   _IncreWidth, int     _StartTrans,
  int     _EndTrans,   int     _IncreTrans,
  int     _ColorMode,  color   _Color1_1,
  color   _Color1_2,   color   _Color2_1,
  color   _Color2_2,   float   _Top_High,
  float   _Top_Low,    float   _Bottom_High,
  float   _Bottom_Low) =>
    var line l_1 =na
    var line l_2 =na
    var line l_3 =na
    var line l_4 =na
    var line l_5 =na
    var line l_6 =na

    int      i_1 =bar_index - _Histories, i_2 =i_1, i_3 =i_1, i_4 =i_1
    float    p_1 =0., p_2 =0., p_3 =0., p_4 =0.

    bool     flg =array.get(_a_PHiLo, 0) >= array.get(_a_PHiLo, 1)          // p_1 >= p_2 の時：True p_1 < p_2 の時：False
    
    float    width =0., trans =0.

    int      histories_1 =_Histories - 1
    int      histories_2 =_Histories - 1
    // 偶数
    if (histories_1) % 2 != 0
        histories_1 := histories_1 - 1
    // 奇数
    if (histories_2) % 2 == 0
        histories_2 := histories_2 - 1

    float    top_Hi    =_Top_High
    float    top_Lo    =_Top_Low
    float    bottom_Hi =_Bottom_High
    float    bottom_Lo =_Bottom_Low

    color    c1        =color.red
    color    c2        =color.blue

    if _MultiLine
        for int i =0 to _Histories - 1 by 2
            i_1 :=array.get(_a_IHiLo, i)
            p_1 :=array.get(_a_PHiLo, i)

            width :=_StartWidth + (i * _IncreWidth)
            if _IncreWidth > 0
                if width > _EndWidth
                    width :=_EndWidth
            else
                if width < _EndWidth
                    width :=_EndWidth

            trans :=_StartTrans + (i * _IncreTrans)
            if _IncreTrans > 0
                if trans > _EndTrans
                    trans :=_EndTrans
            else
                if trans < _EndTrans
                    trans :=_EndTrans

            for int j =histories_1 to i by 2
                if j < 0
                    break

                ShowLabel("histories_1:" + str.tostring(histories_1) + "/j:" + str.tostring(j), bar_index, high, label.style_label_down, size.auto, yloc.abovebar, color.white)

                i_3 :=array.get(_a_IHiLo, j)
                p_3 :=array.get(_a_PHiLo, j)
                if _ColorMode == 1
                    if flg  // p_1 → p_3 が p_2 → p_4 より上の時
                        if p_1 >= p_3   //  上向き⤴
                            // c1 :=color.new(color.from_gradient(math.abs((p_1 - p_3) / 2), bottom_Hi, top_Hi, _Color1_1, _Color1_2), trans)
                            c1 :=color.new(color.from_gradient(p_1, bottom_Hi, top_Hi, _Color1_1, _Color1_2), trans)
                        else            //　下向き⤵
                            // c1 :=color.new(color.from_gradient(math.abs((p_1 - p_3) / 2), bottom_Hi, top_Hi, _Color2_1, _Color2_2), trans)
                            c1 :=color.new(color.from_gradient(p_1, bottom_Hi, top_Hi, _Color2_1, _Color2_2), trans)
                    else
                        if p_1 >= p_3   //  上向き⤴
                            // c1 :=color.new(color.from_gradient(math.abs((p_1 - p_3) / 2), bottom_Lo, top_Lo, _Color1_1, _Color1_2), trans)
                            c1 :=color.new(color.from_gradient(p_1, bottom_Lo, top_Lo, _Color1_1, _Color1_2), trans)
                        else            //　下向き⤵
                            // c1 :=color.new(color.from_gradient(math.abs((p_1 - p_3) / 2), bottom_Lo, top_Lo, _Color2_1, _Color2_2), trans)
                            c1 :=color.new(color.from_gradient(p_1, bottom_Lo, top_Lo, _Color2_1, _Color2_2), trans)
                else
                    c1 :=color.new(GetColor(j), trans)

                l_1 :=line.new(i_1, p_1 + width, i_3, p_3 + width, color =c1, width =1, extend =extend.right)
                l_2 :=line.new(i_1, p_1,         i_3, p_3,         color =c1, width =1, extend =extend.right, style =line.style_dotted)
                l_3 :=line.new(i_1, p_1 - width, i_3, p_3 - width, color =c1, width =1, extend =extend.right)
                linefill.new(l_1, l_3, color.new(c1, 90))

        for int i =1 to _Histories - 1 by 2
            i_2 :=array.get(_a_IHiLo, i)
            p_2 :=array.get(_a_PHiLo, i)
    
            width :=_StartWidth + (i * _IncreWidth)
            if _IncreWidth > 0
                if width > _EndWidth
                    width :=_EndWidth
            else
                if width < _EndWidth
                    width :=_EndWidth

            trans :=_StartTrans + (i * _IncreTrans)
            if _IncreTrans > 0
                if trans > _EndTrans
                    trans :=_EndTrans
            else
                if trans < _EndTrans
                    trans :=_EndTrans

            for int j =histories_2 to i by 2
                if j < 0
                    break

                ShowLabel("histories_2:" + str.tostring(histories_2) + "/j:" + str.tostring(j), bar_index, low, label.style_label_up, size.auto, yloc.abovebar, color.white)

                i_4 :=array.get(_a_IHiLo, j)
                p_4 :=array.get(_a_PHiLo, j)
                if _ColorMode == 1
                    if flg  // p_1 → p_3 が p_2 → p_4 より上の時
                        if p_2 >= p_4   //  上向き⤴
                            c2 :=color.new(color.from_gradient(p_2, bottom_Lo, top_Lo, _Color1_1, _Color1_2), trans)
                        else            //　下向き⤵
                            c2 :=color.new(color.from_gradient(p_2, bottom_Lo, top_Lo, _Color2_1, _Color2_2), trans)
                    else
                        if p_2 >= p_4   //  上向き⤴
                            c2 :=color.new(color.from_gradient(p_2, bottom_Hi, top_Hi, _Color1_1, _Color1_2), trans)
                        else            //　下向き⤵
                            c2 :=color.new(color.from_gradient(p_2, bottom_Hi, top_Hi, _Color2_1, _Color2_2), trans)
                else
                    c2 :=color.new(GetColor(j), trans)

                l_4 :=line.new(i_2, p_2 + width, i_4, p_4 + width, color =c2, width =1, extend =extend.right)
                l_5 :=line.new(i_2, p_2,         i_4, p_4,         color =c2, width =1, extend =extend.right, style =line.style_dotted)
                l_6 :=line.new(i_2, p_2 - width, i_4, p_4 - width, color =c2, width =1, extend =extend.right)
                linefill.new(l_4, l_6, color.new(c2, 90))
    else
        for int i =0 to _Histories - 1
            i_4 :=i_3
            p_4 :=p_3
            i_3 :=i_2
            p_3 :=p_2
            i_2 :=i_1
            p_2 :=p_1
            i_1 :=array.get(_a_IHiLo, i)
            p_1 :=array.get(_a_PHiLo, i)

            width :=_StartWidth + (i * _IncreWidth)
            if _IncreWidth > 0
                if width > _EndWidth
                    width :=_EndWidth
            else
                if width < _EndWidth
                    width :=_EndWidth

            trans :=_StartTrans + (i * _IncreTrans)
            if _IncreTrans > 0
                if trans > _EndTrans
                    trans :=_EndTrans
            else
                if trans < _EndTrans
                    trans :=_EndTrans

            if p_4 !=0
                if _ColorMode == 1
                    if p_1 > p_3
                        c1 :=color.new(color.from_gradient(p_1, bottom_Hi, top_Hi, _Color1_1, _Color1_2), trans)
                    else
                        c1 :=color.new(color.from_gradient(p_1, bottom_Hi, top_Hi, _Color2_1, _Color2_2), trans)
                    if p_2 > p_4
                        c2 :=color.new(color.from_gradient(p_2, bottom_Lo, top_Lo, _Color1_1, _Color1_2), trans)
                    else
                        c2 :=color.new(color.from_gradient(p_2, bottom_Lo, top_Lo, _Color2_1, _Color2_2), trans)
                else
                    c1 :=color.new(GetColor(i),     trans)
                    c2 :=color.new(GetColor(i + 1), trans)

                l_1 :=line.new(i_1, p_1 + width, i_3, p_3 + width, color =c1, width =2, extend= extend.left)
                l_2 :=line.new(i_1, p_1,         i_3, p_3,         color =c1, width =2, extend= extend.left, style =line.style_dotted)
                l_3 :=line.new(i_1, p_1 - width, i_3, p_3 - width, color =c1, width =2, extend= extend.left)
                l_4 :=line.new(i_2, p_2 + width, i_4, p_4 + width, color =c2, width =2, extend= extend.left)
                l_5 :=line.new(i_2, p_2,         i_4, p_4,         color =c2, width =2, extend= extend.left, style =line.style_dotted)
                l_6 :=line.new(i_2, p_2 - width, i_4, p_4 - width, color =c2, width =2, extend= extend.left)
                linefill.new(l_1, l_3, color.new(c1, 90))
                linefill.new(l_4, l_6, color.new(c2, 90))

// @function                 TODO: Draw a Fibonacci line
// @param _a_Fibonacci       TODO: Fibonacci Percentage Array
// @param _a_PHiLo           TODO: High-Low price array
// @param _Provisional_PHiLo TODO: Provisional High-Low price (when _Index is 0)
// @param _Index             TODO: Where to draw the Fibonacci line
// @param _FrontMargin       TODO: Fibonacci line front-margin
// @param _BackMargin        TODO: Fibonacci line back-margin
// @returns                  TODO: No return value
export Fibonacci(
  float[] _a_Fibonacci,
  float[] _a_PHiLo,
  float   _Provisional_PHiLo, int   _Index,
  int     _FrontMargin,       int   _BackMargin) =>

    int    i_1 =0 , i_2 =0
    float  p_1 =0., p_2 =0.

    line   l   =na
    line[] ls  =array.new_line()

    int    index_1 =array.size(_a_PHiLo) - _Index
    int    index_2 =index_1 - 1

    float dir  =0.
    float diff =0.

    var label lbl1 = na

    i_1 :=bar_index + _FrontMargin
    i_2 :=bar_index + _BackMargin

    if _Index == 0
        p_1 :=_Provisional_PHiLo
    else
        p_1 :=array.get(_a_PHiLo, index_1)

    p_2 :=array.get(_a_PHiLo, index_2)

    // 上昇・下降判断用
    dir :=p_1 - p_2
    // 差の絶対値
    diff :=math.abs(dir)

    for i1 =0 to array.size(_a_Fibonacci) -1
        float _f =0.
        float _Fib =array.get(_a_Fibonacci, i1)
        // 上昇
        if dir > 0
            _f :=p_1 - (diff * _Fib)
        else
            _f :=p_1 + (diff * _Fib)

        l :=line.new(i_1, _f, i_2, _f, color =color.red, width =1)
        array.push(ls, l)
        lbl1 := label.new(x =i_1 + 7, y =_f, text =str.tostring(_Fib, "0.000") + " : " + str.tostring(_f, "0.000"), yloc = yloc.price, style =label.style_none) //, textalign =text.align_left)

    for i2 =0 to array.size(ls) -2
        if array.size(ls) >= 2
            line l1 =array.get(ls, i2)
            line l2 =array.get(ls, i2 + 1)
            linefill.new(l1, l2, color.new(GetColor(i2), 90))

// @function                 TODO: Draw a Fibonacci line
// @param _a_Fibonacci       TODO: Fibonacci Percentage Array
// @param _a_PHiLo           TODO: High-Low price array
// @param _Provisional_PHiLo TODO: Provisional High-Low price (when _Index is 0)
// @param _Index1            TODO: Where to draw the Fibonacci line 1
// @param _FrontMargin1      TODO: Fibonacci line front-margin 1
// @param _BackMargin1       TODO: Fibonacci line back-margin 1
// @param _Transparent1      TODO: Transparent rate 1
// @param _Index2            TODO: Where to draw the Fibonacci line 2
// @param _FrontMargin2      TODO: Fibonacci line front-margin 2
// @param _BackMargin2       TODO: Fibonacci line back-margin 2
// @param _Transparent2      TODO: Transparent rate 2
// @returns                  TODO: No return value
export Fibonacci(
  float[] _a_Fibonacci,       float[] _a_PHiLo,
  float   _Provisional_PHiLo,
  int     _Index1,            int     _FrontMargin1,
  int     _BackMargin1,       int     _Transparent1,
  int     _Index2,            int     _FrontMargin2,
  int     _BackMargin2,       int     _Transparent2) =>

    int    i1_1 =0 , i1_2 =0 , i2_1 =0 , i2_2 =0
    float  p1_1 =0., p1_2 =0., p2_1 =0., p2_2 =0.

    line   l1   =na
    line   l2   =na
    line[] ls1  =array.new_line(), ls2  =array.new_line()

    int    index1_1 =array.size(_a_PHiLo) - _Index1
    int    index1_2 =index1_1 - 1

    int    index2_1 =array.size(_a_PHiLo) - _Index2
    int    index2_2 =index2_1 - 1

    float dir1  =0., dir2  =0.
    float diff1 =0., diff2 =0.

    var label lbl1 = na
    var label lbl2 = na

    i1_1 :=bar_index + _FrontMargin1
    i1_2 :=bar_index + _BackMargin1

    i2_1 :=bar_index + _FrontMargin2
    i2_2 :=bar_index + _BackMargin2

    if _Index1 == 0
        p1_1 :=_Provisional_PHiLo
    else
        p1_1 :=array.get(_a_PHiLo, index1_1)

    if _Index2 == 0
        p2_1 :=_Provisional_PHiLo
    else
        p2_1 :=array.get(_a_PHiLo, index2_1)

    p1_2 :=array.get(_a_PHiLo, index1_2)
    p2_2 :=array.get(_a_PHiLo, index2_2)

    // 上昇・下降判断用
    dir1 :=p1_1 - p1_2
    dir2 :=p2_1 - p2_2
    // 差の絶対値
    diff1 :=math.abs(dir1)
    diff2 :=math.abs(dir2)

    for i =0 to array.size(_a_Fibonacci) -1
        float _f1 =0., _f2 =0.
        float _Fib =array.get(_a_Fibonacci, i)
        // 上昇
        if dir1 > 0
            _f1 :=p1_1 - (diff1 * _Fib)
        else
            _f1 :=p1_1 + (diff1 * _Fib)

        if dir2 > 0
            _f2 :=p2_1 - (diff2 * _Fib)
        else
            _f2 :=p2_1 + (diff2 * _Fib)

        l1 :=line.new(i1_1, _f1, i1_2, _f1, color =color.red, width =1)
        array.push(ls1, l1)
        l2 :=line.new(i2_1, _f2, i2_2, _f2, color =color.red, width =1)
        array.push(ls2, l2)

        lbl1 := label.new(x =i1_1 + 7, y =_f1, text =str.tostring(_Fib, "0.000") + " : " + str.tostring(_f1, "0.000"), yloc = yloc.price, style =label.style_none) //, textcolor =color.red)
        lbl2 := label.new(x =i2_1 + 7, y =_f2, text =str.tostring(_Fib, "0.000") + " : " + str.tostring(_f2, "0.000"), yloc = yloc.price, style =label.style_none) //, textcolor =color.red)

    for i =0 to array.size(ls1) -2
        if array.size(ls1) >= 2
            line l1_1 =array.get(ls1, i)
            line l1_2 =array.get(ls1, i + 1)
            linefill.new(l1_1, l1_2, color.new(GetColor(i), _Transparent1))
        if array.size(ls2) >= 2
            line l2_1 =array.get(ls2, i)
            line l2_2 =array.get(ls2, i + 1)
            linefill.new(l2_1, l2_2, color.new(GetColor(i), _Transparent2))

// @function           TODO: Judges High-Low
// @param _Length      TODO: High-Low Confirmation Length
// @param _Extension   TODO: Length of extension when the difference did not open
// @param _Difference  TODO: Difference size
// @returns            TODO: _HiLo=High-Low flag 0:Neither high nor low、1:High、2:Low、3:High-Low
//                           _PHi=high price、_PLo=low price、_IHi=High Price Index、_ILo=Low Price Index、
//                           _Cnt=count、_ECnt=Extension count、
//                           _DiffHi=Difference from Start(High)、_DiffLo=Difference from Start(Low)、
//                           _StartHi=Start value(High)、_StartLo=Start value(Low)
export High_Low_Judgment(
  int   _Length,
  int   _Extension,
  float _Difference) =>

    int _HiLo =0                                                                                            // High-Lowフラグ

    var float _PHi =-9999999999.                                                                            // Price Hi
    var float _PLo = 9999999999.                                                                            // Price Lo

    var int   _IHi =0                                                                                       // Index Hi
    var int   _ILo =0                                                                                       // Index Lo

    var int   _Cnt  =-1                                                                                     // カウント変数
    var int   _ECnt =0                                                                                      // Extカウント変数

    var float _DiffHi  =0.                                                                                  // Highの差
    var float _DiffLo  =0.                                                                                  // Lowの差

    var float _StartHi =0.                                                                                  // Start時のHigh
    var float _StartLo =0.                                                                                  // Start時のLow

    _Cnt +=1                                                                                                // カウントインクリ

    if _Cnt == 0                                                                                            // 初回の時
        _PHi :=high                                                                                         // _PHiにhighを保管
        _PLo :=low                                                                                          // _PLoにlowを保管
        _StartHi :=_PHi                                                                                     // _StartHiに初回highを保管
        _StartLo :=_PLo                                                                                     // _StartLoに初回lowを保管

        _IHi :=bar_index                                                                                    // _IHiにインデックスを保存
        _ILo :=bar_index                                                                                    // _ILoにインデックスを保存
    else                                                                                                    // 2回目以降の時
        if _PHi < high                                                                                      // _PHiよりhighが大きい
            _PHi :=high                                                                                     // _PHiをアップデート
            _IHi :=bar_index                                                                                // _IHiにインデックスを保存
    
        if _PLo > low                                                                                       // _PLoよりlowが小さい
            _PLo :=low                                                                                      // _PLoをアップデート
            _ILo :=bar_index                                                                                // _ILoにインデックスを保存

        if _Cnt >= _Length                                                                                  // _Cntが_Length以上
            _DiffHi :=_PHi - _StartHi                                                                       // _StartHi(初回)と_PHiとの差
            _DiffLo :=_StartLo - _PLo                                                                       // _StartLo(初回)と_PLoとの差
            if _DiffHi > _DiffLo                                                                            // Highの方が差が大きい
                if _DiffHi >= _Difference                                                                   // _DiffHiが_Difference以上
                    _HiLo :=1                                                                               // High-Lowフラグに1をセット
                    _Cnt  :=-1                                                                              // カウント変数リセット
                    _ECnt :=0                                                                               // Extカウント変数リセット
            else if _DiffLo > _DiffHi                                                                       // Lowの方が差が大きい
                if _DiffLo >= _Difference                                                                   // _DiffLoが_Difference以上
                    _HiLo :=2                                                                               // High-Lowフラグに2をセット
                    _Cnt  :=-1                                                                              // カウント変数リセット
                    _ECnt :=0                                                                               // Extカウント変数リセット
            else                                                                                            // High-Lowの差が同じ
                if _DiffHi >= _Difference                                                                   // _DiffLoが_Difference以上
                    _HiLo :=3                                                                               // High-Lowフラグに3をセット
                    _Cnt  :=-1                                                                              // カウント変数リセット
                    _ECnt :=0                                                                               // Extカウント変数リセット

            if _ECnt > _Extension                                                                           // _ECntが_Extension以上
                _Cnt  :=-1                                                                                  // カウント変数リセット
                _ECnt :=0                                                                                   // Extカウント変数リセット
                if _HiLo == 0
                    if _DiffHi > _DiffLo                                                                    // Highの方が大きい
                        _HiLo :=1                                                                           // High-Lowフラグに1をセット
                    else if _DiffLo > _DiffHi                                                               // Lowの方が大きい
                        _HiLo :=2                                                                           // High-Lowフラグに2をセット
                    else                                                                                    // High-Low同じ大きさ
                        _HiLo :=3                                                                           // High-Lowフラグに3をセット

            else
                _ECnt +=1

    [_HiLo, _PHi, _PLo, _IHi, _ILo, _Cnt, _ECnt, _DiffHi, _DiffLo, _StartHi, _StartLo]

// @function             TODO: Adds and updates High-Low related arrays from given parameters
// @param _HiLo          TODO: High-Low flag
// @param _Histories     TODO: Array size (High-Low length)
// @param _PHi           TODO: Price Hi
// @param _PLo           TODO: Price Lo
// @param _IHi           TODO: Index Hi
// @param _ILo           TODO: Index Lo
// @param _DiffHi        TODO: Difference in High
// @param _DiffLo        TODO: Difference in Low
// @param _a_PHiLo       TODO: High-Low price array
// @param _a_IHiLo       TODO: High-Low INDEX array
// @param _a_FHiLo       TODO: High-Low flag array 1:High 2:Low
// @param _a_DHiLo       TODO: High-Low Price Differential Array 
// @returns              TODO: _PHiLo price array、_IHiLo indexed array、_FHiLo flag array、_DHiLo price-matching array、
//                             Provisional_PHiLo Provisional price、Provisional_IHiLo 暫定インデックス
export High_Low_Data_AddedAndUpdated(
  int     _HiLo,    int     _Histories,
  float   _PHi,     float   _PLo,
  int     _IHi,     int     _ILo,
  float   _DiffHi,  float   _DiffLo,
  float[] _a_PHiLo, int[]   _a_IHiLo,
  int[]   _a_FHiLo, float[] _a_DHiLo) =>

    float Provisional_PHiLo =na																			    // 暫定High-Low 価格
    int   Provisional_IHiLo =na																			    // 暫定High-Low インデックス

    if _HiLo != 0																					        // High-Low フラグ 0=初期値でない時
        if array.get(_a_FHiLo, _Histories-1) == 1													        // 前回High-Low フラグ 1=High(高値)の時
            if _PHi >= array.get(_a_PHiLo, _Histories-1)											        // 前回High-Low 価格より現在High(高値)の方が高い(以上)
                ChangeHighLowArray(_a_PHiLo, _a_IHiLo, _a_DHiLo, _PHi, _IHi, _DiffHi, _Histories)	        // 前回High-Low 価格、インデックス、価格差を置き換える
                if _IHi <= _ILo																		        // 前回High-Low 情報(High)を置き換えたので、HighインデックスよりLowインデックスの方が大きいか確認する
																									        // ↑ちなみにHighは書き換え済みなので何もしない
                    if _HiLo == 2																	        // 今回がLowの時
                        SetHighLowArray(_a_PHiLo, _a_IHiLo, _a_FHiLo, _a_DHiLo, _PLo, _ILo, _HiLo, _DiffLo)	// 配列にLow値を追記する
            else																					        // 前回High-Low 価格より現在High(高値)の方が低い
                if _HiLo == 2																		        // 今回がLowの時
                    SetHighLowArray(_a_PHiLo, _a_IHiLo, _a_FHiLo, _a_DHiLo, _PLo, _ILo, _HiLo, _DiffLo)		// 配列にLow値を追記する
                else if _HiLo == 3																	        // 今回がHigh-Lowの時(HighでもLowでもある時)
                    SetHighLowArray(_a_PHiLo, _a_IHiLo, _a_FHiLo, _a_DHiLo, _PLo, _ILo, 2, _DiffLo)			// 前回がHighなので、配列にLow値から追記する
                    SetHighLowArray(_a_PHiLo, _a_IHiLo, _a_FHiLo, _a_DHiLo, _PHi, _IHi, 1, _DiffHi)			// 配列にLow値を追記したのでHigh値を追記する
        if array.get(_a_FHiLo, _Histories-1) == 2														    // 前回High-Low フラグ 2=Low(安値)の時
            if _PLo <= array.get(_a_PHiLo, _Histories-1)												    // 前回High-Low 価格より現在Low(安値)の方が低い(以下)
                ChangeHighLowArray(_a_PHiLo, _a_IHiLo, _a_DHiLo, _PLo, _ILo, _DiffLo, _Histories)			// 前回High-Low 価格、インデックス、価格差を置き換える
                if _ILo <= _IHi																		        // 前回High-Low 情報(Low)を置き換えたので、LowインデックスよりHighインデックスの方が大きいか確認する
																									        // ↑ちなみにLowは書き換え済みなので何もしない
                    if _HiLo == 1																	        // 今回がHighの時
                        SetHighLowArray(_a_PHiLo, _a_IHiLo, _a_FHiLo, _a_DHiLo, _PHi, _IHi, _HiLo, _DiffHi)	// 配列にHigh値を追記する
            else
                if _HiLo == 1																		        // 今回がHighの時
                    SetHighLowArray(_a_PHiLo, _a_IHiLo, _a_FHiLo, _a_DHiLo, _PHi, _IHi, _HiLo, _DiffHi)		// 配列にHigh値を追記する
                else if _HiLo == 3																	        // 今回がHigh-Lowの時(HighでもLowでもある時)
                    SetHighLowArray(_a_PHiLo, _a_IHiLo, _a_FHiLo, _a_DHiLo, _PHi, _IHi, 1, _DiffHi)			// 前回Lowなので、配列にHigh値から追記する
                    SetHighLowArray(_a_PHiLo, _a_IHiLo, _a_FHiLo, _a_DHiLo, _PLo, _ILo, 2, _DiffLo)			// 配列にHigh値を追記したのでLow値を追記する
        if array.get(_a_FHiLo, _Histories-1) == 0														    // 前回High-Low フラグ 0=初回の時
            if _HiLo == 1																			        // 今回がHighの時
                SetHighLowArray(_a_PHiLo, _a_IHiLo, _a_FHiLo, _a_DHiLo, _PHi, _IHi, _HiLo, _DiffHi)			// 配列にHigh値を追記する
            else if _HiLo == 2																		        // 今回がLowの時
                SetHighLowArray(_a_PHiLo, _a_IHiLo, _a_FHiLo, _a_DHiLo, _PLo, _ILo, _HiLo, _DiffLo)			// 配列にLow値を追記する
            else if _HiLo == 3																		        // 今回がHigh-Lowの時(HighでもLowでもある時)
                SetHighLowArray(_a_PHiLo, _a_IHiLo, _a_FHiLo, _a_DHiLo, _PHi, _IHi, 1, _DiffHi)				// とりあえず、配列にHigh値から追記する
                SetHighLowArray(_a_PHiLo, _a_IHiLo, _a_FHiLo, _a_DHiLo, _PLo, _ILo, 2, _DiffLo)				// 配列にHigh値を追記したのでLow値を追記する
    else																							        // High-Low フラグ 0=初期値の時
        float _price =array.get(_a_PHiLo, _Histories-1)												        // 前回価格の取得
        if array.get(_a_FHiLo, _Histories-1) == 1														    // 前回High-Low フラグ 1=High(高値)の時
            if _price <= _PHi																		        // 前回High-Low 価格より現在High(高値)の方が高い(以上)
                ChangeHighLowArray(_a_PHiLo, _a_IHiLo, _a_DHiLo, _PHi, _IHi, _DiffHi, _Histories)			// 前回High-Low 価格、インデックス、価格差を置き換える
            else
                Provisional_PHiLo :=_PLo																    // Lowとして暫定価格をセット
                Provisional_IHiLo :=_ILo																    // Lowとして暫定インデックスをセット
        if array.get(_a_FHiLo, _Histories-1) == 2														    // 前回High-Low フラグ 2=Low(安値)の時
            if _price >= _PLo																		        // 前回High-Low 価格より現在Low(安値)の方が低い(以下)
                ChangeHighLowArray(_a_PHiLo, _a_IHiLo, _a_DHiLo, _PLo, _ILo, _DiffLo, _Histories)			// 前回High-Low 価格、インデックス、価格差を置き換える
            else
                Provisional_PHiLo :=_PHi																    // Highとして暫定価格をセット
                Provisional_IHiLo :=_IHi																    // Highとして暫定インデックスをセット

    [_a_PHiLo, _a_IHiLo, _a_FHiLo, _a_DHiLo, Provisional_PHiLo, Provisional_IHiLo]

// @function               TODO: Draw the contents of the High-Low array.
// @param _a_PHiLo         TODO: High-Low price array
// @param _a_IHiLo         TODO: High-Low INDEX array
// @param _a_FHiLo         TODO: High-Low flag sequence 1:High 2:Low
// @param _a_DHiLo         TODO: High-Low Price Differential Array
// @param _a_Fibonacci     TODO: Fibonacci Gnar Matching
// @param _Length          TODO: Length of confirmation
// @param _Extension       TODO: Extension Length of extension when the difference did not open
// @param _Difference      TODO: Difference size
// @param _Histories       TODO: High-Low Length
// @param _ShowZigZag      TODO: ZigZag Display
// @param _ZigZagColor1    TODO: Colors of ZigZag1
// @param _ZigZagWidth1    TODO: Width of ZigZag1
// @param _ZigZagColor2    TODO: Colors of ZigZag2
// @param _ZigZagWidth2    TODO: Width of ZigZag2
// @param _ShowZigZagLabel TODO: ZigZagLabel Display
// @param _ShowHighLowBar  TODO: High-Low Bar Display
// @param _ShowTrendLine   TODO: Trend Line Display
// @param _TrendMultiLine  TODO: Trend Multi Line Display
// @param _TrendStartWidth TODO: Line width start value 
// @param _TrendEndWidth   TODO: Line width end value
// @param _TrendIncreWidth TODO: Line width increment value
// @param _TrendStartTrans TODO: Starting transmittance value
// @param _TrendEndTrans   TODO: Transmittance End Value
// @param _TrendIncreTrans TODO: Increased transmittance value
// @param _TrendColorMode  TODO: color mode
// @param _TrendColor1_1   TODO: Trend Color 1_1
// @param _TrendColor1_2   TODO: Trend Color 1_2
// @param _TrendColor2_1   TODO: Trend Color 2_1
// @param _TrendColor2_2   TODO: Trend Color 2_2
// @param _ShowFibonacci1  TODO: Fibonacci1 Display
// @param _FibIndex1       TODO: Fibonacci1 Index No.
// @param _FibFrontMargin1 TODO: Fibonacci1 Front margin
// @param _FibBackMargin1  TODO: Fibonacci1 Back Margin
// @param _FibTransparent1 TODO: Fibonacci1 Transmittance
// @param _ShowFibonacci2  TODO: Fibonacci2 Display
// @param _FibIndex2       TODO: Fibonacci2 Index No.
// @param _FibFrontMargin2 TODO: Fibonacci2 Front margin
// @param _FibBackMargin2  TODO: Fibonacci2 Back Margin
// @param _FibTransparent2 TODO: Fibonacci2 Transmittance
// @param _ShowInfoTable1  TODO: InfoTable1 Display
// @param _TablePosition1  TODO: InfoTable1 position
// @param _ShowInfoTable2  TODO: InfoTable2 Display
// @param _TablePosition2  TODO: InfoTable2 position
// @returns                TODO: 無し
export High_Low(
  float[] _a_PHiLo,         int[]   _a_IHiLo,
  int[]   _a_FHiLo,         float[] _a_DHiLo,
  float[] _a_Fibonacci,
  int     _Length,          int     _Extension,
  float   _Difference,      int     _Histories,
  bool    _ShowZigZag,
  color   _ZigZagColor1,    int     _ZigZagWidth1,
  color   _ZigZagColor2,    int     _ZigZagWidth2,
  bool    _ShowZigZagLabel, string  _ZigZagLabelSize,
  bool    _ShowHighLowBar,  int     _HighLowBarWidth,
  bool    _ShowTrendLine,   bool    _TrendMultiLine,
  float   _TrendStartWidth, float   _TrendEndWidth,
  float   _TrendIncreWidth, int     _TrendStartTrans,
  int     _TrendEndTrans,   int     _TrendIncreTrans,
  int     _TrendColorMode,
  color   _TrendColor1_1,   color   _TrendColor1_2,
  color   _TrendColor2_1,   color   _TrendColor2_2,
  string  _ShowFibonacci,
  int     _FibIndex1,       int     _FibFrontMargin1,
  int     _FibBackMargin1,  int     _FibTransparent1,
  int     _FibIndex2,       int     _FibFrontMargin2,
  int     _FibBackMargin2,  int     _FibTransparent2,
  bool    _ShowInfoTable1,  string  _TablePosition1,
  bool    _ShowInfoTable2,  string  _TablePosition2) =>

    [rHiLo, rPHi, rPLo, rIHi, rILo, rCnt, rECnt, rDiffHi, rDiffLo, rStartHi, rStartLo]
      =High_Low_Judgment(_Length, _Extension, _Difference)

    [rPHiLo, rIHiLo, rFHiLo, rDHiLo, Provisional_PHiLo, Provisional_IHiLo]
      =High_Low_Data_AddedAndUpdated(rHiLo, _Histories, rPHi, rPLo, rIHi, rILo, rDiffHi, rDiffLo, _a_PHiLo, _a_IHiLo, _a_FHiLo, _a_DHiLo)

    float top_Hi    =ta.highest(high, _Histories) * 0.1
    float top_Lo    =ta.highest(low,  _Histories) * 0.1
    float bottom_Hi =ta.lowest (high, _Histories) * 0.1
    float bottom_Lo =ta.lowest (low,  _Histories) * 0.1

    if _ShowInfoTable1
        var table    TBL_INFO_1    =na
        // テーブル作成
        TBL_INFO_1 :=table.new(Tbl_position(_TablePosition1), _Histories + 1, 3, border_width = 1)
        //// テーブルに値セット
        // 左タイトル
        table.cell(TBL_INFO_1, 0, 0, "",      bgcolor =color.new(color.lime, 0), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_1, 0, 1, "PRICE", bgcolor =color.new(color.lime, 0), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_1, 0, 2, "INDEX", bgcolor =color.new(color.lime, 0), text_color =color.black, text_size =size.auto)
    
        for i =0 to _Histories - 1
            // ヘッダー
            table.cell(TBL_INFO_1, i + 1, 0, str.tostring(i),                               bgcolor =color.new(color.lime,  0), text_color =color.black, text_size =size.auto)
            table.cell(TBL_INFO_1, i + 1, 1, str.tostring(array.get(_a_PHiLo, i), "0.000"), bgcolor =color.new(color.blue, 80), text_color =color.black, text_size =size.auto)
            table.cell(TBL_INFO_1, i + 1, 2, str.tostring(array.get(_a_IHiLo, i)),          bgcolor =color.new(color.red,  80), text_color =color.black, text_size =size.auto)

    if _ShowInfoTable2
        var table    TBL_INFO_2    =na
        // テーブル作成
        TBL_INFO_2 :=table.new(Tbl_position(_TablePosition2), 2, 12, border_width = 1)

        // 左タイトル
        table.cell(TBL_INFO_2, 0, 0,  "HiLo",    bgcolor =color.new(color.lime, 0), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 0, 1,  "PHi",     bgcolor =color.new(color.lime, 0), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 0, 2,  "PLo",     bgcolor =color.new(color.lime, 0), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 0, 3,  "IHi",     bgcolor =color.new(color.lime, 0), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 0, 4,  "ILo",     bgcolor =color.new(color.lime, 0), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 0, 5,  "Cnt",     bgcolor =color.new(color.lime, 0), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 0, 6,  "ECnt",    bgcolor =color.new(color.lime, 0), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 0, 7,  "DiffHi",  bgcolor =color.new(color.lime, 0), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 0, 8,  "DiffLo",  bgcolor =color.new(color.lime, 0), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 0, 9,  "StartHi", bgcolor =color.new(color.lime, 0), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 0, 10, "StartLo", bgcolor =color.new(color.lime, 0), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 0, 11, "INDEX",   bgcolor =color.new(color.lime, 0), text_color =color.black, text_size =size.auto)
    
        table.cell(TBL_INFO_2, 1, 0,  str.tostring(rHiLo),             bgcolor =color.new(color.red, 80), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 1, 1,  str.tostring(rPHi, "0.000"),     bgcolor =color.new(color.red, 80), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 1, 2,  str.tostring(rPLo, "0.000"),     bgcolor =color.new(color.red, 80), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 1, 3,  str.tostring(rIHi),              bgcolor =color.new(color.red, 80), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 1, 4,  str.tostring(rILo),              bgcolor =color.new(color.red, 80), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 1, 5,  str.tostring(rCnt),              bgcolor =color.new(color.red, 80), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 1, 6,  str.tostring(rECnt),             bgcolor =color.new(color.red, 80), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 1, 7,  str.tostring(rDiffHi,  "0.000"), bgcolor =color.new(color.red, 80), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 1, 8,  str.tostring(rDiffLo,  "0.000"), bgcolor =color.new(color.red, 80), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 1, 9,  str.tostring(rStartHi, "0.000"), bgcolor =color.new(color.red, 80), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 1, 10, str.tostring(rStartLo, "0.000"), bgcolor =color.new(color.red, 80), text_color =color.black, text_size =size.auto)
        table.cell(TBL_INFO_2, 1, 11, str.tostring(bar_index),         bgcolor =color.new(color.red, 80), text_color =color.black, text_size =size.auto)

    if _ShowZigZag
        ZigZag(rPHiLo, rIHiLo, rFHiLo, rDHiLo, _Histories, Provisional_PHiLo, Provisional_IHiLo,
          _ZigZagColor1, _ZigZagWidth1, _ZigZagColor2, _ZigZagWidth2, _ShowZigZagLabel, _ZigZagLabelSize, _ShowHighLowBar, _HighLowBarWidth)
    if _ShowTrendLine
        TrendLine(_a_PHiLo, _a_IHiLo, _Histories, _TrendMultiLine, _TrendStartWidth, _TrendEndWidth, _TrendIncreWidth, _TrendStartTrans, _TrendEndTrans, _TrendIncreTrans, _TrendColorMode, _TrendColor1_1, _TrendColor1_2, _TrendColor2_1, _TrendColor2_2, top_Hi, top_Lo, bottom_Hi, bottom_Lo)
    if _ShowFibonacci == "double"
        Fibonacci(_a_Fibonacci, rPHiLo, Provisional_PHiLo, _FibIndex1, _FibFrontMargin1, _FibBackMargin1, _FibTransparent1, _FibIndex2, _FibFrontMargin2, _FibBackMargin2, _FibTransparent2)
    else
        Fibonacci(_a_Fibonacci, rPHiLo, Provisional_PHiLo, _FibIndex1, _FibFrontMargin1, _FibBackMargin1)
