tendencyCalculator

  1from numpy import average
  2import pandas as pd
  3
  4BIG_NUMBER = 999999999
  5predefined_type_of_price = 'Close'
  6
  7#TODO Añadir que con longer dataset compruebe si pasa la resistencia
  8
  9def findPatternTendency(data_sequence, longer_data_sequence, type):
 10    """Method to redirect and calculate the tendency for a given dataframe"""
 11    if type == 'double_top':
 12        return findDoubleTopTendency(data_sequence, longer_data_sequence)
 13    if type == 'double_bottom':
 14        return findDoubleBottomTendency(data_sequence, longer_data_sequence)
 15    else:
 16        raise Exception('Pattern type not found')
 17
 18def findDoubleTopTendency(data_sequence, longer_data_sequence):
 19    """Calculates the tendency for a double top pattern  
 20    
 21        Args:  
 22            data_sequence (dataframe): dataframe representing the pattern
 23            longer_data_sequence (dataframe): dataframe representing the pattern but ends on the day the search is made  
 24        Return:  
 25            tendency (Pair[]): first element for True, False or None, and second element for the specific dataframe containing the pattern
 26            but it ends where the tendency was determined
 27    """
 28    first_top = [0, None] #index 0 representa el valor y el index 1 representa la posicion dentro del dataframe
 29    second_top = [0, None]
 30    for i in range(data_sequence.size - 1): #Buscar los dos techos
 31        day_value = data_sequence.iloc[i][predefined_type_of_price]
 32        if i > 0:
 33            previous_day_value = data_sequence.iloc[i - 1][predefined_type_of_price]
 34        if i < data_sequence.size - 1:
 35            next_day_value = data_sequence.iloc[i + 1][predefined_type_of_price]
 36        if i > 0 and previous_day_value < day_value and day_value > next_day_value: #hemos encontrado un maximo
 37            relative_maximum = day_value
 38            if relative_maximum > first_top[0]: # [1] para acceder a lo que no es timestamps y Close porque es la etiqueta del valor
 39                first_top = second_top
 40                second_top = [relative_maximum, i]
 41            elif relative_maximum > second_top[0]:
 42                second_top = [relative_maximum, i]
 43    
 44    if first_top[1] == None or second_top[1] == None:
 45        return None #No se encontraron dos techos
 46
 47    resistance = [BIG_NUMBER, None]
 48    for i in range(first_top[1], second_top[1]): #Busqueda de la linea de apoyo
 49        current_value = data_sequence.iloc[i][predefined_type_of_price]
 50        if current_value < resistance[0]:
 51            resistance[0] = current_value
 52            resistance[1] = i
 53
 54    #Añadir que los dos techo no estas muy lejos, como mucho en la mitad entre el mas alto y la linea de soporte
 55
 56    first_top_to_resistance_distance = first_top[0] - resistance[0]
 57    second_top_to_resistance_distance = second_top[0] - resistance[0]
 58    if first_top_to_resistance_distance > second_top_to_resistance_distance and second_top_to_resistance_distance < first_top_to_resistance_distance * 2 / 3:
 59        return None # Demasiada diferencia entre techos
 60    if second_top_to_resistance_distance > first_top_to_resistance_distance and first_top_to_resistance_distance < second_top_to_resistance_distance * 2 / 3:
 61        return None # Demasiada diferencia entre techos
 62
 63    breaks_resistance_from_left = [False, None]
 64    breaks_resistance_from_right = [False, None]
 65
 66    #Confirmar que en rompe por la linea de apoyo en ambos lados
 67    i = first_top[1]
 68    while i >= 0 and not breaks_resistance_from_left[0]:
 69        current_value_left = data_sequence.iloc[i][predefined_type_of_price]
 70        if current_value_left < resistance[0]:
 71            breaks_resistance_from_left[0] = True
 72            breaks_resistance_from_left[1] = i
 73        i -= 1
 74
 75    # Hacer esto pero en longer dataset
 76    i = second_top[1]
 77    while i < data_sequence.size and not breaks_resistance_from_right[0]:
 78        current_value_right = data_sequence.iloc[i][predefined_type_of_price]
 79        if current_value_right < resistance[0]:
 80            breaks_resistance_from_right[0] = True
 81            breaks_resistance_from_right[1] = i
 82        i += 1
 83
 84    if breaks_resistance_from_left[1] is None or breaks_resistance_from_right[1] is None: # Comprobar que se rompe la linea de apoyo
 85        return None
 86        #DiscardPatterns
 87    #Una vez rompe el patron, debemos averiguar en que direccion
 88
 89    pattern_width = breaks_resistance_from_right[1] - breaks_resistance_from_left[1]
 90
 91    average_height = ((first_top[0] + second_top[0]) / 2) - resistance[0]
 92    objective = resistance[0] - average_height
 93
 94    if pattern_width:
 95        for i in range(breaks_resistance_from_right[1], breaks_resistance_from_right[1] + pattern_width * 2):
 96            if i >= longer_data_sequence.size:
 97                break
 98            current_value = longer_data_sequence.iloc[i][predefined_type_of_price]
 99            if current_value > resistance[0]:
