slingshot detection class 
class HPAT(indchecks):
    def __init__(self, df, window=6, thresholdval=0.05, window2=4):
        super().__init__(df)
        self.window_double = window
        self.threshold = thresholdval
        self.window_leg = window2
        
        # Initialize new columns as boolean
        self.df['double_pattern'] = None  # 'Double Top' or 'Double Bottom'
        self.df['h_pattern'] = False      # True for H Pattern
        self.df['inverted_h_pattern'] = False  # True for Inverted H Pattern
        
        # Configure logging
        logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

    def detect_double_top_bottom(self):
        roll_window = self.window_double
        range_threshold = self.threshold

        # Identify peaks and troughs
        self.df['peak'] = (self.df['High'] == self.df['High'].rolling(window=roll_window, center=True).max())
        self.df['trough'] = (self.df['Low'] == self.df['Low'].rolling(window=roll_window, center=True).min())

        # Iterate through the DataFrame to identify double tops and bottoms
        for i in range(roll_window + self.window_leg + 1, len(self.df) - roll_window - self.window_leg - 1):
            # Double Top Detection
            if self.df['peak'].iloc[i] and self.df['peak'].iloc[i + self.window_leg + 1]:
                peak1 = self.df['High'].iloc[i]
                peak2 = self.df['High'].iloc[i + self.window_leg + 1]
                avg_peak = (peak1 + peak2) / 2
                if abs(peak1 - peak2) <= range_threshold * avg_peak:
                    self.df.loc[i + self.window_leg + 1, 'double_pattern'] = 'Double Top'
                    logging.info(f"Double Top detected at index {i + self.window_leg + 1}")

            # Double Bottom Detection
            if self.df['trough'].iloc[i] and self.df['trough'].iloc[i + self.window_leg + 1]:
                trough1 = self.df['Low'].iloc[i]
                trough2 = self.df['Low'].iloc[i + self.window_leg + 1]
                avg_trough = (trough1 + trough2) / 2
                if abs(trough1 - trough2) <= range_threshold * avg_trough:
                    self.df.loc[i + self.window_leg + 1, 'double_pattern'] = 'Double Bottom'
                    logging.info(f"Double Bottom detected at index {i + self.window_leg + 1}")

        # Detect H Patterns based on double patterns
        for i in range(len(self.df)):
            if self.df['double_pattern'].iloc[i] == 'Double Bottom':
                flaglow = True
                for j in range(1, self.window_leg +1):
                    if i - j -1 < 0:
                        flaglow = False
                        break
                    if self.df['Low'].iloc[i - j -1] <= self.df['Low'].iloc[i - j]:
                        flaglow = False
                        break
                if flaglow and self.df['Low'].iloc[i] >= self.df['Low'].iloc[i - self.window_leg]:
                    self.df.loc[i, 'h_pattern'] = True
                    logging.info(f"H Pattern detected at index {i}")

            elif self.df['double_pattern'].iloc[i] == 'Double Top':
                flaghigh = True
                for j in range(1, self.window_leg +1):
                    if i - j -1 < 0:
                        flaghigh = False
                        break
                    if self.df['High'].iloc[i - j -1] >= self.df['High'].iloc[i - j]:
                        flaghigh = False
                        break
                if flaghigh and self.df['High'].iloc[i] <= self.df['High'].iloc[i - self.window_leg]:
                    self.df.loc[i, 'inverted_h_pattern'] = True
                    logging.info(f"Inverted H Pattern detected at index {i}")

    def run(self):
        self.df['HPAT'] = 0 
        self.detect_double_top_bottom()
        
        for i in range(2, len(self.df)-2):
            # Short Signal for Inverted H Pattern
            if ( (self.fastdisgreater(80, i) or self.doublekisgreater(80, i)) and
                 (self.fastdisdecreasing(i-2, i) or self.doublekisdecreasing(i-2, i)) and
                 self.df['inverted_h_pattern'].iloc[i] ):
                self.df.loc[i, 'HPAT'] = -1 
                logging.info(f"Short signal (Inverted H) at index {i}")
            
            # Long Signal for H Pattern
            if ( (self.fastdislesser(20, i) or self.doublekislesser(20, i)) and
                 (self.fastdisincreasing(i-2, i) or self.doublekisincreasing(i-2, i)) and
                 self.df['h_pattern'].iloc[i] ):
                self.df.loc[i, 'HPAT'] = 1 
                logging.info(f"Long signal (H) at index {i}")

        # Optionally, drop intermediate columns
        columns_to_drop = ['peak', 'trough']
        self.df.drop(columns=columns_to_drop, inplace=True, errors='ignore')
        
        return self.df