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

//@version=5

// @description Functions to detect/check harmonic patterns from provided values.
library("HarmonicPattern")

// @function Compute the price rate of the line AB divided by the the line BC
// @param point_c float, the price at point C.
// @param point_b float, the price at point B.
// @param point_a float, the price at point A.
// @returns float
export line_price_rate (float point_c, float point_b, float point_a) => //{
//  C   A
//   \ /
//    B
    (point_a - point_b) / (point_b - point_c)
//}

// @function Compute the time rate of the line AB divided by the the line BC
// @param _c float, the time or bar_index at point C.
// @param _b float, the time or bar_index at point B.
// @param _a float, the time or bar_index at point A.
// @returns float
export line_time_rate (float point_c, float point_b, float point_a) => //{
//  C   A
//   \ /
//    B
    (0 - (point_a - point_b)) / (point_b - point_c)
//}

// @function Check if value is within min/max range of tolerance.
// @param value float, value to check tolerance.
// @param target float, min value to check range of tolerance.
// @param target float, max value to check range of tolerance.
// @param margin_of_error float, margin of error to validate range.
// @param calculation_type string, default='additive', options=['additive', 'multiplicative'], type of margin of error.
// @returns bool
export is_inrange (float value, float min, float max, float margin_of_error=0.05, string calculation_type="additive") => //{
    switch
        (calculation_type == 'additive')        => (value <= (max + margin_of_error)) and (value >= (min - margin_of_error))
        (calculation_type == 'multiplicative')  => (value <= (max * (1.0 + margin_of_error))) and (value >= (min * (1.0 - margin_of_error)))
        => runtime.error('HarmonicPattern -> is_inrange(): undefined margin calcultion type.'), bool(na)
//}


//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//  rates are expected in a backwards manner and of negative value.           ||
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//  G   E   C   A                                                             ||
//   \ / \ / \ /                                                              ||
//    F   D   B                                                               ||
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

// @function Check if the rate(s) correspond to pattern ("Harmonic Triangle").
// @param rate_cba float, percent rate of the triangle CBA. expects a negative rate.
// @param margin_of_error float, percent rate of expected error margin, default 0.05(5%).
// @param calculation_type string, default='additive', options=['additive', 'multiplicative'], type of margin of error.
// @returns bool
export isHarmonicTriangle (float rate_cba, float margin_of_error=0.05, string calculation_type="additive") => //{
    bool _return = false
    // return true if its rate is near a harmonic rate:
    // this is analogous with the fibonnaci sequence, but is capped at (-5 --> 12) to limit resource usage
	// 0.146, 0.236, 0.382, 0.618, 1, 1.618, 2.618, 4.236, 6.854, 11.089, 17.942, 29.03
    for _i = 1 to 12
        // calculate the derivative of phi sequence:
        float _phid = 0 - math.pow(math.phi, -5.0 + _i)
        if is_inrange(rate_cba, _phid, _phid, margin_of_error, calculation_type)
            _return := true
            break
    _return
//}

// @function Check if the rate(s) correspond to pattern ("2Tap", 'Double Top / Bottom').
// @param rate_cba float, percent rate of the triangle CBA. expects a negative rate.
// @param margin_of_error float, percent rate of expected error margin, default 0.05(5%).
// @param calculation_type string, default='additive', options=['additive', 'multiplicative'], type of margin of error.
// @returns bool
export is2Tap (float rate_cba, float margin_of_error=0.05, string calculation_type="additive") => //{
    is_inrange(rate_cba, -1.000, -1.000, margin_of_error, calculation_type)
//}

