please look over my code and check for duplicate lines, imports, any errors, debug it and then send me the full complete updated code please. import numpy as np
import json
import logging
import requests
import time
import csv
from datetime import datetime, timedelta
from keras.models import load_model
from sklearn.preprocessing import MinMaxScaler
import signal
import sys
import tensorflow as tf 
import pandas as pd

# GPU memory management
gpus = tf.config.list_physical_devices('GPU')
if gpus:
    for gpu in gpus:
        tf.config.experimental.set_memory_growth(gpu, True)


# PerformanceLogger Implementation
class PerformanceLogger:
    def __init__(self, log_file='performance_log.csv'):
        self.log_file = log_file
        self.trades = []
        # Initialize CSV file with headers if not exists
        try:
            with open(self.log_file, 'x', newline='') as file:
                writer = csv.writer(file)
                writer.writerow([
                    "Timestamp", "Action", "Side", "Symbol", "Quantity",
                    "Price", "Order_ID", "Profit", "Account_Balance"
                ])
        except FileExistsError:
            pass  # File already exists

    def log_trade(self, action, side, symbol, quantity, price, order_id, profit, account_balance):
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.trades.append({
            "Timestamp": timestamp,
            "Action": action,
            "Side": side,
            "Symbol": symbol,
            "Quantity": quantity,
            "Price": price,
            "Order_ID": order_id,
            "Profit": profit,
            "Account_Balance": account_balance
        })
        with open(self.log_file, 'a', newline='') as file:
            writer = csv.writer(file)
            writer.writerow([
                timestamp, action, side, symbol, quantity,
                price, order_id, profit, account_balance
            ])

    def log_final_summary(self):
        if not self.trades:
            logging.info("No trades were executed.")
            return

        total_profit = sum(trade['Profit'] for trade in self.trades)
        total_trades = len(self.trades)
        winning_trades = len([trade for trade in self.trades if trade['Profit'] > 0])
        losing_trades = len([trade for trade in self.trades if trade['Profit'] <= 0])
        win_rate = (winning_trades / total_trades) * 100 if total_trades > 0 else 0
        average_profit = total_profit / total_trades if total_trades > 0 else 0

        summary = (
            f"Final Performance Summary:\n"
            f"Total Trades: {total_trades}\n"
            f"Winning Trades: {winning_trades}\n"
            f"Losing Trades: {losing_trades}\n"
            f"Win Rate: {win_rate:.2f}%\n"
            f"Total Profit/Loss: ${total_profit:.2f}\n"
            f"Average Profit/Loss per Trade: ${average_profit:.2f}"
        )
        logging.info(summary)

        # Optionally, write summary to a separate CSV or log file
        with open('performance_summary.txt', 'a') as file:
            file.write(summary + "\n\n")

# Tradier Sandbox API setup
SANDBOX_API_KEY = "ljLUShMNM75Ub7oibl6NnR1InwqF"
ACCOUNT_ID = "VA90929848"
BASE_URL = "https://sandbox.tradier.com/v1"
HEADERS = {
    "Authorization": f"Bearer {SANDBOX_API_KEY}",
    "Accept": "application/json",
    "Content-Type": "application/json"
}

# Logging setup
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s")

# Initialize account balance and trade history
account_balance = None
trade_history = []

def load_trained_model(model_path, model_name):
    try:
        model = tf.keras.models.load_model(model_path)
        logging.info(f"{model_name} loaded successfully.")
        return model
    except Exception as e:
        logging.error(f"Failed to load {model_name}: {str(e)}")
        return None

import os
from keras.models import load_model
import pickle
import logging


# Define custom objects if needed
custom_objects = {}  # Add any custom layers or metrics here if used

# Load models from correct paths
try:
    lstm_model = load_model("enhancedcorrectmodels/final_lstm_model.keras", custom_objects=custom_objects)
    logging.info("LSTM model loaded successfully.")
    
    gru_model = load_model("enhancedcorrectmodels/final_gru_model.keras", custom_objects=custom_objects)
    logging.info("GRU model loaded successfully.")
    
    # Load scaler
    with open("enhancedcorrectmodels/final_scaler.pkl", "rb") as f:
        scaler = pickle.load(f)
    logging.info("Scaler loaded successfully.")
    
