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
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
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
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
""" :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': }