// @function Check if the rate(s) correspond to pattern ("3Tap", "Triple Top / Bottom").
// @param rate_edc float, percent rate of the triangle EDC. expects a negative rate.
// @param rate_cba float, percent rate of the triangle CBA. expects a negative rate.
// @param margin_of_error float, percent rate of expected error margin, default 0.05(5%).
// @param calculation_type string, default='additive', options=['additive', 'multiplicative'], type of margin of error.
// @returns bool
export is3Tap (float rate_edc, float rate_cba, float margin_of_error=0.05, string calculation_type="additive") => //{
    _is_edc = is_inrange(rate_edc, -1.000, -1.000, margin_of_error, calculation_type)
    _is_cba = is_inrange(rate_cba, -1.000, -1.000, margin_of_error, calculation_type)
    _is_edc and _is_cba
//}

// @function Check if the rate(s) correspond to pattern ("4Tap", "Quadruple Top / Bottom").
// @param rate_gfe float, percent rate of the triangle GFE. expects a negative rate.
// @param rate_edc float, percent rate of the triangle EDC. expects a negative rate.
// @param rate_cba float, percent rate of the triangle CBA. expects a negative rate.
// @param margin_of_error float, percent rate of expected error margin, default 0.05(5%).
// @param calculation_type string, default='additive', options=['additive', 'multiplicative'], type of margin of error.
// @returns bool
export is4Tap (float rate_gfe, float rate_edc, float rate_cba, float margin_of_error=0.05, string calculation_type="additive") => //{
    _is_gfe = is_inrange(rate_gfe, -1.000, -1.000, margin_of_error, calculation_type)
    _is_edc = is_inrange(rate_edc, -1.000, -1.000, margin_of_error, calculation_type)
    _is_cba = is_inrange(rate_cba, -1.000, -1.000, margin_of_error, calculation_type)
    _is_gfe and _is_edc and _is_cba
//}

// @function Check if the rate(s) correspond to pattern ("AB=CD").
// @param rate_cba float, percent rate of the triangle CBA. expects a negative rate.
// @param rate_dcb float, percent rate of the triangle DCB. expects a negative rate.
// @param margin_of_error float, percent rate of expected error margin, default 0.05(5%).
// @param calculation_type string, default='additive', options=['additive', 'multiplicative'], type of margin of error.
// @returns bool
export isABCD (float rate_cba, float rate_dcb, float margin_of_error=0.05, string calculation_type="additive") => //{
    _is_cba = is_inrange(rate_cba, -1.618, -1.270, margin_of_error, calculation_type)
    _is_dcb = is_inrange(rate_dcb, -0.786, -0.618, margin_of_error, calculation_type)
    _is_cba and _is_dcb
//}

// @function Check if the rate(s) correspond to pattern ("Bat").
// @param rate_edc float, percent rate of the triangle EDC. expects a negative rate.
// @param rate_dcb float, percent rate of the triangle DCB. expects a negative rate.
// @param rate_cba float, percent rate of the triangle CBA. expects a negative rate.
// @param rate_eda float, percent rate of the triangle EDA. expects a negative rate.
// @param margin_of_error float, percent rate of expected error margin, default 0.05(5%).
// @param calculation_type string, default='additive', options=['additive', 'multiplicative'], type of margin of error.
// @returns bool
export isBat (float rate_edc, float rate_dcb, float rate_cba, float rate_eda, float margin_of_error=0.05, string calculation_type="additive") => //{
    _is_edc = is_inrange(rate_edc, -0.500, -0.382, margin_of_error, calculation_type)
    _is_dcb = is_inrange(rate_dcb, -0.886, -0.382, margin_of_error, calculation_type)
    _is_cba = is_inrange(rate_cba, -2.618, -1.618, margin_of_error, calculation_type)
    _is_eda = is_inrange(rate_eda, -0.886, -0.886, margin_of_error, calculation_type)
    _is_edc and _is_dcb and _is_cba and _is_eda
//}