except Exception as e:
    logging.error(f"Error loading models: {str(e)}")
    raise
# Load data
data = pd.read_csv("clean_spy_data.csv")

# Define features
features = ["Open", "High", "Low", "Volume"]

# Create feature matrix
X = data[features]

# Scale features using loaded scaler
X_scaled = scaler.transform(X)  # Using transform instead of fit_transform since scaler is already fitted

# Reshape for model input
X_scaled_reshaped = X_scaled.reshape(-1, 1, X_scaled.shape[1])
# Instantiate the PerformanceLogger
performance_logger = PerformanceLogger()

# Constants
MARKET_OPEN_HOUR = 9  # Market opens at 9:30 AM EST
MARKET_OPEN_MINUTE = 30
MARKET_CLOSE_HOUR = 16  # Market closes at 4:00 PM EST
MARKET_CLOSE_MINUTE = 0
MAX_RETRIES = 3
RETRY_DELAY = 5
RISK_PERCENTAGE = 0.02  # 2% risk per trade
CHECK_INTERVAL = 60  # Check every 60 seconds
OPTION_TYPE = 'call'  # Options type: 'call' or 'put'

# CSV logging function
def log_to_csv(data):
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    with open('trading_log.csv', 'a', newline='') as file:
        writer = csv.writer(file)
        writer.writerow([timestamp] + list(data.values()))

# Signal handling for graceful shutdown and final summary
def handle_exit_signal(signal_number, frame):
    cleanup_resources()
    logging.info("Performance summary saved and script exiting.")
    sys.exit(0)

# Bind the signal handlers
signal.signal(signal.SIGINT, handle_exit_signal)
signal.signal(signal.SIGTERM, handle_exit_signal)

def check_trailing_stop(entry_price, current_price, highest_price, trailing_percent=0.05):
    """
    Check if the trailing stop condition is met.
    """
    if current_price > highest_price:
        highest_price = current_price
    stop_price = highest_price * (1 - trailing_percent)
    trailing_stop_hit = current_price <= stop_price
    return trailing_stop_hit, highest_price

def cleanup_resources():
    """
    Cleanup resources on exit.
    """
    performance_logger.log_final_summary()
    log_to_csv({"action": "strategy_exit", "account_balance": account_balance})
    logging.info("Resources cleaned up and strategy exited.")

class RateLimiter:
    def __init__(self, calls_per_second=1):
        self.calls_per_second = calls_per_second
        self.last_call = 0

    def wait(self):
        current_time = time.time()
        time_since_last_call = current_time - self.last_call
        if time_since_last_call < 1 / self.calls_per_second:
            time.sleep(1 / self.calls_per_second - time_since_last_call)
        self.last_call = time.time()

rate_limiter = RateLimiter()

def api_request(method, endpoint, **kwargs):
    """Wrapper for API requests with retry logic"""
    for retry in range(MAX_RETRIES):
        rate_limiter.wait()
        try:
            response = method(endpoint, **kwargs)
            if response.status_code in [200, 201]:
                return response.json()
            elif response.status_code == 429:  # Rate limit
                logging.warning(f"Rate limit hit. Retrying in {RETRY_DELAY * (2 ** retry)} seconds.")
                time.sleep(RETRY_DELAY * (2 ** retry))
                continue
            else:
                logging.error(f"API request failed: {response.status_code} - {response.text}")
                return None
        except requests.exceptions.RequestException as e:
            logging.error(f"Request failed: {str(e)}")
            if retry < MAX_RETRIES - 1:
                logging.info(f"Retrying after {RETRY_DELAY * (2 ** retry)} seconds...")
                time.sleep(RETRY_DELAY * (2 ** retry))
            else:
                logging.error("Max retries reached. Moving on.")
                return None

class TradingState:
    def __init__(self):
        self.position_open = False
        self.entry_price = None
        self.highest_price = None
        self.exit_level = None
        self.quantity = None
        self.order_id = None

