def HSAR(ys, pflag, x, method='RW', **kwargs):
    """
    The HSAR(*) identifies HSARs at time t conditioning information up to time t-1.
    Function RW from processing is embedded.

    :param ys: column vector of price series with time index
    :param w: width of the rolling window (total 2w+1)
    :param x: desired percentage that will give the bounds for the HSARs (e.g., 5%)
    warning: for commodity prices which base price is large, I consider calculate x
    based on the minimum price change, where x = minimum price change / ys.mean()
    :param pflag: plot a graph if 1
    :return:
        SAR: horizontal support and resistance levels
        Bounds: bounds of bins used to classify the peaks and bottoms
        Freq: frequencies for each bin
        x_act: actual percentage of the bins' distance
    """
    if method == 'RW':
        Peaks, Bottoms = RW(ys, w=kwargs['w'], iteration=kwargs['iteration'])
    elif method == 'TP':
        Peaks, Bottoms = TP(ys, iteration=kwargs['iteration'])

    l = len(ys)
    if l > 250:
        pflag = 0

    if pflag == 1:
        PB_plotting(ys, Peaks, Bottoms)

    # TODO: commodity price is not continuously changing, should be careful with
    # TODO: data preprocessing
    L = Peaks.append(Bottoms)
    x = 10 / ys.mean()
    L1 = L.min() / (1 + x / 2)
    Ln = L.max() * (1 + x / 2)
    # My modification to calculate number of bins, for the problem that
    # for commodity prices, the base price is large, so pct bandwidth is hard
    # to find
    n = np.log(Ln / L1) / np.log(1 + x)
    N_act = np.int(np.round(n))
    x_act = (Ln / L1)**(1 / N_act) - 1

    Bounds = L1 * (1 + x_act)**(pd.Series(np.arange(0, N_act + 1)))
    Freq = [0] * N_act
    for i in range(0, N_act):
        Freq[i] = np.count_nonzero((L >= Bounds[i]) & (L < Bounds[i + 1]))
    ls_idx = [i for i, x in enumerate(Freq) if x >= 2]

    if len(ls_idx) == 0:
        print('No HSARs identified')
        SAR = []
    else:
        m = len(ls_idx)
        SAR = (Bounds[ls_idx].values + Bounds[[i + 1
                                               for i in ls_idx]].values) / 2

    return SAR, Bounds, Freq, x_act, Peaks, Bottoms
Esempio n. 2
0
def wave_check(ys, method='RW', **kwargs):
    l = len(ys)
    if method == 'RW':
        Peaks, Bottoms = RW(ys, w=kwargs['w'], iteration=kwargs['iteration'])
        # Peaks, Bottoms = RW(ys, w=1, iteration=2)
    elif method == 'TP':
        Peaks, Bottoms = TP(ys, iteration=kwargs['iteration'])

    ls_x = ys.index.tolist()
    ls_p = Peaks.index.tolist()
    ls_b = Bottoms.index.tolist()
    P_idx = [ys.index.get_loc(x) for x in ls_p]
    B_idx = [ys.index.get_loc(x) for x in ls_b]

    P_idx = pd.Series(index=ls_p, data=[1] * len(ls_p))
    B_idx = pd.Series(index=ls_b, data=[2] * len(ls_b))
    PB_idx = P_idx.append(B_idx)
    PB_idx.sort_index(inplace=True)
    m = len(PB_idx.index)

    Pot_Wave_up1 = [2, 1]
    Pot_Wave_down1 = [1, 2]
    Pot_Index = [0] * m

    for i in range(m - 1, 0, -1):
        # print(i)
        if PB_idx.iloc[i - 1:i + 1].values.tolist() == Pot_Wave_up1:
            Pot_Index[i - 1] = 1
        elif PB_idx.iloc[i - 1:i + 1].values.tolist() == Pot_Wave_down1:
            Pot_Index[i - 1] = 2

    PNidx = [i for i, x in enumerate(Pot_Index) if x == 1]
    PIidx = [i for i, x in enumerate(Pot_Index) if x == 2]

    Wave_up = ys.loc[(PB_idx.iloc[PNidx[-1]:PNidx[-1] +
                                  2]).index.tolist()].copy()
    Wave_down = ys.loc[(PB_idx.iloc[PIidx[-1]:PIidx[-1] +
                                    2]).index.tolist()].copy()

    MA = SMA(ys, w=5)['SMA']
    # wave_plotting(ys, Peaks, Bottoms, MA=MA)

    dict_results = {
        'Up': Wave_up,
        'Down': Wave_down,
        'Peaks': Peaks,
        'Bottoms': Bottoms,
        'MA': MA
    }

    return dict_results