// @function Check if the rate(s) correspond to pattern ("Butterfly").
// @param rate_edc float, percent rate of the triangle EDC. expects a negative rate.
// @param rate_dcb float, percent rate of the triangle DCB. expects a negative rate.
// @param rate_cba float, percent rate of the triangle CBA. expects a negative rate.
// @param rate_eda float, percent rate of the triangle EDA. expects a negative rate.
// @param margin_of_error float, percent rate of expected error margin, default 0.05(5%).
// @param calculation_type string, default='additive', options=['additive', 'multiplicative'], type of margin of error.
// @returns bool
export isButterfly (float rate_edc, float rate_dcb, float rate_cba, float rate_eda, float margin_of_error=0.05, string calculation_type="additive") => //{
    _is_edc = is_inrange(rate_edc, -0.786, -0.786, margin_of_error, calculation_type)
    _is_dcb = is_inrange(rate_dcb, -0.886, -0.382, margin_of_error, calculation_type)
    _is_cba = is_inrange(rate_cba, -2.618, -1.618, margin_of_error, calculation_type)
    _is_eda = is_inrange(rate_eda, -1.618, -1.270, margin_of_error, calculation_type)
    _is_edc and _is_dcb and _is_cba and _is_eda
//}

// @function Check if the rate(s) correspond to pattern ("Gartley").
// @param rate_edc float, percent rate of the triangle EDC. expects a negative rate.
// @param rate_dcb float, percent rate of the triangle DCB. expects a negative rate.
// @param rate_cba float, percent rate of the triangle CBA. expects a negative rate.
// @param rate_eda float, percent rate of the triangle EDA. expects a negative rate.
// @param margin_of_error float, percent rate of expected error margin, default 0.05(5%).
// @param calculation_type string, default='additive', options=['additive', 'multiplicative'], type of margin of error.
// @returns bool
export isGartley (float rate_edc, float rate_dcb, float rate_cba, float rate_eda, float margin_of_error=0.05, string calculation_type="additive") => //{
    _is_edc = is_inrange(rate_edc, -0.618, -0.618, margin_of_error, calculation_type)
    _is_dcb = is_inrange(rate_dcb, -0.886, -0.382, margin_of_error, calculation_type)
    _is_cba = is_inrange(rate_cba, -2.618, -1.130, margin_of_error, calculation_type)
    _is_eda = is_inrange(rate_eda, -0.786, -0.786, margin_of_error, calculation_type)
    _is_edc and _is_dcb and _is_cba and _is_eda
//}

// @function Check if the rate(s) correspond to pattern ("Crab").
// @param rate_edc float, percent rate of the triangle EDC. expects a negative rate.
// @param rate_dcb float, percent rate of the triangle DCB. expects a negative rate.
// @param rate_cba float, percent rate of the triangle CBA. expects a negative rate.
// @param rate_eda float, percent rate of the triangle EDA. expects a negative rate.
// @param margin_of_error float, percent rate of expected error margin, default 0.05(5%).
// @param calculation_type string, default='additive', options=['additive', 'multiplicative'], type of margin of error.
// @returns bool
export isCrab (float rate_edc, float rate_dcb, float rate_cba, float rate_eda, float margin_of_error=0.05, string calculation_type="additive") => //{
    _is_edc = is_inrange(rate_edc, -0.886, -0.886, margin_of_error, calculation_type)
    _is_dcb = is_inrange(rate_dcb, -0.886, -0.382, margin_of_error, calculation_type)
    _is_cba = is_inrange(rate_cba, -3.618, -2.000, margin_of_error, calculation_type)
    _is_eda = is_inrange(rate_eda, -1.618, -1.618, margin_of_error, calculation_type)
    _is_edc and _is_dcb and _is_cba and _is_eda
//}