def place_order(symbol, side, quantity, order_type="market", price=None, stop=None):
    option_symbol = get_option_symbol(symbol)
    if not option_symbol:
        logging.error("Cannot place order: Invalid option symbol.")
        return None

    tradier_side = 'buy_to_open' if side.lower() == 'buy' else 'sell_to_close'

    data = {
        'class': 'option',
        'symbol': symbol,
        'option_symbol': option_symbol,
        'side': tradier_side,
        'quantity': str(quantity),
        'type': order_type,
        'duration': 'day',
    }
    if price is not None:
        data['price'] = str(price)
    if stop is not None:
        data['stop'] = str(stop)

    logging.debug(f"Order data being sent: {data}")

    response = requests.post(f"{BASE_URL}/accounts/{ACCOUNT_ID}/orders", data=data, headers=HEADERS)

    if response.status_code in [200, 201]:
        order_id = response.json().get('order', {}).get('id')
        if order_id:
            logging.info(f"Order placed: {side} {quantity} {option_symbol} at {price if price else 'market'}, Order ID: {order_id}")
            log_to_csv({
                "action": "order_placed",
                "side": tradier_side,
                "quantity": quantity,
                "symbol": option_symbol,
                "price": price if price else "market",
                "order_id": order_id
            })
            return order_id
    else:
        logging.error(f"Failed to place order: {response.status_code} - {response.text}")
        log_to_csv({
            "action": "order_failed",
            "side": tradier_side,
            "quantity": quantity,
            "symbol": option_symbol,
            "price": price if price else "market",
            "error": response.text
        })
    return None

def order_status(order_id):
    """Check the status of an order."""
    response = requests.get(f"{BASE_URL}/accounts/{ACCOUNT_ID}/orders/{order_id}", headers=HEADERS)
    if response.status_code == 200:
        order_info = response.json().get("order", {})
        status = order_info.get("status")
        logging.info(f"Order {order_id} status: {status}")
        return status
    else:
        logging.error(f"Failed to fetch order status: {response.status_code} - {response.text}")
        return None

def get_account_balance():
    """
    Fetch account balance from Tradier API
    """
    endpoint = f"{BASE_URL}/accounts/{ACCOUNT_ID}/balances"

    response = api_request(requests.get, endpoint, headers=HEADERS)
    if response:
        balance_data = response.get('balances', {})
        total_equity = balance_data.get('total_equity', 0)
        try:
            logging.info(f"Current account balance: ${float(total_equity):.2f}")
            return float(total_equity)
        except ValueError:
            logging.error("Invalid total_equity value received.")
            return None
    return None

def get_option_symbol(symbol):
    """
    Retrieve the At-The-Money (ATM) option symbol for the given symbol.
    """
    endpoint = f"{BASE_URL}/markets/options/chains"
    today = datetime.now().date()
    # Fetch options expiring in the next 30 days
    expiration_date = (today + timedelta(days=30)).strftime("%Y-%m-%d")

    params = {
        "symbol": symbol,
        "expiration": expiration_date,
        "greeks": "false",
        "strike": "atm"  # ATM strike
    }

    response = api_request(requests.get, endpoint, headers=HEADERS, params=params)
    if response and 'options' in response and 'option' in response['options']:
        options = response['options']['option']
        current_price_data = get_market_data(symbol)
        if not current_price_data:
            logging.error("Unable to retrieve current price for option selection.")
            return None
        current_price = current_price_data.get('last')
        if not current_price:
            logging.error("Current price data missing 'last' price.")
            return None
        # Find the strike closest to current_price
        closest_option = min(options, key=lambda x: abs(float(x['strike']) - float(current_price)))
        option_symbol = closest_option.get('symbol')
        logging.info(f"Selected Option Symbol: {option_symbol}")
        return option_symbol
    else:
        logging.error("No options data retrieved.")
    return None

def get_market_data(symbol):
    """
    Fetch market data from Tradier API with proper value validation
    """
    endpoint = f"{BASE_URL}/markets/quotes"
    params = {"symbols": symbol}

    response = api_request(requests.get, endpoint, headers=HEADERS, params=params)
    if response and 'quotes' in response and 'quote' in response['quotes']:
        data = response['quotes']['quote']

        if data:
            try:
                market_data = {
                    "open": float(data.get('open', 0)),
                    "high": float(data.get('high', 0)),
                    "low": float(data.get('low', 0)),
                    "last": float(data.get('last', 0)),
                    "volume": int(data.get('volume', 0))
                }
                return market_data
            except (TypeError, ValueError) as e:
                logging.error(f"Error parsing market data: {str(e)}")
                return None
        else:
            logging.warning("No quote data available.")
            return None
    else:
        logging.error("Failed to retrieve market data.")
    return None