100                return [False, longer_data_sequence.iloc[:i + 1]]
101            if current_value < objective:
102                return [True, longer_data_sequence.iloc[:i + 1]]
103    else:
104        return None #Significa que el valor no cruzo ningun limite
105
106def findDoubleBottomTendency(data_sequence, longer_data_sequence):
107    """Calculates the tendency for a double top pattern  
108
109        Args:  
110            data_sequence (dataframe): dataframe representing the pattern
111            longer_data_sequence (dataframe): dataframe representing the pattern but ends on the day the search is made  
112        Return:  
113            tendency (Pair[]): first element for True, False or None, and second element for the specific dataframe containing the pattern
114            but it ends where the tendency was determined
115    """
116    first_bottom = [BIG_NUMBER, None] #index 0 representa el valor y el index 1 representa la posicion dentro del dataframe
117    second_bottom = [BIG_NUMBER, None]
118    for i in range(data_sequence.size - 1): #Buscar los dos suelos
119        day_value = data_sequence.iloc[i][predefined_type_of_price]
120        if i > 0:
121            previous_day_value = data_sequence.iloc[i - 1][predefined_type_of_price]
122        if i < data_sequence.size - 1:
123            next_day_value = data_sequence.iloc[i + 1][predefined_type_of_price]
124        if i > 0 and previous_day_value > day_value and day_value < next_day_value: #hemos encontrado un minimo
125            relative_minimum = day_value
126            if relative_minimum < first_bottom[0]: # [1] para acceder a lo que no es timestamps y Close porque es la etiqueta del valor
127                first_bottom = second_bottom
128                second_bottom = [relative_minimum, i]
129            elif relative_minimum < second_bottom[0]:
130                second_bottom = [relative_minimum, i]
131    
132    if first_bottom[1] == None or second_bottom[1] == None:
133        return None #No se encontraron dos suelos
134
135    resistance = [0, None]
136    for i in range(first_bottom[1], second_bottom[1]): #Busqueda de la linea de apoyo
137        current_value = data_sequence.iloc[i][predefined_type_of_price]
138        if current_value > resistance[0]:
139            resistance[0] = current_value
140            resistance[1] = i
141
142    # Comprobamos si los suelos no estan muy lejos
143    first_bottom_to_resistance_distance = resistance[0] - first_bottom[0]
144    second_bottom_to_resistance_distance = resistance[0] - second_bottom[0]
145    if first_bottom_to_resistance_distance > second_bottom_to_resistance_distance and second_bottom_to_resistance_distance < first_bottom_to_resistance_distance * 2 / 3:
146        return None # Demasiada diferencia entre suelos
147    if second_bottom_to_resistance_distance > first_bottom_to_resistance_distance and first_bottom_to_resistance_distance < second_bottom_to_resistance_distance * 2 / 3:
148        return None # Demasiada diferencia entre suelos
149
150    breaks_resistance_from_left = [False, None]
151    breaks_resistance_from_right = [False, None]
152
153    #Confirmar que en rompe por la linea de apoyo en ambos lados
154    i = first_bottom[1]
155    while i >= 0 and not breaks_resistance_from_left[0]:
156        current_value_left = data_sequence.iloc[i][predefined_type_of_price]
157        if current_value_left > resistance[0]:
158            breaks_resistance_from_left[0] = True
159            breaks_resistance_from_left[1] = i
160        i -= 1
161
162    # Hacer esto pero en longer dataset
163    i = second_bottom[1]
164    while i < data_sequence.size and not breaks_resistance_from_right[0]:
165        current_value_right = data_sequence.iloc[i][predefined_type_of_price]
166        if current_value_right > resistance[0]:
167            breaks_resistance_from_right[0] = True
168            breaks_resistance_from_right[1] = i
169        i += 1
170
171    if breaks_resistance_from_left[1] is None or breaks_resistance_from_right[1] is None: # Comprobar que se rompe la linea de apoyo
172        return None # Pattern\'s resistance not broken
173    #Una vez rompe el patron, debemos averiguar en que direccion
174
175    pattern_width = breaks_resistance_from_right[1] - breaks_resistance_from_left[1]
176
177    average_height = abs(((first_bottom[0] + second_bottom[0]) / 2) - resistance[0])
178    objective = resistance[0] + average_height
179    if pattern_width:
180        for i in range(breaks_resistance_from_right[1], breaks_resistance_from_right[1] + pattern_width):
181            if i >= longer_data_sequence.size:
182                break
183            current_value = longer_data_sequence.iloc[i][predefined_type_of_price]
184            if current_value < resistance[0]:
185                return [False, longer_data_sequence.iloc[:i + 1]]
186            if current_value > objective:
187                return [True, longer_data_sequence.iloc[:i + 1]]
188    else:
189        return None #Significa que el valor no cruzo ningun limite
def findPatternTendency(data_sequence, longer_data_sequence, type)
10def findPatternTendency(data_sequence, longer_data_sequence, type):
11    """Method to redirect and calculate the tendency for a given dataframe"""
12    if type == 'double_top':
13        return findDoubleTopTendency(data_sequence, longer_data_sequence)
14    if type == 'double_bottom':
15        return findDoubleBottomTendency(data_sequence, longer_data_sequence)
16    else:
17        raise Exception('Pattern type not found')