// @function Check if the rate(s) correspond to pattern ("Shark").
// @param rate_edc float, percent rate of the triangle EDC. expects a negative rate.
// @param rate_dcb float, percent rate of the triangle DCB. expects a negative rate.
// @param rate_cba float, percent rate of the triangle CBA. expects a negative rate.
// @param rate_eda float, percent rate of the triangle EDA. expects a negative rate.
// @param margin_of_error float, percent rate of expected error margin, default 0.05(5%).
// @param calculation_type string, default='additive', options=['additive', 'multiplicative'], type of margin of error.
// @returns bool
export isShark(float rate_edc, float rate_dcb, float rate_cba, float rate_eda, float margin_of_error=0.05, string calculation_type="additive") => //{
    _is_edc = is_inrange(rate_edc, -0.886, -0.886, margin_of_error, calculation_type)
    _is_dcb = is_inrange(rate_dcb, -1.618, -1.130, margin_of_error, calculation_type)
    _is_cba = is_inrange(rate_cba, -2.240, -1.270, margin_of_error, calculation_type)
    _is_eda = is_inrange(rate_eda, -1.130, -0.886, margin_of_error, calculation_type)
    _is_edc and _is_dcb and _is_cba and _is_eda
//}

// @function Check if the rate(s) correspond to pattern ("5o").
// @param rate_edc float, percent rate of the triangle EDC. expects a negative rate.
// @param rate_dcb float, percent rate of the triangle DCB. expects a negative rate.
// @param rate_cba float, percent rate of the triangle CBA. expects a negative rate.
// @param rate_eda float, percent rate of the triangle EDA. expects a negative rate.
// @param margin_of_error float, percent rate of expected error margin, default 0.05(5%).
// @param calculation_type string, default='additive', options=['additive', 'multiplicative'], type of margin of error.
// @returns bool
export is5o(float rate_edc, float rate_dcb, float rate_cba, float rate_eda, float margin_of_error=0.05, string calculation_type="additive") => //{
    _is_edc = is_inrange(rate_edc, -1.618, -1.130, margin_of_error, calculation_type)
    _is_dcb = is_inrange(rate_dcb, -2.240, -1.618, margin_of_error, calculation_type)
    _is_cba = is_inrange(rate_cba, -0.500, -0.500, margin_of_error, calculation_type)
    _is_eda = is_inrange(rate_eda, -0.236, +0.236, margin_of_error, calculation_type)
    _is_edc and _is_dcb and _is_cba and _is_eda
//}

// @function Check if the rate(s) correspond to pattern ("Wolfe").
// @param rate_edc float, percent rate of the triangle EDC. expects a negative rate.
// @param rate_dcb float, percent rate of the triangle DCB. expects a negative rate.
// @param rate_cba float, percent rate of the triangle CBA. expects a negative rate.
// @param rate_eda float, percent rate of the triangle EDA. expects a negative rate.
// @param margin_of_error float, percent rate of expected error margin, default 0.05(5%).
// @param calculation_type string, default='additive', options=['additive', 'multiplicative'], type of margin of error.
// @returns bool
export isWolfe(float rate_edc, float rate_dcb, float rate_cba, float rate_eda, float margin_of_error=0.05, string calculation_type="additive") => //{
    _is_edc = is_inrange(rate_edc, -1.618, -1.270, margin_of_error, calculation_type)
    _is_dcb = is_inrange(rate_dcb, -5.000, -0.000, margin_of_error, calculation_type)
    _is_cba = is_inrange(rate_cba, -1.618, -1.270, margin_of_error, calculation_type)
    _is_eda = is_inrange(rate_eda, -5.000, -0.000, margin_of_error, calculation_type)
    _is_edc and _is_dcb and _is_cba and _is_eda
//}