def is_market_open():
    """Check if the market is currently open"""
    now = datetime.now()
    if now.weekday() >= 5:  # Weekend
        return False

    market_time = now.hour + now.minute / 60
    market_open = MARKET_OPEN_HOUR + MARKET_OPEN_MINUTE / 60
    market_close = MARKET_CLOSE_HOUR + MARKET_CLOSE_MINUTE / 60

    return market_open <= market_time <= market_close

def calculate_position_size(account_balance, current_price, stop_loss):
    """Calculate position size based on risk management"""
    risk_amount = account_balance * RISK_PERCENTAGE
    price_difference = abs(current_price - stop_loss)
    if price_difference == 0:
        return 1
    position_size = risk_amount / price_difference
    return max(1, int(position_size))

def validate_market_data(data):
    required_fields = ['open', 'high', 'low', 'volume', 'last']
    return all(field in data and data[field] is not None for field in required_fields)

def generate_signals(boost_model, lstm_model, mlp_model, X, current_price):
    """Generate trading signals using the ensemble of models"""
    if not all([boost_model, lstm_model, mlp_model]):
        logging.error("One or more models are not loaded. Cannot generate signals.")
        return False, False, None

    # Validate current_price
    if current_price is None:
        logging.warning("Current price is None, skipping signal generation")
        return False, False, None

    try:
        # Prepare input for models
        # Assuming models expect [open, high, low, volume]
        # Ensure input is scaled appropriately
        X_scaled = scaler.transform(X)
        X_scaled = X_scaled.reshape((1, ) + X_scaled.shape)  # Reshape for models if needed

        # Get predictions from each model
        boost_preds = boost_model.predict(X_scaled)[0][0]
        lstm_preds = lstm_model.predict(X_scaled)[0][0]
        mlp_preds = mlp_model.predict(X_scaled)[0][0]

        # Ensure all predictions are valid numbers
        if any(np.isnan([boost_preds, lstm_preds, mlp_preds])):
            logging.warning("Invalid model predictions detected")
            return False, False, None

        # Example logic to combine predictions
        combined_pred = (boost_preds + lstm_preds + mlp_preds) / 3

        buy_signal = combined_pred > 0.5
        sell_signal = combined_pred < -0.5

        # Example next level calculation (this should be based on your specific strategy)
        next_level = current_price * (1 + (combined_pred * 0.01))  # 1% move per prediction unit

        logging.debug(f"Signal generation - Boost: {boost_preds:.4f}, LSTM: {lstm_preds:.4f}, MLP: {mlp_preds:.4f}, Combined: {combined_pred:.4f}")

        return buy_signal, sell_signal, next_level
    except Exception as e:
        logging.error(f"Error during signal generation: {str(e)}")
        return False, False, None

def execute_trade(symbol, side, position_size, entry_price=None, stop_loss=None, take_profit=None):
    """Execute a trade with proper risk management"""
    order_id = place_order(symbol, side, position_size)

    if order_id:
        trading_state = TradingState()
        trading_state.position_open = True if side.lower() == "buy" else False
        trading_state.entry_price = entry_price if entry_price else None
        trading_state.highest_price = entry_price if entry_price else None
        trading_state.exit_level = take_profit
        trading_state.quantity = position_size
        trading_state.order_id = order_id

        action = "buy" if side.lower() == "buy" else "sell"
        profit = 0  # Initial profit is 0 for buy orders

        performance_logger.log_trade(
            action=action,
            side=side,
            symbol=symbol,
            quantity=position_size,
            price=entry_price if entry_price else "market",
            order_id=order_id,
            profit=profit,
            account_balance=account_balance
        )

        log_to_csv({
            "action": "trade_executed",
            "symbol": symbol,
            "side": side,
            "position_size": position_size,
            "entry_price": entry_price,
            "stop_loss": stop_loss,
            "take_profit": take_profit
        })

        return trading_state
    return None