Esempio n. 3
0
def TTTB(ys, pflag, method='RW', **kwargs):
    """
    The TTTB(*) identifies Triple Tops/ Triple Bottoms Pattern on a price series by
    adopting the following conditions:

        1) Trend preexistence:
                    TT: uptrend if P1 > P0 & T1 > T0
                    TB: downtrend if P1 < P0 & T1 < T0
        2) Balance:
                    TT: (max(P1, P3) - min(P1, P3)) / min(P1, P3) <= 0.04 & P2 <= max(P1, P3)
                    TB: (max(T1, T3) - min(T1, T3)) / min(T1, T3) <= 0.04 & T2 >= min(T1, T3)
        3) Intervening locals
                    TT: T1 <= T2 <= 1.04T1
                    TB: P2 <= P1 <= 1.04P2
        4) Symmetry:
                    TT: tP2 - tP1 < 2.5(tP3 - tP2) & tP3 - tP2 < 2.5(tP2 - tP1)
                    TB: tT2 - tT1 < 2.5(tT3 - tT2) & tT3 - tT2 < 2.5(tT2 - tT1)
        5) Penetration:
                    TT: tB < tP3 + (tP3 - tP1)
                    TB: tB < tT3 + (tT3 - tT1)

    :param ys: column vector of price series with time index
    :param pflag: plot a graph if 1
    :param method:
        1) RW: rolling window method to find turning points
                kwargs['w']
        2) TP: turning points with filter methods (iter=2)
                kwargs['iteration']
    :param kwargs: {'w': width of the rolling window (total 2w+1)
                    'iteration': iteration number for TP method,
                    'savefig': True,
                    'figname': str(figname)}
    :return:
    """
    l = len(ys)
    if method == 'RW':
        Peaks, Bottoms = RW(ys, w=kwargs['w'], iteration=kwargs['iteration'])
    elif method == 'TP':
        Peaks, Bottoms = TP(ys, iteration=kwargs['iteration'])

    Peaks, Bottoms = RW(ys, w=1, iteration=0)
    pflag = 1
    if l > 250:
        pflag = 0

    if pflag == 1:
        PB_plotting(ys, Peaks, Bottoms)

    ls_x = ys.index.tolist()
    ls_p = Peaks.index.tolist()
    ls_b = Bottoms.index.tolist()

    P_idx = pd.Series(index=ls_p, data=[1] * len(ls_p))
    B_idx = pd.Series(index=ls_b, data=[2] * len(ls_b))
    PB_idx = P_idx.append(B_idx)
    PB_idx.sort_index(inplace=True)
    m = len(PB_idx.index)

    Pot_Normal = [1, 2, 1, 2, 1]
    Pot_Inverse = [2, 1, 2, 1, 2]
    Pot_Index = [0] * m

    for i in range(0, m - 4):
        if PB_idx.iloc[i:i + 5].values.tolist() == Pot_Normal:
            Pot_Index[i + 4] = 1
        elif PB_idx.iloc[i:i + 5].values.tolist() == Pot_Inverse:
            Pot_Index[i + 4] = 2

    PNidx = [i for i, x in enumerate(Pot_Index) if x == 1]
    PIidx = [i for i, x in enumerate(Pot_Index) if x == 2]

    # TODO
    ## Triple Tops (Normal Form)
    # Definition of outputs
    Patterns_Normal_Points = []
    Patterns_Normal_Necklines = []
    Patterns_Normal_Breakpoints = []
    Patterns_Normal_Widths = []
    Patterns_Normal_Heights = []
    Patterns_Normal_TL = []
    Patterns_Normal_PT = []

    mn = len(PNidx)
    Pot_Normalcases_Percases = [0] * mn
    if mn != 0:
        Pot_Normalcases_Idx = [0] * mn
        for i in range(0, mn):
            # Conditions check
            PerCase = pd.DataFrame(columns=['P/B', 'Price'])
            PerCase.loc[:, 'P/B'] = PB_idx.iloc[PNidx[i] - 4:PNidx[i] + 1]
            PerCase.loc[:, 'Price'] = ys.loc[PerCase.index.tolist()].values
            # Condition 2 3 4
            ls_tmp = [PerCase.iloc[0]['Price'], PerCase.iloc[4]['Price']]
            if (PerCase.iloc[2]['Price'] <= np.max([PerCase.iloc[0]['Price'], PerCase.iloc[4]['Price']])) & \
                    ((np.max(ls_tmp) - np.min(ls_tmp))/np.min(ls_tmp) <= 0.04) & \
                    (PerCase.iloc[1]['Price'] <= PerCase.iloc[3]['Price'] <= 1.4*(PerCase.iloc[1]['Price'])) & \
                    ((ls_x.index(PerCase.index.tolist()[2]) - ls_x.index(PerCase.index.tolist()[0])) <
                     2.5 * (ls_x.index(PerCase.index.tolist()[4]) - ls_x.index(PerCase.index.tolist()[2]))) & \
                    ((ls_x.index(PerCase.index.tolist()[4]) - ls_x.index(PerCase.index.tolist()[2])) <
                     2.5 * (ls_x.index(PerCase.index.tolist()[2]) - ls_x.index(PerCase.index.tolist()[0]))):
                Pot_Normalcases_Idx[i] = 1
                Pot_Normalcases_Percases[i] = PerCase
    else:
        Pot_Normalcases_Idx = 0

    mnn = np.sum(Pot_Normalcases_Idx)
    if mnn == 0:
        pass
    else:
        Pot_Normalcases_Idx2 = [
            i for i, x in enumerate(Pot_Normalcases_Idx) if x == 1
        ]
    j = 0
    if mnn != 0:
        for i in range(0, mnn):
            NPerCase = Pot_Normalcases_Percases[Pot_Normalcases_Idx2[i]]
            Timelimit = ls_x.index(NPerCase.index.tolist()[4]) + ls_x.index(NPerCase.index.tolist()[4]) - \
                        ls_x.index(NPerCase.index.tolist()[0])
            # TODO
            # Neckline_Beta = (NPerCase.iloc[3]['Price'] - NPerCase.iloc[1]['Price']) / \
            #                 (ls_x.index(NPerCase.index.tolist()[3]) - ls_x.index(NPerCase.index.tolist()[1]))
            # Neckline_Alpha = NPerCase.iloc[1]['Price'] - Neckline_Beta * ls_x.index(NPerCase.index.tolist()[1])
            if Timelimit <= l:
                Neckline_OU = list(
                    range(
                        ls_x.index(NPerCase.index.tolist()[4]) + 1, Timelimit))
            else:
                Neckline_OU = list(
                    range(ls_x.index(NPerCase.index.tolist()[4]) + 1, l))

            Neckline_OU = pd.DataFrame(index=[ls_x[i] for i in Neckline_OU],
                                       data=ys.iloc[Neckline_OU])
            Neckline_OU.columns = ['Price']
            Neckline_OU.loc[:, 'Line'] = [
                ls_x.index(i) for i in Neckline_OU.index.tolist()
            ]
            Neckline_OU.loc[:,
                            'Line'] = Neckline_OU.loc[:,
                                                      'Line'] * Neckline_Beta + Neckline_Alpha
            Neckline_OU.loc[:,
                            'Diff'] = Neckline_OU.loc[:,
                                                      'Price'] - Neckline_OU.loc[:,
                                                                                 'Line']
            # TODO: optimize codes
            if len((Neckline_OU.where(Neckline_OU.loc[:, 'Diff'] < 0).dropna()
                    ).index.tolist()) != 0:
                Neckline_Breakpoint = ls_x.index((Neckline_OU.where(
                    Neckline_OU.loc[:,
                                    'Diff'] < 0).dropna()).index.tolist()[0])
                j += 1
                Patterns_Normal_Points.append(NPerCase)
                Patterns_Normal_Necklines.append(
                    [Neckline_Alpha, Neckline_Beta])
                Patterns_Normal_Breakpoints.append([
                    ls_x[Neckline_Breakpoint],
                    ys.loc[ls_x[Neckline_Breakpoint]]
                ])
                Patterns_Normal_Widths.append(
                    ls_x.index(NPerCase.index.tolist()[3]) -
                    ls_x.index(NPerCase.index.tolist()[1]))
                Patterns_Normal_Heights.append(NPerCase.iloc[2]['Price'] - (
                    Neckline_Beta * ls_x.index(NPerCase.index.tolist()[2]) +
                    Neckline_Alpha))
                Patterns_Normal_TL.append(
                    ls_x.index(Patterns_Normal_Breakpoints[-1][0]) +
                    Patterns_Normal_Widths[-1])
                tstar, ystar, LU, LD = line_inter([
                    [
                        ls_x.index(NPerCase.index.tolist()[1]),
                        NPerCase.iloc[1]['Price']
                    ],
                    [
                        ls_x.index(NPerCase.index.tolist()[3]),
                        NPerCase.iloc[3]['Price']
                    ]
                ], [[
                    ls_x.index(Patterns_Normal_Breakpoints[-1][0]) - 1,
                    ys.iloc[ls_x.index(Patterns_Normal_Breakpoints[-1][0]) - 1]
                ],
                    [
                        ls_x.index(Patterns_Normal_Breakpoints[-1][0]),
                        Patterns_Normal_Breakpoints[-1][1]
                    ]])
                Patterns_Normal_PT.append(ystar - Patterns_Normal_Heights[-1])
    Patterns_Normal_Numberofnormals = j

    ## Triple Bottoms (Inverse Form)
    # Definition of outputs
    Patterns_Inverse_Points = []
    Patterns_Inverse_Necklines = []
    Patterns_Inverse_Breakpoints = []
    Patterns_Inverse_Widths = []
    Patterns_Inverse_Heights = []
    Patterns_Inverse_TL = []
    Patterns_Inverse_PT = []

    mi = len(PIidx)
    Pot_Inversecases_Percases = [0] * mi  # bug??
    if mi != 0:
        Pot_Inversecases_Idx = [0] * mi
        for i in range(0, mi):
            # Conditions check
            PerCase = pd.DataFrame(columns=['P/B', 'Price'])
            PerCase.loc[:, 'P/B'] = PB_idx.iloc[PIidx[i] - 4:PIidx[i] + 1]
            PerCase.loc[:, 'Price'] = ys.loc[PerCase.index.tolist()].values
            # Condition 1 3 4
            if ((PerCase.iloc[2]['Price'] < np.min(
                [PerCase.iloc[0]['Price'], PerCase.iloc[4]['Price']])) &
                (PerCase.iloc[0]['Price'] <= 0.5 *
                 np.sum([PerCase.iloc[3]['Price'], PerCase.iloc[4]['Price']]))
                    &
                (PerCase.iloc[4]['Price'] <= 0.5 *
                 np.sum([PerCase.iloc[0]['Price'], PerCase.iloc[1]['Price']]))
                    & ((ls_x.index(PerCase.index.tolist()[2]) -
                        ls_x.index(PerCase.index.tolist()[0])) < 2.5 *
                       (ls_x.index(PerCase.index.tolist()[4]) -
                        ls_x.index(PerCase.index.tolist()[2]))) &
                ((ls_x.index(PerCase.index.tolist()[4]) -
                  ls_x.index(PerCase.index.tolist()[2])) < 2.5 *
                 (ls_x.index(PerCase.index.tolist()[2]) -
                  ls_x.index(PerCase.index.tolist()[0])))):
                Pot_Inversecases_Idx[i] = 1
                Pot_Inversecases_Percases[i] = PerCase  # bug??
    else:
        Pot_Inversecases_Idx = 0

    mii = np.sum(Pot_Inversecases_Idx)
    if mii == 0:
        pass
    else:
        Pot_Inversecases_Idx2 = [
            i for i, x in enumerate(Pot_Inversecases_Idx) if x == 1
        ]
    jj = 0
    if mii != 0:
        for i in range(0, mii):
            NPerCase = Pot_Inversecases_Percases[Pot_Inversecases_Idx2[i]]
            Timelimit = ls_x.index(NPerCase.index.tolist()[4]) + ls_x.index(NPerCase.index.tolist()[4]) - \
                        ls_x.index(NPerCase.index.tolist()[0])
            Neckline_Beta = (NPerCase.iloc[3]['Price'] - NPerCase.iloc[1]['Price']) / \
                            (ls_x.index(NPerCase.index.tolist()[3]) - ls_x.index(NPerCase.index.tolist()[1]))
            Neckline_Alpha = NPerCase.iloc[1][
                'Price'] - Neckline_Beta * ls_x.index(
                    NPerCase.index.tolist()[1])
            if Timelimit <= l:
                Neckline_OU = list(
                    range(
                        ls_x.index(NPerCase.index.tolist()[4]) + 1, Timelimit))
            else:
                Neckline_OU = list(
                    range(ls_x.index(NPerCase.index.tolist()[4]) + 1, l))

            Neckline_OU = pd.DataFrame(index=[ls_x[i] for i in Neckline_OU],
                                       data=ys.iloc[Neckline_OU])
            Neckline_OU.columns = ['Price']
            Neckline_OU.loc[:, 'Line'] = [
                ls_x.index(i) for i in Neckline_OU.index.tolist()
            ]
            Neckline_OU.loc[:,
                            'Line'] = Neckline_OU.loc[:,
                                                      'Line'] * Neckline_Beta + Neckline_Alpha
            Neckline_OU.loc[:,
                            'Diff'] = Neckline_OU.loc[:,
                                                      'Price'] - Neckline_OU.loc[:,
                                                                                 'Line']
            # TODO: optimize codes
            if len((Neckline_OU.where(Neckline_OU.loc[:, 'Diff'] > 0).dropna()
                    ).index.tolist()) != 0:
                Neckline_Breakpoint = ls_x.index((Neckline_OU.where(
                    Neckline_OU.loc[:,
                                    'Diff'] > 0).dropna()).index.tolist()[0])
                jj += 1
                Patterns_Inverse_Points.append(NPerCase)
                Patterns_Inverse_Necklines.append(
                    [Neckline_Alpha, Neckline_Beta])
                Patterns_Inverse_Breakpoints.append([
                    ls_x[Neckline_Breakpoint],
                    ys.loc[ls_x[Neckline_Breakpoint]]
                ])
                Patterns_Inverse_Widths.append(
                    ls_x.index(NPerCase.index.tolist()[3]) -
                    ls_x.index(NPerCase.index.tolist()[1]))
                Patterns_Inverse_Heights.append(
                    np.abs(NPerCase.iloc[2]['Price'] -
                           (Neckline_Beta *
                            ls_x.index(NPerCase.index.tolist()[2]) +
                            Neckline_Alpha)))
                Patterns_Inverse_TL.append(
                    ls_x.index(Patterns_Inverse_Breakpoints[-1][0]) +
                    Patterns_Inverse_Widths[-1])
                tstar, ystar, LU, LD = line_inter([
                    [
                        ls_x.index(NPerCase.index.tolist()[1]),
                        NPerCase.iloc[1]['Price']
                    ],
                    [
                        ls_x.index(NPerCase.index.tolist()[3]),
                        NPerCase.iloc[3]['Price']
                    ]
                ], [[
                    ls_x.index(Patterns_Inverse_Breakpoints[-1][0]) - 1,
                    ys.iloc[ls_x.index(Patterns_Inverse_Breakpoints[-1][0]) -
                            1]
                ],
                    [
                        ls_x.index(Patterns_Inverse_Breakpoints[-1][0]),
                        Patterns_Inverse_Breakpoints[-1][1]
                    ]])
                Patterns_Inverse_PT.append(ystar +
                                           Patterns_Inverse_Heights[-1])
    Patterns_Inverse_Numberofinverses = jj

    dict_Patterns = {
        'Normal': {
            'Points': Patterns_Normal_Points,
            'Breakpoints': Patterns_Normal_Breakpoints,
            'Necklines': Patterns_Normal_Necklines,
            'Number': Patterns_Normal_Numberofnormals,
            'PriceTarget': Patterns_Normal_PT
        },
        'Inverse': {
            'Points': Patterns_Inverse_Points,
            'Breakpoints': Patterns_Inverse_Breakpoints,
            'Necklines': Patterns_Inverse_Necklines,
            'Number': Patterns_Inverse_Numberofinverses,
            'PriceTarget': Patterns_Inverse_PT
        }
    }

    return dict_Patterns, Peaks, Bottoms