// @function Check if the rate(s) correspond to pattern ("3 Driver").
// @param rate_edc float, percent rate of the triangle EDC. expects a negative rate.
// @param rate_dcb float, percent rate of the triangle DCB. expects a negative rate.
// @param rate_cba float, percent rate of the triangle CBA. expects a negative rate.
// @param rate_eda float, percent rate of the triangle EDA. expects a negative rate.
// @param margin_of_error float, percent rate of expected error margin, default 0.05(5%).
// @param calculation_type string, default='additive', options=['additive', 'multiplicative'], type of margin of error.
// @returns bool
export is3Driver(float rate_edc, float rate_dcb, float rate_cba, float rate_eda, float margin_of_error=0.05, string calculation_type="additive") => //{
    _is_edc = is_inrange(rate_edc, -1.618, -1.270, margin_of_error, calculation_type)
    _is_dcb = is_inrange(rate_dcb, -5.000, -0.000, margin_of_error, calculation_type)
    _is_cba = is_inrange(rate_cba, -1.618, -1.270, margin_of_error, calculation_type)
    _is_eda = is_inrange(rate_eda, -5.000, -0.000, margin_of_error, calculation_type)
    _is_edc and _is_dcb and _is_cba and _is_eda
//}

// @function Check if the rate(s) correspond to pattern ("Contracting Triangle").
// @param rate_edc float, percent rate of the triangle EDC. expects a negative rate.
// @param rate_dcb float, percent rate of the triangle DCB. expects a negative rate.
// @param rate_cba float, percent rate of the triangle CBA. expects a negative rate.
// @param rate_eda float, percent rate of the triangle EDA. expects a negative rate.
// @param margin_of_error float, percent rate of expected error margin, default 0.05(5%).
// @param calculation_type string, default='additive', options=['additive', 'multiplicative'], type of margin of error.
// @returns bool
export isConTria(float rate_edc, float rate_dcb, float rate_cba, float rate_eda, float margin_of_error=0.05, string calculation_type="additive") => //{
    _is_edc = is_inrange(rate_edc, -0.886, -0.236, margin_of_error, calculation_type)
    _is_dcb = is_inrange(rate_dcb, -0.886, -0.236, margin_of_error, calculation_type)
    _is_cba = is_inrange(rate_cba, -0.886, -0.236, margin_of_error, calculation_type)
    _is_eda = is_inrange(rate_eda, -0.886, -0.236, margin_of_error, calculation_type)
    _is_edc and _is_dcb and _is_cba and _is_eda
//}

// @function Check if the rate(s) correspond to pattern ("Expanding Triangle").
// @param rate_edc float, percent rate of the triangle EDC. expects a negative rate.
// @param rate_dcb float, percent rate of the triangle DCB. expects a negative rate.
// @param rate_cba float, percent rate of the triangle CBA. expects a negative rate.
// @param rate_eda float, percent rate of the triangle EDA. expects a negative rate.
// @param margin_of_error float, percent rate of expected error margin, default 0.05(5%).
// @param calculation_type string, default='additive', options=['additive', 'multiplicative'], type of margin of error.
// @returns bool
export isExpTria(float rate_edc, float rate_dcb, float rate_cba, float rate_eda, float margin_of_error=0.05, string calculation_type="additive") => //{
    _is_edc = is_inrange(rate_edc, -2.618, -1.125, margin_of_error, calculation_type)
    _is_dcb = is_inrange(rate_dcb, -2.618, -1.125, margin_of_error, calculation_type)
    _is_cba = is_inrange(rate_cba, -2.618, -1.125, margin_of_error, calculation_type)
    _is_eda = is_inrange(rate_eda, -2.618, -1.125, margin_of_error, calculation_type)
    _is_edc and _is_dcb and _is_cba and _is_eda
//}