Method to redirect and calculate the tendency for a given dataframe

def findDoubleTopTendency(data_sequence, longer_data_sequence)
 19def findDoubleTopTendency(data_sequence, longer_data_sequence):
 20    """Calculates the tendency for a double top pattern  
 21    
 22        Args:  
 23            data_sequence (dataframe): dataframe representing the pattern
 24            longer_data_sequence (dataframe): dataframe representing the pattern but ends on the day the search is made  
 25        Return:  
 26            tendency (Pair[]): first element for True, False or None, and second element for the specific dataframe containing the pattern
 27            but it ends where the tendency was determined
 28    """
 29    first_top = [0, None] #index 0 representa el valor y el index 1 representa la posicion dentro del dataframe
 30    second_top = [0, None]
 31    for i in range(data_sequence.size - 1): #Buscar los dos techos
 32        day_value = data_sequence.iloc[i][predefined_type_of_price]
 33        if i > 0:
 34            previous_day_value = data_sequence.iloc[i - 1][predefined_type_of_price]
 35        if i < data_sequence.size - 1:
 36            next_day_value = data_sequence.iloc[i + 1][predefined_type_of_price]
 37        if i > 0 and previous_day_value < day_value and day_value > next_day_value: #hemos encontrado un maximo
 38            relative_maximum = day_value
 39            if relative_maximum > first_top[0]: # [1] para acceder a lo que no es timestamps y Close porque es la etiqueta del valor
 40                first_top = second_top
 41                second_top = [relative_maximum, i]
 42            elif relative_maximum > second_top[0]:
 43                second_top = [relative_maximum, i]
 44    
 45    if first_top[1] == None or second_top[1] == None:
 46        return None #No se encontraron dos techos
 47
 48    resistance = [BIG_NUMBER, None]
 49    for i in range(first_top[1], second_top[1]): #Busqueda de la linea de apoyo
 50        current_value = data_sequence.iloc[i][predefined_type_of_price]
 51        if current_value < resistance[0]:
 52            resistance[0] = current_value
 53            resistance[1] = i
 54
 55    #Añadir que los dos techo no estas muy lejos, como mucho en la mitad entre el mas alto y la linea de soporte
 56
 57    first_top_to_resistance_distance = first_top[0] - resistance[0]
 58    second_top_to_resistance_distance = second_top[0] - resistance[0]
 59    if first_top_to_resistance_distance > second_top_to_resistance_distance and second_top_to_resistance_distance < first_top_to_resistance_distance * 2 / 3:
 60        return None # Demasiada diferencia entre techos
 61    if second_top_to_resistance_distance > first_top_to_resistance_distance and first_top_to_resistance_distance < second_top_to_resistance_distance * 2 / 3:
 62        return None # Demasiada diferencia entre techos
 63
 64    breaks_resistance_from_left = [False, None]
 65    breaks_resistance_from_right = [False, None]
 66
 67    #Confirmar que en rompe por la linea de apoyo en ambos lados
 68    i = first_top[1]
 69    while i >= 0 and not breaks_resistance_from_left[0]:
 70        current_value_left = data_sequence.iloc[i][predefined_type_of_price]
 71        if current_value_left < resistance[0]:
 72            breaks_resistance_from_left[0] = True
 73            breaks_resistance_from_left[1] = i
 74        i -= 1
 75
 76    # Hacer esto pero en longer dataset
 77    i = second_top[1]
 78    while i < data_sequence.size and not breaks_resistance_from_right[0]:
 79        current_value_right = data_sequence.iloc[i][predefined_type_of_price]
 80        if current_value_right < resistance[0]:
 81            breaks_resistance_from_right[0] = True
 82            breaks_resistance_from_right[1] = i
 83        i += 1
 84
 85    if breaks_resistance_from_left[1] is None or breaks_resistance_from_right[1] is None: # Comprobar que se rompe la linea de apoyo
 86        return None
 87        #DiscardPatterns
 88    #Una vez rompe el patron, debemos averiguar en que direccion
 89
 90    pattern_width = breaks_resistance_from_right[1] - breaks_resistance_from_left[1]
 91
 92    average_height = ((first_top[0] + second_top[0]) / 2) - resistance[0]
 93    objective = resistance[0] - average_height
 94
 95    if pattern_width:
 96        for i in range(breaks_resistance_from_right[1], breaks_resistance_from_right[1] + pattern_width * 2):
 97            if i >= longer_data_sequence.size:
 98                break
 99            current_value = longer_data_sequence.iloc[i][predefined_type_of_price]
