import os
import time
import pytz
import pandas as pd
import numpy as np
np.NaN = np.nan  # Add this line before importing pandas_ta
import pandas_ta as ta
import logging
from datetime import datetime, timedelta
from typing import List
from thefirstock import thefirstock
import requests
import json
import sys
import math


class StockDataFetcher:
    def __init__(self, client_details: List[str], createEntries: bool = False):
        self.client_details = client_details
        self.user_id = client_details[0]
        self.ist = pytz.timezone('Asia/Kolkata')
        self.logger = self.setup_logger()
        self.total = {}
        self.buyStrikePrice = 0
        self.HedgeLevel = 50
        self.hedgeOneStrikePrice = 0
        self.hedgeTwoStrikePrice = 0
        self.debug_data = {}
        self.debug_data['debug'] = ''
        self.dataPoints = { 'time': [],
                           'price': [],
					'strikePrice': [],
                    'tradeType': [],
					'action': [],  
					'quantity': [],
                    'strikeType' : []
				  }
        
        self.STRIKE_TYPE_1 = 0
        self.STRIKE_TYPE_2 = 1
        self.STRIKE_TYPE_3 = 2

        self.newTradeStopTime = '14:57'

        self.orderNo = 0
        self.createEntries = createEntries
        self.activeOrders = {}
        self.lowCostClientActiveOrders = {}


    def setup_logger(self) -> logging.Logger:
        logger = logging.getLogger(__name__)
        logger.setLevel(logging.INFO)
        if not logger.handlers:
            formatter = self.ISTFormatter('%(asctime)s - %(levelname)s - %(message)s')
            console_handler = logging.StreamHandler()
            console_handler.setFormatter(formatter)
            logger.addHandler(console_handler)
        logging.getLogger().handlers.clear()
        return logger

    class ISTFormatter(logging.Formatter):
        def formatTime(self, record, datefmt=None):
            ist = pytz.timezone('Asia/Kolkata')
            record_time = datetime.fromtimestamp(record.created, tz=ist)
            return record_time.strftime(datefmt or '%Y-%m-%d %H:%M:%S')

    def login(self):
        try:
            self.addLogData(f"Attempting login for {self.client_details[0]}")
            response = thefirstock.firstock_login(*self.client_details)
            if response.get("status") == "success":
                self.addLogData("Login successful")
            else:
                self.addLogData(f"Login failed: {response}")
        except Exception as e:
            self.addLogData(f"Login error: {e}")

    def fetch_time_price_series(
        self, exchange: str, trading_symbol: str, start_time: str, end_time: str, interval: str
    ) -> pd.DataFrame:
        
        self.addLogData(f"Fetching data for {trading_symbol} from {start_time} to {end_time}. interval:{interval}")
        try:
            response = thefirstock.firstock_TimePriceSeries(
                userId=self.user_id,
                exchange=exchange,
                tradingSymbol=trading_symbol,
                startTime=start_time,
                endTime=end_time,
                interval=interval,
            )
            if response.get("status") == "success":
                return pd.DataFrame(response.get("data", []))
            else:
                self.addLogData(f"Fetch failed: {response}")
                return pd.DataFrame()
        except Exception as e:
            self.addLogData(f"Error fetching series: {e}")
            return pd.DataFrame()
        
    def calculate_pivot_levels(self, ohlc):
        open_price = float(ohlc['open'])
        high = float(ohlc['high'])
        low = float(ohlc['low'])
        close = float(ohlc['close'])
        
        # Calculate Pivot Point
        pivot = (high + close + low + open_price) / 4

        # Calculate Resistance Levels
        r1 = (2 * pivot) - low
        r2 = pivot + (r1 - ((2 * pivot) - high))
        r3 = high + 2 * (pivot - low)

        # Calculate Support Levels
        s1 = (2 * pivot) - high
        s2 = pivot - (r1 - s1)
        s3 = low - 2 * (high - pivot)


        r4 = r3 + (high - low) / 2    # R4
        r5 = r3 + (high - low)    # R5
        r6 = r3 + (high - low) * 1.5   # R6

        s4 = s3 - (high - low) / 2    # S4
        s5 = s3 - (high - low)    # S5
        s6 = s3 - (high - low) * 1.5   # S6

        pivot_data = {
                'open' :open_price,
                'high' :high,
                'low'  :low,
                'close':close,
                'R6': round(r6),
                'R5': round(r5),
                'R4': round(r4),
                'R3': round(r3),
                'R2': round(r2),
                'R1': round(r1),
                'PP': round(pivot),
                'S1': round(s1),
                'S2': round(s2),
                'S3': round(s3),
                'S4': round(s4),
                'S5': round(s5),
                'S6': round(s6)
            }
        
        
        self.addLogData(f'Range Details : R6:{pivot_data['R6']} R5:{pivot_data['R5']} R4:{pivot_data['R4']}')
        self.addLogData(f'Range Details : R3:{pivot_data['R3']} R2:{pivot_data['R2']} R1:{pivot_data['R1']}')
        self.addLogData(f'Range Details : PP:{pivot_data['PP']}')
        self.addLogData(f'Range Details : S1:{pivot_data['S1']} S2:{pivot_data['S2']} S3:{pivot_data['S3']}')
        self.addLogData(f'Range Details : S4:{pivot_data['S4']} S5:{pivot_data['S5']} S6:{pivot_data['S6']}')

        return pivot_data
    
    def getLowHighBoundry(self, initialClosePrice, pivot_data):

        lowBound = 'NA'
        highBound = 'NA'
        levelAbove = 'NA'
        levelBelow= 'NA'

        if pivot_data['R3'] >= initialClosePrice >= pivot_data['R2']:
            lowBound = 'R2'
            highBound = 'R3'
            levelBelow= 'R1'
        elif pivot_data['R2'] >= initialClosePrice >= pivot_data['R1']:
            lowBound = 'R1'
            highBound = 'R2'
            levelAbove = 'R3'
            levelBelow= 'PP'
        elif pivot_data['R1'] >= initialClosePrice >= pivot_data['PP']:
            lowBound = 'PP'
            highBound = 'R1'
            levelAbove = 'R2'
            levelBelow= 'S1'
        elif pivot_data['PP'] >= initialClosePrice >= pivot_data['S1']:
            lowBound = 'S1'
            highBound = 'PP'
            levelAbove = 'R1'
            levelBelow= 'S2'
        elif pivot_data['S1'] >= initialClosePrice >= pivot_data['S2']:
            lowBound = 'S2'
            highBound = 'S1'
            levelAbove = 'PP'
            levelBelow= 'S3'
        elif pivot_data['S2'] >= initialClosePrice >= pivot_data['S3']:
            lowBound = 'S3'
            highBound = 'S2'
            levelAbove = 'S1'



        return lowBound, highBound, levelAbove, levelBelow
    
    def getSellLevels(self, pivot_data, label, buy_level):

        sell_level_1 = 'NA'
        sell_level_2 = 'NA'
        itm_sell_level_1 = 'NA'
        itm_sell_level_2 = 'NA'

        level_alignment = ['S5', 'S4', 'S3', 'S2', 'S1', 'PP', 'R1', 'R2', 'R3', 'R4', 'R5']
        index = level_alignment.index(buy_level)


        if label == 'CE':
            next_two = level_alignment[index + 1:index + 3]
            sell_level_1 = next_two[0]
            sell_level_2 = next_two[1]

            previous_two = level_alignment[index - 3:index - 1]
            itm_sell_level_1 = previous_two[1]
            itm_sell_level_2 = previous_two[0]

        else:
            previous_two = level_alignment[index - 2:index]
            sell_level_1 = previous_two[1]
            sell_level_2 = previous_two[0]

            next_two = level_alignment[index + 2:index + 4]
            itm_sell_level_1 = next_two[0]
            itm_sell_level_2 = next_two[1]


        '''


        if sell_level_1 in ['S4', 'S5']:
            sell_level_1 = 'S3'
        elif sell_level_1 in ['R4', 'R5']:
            sell_level_1 = 'R3'

        if sell_level_2 in ['S4', 'S5']:
            sell_level_2 = 'S3'
        elif sell_level_2 in ['R4', 'R5']:
            sell_level_2 = 'R3'


        if itm_sell_level_1 in ['S4', 'S5']:
            itm_sell_level_1 = 'S3'
        elif itm_sell_level_1 in ['R4', 'R5']:
            itm_sell_level_1 = 'R3'

        if itm_sell_level_2 in ['S4', 'S5']:
            itm_sell_level_2 = 'S3'
        elif itm_sell_level_2 in ['R4', 'R5']:
            itm_sell_level_2 = 'R3'

        '''
            

        sell_level_2 = pivot_data[sell_level_2]
        sell_level_1 = pivot_data[sell_level_1]
        itm_sell_level_2 = pivot_data[itm_sell_level_2]
        itm_sell_level_1 = pivot_data[itm_sell_level_1]


        return sell_level_1, sell_level_2, itm_sell_level_1, itm_sell_level_2
    
    def getStrikePrice(self, curPrice, label):
        curPrice = float(curPrice)
        if label == 'CE':
            strikePrice = math.floor(curPrice / 50) * 50
        else:
            strikePrice = math.ceil(curPrice / 50) * 50

        return strikePrice

    def addLogData(self, text):
        self.logger.info(f'{text}')
        self.debug_data['debug'] = self.debug_data['debug'] + text + '\n'

    def addDataPoints(self, time: str, currentPrice: float, strikePrice: float, tradeType: str, action: str, quantity: int, strikeType : int) -> None:

        self.dataPoints['time'].append(time)
        self.dataPoints['price'].append(currentPrice)
        self.dataPoints['strikePrice'].append(strikePrice)
        self.dataPoints['tradeType'].append(tradeType.upper())
        self.dataPoints['action'].append(action.upper())
        self.dataPoints['quantity'].append(quantity)
        self.dataPoints['strikeType'].append(strikeType)

        strikePrice = 'NIFTY' + str(strikePrice) + str(tradeType)
        orderType = str(quantity)
        self.orderNo = self.orderNo + 1
        time = time + ':' + str(self.orderNo).zfill(3)

        if self.createEntries:
            self.createEntry(time, strikePrice, currentPrice, action.upper(), orderType)

            t_quan = quantity
            if action.upper() != 'BUY':
                t_quan = -1 * quantity
            t_key = strikePrice

            try:
                t_old = self.activeOrders[t_key]
                t_quan = t_old + t_quan
            except:
                pass
           
            self.activeOrders[t_key] = t_quan

       

        #for Low cost clients
        if strikeType == self.STRIKE_TYPE_2  or  strikeType == self.STRIKE_TYPE_3:

            if tradeType.upper() == 'CE':
                tradeType = 'PE'
                if strikeType == self.STRIKE_TYPE_2:
                    strikePrice = int(self.buyStrikePrice) - 50
                else:
                    strikePrice = int(self.buyStrikePrice) + 50

            else:
                tradeType = 'CE'
                if strikeType == self.STRIKE_TYPE_2:
                    strikePrice = int(self.buyStrikePrice) + 50
                else:
                    strikePrice = int(self.buyStrikePrice) - 50

            strikePrice = 'NIFTY' + str(strikePrice) + str(tradeType)

            if action.upper() == 'BUY':
                action = 'SELL'
            else:
                action = 'BUY'

        if self.createEntries:
            self.createLowCostEntry(time, strikePrice, currentPrice, action.upper(), orderType)
            t_quan = quantity
            if action.upper() != 'BUY':
                t_quan = -1 * quantity
            t_key = strikePrice

            try:
                t_old = self.lowCostClientActiveOrders[t_key]
                t_quan = t_old + t_quan
            except:
                pass
           
            self.lowCostClientActiveOrders[t_key] = t_quan


    def createLowCostEntry(self, tickTime_str, instrument, closePrice, signal, orderType):

        url = "http://143.244.141.41/php/openIntLowCostEntry.php"  # Replace with your actual URL


        # Define the parameters
        params = {
            'tickTime': str(tickTime_str),
            'instrument': str(instrument),
            'closePrice': str(closePrice),
            'signal': str(signal),
            'orderType': str(orderType)
        }

        # Perform the GET request
        #self.logger.info(f"Get Request with params: {params}")
        response = requests.get(url, params=params)
        if response.status_code != 200:
            self.logger.error(f"Request failed with status code: {response.status_code}")
            if response.text != '':
                self.logger.error(response.text + "\n")  # Print error message if available
        else:
            #self.logger.info(f"Request success: {response.text}\n")
            pass

    def createEntry(self, tickTime_str, instrument, closePrice, signal, orderType):

        url = "http://143.244.141.41/php/createDeepSeekEntry.php"  # Replace with your actual URL


        # Define the parameters
        params = {
            'tickTime': str(tickTime_str),
            'instrument': str(instrument),
            'closePrice': str(closePrice),
            'signal': str(signal),
            'orderType': str(orderType)
        }

        # Perform the GET request
        #self.logger.info(f"Get Request with params: {params}")
        response = requests.get(url, params=params)
        if response.status_code != 200:
            self.logger.error(f"Request failed with status code: {response.status_code}")
            if response.text != '':
                self.logger.error(response.text + "\n")  # Print error message if available
        else:
            #self.logger.info(f"Request success: {response.text}\n")
            pass

    def closeAllPendingOrders(self, tickTime_str, price):

        self.addLogData(f'closeAllPendingOrders :')

        self.addLogData(f'pending entries to be closed: {self.activeOrders}')
        for instrument, quantity in self.activeOrders.items():
            # Deal with negative quantities first
            if quantity < 0 :
                action = 'BUY'
                orderType = str(abs(quantity))
                self.orderNo = self.orderNo + 1
                time = tickTime_str + ':' + str(self.orderNo).zfill(3)
                if self.createEntries:
                    self.createEntry(time, instrument, price, action, orderType)
                    strikePriceStr = instrument.replace('NIFTY','')
                    self.addLogData(f'{tickTime_str} Force close - {action} {orderType} {strikePriceStr} price:{price}')

        for instrument, quantity in self.activeOrders.items():
            # Deal with positive quantities
            if quantity > 0 :
                action = 'SELL'
                orderType = str(quantity)
                self.orderNo = self.orderNo + 1
                time = tickTime_str + ':' + str(self.orderNo).zfill(3)
                if self.createEntries:
                    self.createEntry(time, instrument, price, action, orderType)
                    strikePriceStr = instrument.replace('NIFTY','')
                    self.addLogData(f'{tickTime_str} Force close - {action} {orderType} {strikePriceStr} price:{price}')


        self.addLogData(f'pending low cost entries: {self.lowCostClientActiveOrders}')
        #Low cost entries have only Buy pending ...
        for instrument, quantity in self.lowCostClientActiveOrders.items():
            if quantity > 0:
                action = 'SELL'
                orderType = str(quantity)
                self.orderNo = self.orderNo + 1
                time = tickTime_str + ':' + str(self.orderNo).zfill(3)
                if self.createEntries:
                    self.createLowCostEntry(time, instrument, price, action, orderType)
                    strikePriceStr = instrument.replace('NIFTY','')
                    self.addLogData(f'{tickTime_str} Force close - {action} {orderType} {strikePriceStr} price:{price}')

    def getDataPoints(self):
        return self.dataPoints

    def process_symbol_data(self, symbol: str, interval: int, start_time: datetime, end_time: datetime):

        exchange, trading_symbol = symbol.split(":")
        df = self.fetch_time_price_series(
            exchange, trading_symbol,
            start_time.strftime("%d/%m/%Y %H:%M:%S"),
            end_time.strftime("%d/%m/%Y %H:%M:%S"),
            str(interval),
        )

        niftydf = self.fetch_time_price_series(
            'NSE', 'Nifty 50',
            start_time.strftime("%d/%m/%Y %H:%M:%S"),
            end_time.strftime("%d/%m/%Y %H:%M:%S"),
            str(interval),
        )

        formatted_date = datetime.now().date().strftime('%d-%m-%Y')
        niftydf = niftydf[niftydf['time'] != f'{formatted_date} 09:14:00']

        df['niftyPrice'] = niftydf['intc'].values

        # Preprocess timestamps and ensure data integrity
        df['time'] = pd.to_datetime(df['time'], errors='coerce', dayfirst=True)
        df['time'] = df['time'].dt.tz_localize(self.ist)

        numeric_cols = ['intc', 'intv', 'into', 'inth', 'intl', 'oi', 'intoi', 'niftyPrice']
        for col in numeric_cols:
            df[col] = pd.to_numeric(df[col], errors='coerce')

        df = df.sort_values(by='time', ascending=True)
        df = df.iloc[0:].reset_index(drop=True)
        df['intoi'] = df['intoi'] / 75
        mydf = df[['time', 'into', 'inth', 'intl', 'intc', 'intoi', 'niftyPrice']]

        mydf = mydf.copy()
        first_intc = mydf['into'].iloc[0]
        mydf['priceChange'] = mydf['intc'] - first_intc

        mydf.at[0, 'intoi'] = 0
        mydf['sumOI'] = mydf['intoi'].cumsum()

        mydf1 = mydf.copy()
        mydf1 = mydf1[mydf1['intoi'] != 0]

        pivot_data = {}

        graph_data = {
        'time': mydf['time'].dt.strftime('%Y-%m-%d %H:%M:%S').tolist(),
        'priceChange': mydf['priceChange'].tolist(),
        'sumOI': mydf['sumOI'].tolist(),
        }

        price_data = {
        'time': mydf['time'].dt.strftime('%Y-%m-%d %H:%M:%S').tolist(),
        'close': mydf['intc'].tolist(),
        'niftyClose': mydf['niftyPrice'].tolist()
        }


        if len(df) < 15:
            self.addLogData('Not enough Candles. Do Nothing')
            return price_data, graph_data, pivot_data, self.debug_data, self.dataPoints
        

        ohlc = {}
        ohlc['open'] = mydf['into'].iloc[0]
        ohlc['high'] = mydf.head(15)['inth'].max()
        ohlc['low'] = mydf.head(15)['intl'].min()
        ohlc['close'] = mydf['intc'].iloc[14]

        self.addLogData(f'OHLC Details : open:{ohlc['open']} High:{ohlc['high']} Low:{ohlc['low']} Close:{ohlc['close']}')

        pivot_data = self.calculate_pivot_levels(ohlc)

        priceDiff =  ohlc['close'] - ohlc['open']
        pivot_data['priceTrend'] = 'Down'
        priceDiff = round(priceDiff, 2)
        if priceDiff > 5 :
            pivot_data['priceTrend'] = 'Up'


        openOI = mydf['sumOI'].iloc[0]
        closeOI = mydf['sumOI'].iloc[14]
        OIdiff =  closeOI - openOI
        pivot_data['OITrend'] = 'Down'
        if OIdiff > 1000 :
            pivot_data['OITrend'] = 'Up'

        initialClosePrice = mydf['intc'].iloc[14]
        datadf = mydf.iloc[15:].reset_index(drop=True)
        lowBound, highBound, levelAbove, levelBelow  = self.getLowHighBoundry(initialClosePrice, pivot_data) 
        pe_buy_exception_allowed = False
        ce_buy_exception_allowed = False

        self.addLogData(f'Trend Details : priceTrend - {pivot_data['priceTrend']}, OITrend - {pivot_data['OITrend']}, priceDiff - {priceDiff}, OIdiff - {OIdiff}')

        if pivot_data['priceTrend'] == 'Up':
            #buy CE above highBound  
            #buy PE below lowBound
            CE_buy_label = highBound
            PE_buy_label = lowBound
            if pivot_data['OITrend'] == 'Up':
                ce_buy_exception_allowed = True
                self.addLogData(f'Trend Exception : ce_buy_exception_allowed')
                PE_buy_label = levelBelow
                CE_buy_label = lowBound
 
        else:

            if pivot_data['OITrend'] == 'Up':
                #buy CE above levelAbove
                #buy PE above highBound  
                CE_buy_label = levelAbove
                PE_buy_label = highBound
                pe_buy_exception_allowed = True
                self.addLogData(f'Trend Exception : pe_buy_exception_allowed')
                CE_buy_label = levelAbove
                PE_buy_label = highBound
            else:
                #buy CE below lowBound 
                #buy PE below levelBelow
                CE_buy_label = lowBound
                PE_buy_label = levelBelow
                


        CE_sell_level_1, CE_sell_level_2, CE_itm_sell_level_1, CE_itm_sell_level_2 = self.getSellLevels(pivot_data, 'CE', CE_buy_label)
        PE_sell_level_1, PE_sell_level_2, PE_itm_sell_level_1, PE_itm_sell_level_2 = self.getSellLevels(pivot_data, 'PE', PE_buy_label)

        pivot_data['CE_sell_level_1'] = CE_sell_level_1
        pivot_data['CE_sell_level_2'] = CE_sell_level_2
        pivot_data['PE_sell_level_1'] = PE_sell_level_1
        pivot_data['PE_sell_level_2'] = PE_sell_level_2
        pivot_data['CE_itm_sell_level_1'] = CE_itm_sell_level_1
        pivot_data['CE_itm_sell_level_2'] = CE_itm_sell_level_2
        pivot_data['PE_itm_sell_level_1'] = PE_itm_sell_level_1
        pivot_data['PE_itm_sell_level_2'] = PE_itm_sell_level_2

        CE_buy_price = pivot_data[CE_buy_label]
        PE_buy_price = pivot_data[PE_buy_label]

        self.addLogData(f'CE Buy Price : {CE_buy_price}')
        self.addLogData(f'CE Sell Levels : L1:{CE_sell_level_1} L2:{CE_sell_level_2} itm_L1:{CE_itm_sell_level_1} itm_L2:{CE_itm_sell_level_2}')
        self.addLogData(f'PE Buy Price : {PE_buy_price}')
        self.addLogData(f'PE Sell Levels : L1:{PE_sell_level_1} L2:{PE_sell_level_2} itm_L1:{PE_itm_sell_level_1} itm_L2:{PE_itm_sell_level_2}')


        pivot_data['CE_buy_label'] = CE_buy_label
        pivot_data['PE_buy_label'] = PE_buy_label
        pivot_data['CE_buy_price'] = CE_buy_price
        pivot_data['PE_buy_price'] = PE_buy_price

        ce_buy_condition_met = False
        pe_buy_condition_met = False
        trade_in_progress = False
        trade_type = 'NA'
        target_1_met = False
        target_2_met = False
        itm_target_1_met = False
        itm_target_2_met = False
        oom_hedge_active = False
        oom_hedge_tobe_closed_1 = False
        oom_hedge_tobe_closed_2 = False
        itm_hedge_active = False
        itm_hedge_tobe_closed_1 = False
        itm_hedge_tobe_closed_2 = False
        recalculate_target_if_needed = False

        self.addLogData("--------------------------------------")
        self.addLogData('Start the Music :')
        self.addLogData("--------------------------------------")

        stop_time_reached = False

        for index, row in datadf.iterrows():

            if not stop_time_reached:
                low = row['intl']
                high = row['inth']
                price = row['intc']
                nifty_price = row['niftyPrice']
                time = row['time']
                timeStr = time.strftime('%Y-%m-%d %H:%M:%S')

            if time.time() > pd.Timestamp(self.newTradeStopTime).time():
                if not stop_time_reached:
                    self.addLogData(f'{time} End Time reached. All pending orders can be closed ..')
                    stop_time_reached = True

                continue

            # trade not intiated yet
            if not trade_in_progress:

                if not ce_buy_condition_met and ((low < pivot_data['CE_buy_price'] and low > pivot_data['PE_buy_price']) or ce_buy_exception_allowed ):
                    ce_buy_condition_met = True
                    text = f'{time} no trade_in_progress:ce_buy_condition_met low: {low} CE_buy_price:{pivot_data['CE_buy_price']} PE_buy_price:{pivot_data['PE_buy_price']} ce_buy_exception_allowed:{ce_buy_exception_allowed}'
                    self.addLogData(text)
                    if ce_buy_exception_allowed:
                        recalculate_target_if_needed = True
                    ce_buy_exception_allowed = False

                if ce_buy_condition_met and price >= pivot_data['CE_buy_price'] and low > pivot_data['CE_buy_price']:
                    self.buyStrikePrice = self.getStrikePrice(nifty_price, 'CE')
                    quantity = 2
                    trade_type = 'CE'
                    text = f"{time} no trade_in_progress: Buy {quantity} {self.buyStrikePrice} CE at Price:{price} low:{low} CE_buy_price:{pivot_data['CE_buy_price']} initial_buy ++"
                    self.addLogData(text)
                    self.addDataPoints(timeStr, price, self.buyStrikePrice, trade_type, 'BUY', 2, self.STRIKE_TYPE_1)
                    ce_buy_condition_met = False
                    pe_buy_condition_met = False
                    trade_in_progress = True
                    
                    target_1_met = False
                    target_2_met = False
                    oom_hedge_condition_met = False
                    itm_hedge_condition_met = False
                    oom_hedge_active = False
                    itm_hedge_active = False
                    oom_hedge_t1_condition_met = False
                    oom_hedge_tobe_closed_1 = False
                    oom_hedge_tobe_closed_2 = False
                    itm_hedge_tobe_closed_1 = False
                    itm_hedge_tobe_closed_2 = False

                    if recalculate_target_if_needed :
                        if price > pivot_data['CE_sell_level_1']:
                            pivot_data['CE_sell_level_1'] = price + 20
                            self.addLogData(f'{time} Recalculting target 1 price : new price {pivot_data['CE_sell_level_1']} ..')

                        if price > pivot_data['CE_sell_level_2']:
                            pivot_data['CE_sell_level_2'] = price + 60
                            self.addLogData(f'{time} Recalculting target 2 price : new price {pivot_data['CE_sell_level_2']} ..')

                        recalculate_target_if_needed = False



                if not pe_buy_condition_met and ( (high > pivot_data['PE_buy_price'] and high < pivot_data['CE_buy_price']) or pe_buy_exception_allowed ):
                    pe_buy_condition_met = True
                    text = f'{time} no trade_in_progress:pe_buy_condition_met high: {high} CE_buy_price:{pivot_data['CE_buy_price']} PE_buy_price:{pivot_data['PE_buy_price']} pe_buy_exception_allowed:{pe_buy_exception_allowed}'
                    self.addLogData(text)
                    if pe_buy_exception_allowed:
                        recalculate_target_if_needed = True
                    pe_buy_exception_allowed = False

                if pe_buy_condition_met and price <= pivot_data['PE_buy_price'] and high < pivot_data['PE_buy_price']:
                    self.buyStrikePrice = self.getStrikePrice(nifty_price, 'PE')
                    trade_type = 'PE'
                    quantity = 2
                    text = f"{time} no trade_in_progress: Buy {quantity} {self.buyStrikePrice} PE at Price:{price} high:{high} PE_buy_price:{pivot_data['PE_buy_price']} initial_buy ++"
                    self.addLogData(text)
                    self.addDataPoints(timeStr, price, self.buyStrikePrice, trade_type, 'BUY', 2, self.STRIKE_TYPE_1)
                    pe_buy_condition_met = False
                    ce_buy_condition_met = False
                    trade_in_progress = True
                    
                    target_1_met = False
                    target_2_met = False
                    oom_hedge_condition_met = False
                    itm_hedge_condition_met = False
                    oom_hedge_active = False
                    itm_hedge_active = False
                    oom_hedge_t1_condition_met = False
                    oom_hedge_tobe_closed_1 = False
                    oom_hedge_tobe_closed_2 = False
                    itm_hedge_tobe_closed_1 = False
                    itm_hedge_tobe_closed_2 = False

                    if recalculate_target_if_needed:
                        if price < pivot_data['PE_sell_level_1']:
                            pivot_data['PE_sell_level_1'] = price - 20
                            self.addLogData(f'{time} Recalculting target 1 price : new price {pivot_data['PE_sell_level_1']} ..')

                        if price < pivot_data['PE_sell_level_2']:
                            pivot_data['PE_sell_level_2'] = price - 60
                            self.addLogData(f'{time} Recalculting target 2 price : new price {pivot_data['PE_sell_level_2']} ..')

                        recalculate_target_if_needed = False
                    
            else:
                # trade intiated 
                if trade_type == 'CE':
                    self.hedgeOneStrikePrice = self.buyStrikePrice + self.HedgeLevel
                    self.hedgeTwoStrikePrice = self.buyStrikePrice - self.HedgeLevel
                    target_1 = pivot_data['CE_sell_level_1']
                    target_2 = pivot_data['CE_sell_level_2']
                    itm_target_1 = pivot_data['CE_itm_sell_level_1']
                    itm_target_2 = pivot_data['CE_itm_sell_level_2']
                    target_1_dev = round((price - target_1),2)
                    target_2_dev = round((price - target_2),2)
                    itm_target_1_dev = round((price - itm_target_1),2)
                    itm_target_2_dev = round((price - itm_target_2),2)

                else:
                    self.hedgeOneStrikePrice = self.buyStrikePrice - self.HedgeLevel
                    self.hedgeTwoStrikePrice = self.buyStrikePrice + self.HedgeLevel
                    target_1 = pivot_data['PE_sell_level_1']
                    target_2 = pivot_data['PE_sell_level_2']
                    itm_target_1 = pivot_data['PE_itm_sell_level_1']
                    itm_target_2 = pivot_data['PE_itm_sell_level_2']
                    target_1_dev = round((target_1 - price),2)
                    target_2_dev = round((target_2 - price),2)
                    itm_target_1_dev = round((itm_target_1 - price),2) 
                    itm_target_2_dev = round((itm_target_2 - price),2) 

                #first target not met
                if not target_1_met: 

                    #check for oom hedge
                    if not oom_hedge_active:
                        if trade_type == 'CE':
                            #change the condition 
                            if not oom_hedge_condition_met and low < pivot_data['CE_buy_price']:
                                oom_hedge_condition_met = True
                                oom_quantity = 2
                                text = f'Sell {oom_quantity} {self.hedgeOneStrikePrice} CE price:{price} high:{high} CE_buy_price:{pivot_data['CE_buy_price']} oom_hedge_start ++'
                                self.addLogData(f'{time} no target_1_met: no oom_hedge_active: {text}')
                                self.addDataPoints(timeStr, price, self.hedgeOneStrikePrice, trade_type, 'SELL', 2, self.STRIKE_TYPE_2)
                                oom_hedge_active = True
                                oom_hedge_tobe_closed_1 = True
                                oom_hedge_tobe_closed_2 = True
                                itm_hedge_active = False
                                itm_hedge_tobe_closed_1 = False
                                itm_hedge_tobe_closed_2 = False
                                itm_target_1_met = False
                                itm_target_2_met = False

                        else:
                            if not oom_hedge_condition_met and high > pivot_data['PE_buy_price']:
                                oom_hedge_condition_met = True
                                oom_quantity = 2
                                text = f'Sell {oom_quantity} {self.hedgeOneStrikePrice} PE price:{price} low:{low} PE_buy_price:{pivot_data['PE_buy_price']} oom_hedge_start ++'
                                self.addLogData(f'{time} no target_1_met: no oom_hedge_active: {text}')
                                self.addDataPoints(timeStr, price, self.hedgeOneStrikePrice, trade_type, 'SELL', 2, self.STRIKE_TYPE_2)
                                oom_hedge_active = True
                                oom_hedge_tobe_closed_1 = True
                                oom_hedge_tobe_closed_2 = True
                                itm_hedge_active = False
                                itm_hedge_tobe_closed_1 = False
                                itm_hedge_tobe_closed_2 = False
                                itm_target_1_met = False
                                itm_target_2_met = False

                    #check for target one reached case
                    if target_1_dev > -2 :
                        if oom_hedge_tobe_closed_1:
                            oom_hedge_tobe_closed_1 = False
                            text = f"no target_1_met: target_1_reached : close first oom hedge : Buy 1 {self.hedgeOneStrikePrice} {trade_type} at Price: {price} oom_hedge_1_closure ++"
                            self.addLogData(f'{time} {text}')
                            self.addDataPoints(timeStr, price, self.hedgeOneStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_2)

                        if itm_hedge_tobe_closed_1:
                            itm_hedge_tobe_closed_1 = False
                            text = f"no target_1_met: target_1_reached : close first itm hedge : Buy 1 {self.hedgeTwoStrikePrice} {trade_type} at Price: {price} itm_hedge_1_closure ++"
                            self.addLogData(f'{time} {text}')
                            self.addDataPoints(timeStr, price, self.hedgeTwoStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_3)


                        target_1_met = True
                        text = f"no target_1_met: target_1_reached. Sell 1 {self.buyStrikePrice} {trade_type} at Price: {price} target_1_dev:{target_1_dev} target_1 ++"
                        self.addLogData(f'{time} {text}')
                        self.addDataPoints(timeStr, price, self.buyStrikePrice, trade_type, 'SELL', 1, self.STRIKE_TYPE_1)

                    #check for itm hedge swap
                    if oom_hedge_active:

                        if not itm_hedge_active:

                            if trade_type == 'CE':
                                if not itm_hedge_condition_met and low < pivot_data['PE_buy_price']:

                                    no_of_lots_itm_hedge = 0

                                    if oom_hedge_tobe_closed_1:
                                        oom_hedge_tobe_closed_1 = False
                                        text = f"no target_1_met: itm_hedge_swap : Buy 1 {self.hedgeOneStrikePrice} {trade_type} at Price: {price} oom_hedge_1_closure ++"
                                        self.addLogData(f'{time} {text}')
                                        self.addDataPoints(timeStr, price, self.hedgeOneStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_2)
                                        no_of_lots_itm_hedge = no_of_lots_itm_hedge + 1
                                        itm_hedge_tobe_closed_1 = True

                                    if oom_hedge_tobe_closed_2:
                                        oom_hedge_tobe_closed_2 = False
                                        text = f"no target_1_met: itm_hedge_swap : Buy 1 {self.hedgeOneStrikePrice} {trade_type} at Price: {price} oom_hedge_2_closure ++"
                                        self.addLogData(f'{time} {text}')
                                        self.addDataPoints(timeStr, price, self.hedgeOneStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_2)
                                        no_of_lots_itm_hedge = no_of_lots_itm_hedge + 1
                                        itm_hedge_tobe_closed_2 = True
                                        oom_hedge_active = True
                                    
                                    itm_hedge_condition_met = True
                                    text = f"no target_1_met: itm_hedge_swap : Sell {no_of_lots_itm_hedge} {self.hedgeTwoStrikePrice} {trade_type} at Price: {price} high:{high} PE_buy_price:{pivot_data['PE_buy_price']} itm_hedge_swap ++"
                                    self.addLogData(f'{time} {text}')
                                    self.addDataPoints(timeStr, price, self.hedgeTwoStrikePrice, trade_type, 'SELL', no_of_lots_itm_hedge, self.STRIKE_TYPE_3)
                                    itm_hedge_active = True
                                    

                            else:
                                if not itm_hedge_condition_met and high > pivot_data['CE_buy_price']:

                                    no_of_lots_itm_hedge = 0

                                    if oom_hedge_tobe_closed_1:
                                        oom_hedge_tobe_closed_1 = False
                                        text = f"no target_1_met: itm_hedge_swap : Buy 1 {self.hedgeOneStrikePrice} {trade_type} at Price: {price} oom_hedge_1_closure ++"
                                        self.addLogData(f'{time} {text}')
                                        self.addDataPoints(timeStr, price, self.hedgeOneStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_2)
                                        no_of_lots_itm_hedge = no_of_lots_itm_hedge + 1
                                        itm_hedge_tobe_closed_1 = True

                                    if oom_hedge_tobe_closed_2:
                                        oom_hedge_tobe_closed_2 = False
                                        text = f"no target_1_met: itm_hedge_swap : Buy 1 {self.hedgeOneStrikePrice} {trade_type} at Price: {price} oom_hedge_2_closure ++"
                                        self.addLogData(f'{time} {text}')
                                        self.addDataPoints(timeStr, price, self.hedgeOneStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_2)
                                        no_of_lots_itm_hedge = no_of_lots_itm_hedge + 1
                                        itm_hedge_tobe_closed_2 = True
                                        oom_hedge_active = True
                                    
                                    itm_hedge_condition_met = True
                                    text = f"no target_1_met: itm_hedge_swap : Sell {no_of_lots_itm_hedge} {self.hedgeTwoStrikePrice} {trade_type} at Price: {price} low:{low} CE_buy_price:{pivot_data['CE_buy_price']} itm_hedge_swap ++"
                                    self.addLogData(f'{time} {text}')
                                    self.addDataPoints(timeStr, price, self.hedgeTwoStrikePrice, trade_type, 'SELL', no_of_lots_itm_hedge, self.STRIKE_TYPE_3)
                                    itm_hedge_active = True

                    #check for itm hedge handling
                    if itm_hedge_active:

                        #check for itm target 1
                        if itm_target_1_dev < 2 :
                            if itm_hedge_tobe_closed_1:
                                itm_hedge_tobe_closed_1 = False
                                itm_target_1_met = True
                                text = f"no target_1_met: itm target 1 reached : Buy 1 {self.hedgeTwoStrikePrice} {trade_type} at Price: {price} itm_target_1_dev:{itm_target_1_dev} itm_hedge_1_closure_itm_target_1 ++"
                                self.addLogData(f'{time} {text}')
                                self.addDataPoints(timeStr, price, self.hedgeTwoStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_3)
                                if not target_1_met:
                                    target_1_met = True 
                                    text = f"no target_1_met: itm target 1 reached : Sell 1 {self.buyStrikePrice} PE at Price: {price} target_1_closure_itm_target_1 ++"
                                    self.addLogData(f'{time} {text}')
                                    self.addDataPoints(timeStr, price, self.buyStrikePrice, trade_type, 'SELL', 1, self.STRIKE_TYPE_1)

                        #check for itm target 2
                        if itm_target_2_dev < 2 :

                            if itm_hedge_tobe_closed_2:
                                itm_hedge_tobe_closed_1 = False
                                itm_target_2_met = True
                                text = f"no target_1_met: itm target 2 reached : Buy 1 {self.hedgeTwoStrikePrice} {trade_type} at Price: {price} itm_target_2_dev:{itm_target_2_dev} itm_hedge_2_closure_itm_target_2 ++"
                                self.addLogData(f'{time} {text}')
                                self.addDataPoints(timeStr, price, self.hedgeTwoStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_3)

                                if not target_2_met:
                                    target_2_met = True
                                    trade_in_progress = False
                                    text = f"no target_1_met: itm target 2 reached : Sell 1 {self.buyStrikePrice} PE at Price: {price} target_2_closure_itm_target_2 ++"
                                    self.addLogData(f'{time} {text}')
                                    self.addDataPoints(timeStr, price, self.buyStrikePrice, trade_type, 'SELL', 1, self.STRIKE_TYPE_1)

                                #reset all flags to initial condition
                                ce_buy_condition_met = False
                                pe_buy_condition_met = False
                                trade_in_progress = False
                                trade_type = 'NA'
                                target_1_met = False
                                target_2_met = False
                                itm_target_1_met = False
                                itm_target_2_met = False
                                oom_hedge_active = False
                                oom_hedge_tobe_closed_1 = False
                                oom_hedge_tobe_closed_2 = False
                                itm_hedge_active = False
                                itm_hedge_tobe_closed_1 = False
                                itm_hedge_tobe_closed_2 = False
                                self.addLogData("--------------------------------------")

                        #check for itm to oom hedge swap
                        if ( ( (high > pivot_data['CE_buy_price']) and (trade_type == 'CE') ) or 
                             ( (low < pivot_data['PE_buy_price']) and (trade_type == 'PE') ) ):

                            if trade_type == 'CE':
                                if high > pivot_data['CE_buy_price']:

                                    oom_quantity = 0
                                    oom_hedge_active = True

                                    if not itm_target_1_met:
                                        text = f"no target_1_met: itm to oom hedge swap : Buy 1 {self.hedgeTwoStrikePrice} {trade_type} at Price: {price} itm_to_oom_hedge_swap_itm_1_closure ++"
                                        self.addLogData(f'{time} {text}')
                                        self.addDataPoints(timeStr, price, self.hedgeTwoStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_3)
                                        itm_target_1_met = True
                                        oom_quantity = oom_quantity + 1
                                        oom_hedge_tobe_closed_1 = True

                                    if not itm_target_2_met:
                                        text = f"no target_1_met: itm to oom hedge swap : Buy 1 {self.hedgeTwoStrikePrice} {trade_type} at Price: {price} itm_to_oom_hedge_swap_itm_2_closure ++"
                                        self.addLogData(f'{time} {text}')
                                        self.addDataPoints(timeStr, price, self.hedgeTwoStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_3)
                                        itm_target_2_met = True
                                        oom_quantity = oom_quantity + 1
                                        oom_hedge_tobe_closed_2 = True

                                    oom_hedge_condition_met = True
                                    text = f"no target_1_met: itm to oom hedge swap : Sell {oom_quantity} {self.hedgeOneStrikePrice} {trade_type} at Price: {price} itm_to_oom_hdege_swap_oom_start ++"
                                    self.addLogData(f'{time} {text}')
                                    self.addDataPoints(timeStr, price, self.hedgeOneStrikePrice, trade_type, 'SELL', oom_quantity, self.STRIKE_TYPE_2)
                                    itm_hedge_active = False
                                    itm_hedge_tobe_closed_1 = False
                                    itm_hedge_tobe_closed_2 = False

                            else:
                                if low < pivot_data['PE_buy_price']:

                                    oom_quantity = 0
                                    oom_hedge_active = True

                                    if not itm_target_1_met:
                                        text = f"no target_1_met: itm to oom hedge swap : Buy 1 {self.hedgeTwoStrikePrice} {trade_type} at Price: {price} itm_to_oom_hedge_swap_itm_1_closure ++"
                                        self.addLogData(f'{time} {text}')
                                        self.addDataPoints(timeStr, price, self.hedgeTwoStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_3)
                                        itm_target_1_met = True
                                        oom_quantity = oom_quantity + 1
                                        oom_hedge_tobe_closed_1 = True

                                    if not itm_target_2_met:
                                        text = f"no target_1_met: itm to oom hedge swap : Buy 1 {self.hedgeTwoStrikePrice} {trade_type} at Price: {price} itm_to_oom_hedge_swap_itm_2_closure ++"
                                        self.addLogData(f'{time} {text}')
                                        self.addDataPoints(timeStr, price, self.hedgeTwoStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_3)
                                        itm_target_2_met = True
                                        oom_quantity = oom_quantity + 1
                                        oom_hedge_tobe_closed_2 = True

                                    oom_hedge_condition_met = True
                                    text = f"no target_1_met: itm to oom hedge swap : Sell {oom_quantity} {self.hedgeOneStrikePrice} {trade_type} at Price: {price} itm_to_oom_hdege_swap_oom_start ++"
                                    self.addLogData(f'{time} {text}')
                                    self.addDataPoints(timeStr, price, self.hedgeOneStrikePrice, trade_type, 'SELL', oom_quantity, self.STRIKE_TYPE_2)
                                    itm_hedge_active = False
                                    itm_hedge_tobe_closed_1 = False
                                    itm_hedge_tobe_closed_2 = False

                #first target met but not second target
                elif target_1_met and not target_2_met: 

                    # target 2 not reached condition
                    if not target_2_dev > -2 :

                        # check for oom hedge required - one
                        if not oom_hedge_active and not itm_hedge_active:

                            if trade_type == 'CE':
                                if not oom_hedge_t1_condition_met and low < pivot_data['CE_buy_price']:
                                    oom_hedge_t1_condition_met = True
                                    text = f'Sell 1 {self.hedgeOneStrikePrice} {trade_type} price:{price} high:{high} CE_buy_price:{pivot_data['CE_buy_price']} oom_hedge_2_start ++'
                                    self.addLogData(f'{time} target_1_met: not oom_hedge_active: {text}')
                                    self.addDataPoints(timeStr, price, self.hedgeOneStrikePrice, trade_type, 'SELL', 1, self.STRIKE_TYPE_2)
                                    oom_hedge_active = True
                                    oom_hedge_tobe_closed_2 = True
                                    itm_hedge_active = False
                                    itm_hedge_tobe_closed_1 = False
                                    itm_hedge_tobe_closed_2 = False
                                    itm_hedge_condition_met = False
                                    itm_target_1_met = False
                                    itm_target_2_met = False


                            else:
                                if not oom_hedge_t1_condition_met and high > pivot_data['PE_buy_price']:
                                    oom_hedge_t1_condition_met = True
                                    text = f'Sell 1 {self.hedgeOneStrikePrice} {trade_type} price:{price} low:{low} PE_buy_price:{pivot_data['PE_buy_price']} oom_hedge_start_1 ++'
                                    self.addLogData(f'{time} target_1_met: not oom_hedge_active: {text}')
                                    self.addDataPoints(timeStr, price, self.hedgeOneStrikePrice, trade_type, 'SELL', 1, self.STRIKE_TYPE_2)
                                    oom_hedge_active = True
                                    oom_hedge_tobe_closed_2 = True
                                    itm_hedge_active = False
                                    itm_hedge_tobe_closed_1 = False
                                    itm_hedge_tobe_closed_2 = False
                                    itm_hedge_condition_met = False
                                    itm_target_1_met = False
                                    itm_target_2_met = False

                        # check for itm hedge swap - one
                        elif oom_hedge_active and not itm_hedge_active:

                            

                            if trade_type == 'CE':
                                if not itm_hedge_condition_met and low < pivot_data['PE_buy_price']:

                                    no_of_lots_itm_hedge = 0

                                    if oom_hedge_tobe_closed_2:
                                        oom_hedge_tobe_closed_2 = False
                                        text = f'Buy 1 {self.hedgeOneStrikePrice} {trade_type} price:{price} oom_to_itm_hedge_swap_oom_hedge_2_closure ++'
                                        self.addLogData(f'{time} target_1_met: oom_to_itm_hedge_swap: {text}')
                                        self.addDataPoints(timeStr, price, self.hedgeOneStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_2)
                                        no_of_lots_itm_hedge = no_of_lots_itm_hedge + 1
                                    
                                    itm_hedge_condition_met = True
                                    text = f'Sell 1 {self.hedgeTwoStrikePrice} {trade_type} price:{price} low:{low} PE_buy_price:{pivot_data['PE_buy_price']} oom_to_itm_hedge_swap_itm_hedge_2_start ++'
                                    self.addLogData(f'{time} target_1_met: oom_to_itm_hedge_swap: {text}')
                                    self.addDataPoints(timeStr, price, self.hedgeTwoStrikePrice, trade_type, 'SELL', 1, self.STRIKE_TYPE_3)
                                    itm_hedge_active = True
                                    oom_hedge_active = False
                                    itm_hedge_tobe_closed_2 = True
                                    itm_target_2_met = False

                            else:
                                if not itm_hedge_condition_met and high > pivot_data['CE_buy_price']:

                                    no_of_lots_itm_hedge = 0

                                    if oom_hedge_tobe_closed_2:
                                        oom_hedge_tobe_closed_2 = False
                                        text = f'Buy 1 {self.hedgeOneStrikePrice} {trade_type} price:{price} oom_to_itm_hedge_swap_oom_2_closure ++'
                                        self.addLogData(f'{time} target_1_met: oom_to_itm_hedge_swap: {text}')
                                        self.addDataPoints(timeStr, price, self.hedgeOneStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_2)
                                        no_of_lots_itm_hedge = no_of_lots_itm_hedge + 1
                                        
                                    itm_hedge_condition_met = True
                                    text = f'Sell 1 {self.hedgeTwoStrikePrice} {trade_type} price:{price} high:{high} CE_buy_price:{pivot_data['CE_buy_price']} oom_to_itm_hedge_swap_itm_2_start ++'
                                    self.addLogData(f'{time} target_1_met: oom_to_itm_hedge_swap: {text}')
                                    self.addDataPoints(timeStr, price, self.hedgeTwoStrikePrice, trade_type, 'SELL', 1, self.STRIKE_TYPE_3)
                                    itm_hedge_active = True
                                    oom_hedge_active = False
                                    itm_hedge_tobe_closed_2 = True
                                    itm_target_2_met = False

                        # check for itm hedge active cases
                        if itm_hedge_active:

                            #check for itm target 2
                            #Note: if we are dealing with one itm hedge, close at first itm target itself
                            if itm_target_1_dev < 2 :
                            #if itm_target_2_dev < 2 :
                                
                                text = f'Buy 1 {self.hedgeTwoStrikePrice} {trade_type} price:{price} itm_target_1_dev:{itm_target_1_dev} tgt_1_done_itm_tgt_2_rchd ++'
                                self.addLogData(f'{time} target_1_met: itm_hedge_active: {text}')
                                self.addDataPoints(timeStr, price, self.hedgeTwoStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_3)
                                
                                if not target_2_met:
                                    text = f'Sell 1 {self.buyStrikePrice} {trade_type} price:{price} tgt_1_done_itm_tgt_2_rchd_target_2_closure ++'
                                    self.addLogData(f'{time} target_1_met: itm_hedge_active: {text}')
                                    self.addDataPoints(timeStr, price, self.buyStrikePrice, trade_type, 'SELL', 1, self.STRIKE_TYPE_1)
                                    
                                #reset all flags to initial condition
                                ce_buy_condition_met = False
                                pe_buy_condition_met = False
                                trade_in_progress = False
                                trade_type = 'NA'
                                target_1_met = False
                                target_2_met = False
                                itm_target_1_met = False
                                itm_target_2_met = False
                                oom_hedge_active = False
                                oom_hedge_tobe_closed_1 = False
                                oom_hedge_tobe_closed_2 = False
                                itm_hedge_active = False
                                itm_hedge_tobe_closed_1 = False
                                itm_hedge_tobe_closed_2 = False
                                self.addLogData("--------------------------------------")

                            #check for itm to oom hedge swap
                            if ( ( (high > pivot_data['CE_buy_price']) and (trade_type == 'CE') ) or 
                             ( (low < pivot_data['PE_buy_price']) and (trade_type == 'PE') ) ):
                                
                                if trade_type == 'CE':
                                    if high > pivot_data['CE_buy_price']:

                                        oom_quantity = 0
                                        oom_hedge_active = True

                                        if not itm_target_2_met:
                                            text = f'Buy 1 {self.hedgeTwoStrikePrice} {trade_type} price:{price} tgt_1_done_itm_2_oom_itm_hedge_2_closure ++'
                                            self.addLogData(f'{time} target_1_met: itm_hedge_active: {text}')
                                            self.addDataPoints(timeStr, price, self.hedgeTwoStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_3)
                                            itm_target_2_met = True
                                            oom_quantity = oom_quantity + 1
                                            oom_hedge_tobe_closed_2 = True

                                        oom_hedge_condition_met = True
                                        text = f'Sell 1 {self.hedgeOneStrikePrice} {trade_type} price:{price} high{high} CE_buy_price:{pivot_data['CE_buy_price']} tgt_1_done_itm_2_oom_oom_hedge_2_start ++'
                                        self.addLogData(f'{time} target_1_met: itm_hedge_active: {text}')
                                        self.addDataPoints(timeStr, price, self.hedgeOneStrikePrice, trade_type, 'SELL', 1, self.STRIKE_TYPE_2)
                                        itm_hedge_active = False
                                        itm_hedge_tobe_closed_1 = False
                                        itm_hedge_tobe_closed_2 = False
                                        itm_target_1_met = True
                                        oom_hedge_tobe_closed_1 = False
                                        itm_hedge_condition_met = False

                                else:
                                    if low < pivot_data['PE_buy_price']:

                                        oom_quantity = 0
                                        oom_hedge_active = True

                                        if not itm_target_2_met:
                                            text = f'Buy 1 {self.hedgeTwoStrikePrice} {trade_type} price:{price} tgt_1_done_itm_2_oom_itm_hedge_2_closure ++'
                                            self.addLogData(f'{time} target_1_met: itm_hedge_active: {text}')
                                            self.addDataPoints(timeStr, price, self.hedgeTwoStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_3)
                                            itm_target_2_met = True
                                            oom_quantity = oom_quantity + 1
                                            oom_hedge_tobe_closed_2 = True

                                        oom_hedge_condition_met = True
                                        text = f'Sell 1 {self.hedgeOneStrikePrice} {trade_type} price:{price} low:{low} PE_buy_price:{pivot_data['PE_buy_price']} tgt_1_done_itm_2_oom_oom_hedge_2_start ++'
                                        self.addLogData(f'{time} target_1_met: itm_hedge_active: {text}')
                                        self.addDataPoints(timeStr, price, self.hedgeOneStrikePrice, trade_type, 'SELL', 1, self.STRIKE_TYPE_2)
                                        itm_hedge_active = False
                                        itm_hedge_tobe_closed_1 = False
                                        itm_hedge_tobe_closed_2 = False
                                        itm_target_1_met = True
                                        oom_hedge_tobe_closed_1 = False
                                        itm_hedge_condition_met = False

                    # target 2 reached condition
                    else :

                        if oom_hedge_tobe_closed_2:
                            text = f'Buy 1 {self.hedgeOneStrikePrice} {trade_type} price:{price} tgt_1_done_oom_hedge_2_close ++'
                            self.addLogData(f'{time} target_1_met: target_2_reached: {text}')
                            self.addDataPoints(timeStr, price, self.hedgeOneStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_2)

                        if itm_hedge_tobe_closed_2:
                            text = f'Buy 1 {self.hedgeTwoStrikePrice} {trade_type} price:{price} tgt_1_done_itm_hedge_2_close ++'
                            self.addLogData(f'{time} target_1_met: target_2_reached: {text}')
                            self.addDataPoints(timeStr, price, self.hedgeTwoStrikePrice, trade_type, 'BUY', 1, self.STRIKE_TYPE_3)

                        text = f'Sell 1 {self.buyStrikePrice} {trade_type} price:{price} tgt_2_done ++'
                        self.addLogData(f'{time} target_1_met: target_2_reached: {text}')
                        self.addDataPoints(timeStr, price, self.buyStrikePrice, trade_type, 'SELL', 1, self.STRIKE_TYPE_1)

                        #reset all flags to initial condition
                        ce_buy_condition_met = False
                        pe_buy_condition_met = False
                        trade_in_progress = False
                        trade_type = 'NA'
                        target_1_met = False
                        target_2_met = False
                        itm_target_1_met = False
                        itm_target_2_met = False
                        oom_hedge_active = False
                        oom_hedge_tobe_closed_1 = False
                        oom_hedge_tobe_closed_2 = False
                        itm_hedge_active = False
                        itm_hedge_tobe_closed_1 = False
                        itm_hedge_tobe_closed_2 = False
                        self.addLogData("--------------------------------------")

        

        if stop_time_reached :
            if createEntries:
                self.closeAllPendingOrders(timeStr, price)
            else:
                self.addLogData('All pending order close initiated ')

        self.addLogData("--------------------------------------")
        self.addLogData(f'{row['time']} final Tick : price - {row['intc']}')
            
        return price_data, graph_data, pivot_data, self.debug_data, self.dataPoints

    def fetch_all_data(self, elapsed):
        symbol = "NFO:NIFTY29MAY25F"
        elapsed = int(elapsed)

        for interval in [1]:
            start_time = datetime.now(self.ist).replace(hour=9, minute=15, second=0)
            start_time = start_time - timedelta(days=elapsed)
            end_time = datetime.now(self.ist).replace(hour=15, minute=30, second=0)
            end_time = end_time - timedelta(days=elapsed)
            price_data, graph_data, pivot_data, debug_data, data_points = self.process_symbol_data(symbol, interval, start_time, end_time)
            time.sleep(1)
            return price_data, graph_data, pivot_data, debug_data, data_points  # Return the graph data instead of printing it

if __name__ == "__main__":

    client_details = ['GA0810', 'O9i8u7y6**', '08101994', 'GA0810_API', '181c21c7e69c67daa41cf515b77f4885']

    elapsed = float(sys.argv[1]) if len(sys.argv) > 1 else 0
    createEntries = len(sys.argv) > 2
    stock_fetcher = StockDataFetcher(client_details, createEntries)
    stock_fetcher.login()
    price_data, graph_data, pivot_data, debug_data, data_points = stock_fetcher.fetch_all_data(elapsed)
    if not createEntries:
        print(json.dumps({
                    "priceData": price_data,
                    "graphData": graph_data,
                    "pivotData": pivot_data,
                    'debug_data': debug_data,
                    'data_points': data_points
                }))