Esempio n. 4
0
def HS(ys, pflag, method='RW', **kwargs):
    """
    The HS(*) identifies Head and Shoulders Pattern on a price series by
    adopting the conditions presented in (Lucke 2003).
    e.g., HS tops pattern
        1) Head recognition: P2 > max(P1, P3)
        2) Trend preexistence: 
                    P1 > P0 & T1 > T0 (trend reversal pattern)
                    P1 < P0 & T1 < T0 (trend continuation pattern)
        3) Balance:
                    P1>=0.5(P3+T2) & P3>=0.5(P1+T1)
        4) Symmetry:
                    tP2 - tP1 < 2.5(tP3 - tP2) &
                    tP3 - tP2 < 2.5(tP2 - tP1)
        5) Penetration:
                    B < ((T2-T1)/(tT2-tT1))*(tB-tT1)+T1
                    tB < tP3 + (tP3 - tP1)

    :param ys: column vector of price series with time index
    :param pflag: plot a graph if 1
    :param method:
        1) RW: rolling window method to find turning points
                kwargs['w']
        2) TP: turning points with filter methods (iter=2)
                kwargs['iteration']
    :param kwargs: {'w': width of the rolling window (total 2w+1)
                    'iteration': iteration number for TP method,
                    'savefig': True,
                    'figname': str(figname)}
    :return:
    """
    l = len(ys)
    if method == 'RW':
        Peaks, Bottoms = RW(ys, w=kwargs['w'], iteration=kwargs['iteration'])
    elif method == 'TP':
        Peaks, Bottoms = TP(ys, iteration=kwargs['iteration'])

    if l > 250:
        pflag = 0

    if pflag == 1:
        PB_plotting(ys, Peaks, Bottoms)

    ls_x = ys.index.tolist()
    ls_p = Peaks.index.tolist()
    ls_b = Bottoms.index.tolist()
    P_idx = [ys.index.get_loc(x) for x in ls_p]
    B_idx = [ys.index.get_loc(x) for x in ls_b]

    P_idx = pd.Series(index=ls_p, data=[1] * len(ls_p))
    B_idx = pd.Series(index=ls_b, data=[2] * len(ls_b))
    PB_idx = P_idx.append(B_idx)
    PB_idx.sort_index(inplace=True)
    m = len(PB_idx.index)

    Pot_Normal = [1, 2, 1, 2, 1]
    Pot_Inverse = [2, 1, 2, 1, 2]
    Pot_Index = [0] * m

    for i in range(0, m - 4):
        if PB_idx.iloc[i:i + 5].values.tolist() == Pot_Normal:
            Pot_Index[i + 4] = 1
        elif PB_idx.iloc[i:i + 5].values.tolist() == Pot_Inverse:
            Pot_Index[i + 4] = 2

    PNidx = [i for i, x in enumerate(Pot_Index) if x == 1]
    PIidx = [i for i, x in enumerate(Pot_Index) if x == 2]

    ## HS Tops (Normal Form)
    # Definition of outputs
    Patterns_Normal_Points = []
    Patterns_Normal_Necklines = []
    Patterns_Normal_Breakpoints = []
    Patterns_Normal_Widths = []
    Patterns_Normal_Heights = []
    Patterns_Normal_TL = []
    Patterns_Normal_PT = []

    mn = len(PNidx)
    Pot_Normalcases_Percases = [0] * mn  # bug??
    if mn != 0:
        Pot_Normalcases_Idx = [0] * mn
        for i in range(0, mn):
            # Conditions check
            PerCase = pd.DataFrame(columns=['P/B', 'Price'])
            PerCase.loc[:, 'P/B'] = PB_idx.iloc[PNidx[i] - 4:PNidx[i] + 1]
            PerCase.loc[:, 'Price'] = ys.loc[PerCase.index.tolist()].values
            # Condition 1 3 4
            if ((PerCase.iloc[2]['Price'] > np.max(
                [PerCase.iloc[0]['Price'], PerCase.iloc[4]['Price']])) &
                (PerCase.iloc[0]['Price'] >= 0.5 *
                 np.sum([PerCase.iloc[3]['Price'], PerCase.iloc[4]['Price']]))
                    &
                (PerCase.iloc[4]['Price'] >= 0.5 *
                 np.sum([PerCase.iloc[0]['Price'], PerCase.iloc[1]['Price']]))
                    & ((ls_x.index(PerCase.index.tolist()[2]) -
                        ls_x.index(PerCase.index.tolist()[0])) < 2.5 *
                       (ls_x.index(PerCase.index.tolist()[4]) -
                        ls_x.index(PerCase.index.tolist()[2]))) &
                ((ls_x.index(PerCase.index.tolist()[4]) -
                  ls_x.index(PerCase.index.tolist()[2])) < 2.5 *
                 (ls_x.index(PerCase.index.tolist()[2]) -
                  ls_x.index(PerCase.index.tolist()[0])))):
                Pot_Normalcases_Idx[i] = 1
                Pot_Normalcases_Percases[i] = PerCase  # bug??
    else:
        Pot_Normalcases_Idx = 0

    mnn = np.sum(Pot_Normalcases_Idx)
    if mnn == 0:
        pass
    else:
        Pot_Normalcases_Idx2 = [
            i for i, x in enumerate(Pot_Normalcases_Idx) if x == 1
        ]
    j = 0
    if mnn != 0:
        for i in range(0, mnn):
            NPerCase = Pot_Normalcases_Percases[Pot_Normalcases_Idx2[i]]
            Timelimit = ls_x.index(NPerCase.index.tolist()[4]) + ls_x.index(NPerCase.index.tolist()[4]) -\
            ls_x.index(NPerCase.index.tolist()[0])
            Neckline_Beta = (NPerCase.iloc[3]['Price'] - NPerCase.iloc[1]['Price']) /\
            (ls_x.index(NPerCase.index.tolist()[3]) - ls_x.index(NPerCase.index.tolist()[1]))
            Neckline_Alpha = NPerCase.iloc[1][
                'Price'] - Neckline_Beta * ls_x.index(
                    NPerCase.index.tolist()[1])
            if Timelimit <= l:
                Neckline_OU = list(
                    range(
                        ls_x.index(NPerCase.index.tolist()[4]) + 1, Timelimit))
            else:
                Neckline_OU = list(
                    range(ls_x.index(NPerCase.index.tolist()[4]) + 1, l))

            Neckline_OU = pd.DataFrame(index=[ls_x[i] for i in Neckline_OU],
                                       data=ys.iloc[Neckline_OU])
            Neckline_OU.columns = ['Price']
            Neckline_OU.loc[:, 'Line'] = [
                ls_x.index(i) for i in Neckline_OU.index.tolist()
            ]
            Neckline_OU.loc[:,
                            'Line'] = Neckline_OU.loc[:,
                                                      'Line'] * Neckline_Beta + Neckline_Alpha
            Neckline_OU.loc[:,
                            'Diff'] = Neckline_OU.loc[:,
                                                      'Price'] - Neckline_OU.loc[:,
                                                                                 'Line']
            # TODO: optimize codes
            if len((Neckline_OU.where(Neckline_OU.loc[:, 'Diff'] < 0).dropna()
                    ).index.tolist()) != 0:
                Neckline_Breakpoint = ls_x.index((Neckline_OU.where(
                    Neckline_OU.loc[:,
                                    'Diff'] < 0).dropna()).index.tolist()[0])
                j += 1
                Patterns_Normal_Points.append(NPerCase)
                Patterns_Normal_Necklines.append(
                    [Neckline_Alpha, Neckline_Beta])
                Patterns_Normal_Breakpoints.append([
                    ls_x[Neckline_Breakpoint],
                    ys.loc[ls_x[Neckline_Breakpoint]]
                ])
                Patterns_Normal_Widths.append(
                    ls_x.index(NPerCase.index.tolist()[4]) -
                    ls_x.index(NPerCase.index.tolist()[0]))
                Patterns_Normal_Heights.append(NPerCase.iloc[2]['Price'] - (
                    Neckline_Beta * ls_x.index(NPerCase.index.tolist()[2]) +
                    Neckline_Alpha))
                Patterns_Normal_TL.append(
                    ls_x.index(Patterns_Normal_Breakpoints[-1][0]) +
                    Patterns_Normal_Widths[-1])
                tstar, ystar, LU, LD = line_inter([
                    [
                        ls_x.index(NPerCase.index.tolist()[1]),
                        NPerCase.iloc[1]['Price']
                    ],
                    [
                        ls_x.index(NPerCase.index.tolist()[3]),
                        NPerCase.iloc[3]['Price']
                    ]
                ], [[
                    ls_x.index(Patterns_Normal_Breakpoints[-1][0]) - 1,
                    ys.iloc[ls_x.index(Patterns_Normal_Breakpoints[-1][0]) - 1]
                ],
                    [
                        ls_x.index(Patterns_Normal_Breakpoints[-1][0]),
                        Patterns_Normal_Breakpoints[-1][1]
                    ]])
                Patterns_Normal_PT.append(ystar - Patterns_Normal_Heights[-1])
    Patterns_Normal_Numberofnormals = j

    ## HS Bottoms (Inverse Form)
    # Definition of outputs
    Patterns_Inverse_Points = []
    Patterns_Inverse_Necklines = []
    Patterns_Inverse_Breakpoints = []
    Patterns_Inverse_Widths = []
    Patterns_Inverse_Heights = []
    Patterns_Inverse_TL = []
    Patterns_Inverse_PT = []

    mi = len(PIidx)
    Pot_Inversecases_Percases = [0] * mi  # bug??
    if mi != 0:
        Pot_Inversecases_Idx = [0] * mi
        for i in range(0, mi):
            # Conditions check
            PerCase = pd.DataFrame(columns=['P/B', 'Price'])
            PerCase.loc[:, 'P/B'] = PB_idx.iloc[PIidx[i] - 4:PIidx[i] + 1]
            PerCase.loc[:, 'Price'] = ys.loc[PerCase.index.tolist()].values
            # Condition 1 3 4
            if ((PerCase.iloc[2]['Price'] < np.min(
                [PerCase.iloc[0]['Price'], PerCase.iloc[4]['Price']])) &
                (PerCase.iloc[0]['Price'] <= 0.5 *
                 np.sum([PerCase.iloc[3]['Price'], PerCase.iloc[4]['Price']]))
                    &
                (PerCase.iloc[4]['Price'] <= 0.5 *
                 np.sum([PerCase.iloc[0]['Price'], PerCase.iloc[1]['Price']]))
                    & ((ls_x.index(PerCase.index.tolist()[2]) -
                        ls_x.index(PerCase.index.tolist()[0])) < 2.5 *
                       (ls_x.index(PerCase.index.tolist()[4]) -
                        ls_x.index(PerCase.index.tolist()[2]))) &
                ((ls_x.index(PerCase.index.tolist()[4]) -
                  ls_x.index(PerCase.index.tolist()[2])) < 2.5 *
                 (ls_x.index(PerCase.index.tolist()[2]) -
                  ls_x.index(PerCase.index.tolist()[0])))):
                Pot_Inversecases_Idx[i] = 1
                Pot_Inversecases_Percases[i] = PerCase  # bug??
    else:
        Pot_Inversecases_Idx = 0

    mii = np.sum(Pot_Inversecases_Idx)
    if mii == 0:
        pass
    else:
        Pot_Inversecases_Idx2 = [
            i for i, x in enumerate(Pot_Inversecases_Idx) if x == 1
        ]
    jj = 0
    if mii != 0:
        for i in range(0, mii):
            NPerCase = Pot_Inversecases_Percases[Pot_Inversecases_Idx2[i]]
            Timelimit = ls_x.index(NPerCase.index.tolist()[4]) + ls_x.index(NPerCase.index.tolist()[4]) - \
                        ls_x.index(NPerCase.index.tolist()[0])
            Neckline_Beta = (NPerCase.iloc[3]['Price'] - NPerCase.iloc[1]['Price']) / \
                            (ls_x.index(NPerCase.index.tolist()[3]) - ls_x.index(NPerCase.index.tolist()[1]))
            Neckline_Alpha = NPerCase.iloc[1][
                'Price'] - Neckline_Beta * ls_x.index(
                    NPerCase.index.tolist()[1])
            if Timelimit <= l:
                Neckline_OU = list(
                    range(
                        ls_x.index(NPerCase.index.tolist()[4]) + 1, Timelimit))
            else:
                Neckline_OU = list(
                    range(ls_x.index(NPerCase.index.tolist()[4]) + 1, l))

            Neckline_OU = pd.DataFrame(index=[ls_x[i] for i in Neckline_OU],
                                       data=ys.iloc[Neckline_OU])
            Neckline_OU.columns = ['Price']
            Neckline_OU.loc[:, 'Line'] = [
                ls_x.index(i) for i in Neckline_OU.index.tolist()
            ]
            Neckline_OU.loc[:,
                            'Line'] = Neckline_OU.loc[:,
                                                      'Line'] * Neckline_Beta + Neckline_Alpha
            Neckline_OU.loc[:,
                            'Diff'] = Neckline_OU.loc[:,
                                                      'Price'] - Neckline_OU.loc[:,
                                                                                 'Line']
            # TODO: optimize codes
            if len((Neckline_OU.where(Neckline_OU.loc[:, 'Diff'] > 0).dropna()
                    ).index.tolist()) != 0:
                Neckline_Breakpoint = ls_x.index((Neckline_OU.where(
                    Neckline_OU.loc[:,
                                    'Diff'] > 0).dropna()).index.tolist()[0])
                jj += 1
                Patterns_Inverse_Points.append(NPerCase)
                Patterns_Inverse_Necklines.append(
                    [Neckline_Alpha, Neckline_Beta])
                Patterns_Inverse_Breakpoints.append([
                    ls_x[Neckline_Breakpoint],
                    ys.loc[ls_x[Neckline_Breakpoint]]
                ])
                Patterns_Inverse_Widths.append(
                    ls_x.index(NPerCase.index.tolist()[4]) -
                    ls_x.index(NPerCase.index.tolist()[0]))
                Patterns_Inverse_Heights.append(
                    np.abs(NPerCase.iloc[2]['Price'] -
                           (Neckline_Beta *
                            ls_x.index(NPerCase.index.tolist()[2]) +
                            Neckline_Alpha)))
                Patterns_Inverse_TL.append(
                    ls_x.index(Patterns_Inverse_Breakpoints[-1][0]) +
                    Patterns_Inverse_Widths[-1])
                tstar, ystar, LU, LD = line_inter([
                    [
                        ls_x.index(NPerCase.index.tolist()[1]),
                        NPerCase.iloc[1]['Price']
                    ],
                    [
                        ls_x.index(NPerCase.index.tolist()[3]),
                        NPerCase.iloc[3]['Price']
                    ]
                ], [[
                    ls_x.index(Patterns_Inverse_Breakpoints[-1][0]) - 1,
                    ys.iloc[ls_x.index(Patterns_Inverse_Breakpoints[-1][0]) -
                            1]
                ],
                    [
                        ls_x.index(Patterns_Inverse_Breakpoints[-1][0]),
                        Patterns_Inverse_Breakpoints[-1][1]
                    ]])
                Patterns_Inverse_PT.append(ystar +
                                           Patterns_Inverse_Heights[-1])
    Patterns_Inverse_Numberofinverses = jj

    dict_Patterns = {
        'Normal': {
            'Points': Patterns_Normal_Points,
            'Breakpoints': Patterns_Normal_Breakpoints,
            'Necklines': Patterns_Normal_Necklines,
            'Number': Patterns_Normal_Numberofnormals,
            'PriceTarget': Patterns_Normal_PT
        },
        'Inverse': {
            'Points': Patterns_Inverse_Points,
            'Breakpoints': Patterns_Inverse_Breakpoints,
            'Necklines': Patterns_Inverse_Necklines,
            'Number': Patterns_Inverse_Numberofinverses,
            'PriceTarget': Patterns_Inverse_PT
        }
    }

    return dict_Patterns, Peaks, Bottoms
Esempio n. 5
0
    """
    
    :param ys: 
    :param pflag: 
    :param x: 
    :param indata: an integer number defining the size of the initial subsample used for the 
    identification of the first HSARs
    :param method: 
    :param kwargs: 
    :return: 
    """

    if method == 'RW':
        Peaks, Bottoms = RW(ys, w=kwargs['w'], iteration=kwargs['iteration'])
    elif method == 'TP':
        Peaks, Bottoms = TP(ys, iteration=kwargs['iteration'])

    l = len(ys)

    if l>250:
        pflag = 0

    if pflag == 1:
        PB_plotting(ys, Peaks, Bottoms)

    dict_Results = {
        'NofSARs': [np.nan]*l,
        'x_act': [np.nan]*l,
        # 'ActSARs': ,
        # 'PofSARs':
    }