// @function Check if the rate(s) correspond to pattern ("Head and Shoulders").
// @param rate_fed float, percent rate of the triangle FED. expects a negative rate.
// @param rate_feb float, percent rate of the triangle FEB. expects a negative rate.
// @param rate_edc float, percent rate of the triangle EDC. expects a negative rate.
// @param rate_dcb float, percent rate of the triangle DCB. expects a negative rate.
// @param rate_cba float, percent rate of the triangle CBA. expects a negative rate.
// @param rate_eda float, percent rate of the triangle EDA. expects a negative rate.
// @param margin_of_error float, percent rate of expected error margin, default 0.05(5%).
// @param calculation_type string, default='additive', options=['additive', 'multiplicative'], type of margin of error.
// @returns bool
export isHnS(float rate_fed, float rate_feb, float rate_edc, float rate_dcb, float rate_cba, float rate_eda, float margin_of_error=0.05, string calculation_type="additive") => //{
    _is_fed = is_inrange(rate_fed, -0.618, -0.090, margin_of_error, calculation_type)
    _is_feb = is_inrange(rate_feb, -0.886, -0.090, margin_of_error, calculation_type)
    _is_edc = is_inrange(rate_edc, -9.999, -1.000, margin_of_error, calculation_type)
    _is_dcb = is_inrange(rate_dcb, -1.250, -0.750, margin_of_error, calculation_type)
    _is_cba = is_inrange(rate_cba, -0.886, -0.090, margin_of_error, calculation_type)
    _is_eda = is_inrange(rate_eda, -1.618, -0.090, margin_of_error, calculation_type)
    _is_fed and _is_feb and _is_edc and _is_eda and _is_dcb and _is_cba
//}