100            if current_value > resistance[0]:
101                return [False, longer_data_sequence.iloc[:i + 1]]
102            if current_value < objective:
103                return [True, longer_data_sequence.iloc[:i + 1]]
104    else:
105        return None #Significa que el valor no cruzo ningun limite

Calculates the tendency for a double top pattern

Args:
data_sequence (dataframe): dataframe representing the pattern longer_data_sequence (dataframe): dataframe representing the pattern but ends on the day the search is made
Return:
tendency (Pair[]): first element for True, False or None, and second element for the specific dataframe containing the pattern but it ends where the tendency was determined

def findDoubleBottomTendency(data_sequence, longer_data_sequence)
107def findDoubleBottomTendency(data_sequence, longer_data_sequence):
108    """Calculates the tendency for a double top pattern  
109
110        Args:  
111            data_sequence (dataframe): dataframe representing the pattern
112            longer_data_sequence (dataframe): dataframe representing the pattern but ends on the day the search is made  
113        Return:  
114            tendency (Pair[]): first element for True, False or None, and second element for the specific dataframe containing the pattern
115            but it ends where the tendency was determined
116    """
117    first_bottom = [BIG_NUMBER, None] #index 0 representa el valor y el index 1 representa la posicion dentro del dataframe
118    second_bottom = [BIG_NUMBER, None]
119    for i in range(data_sequence.size - 1): #Buscar los dos suelos
120        day_value = data_sequence.iloc[i][predefined_type_of_price]
121        if i > 0:
122            previous_day_value = data_sequence.iloc[i - 1][predefined_type_of_price]
123        if i < data_sequence.size - 1:
124            next_day_value = data_sequence.iloc[i + 1][predefined_type_of_price]
125        if i > 0 and previous_day_value > day_value and day_value < next_day_value: #hemos encontrado un minimo
126            relative_minimum = day_value
127            if relative_minimum < first_bottom[0]: # [1] para acceder a lo que no es timestamps y Close porque es la etiqueta del valor
128                first_bottom = second_bottom
129                second_bottom = [relative_minimum, i]
130            elif relative_minimum < second_bottom[0]:
131                second_bottom = [relative_minimum, i]
132    
133    if first_bottom[1] == None or second_bottom[1] == None:
134        return None #No se encontraron dos suelos
135
136    resistance = [0, None]
137    for i in range(first_bottom[1], second_bottom[1]): #Busqueda de la linea de apoyo
138        current_value = data_sequence.iloc[i][predefined_type_of_price]
139        if current_value > resistance[0]:
140            resistance[0] = current_value
141            resistance[1] = i
142
143    # Comprobamos si los suelos no estan muy lejos
144    first_bottom_to_resistance_distance = resistance[0] - first_bottom[0]
145    second_bottom_to_resistance_distance = resistance[0] - second_bottom[0]
146    if first_bottom_to_resistance_distance > second_bottom_to_resistance_distance and second_bottom_to_resistance_distance < first_bottom_to_resistance_distance * 2 / 3:
147        return None # Demasiada diferencia entre suelos
148    if second_bottom_to_resistance_distance > first_bottom_to_resistance_distance and first_bottom_to_resistance_distance < second_bottom_to_resistance_distance * 2 / 3:
149        return None # Demasiada diferencia entre suelos
150
151    breaks_resistance_from_left = [False, None]
152    breaks_resistance_from_right = [False, None]
153
154    #Confirmar que en rompe por la linea de apoyo en ambos lados
155    i = first_bottom[1]
156    while i >= 0 and not breaks_resistance_from_left[0]:
157        current_value_left = data_sequence.iloc[i][predefined_type_of_price]
158        if current_value_left > resistance[0]:
159            breaks_resistance_from_left[0] = True
160            breaks_resistance_from_left[1] = i
161        i -= 1
162
163    # Hacer esto pero en longer dataset
164    i = second_bottom[1]
165    while i < data_sequence.size and not breaks_resistance_from_right[0]:
166        current_value_right = data_sequence.iloc[i][predefined_type_of_price]
167        if current_value_right > resistance[0]:
168            breaks_resistance_from_right[0] = True
169            breaks_resistance_from_right[1] = i
170        i += 1
171
172    if breaks_resistance_from_left[1] is None or breaks_resistance_from_right[1] is None: # Comprobar que se rompe la linea de apoyo
173        return None # Pattern\'s resistance not broken
174    #Una vez rompe el patron, debemos averiguar en que direccion
175
176    pattern_width = breaks_resistance_from_right[1] - breaks_resistance_from_left[1]
177
178    average_height = abs(((first_bottom[0] + second_bottom[0]) / 2) - resistance[0])
179    objective = resistance[0] + average_height
180    if pattern_width:
181        for i in range(breaks_resistance_from_right[1], breaks_resistance_from_right[1] + pattern_width):
182            if i >= longer_data_sequence.size:
183                break
184            current_value = longer_data_sequence.iloc[i][predefined_type_of_price]
185            if current_value < resistance[0]:
186                return [False, longer_data_sequence.iloc[:i + 1]]
187            if current_value > objective:
188                return [True, longer_data_sequence.iloc[:i + 1]]
189    else:
190        return None #Significa que el valor no cruzo ningun limite

Calculates the tendency for a double top pattern

Args:
data_sequence (dataframe): dataframe representing the pattern longer_data_sequence (dataframe): dataframe representing the pattern but ends on the day the search is made
Return:
tendency (Pair[]): first element for True, False or None, and second element for the specific dataframe containing the pattern but it ends where the tendency was determined