def run_trading_strategy():
    global account_balance
    symbol = "SPY"
    trading_state = TradingState()

    account_balance = get_account_balance()
    if account_balance is None:
        logging.error("Unable to retrieve account balance. Exiting strategy.")
        return

    log_to_csv({"action": "strategy_start", "account_balance": account_balance})
    while True:
        try:
            if not is_market_open():
                logging.info("Market is closed")
                time.sleep(CHECK_INTERVAL)
                continue

            market_data = get_market_data(symbol)
            if not market_data or not validate_market_data(market_data):
                logging.warning("Invalid market data received")
                time.sleep(RETRY_DELAY)
                continue

            try:
                current_price = float(market_data["last"])
                if current_price <= 0:
                    raise ValueError("Invalid price value")
            except (TypeError, ValueError):
                logging.warning("Invalid price data received")
                time.sleep(RETRY_DELAY)
                continue

            X = np.array([[market_data["open"], market_data["high"],
                          market_data["low"], market_data["volume"]]], dtype=np.float32)
            # Make predictions using the loaded models
            lstm_predictions = lstm_model.predict(X_scaled_reshaped)
            gru_predictions = gru_model.predict(X_scaled_reshaped)

            def ensemble_predictions(lstm_pred, gru_pred, weights=[0.7, 0.3]):
                """
                Combine predictions from LSTM and GRU models using weighted average
                """
                return weights[0] * lstm_pred + weights[1] * gru_pred

            # Create ensemble predictions
            combined_predictions = ensemble_predictions(lstm_predictions, gru_predictions)

            # Use ensemble predictions for trading signals
            trading_signals = generate_trading_signals(combined_predictions)
            if not trading_state.position_open and buy_signal:
                stop_loss = current_price * 0.99  # 1% stop loss
                position_size = calculate_position_size(account_balance, current_price, stop_loss)

                if position_size > 0:
                    state = execute_trade(symbol, "buy", position_size, entry_price=current_price, stop_loss=stop_loss, take_profit=next_level)
                    if state:
                        trading_state = state
                        account_balance = get_account_balance()  # Update account balance after trade
                        performance_logger.log_trade(
                            action="buy",
                            side="buy_to_open",
                            symbol=symbol,
                            quantity=position_size,
                            price=current_price,
                            order_id=trading_state.order_id,
                            profit=0,
                            account_balance=account_balance
                        )

            elif trading_state.position_open:
                trailing_stop_hit, updated_highest_price = check_trailing_stop(
                    trading_state.entry_price, current_price, trading_state.highest_price)

                trading_state.highest_price = updated_highest_price

                if current_price >= trading_state.exit_level or trailing_stop_hit or sell_signal:
                    if trailing_stop_hit:
                        logging.info("Trailing stop hit.")
                        log_to_csv({
                            "action": "trailing_stop_hit",
                            "current_price": current_price,
                            "stop_loss": trading_state.exit_level
                        })

                    order_id = place_order(symbol, "sell", trading_state.quantity)
                    if order_id:
                        profit = (current_price - trading_state.entry_price) * trading_state.quantity
                        account_balance += profit
                        performance_logger.log_trade(
                            action="sell",
                            side="sell_to_close",
                            symbol=symbol,
                            quantity=trading_state.quantity,
                            price=current_price,
                            order_id=order_id,
                            profit=profit,
                            account_balance=account_balance
                        )
                        log_to_csv({
                            "action": "trade_closed",
                            "symbol": symbol,
                            "quantity": trading_state.quantity,
                            "exit_price": current_price,
                            "profit": profit
                        })
                        trading_state = TradingState()  # Reset state

            # Update account balance each loop
            account_balance = get_account_balance()

            time.sleep(CHECK_INTERVAL)
        except Exception as e:
            logging.error(f"Strategy error: {str(e)}")
            time.sleep(RETRY_DELAY)
if __name__ == "__main__":
    try:
        run_trading_strategy()
    except KeyboardInterrupt:
        cleanup_resources()
    except Exception as e:
        logging.error(f"Fatal error: {str(e)}")
        cleanup_resources()