// @function Extract the available patterns from zigzag prices.
// @returns string array.
export extract (float price_g, float price_f, float price_e, float price_d, float price_c, float price_b, float price_a, float margin_of_error) => //{
    //  triangulate pivots into rates:
    //  note:
    //      • pattern rates should be negative
    //      • if rate is positive center is inside the edges.
    float price_gfc = line_price_rate(price_g, price_f, price_c)
    float price_gfa = line_price_rate(price_g, price_f, price_a)
    float price_gdc = line_price_rate(price_g, price_d, price_c)
    float price_gda = line_price_rate(price_g, price_d, price_a)
    float price_gfe = line_price_rate(price_g, price_f, price_e)
    float price_gba = line_price_rate(price_g, price_b, price_a)
    
    float price_fed = line_price_rate(price_f, price_e, price_d)
    float price_feb = line_price_rate(price_f, price_e, price_b)
    float price_fcb = line_price_rate(price_f, price_c, price_b)
            
    float price_edc = line_price_rate(price_e, price_d, price_c)
    float price_eda = line_price_rate(price_e, price_d, price_a)
    float price_eba = line_price_rate(price_e, price_b, price_a)
    
    float price_dcb = line_price_rate(price_d, price_c, price_b)
    float price_cba = line_price_rate(price_c, price_b, price_a)

    bool _isvalid_gfa = price_fed >= -1 and price_feb >= -1 and price_cba <= -1 and price_eda <= -1
    bool _isvalid_gda = price_fed <= -1 and price_gfe >= -1 and price_cba <= -1 and price_dcb >= -1 
    bool _isvalid_gba = price_feb <= -1 and price_gfe >= -1 and price_cba <= -1 and price_dcb <= -1
    bool _isvalid_eba = price_cba <= -1 and price_dcb <= -1
    bool _isvalid_eda = price_cba <= -1 and price_dcb >= -1
    bool _isvalid_fcb = price_fed >= -1 and price_edc <= -1
    bool _isvalid_feb = price_edc >= -1 and price_dcb <= -1

    string[] _pattern_list = array.new_string(0)
    
    //  Check if its a harmonic triangle:
    if isHarmonicTriangle(price_gfa, margin_of_error) and _isvalid_gfa
        array.push(_pattern_list, "• Harmonic Triangle(GFA) •")
    if isHarmonicTriangle(price_gda, margin_of_error) and _isvalid_gda
        array.push(_pattern_list, "• Harmonic Triangle(GDA) •")
    if isHarmonicTriangle(price_gba, margin_of_error) and _isvalid_gba
        array.push(_pattern_list, "• Harmonic Triangle(GBA) •")
    if isHarmonicTriangle(price_eba, margin_of_error) and _isvalid_eba
        array.push(_pattern_list, "• Harmonic Triangle(EBA) •")
    if isHarmonicTriangle(price_eda, margin_of_error) and _isvalid_eda
        array.push(_pattern_list, "• Harmonic Triangle(EDA) •")
    if isHarmonicTriangle(price_cba, margin_of_error)
        array.push(_pattern_list, "• Harmonic Triangle(CBA) •")
    //  Check if its Double Tap
    if is2Tap(price_cba, margin_of_error) 
        array.push(_pattern_list, "• Double Tap(CBA) •")
    if is2Tap(price_eba, margin_of_error) and _isvalid_eba
        array.push(_pattern_list, "• Double Tap(EBA) •")
    if is2Tap(price_eda, margin_of_error) and _isvalid_eda
        array.push(_pattern_list, "• Double Tap(EDA) •")
    //  Check if its Triple Tap
    if is3Tap(price_edc, price_cba, margin_of_error)
        array.push(_pattern_list, "• Triple Tap(EDC, CBA) •")
    //  Check if its Quadruple Tap
    if is4Tap(price_gfe, price_edc, price_cba, margin_of_error)
        array.push(_pattern_list, "• Quadruple Tap(GFE, EDC, CBA) •")

    //  check if its AB=CD
    if isABCD(price_cba, price_dcb, margin_of_error) 
        array.push(_pattern_list, "• AB=CD(CBA, DCB) •")
    if isABCD(price_cba, price_fcb, margin_of_error) and _isvalid_fcb
        array.push(_pattern_list, "• AB=CD(CBA, FCB) •")
    if isABCD(price_eba, price_feb, margin_of_error) and _isvalid_feb
        array.push(_pattern_list, "• AB=CD(EBA, FEB) •")
    if isABCD(price_eda, price_fed, margin_of_error) and _isvalid_eda
        array.push(_pattern_list, "• AB=CD(EDA, FED) •")
    //  check if its BAT:
    if isBat(price_edc, price_dcb, price_cba, price_eda, margin_of_error)
        array.push(_pattern_list, "• Bat(EDC, DCB, CBA, EDA) •")
    if isBat(price_gfe, price_feb, price_eba, price_gfa, margin_of_error) and _isvalid_eba
        array.push(_pattern_list, "• Bat(GFE, FEB, EBA, GFA) •")
    if isBat(price_gfe, price_fed, price_eda, price_gfa, margin_of_error) and _isvalid_eda
        array.push(_pattern_list, "• Bat(GFE, FED, EDA, GFA) •")
    //  check if its BUTTERFLY
    if isButterfly(price_edc, price_dcb, price_cba, price_eda, margin_of_error) 
        array.push(_pattern_list, "• Butterfly(EDC, DCB, CBA, EDA) •")
    if isButterfly(price_gfe, price_feb, price_eba, price_gfa, margin_of_error) and _isvalid_eba 
        array.push(_pattern_list, "• Butterfly(GFE, FEB, EBA, GFA) •")
    if isButterfly(price_gfe, price_fed, price_eda, price_gfa, margin_of_error) and _isvalid_eda
        array.push(_pattern_list, "• Butterfly(GFE, FED, EDA, GFA) •")
    //  check if its GARTLEY
    if isGartley(price_edc, price_dcb, price_cba, price_eda, margin_of_error)
        array.push(_pattern_list, "• Gartley(EDC, DCB, CBA, EDA) •")
    if isGartley(price_gfe, price_feb, price_eba, price_gfa, margin_of_error) and _isvalid_eba
        array.push(_pattern_list, "• Gartley(GFE, FEB, EBA, GFA) •")
    if isGartley(price_gfe, price_fed, price_eda, price_gfa, margin_of_error) and _isvalid_eda
        array.push(_pattern_list, "• Gartley(GFE, FED, EDA, GFA) •")
    //  check if its CRAB
    if isCrab(price_edc, price_dcb, price_cba, price_eda, margin_of_error)
        array.push(_pattern_list, "• Crab(EDC, DCB, CBA, EDA) •")
    if isCrab(price_gfe, price_feb, price_eba, price_gfa, margin_of_error) and _isvalid_eba
        array.push(_pattern_list, "• Crab(GFE, FEB, EBA, GFA) •")
    if isCrab(price_gfe, price_fed, price_eda, price_gfa, margin_of_error) and _isvalid_eda
        array.push(_pattern_list, "• Crab(GFE, FED, EDA, GFA) •")
    //  check if its SHARK
    if isShark(price_edc, price_dcb, price_cba, price_eda, margin_of_error) 
        array.push(_pattern_list, "• Shark(EDC, DCB, CBA, EDA) •")
    if isShark(price_gfe, price_feb, price_eba, price_gfa, margin_of_error) and _isvalid_eba
        array.push(_pattern_list, "• Shark(GFE, FEB, EBA, GFA) •")
    if isShark(price_gfe, price_fed, price_eda, price_gfa, margin_of_error) and _isvalid_eda
        array.push(_pattern_list, "• Shark(GFE, FED, EDA, GFA) •")
    //  check if its 5o
    if is5o(price_edc, price_dcb, price_cba, price_eda, margin_of_error)
        array.push(_pattern_list, "• 5o(EDC, DCB, CBA, EDA) •")
    if is5o(price_gfe, price_feb, price_eba, price_gfa, margin_of_error) and _isvalid_eba 
        array.push(_pattern_list, "• 5o(GFE, FEB, EBA, GFA) •")
    if is5o(price_gfe, price_fed, price_eda, price_gfa, margin_of_error) and _isvalid_eda
        array.push(_pattern_list, "• 5o(GFE, FED, EDA, GFA) •")
    //  check if its WOLF
    if isWolfe(price_edc, price_dcb, price_cba, price_eda, margin_of_error) 
        array.push(_pattern_list, "• Wolf(EDC, DCB, CBA, EDA) •")
    if isWolfe(price_gfe, price_feb, price_eba, price_gfa, margin_of_error) and _isvalid_eba
        array.push(_pattern_list, "• Wolf(GFE, FEB, EBA, GFA) •")
    if isWolfe(price_gfe, price_fed, price_eda, price_gfa, margin_of_error) and _isvalid_eda
        array.push(_pattern_list, "• Wolf(GFE, FED, EDA, GFA) •")
    //  check if its Contracting Triangle
    if isConTria(price_edc, price_dcb, price_cba, price_eda, margin_of_error)
        array.push(_pattern_list, "• Contracting Triangle(EDC, DCB, CBA, EDA) •")
    if isConTria(price_gfe, price_feb, price_eba, price_gfa, margin_of_error) and _isvalid_eba
        array.push(_pattern_list, "• Contracting Triangle(GFE, FEB, EBA, GFA) •")
    if isConTria(price_gfe, price_fed, price_eda, price_gfa, margin_of_error) and _isvalid_eda
        array.push(_pattern_list, "• Contracting Triangle(GFE, FED, EDA, GFA) •")
    //  check if its Expanding Triangle
    if isExpTria(price_edc, price_dcb, price_cba, price_eda, margin_of_error)
        array.push(_pattern_list, "• Expanding Triangle(EDC, DCB, CBA, EDA) •")
    if isExpTria(price_gfe, price_feb, price_eba, price_gfa, margin_of_error) and _isvalid_eba
        array.push(_pattern_list, "• Expanding Triangle(GFE, FEB, EBA, GFA) •")
    if isExpTria(price_gfe, price_fed, price_eda, price_gfa, margin_of_error) and _isvalid_eda
        array.push(_pattern_list, "• Expanding Triangle(GFE, FED, EDA, GFA) •")
    //  check if its Head and Shoulders
    if isHnS(price_fed, price_feb, price_dcb, price_edc, price_eda, price_cba, margin_of_error)
        array.push(_pattern_list, "• Head and Shoulders(FED, FEB, DCB, EDC, EDA, CBA) •")
    _pattern_list
//}


