please look over this code and check for any errors or bugs. Also if you see anything that could be improved, please modify the code for the improvements and then send me the full updated complete code.. here is the code..import numpy as np
import json
import logging
import requests
import time
import csv
from datetime import datetime, timedelta
import datetime as dt
from keras.models import load_model
from sklearn.preprocessing import MinMaxScaler
from performance_logger import PerformanceLogger  # Import the PerformanceLogger

# 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 = []
entry_price = None
highest_price = None
exit_level = None

# Load models
boost_model = load_model("newboost/final_boost_model.keras")
lstm_model = load_model("correctmodels/final_meta_learner_1.keras")
mlp_model = load_model("correctmodels/final_meta_learner_2.keras")

# Initialize scaler
scaler = MinMaxScaler(feature_range=(0, 1))
scaler.fit(np.array([[0, 0], [1000, 1000000]]))

# Instantiate the PerformanceLogger
performance_logger = PerformanceLogger()

# CSV logging function
def log_to_csv(data):
    timestamp = dt.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
import signal
def handle_exit_signal(signal_number, frame):
    performance_logger.log_final_summary()
    logging.info("Performance summary saved and script exiting.")

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

# Other trading functions (get_account_balance, get_market_data, get_option_symbol, etc.) remain unchanged

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

    # Use 'buy_to_open' or 'sell_to_close' based on side parameter for options trading
    tradier_side = 'buy_to_open' if side == 'buy' else 'sell_to_close'

    # Define order data, ensuring 'class' is set to 'option' and 'option_symbol' is included
    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}")

    # Send the order request using 'data' instead of 'json'
    response = requests.post(f"{BASE_URL}/accounts/{ACCOUNT_ID}/orders", data=data, headers=HEADERS)
    
    if response.status_code == 200:
        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, "order_id": order_id})
            return order_id
    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, "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"
    
    try:
        response = requests.get(endpoint, headers=HEADERS)
        if response.status_code == 200:
            balance_data = response.json().get('balances', {})
            total_equity = balance_data.get('total_equity', 0)
            logging.info(f"Current account balance: ${total_equity}")
            return float(total_equity)
        else:
            logging.error(f"Failed to fetch account balance: {response.status_code} - {response.text}")
            return None
    except Exception as e:
        logging.error(f"Error fetching account balance: {str(e)}")
        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}

    try:
        response = requests.get(endpoint, params=params, headers=HEADERS)
        if response.status_code == 200:
            quotes = response.json().get('quotes', {})
            data = quotes.get('quote', {})
            
            if data:
                # Convert values to float with default values if None
                market_data = {
                    "open": float(data.get('open') or 0),
                    "high": float(data.get('high') or 0),
                    "low": float(data.get('low') or 0),
                    "last": float(data.get('last') or 0),
                    "volume": int(data.get('volume') or 0)
                }
                return market_data
            
        return None
    except Exception as e:
        logging.error(f"Error fetching market data: {str(e)}")
        return None
    

# Add new 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

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))

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 == 200:
                return response.json()
            elif response.status_code == 429:  # Rate limit
                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:
                time.sleep(RETRY_DELAY * (2 ** retry))
            else:
                return None

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

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"""
    # Validate current_price
    if current_price is None:
        logging.warning("Current price is None, skipping signal generation")
        return False, False, None
        
    # Get predictions from each model
    boost_preds = boost_model.predict(X)[0][0]
    X_scaled = scaler.transform(X[:, -2:])
    lstm_preds = scaler.inverse_transform([[lstm_model.predict(X_scaled)[0][0], 0]])[0][0]
    mlp_preds = scaler.inverse_transform([[mlp_model.predict(X_scaled)[0][0], 0]])[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
    
    # Calculate price differences and signals
    boost_price_diff = np.clip(boost_preds * 0.1, -5, 5)
    lstm_price_diff = np.clip(lstm_preds - current_price, -5, 5)
    mlp_price_diff = np.clip(mlp_preds - current_price, -5, 5)
    
    next_level = float(current_price + boost_price_diff)
    combined_preds = (boost_price_diff + lstm_price_diff + mlp_price_diff) / 3
    
    buy_signal = combined_preds > 0.5
    sell_signal = combined_preds < -0.5
    
    logging.debug(f"Signal generation - Boost: ${boost_price_diff}, LSTM: ${lstm_price_diff}, MLP: ${mlp_price_diff}")
    
    return buy_signal, sell_signal, next_level
def execute_trade(symbol, position_size, entry_price, stop_loss, take_profit):
    """Execute a trade with proper risk management"""
    order_id = place_order(symbol, "buy", position_size)
    
    if order_id:
        trading_state = TradingState()
        trading_state.position_open = True
        trading_state.entry_price = entry_price
        trading_state.highest_price = entry_price
        trading_state.exit_level = take_profit
        
        log_to_csv({
            "action": "trade_executed",
            "symbol": symbol,
            "position_size": position_size,
            "entry_price": entry_price,
            "stop_loss": stop_loss,
            "take_profit": take_profit
        })
        
        return trading_state, order_id
    
    return None, None


def run_trading_strategy():
    global entry_price, highest_price, exit_level
    symbol = "SPY"
    position_open = False
    trading_state = TradingState()

    get_account_balance()
    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(60)
                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

            # Safely convert current_price to float with validation
            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)
          
            buy_signal, sell_signal, next_level = generate_signals(
                boost_model, lstm_model, mlp_model, X, current_price)

            if not position_open and buy_signal and current_price is not None:
                stop_loss = float(current_price * 0.99)  # Ensure stop loss is calculated with float
                quantity = calculate_position_size(float(account_balance), current_price, stop_loss)
              
                if quantity > 0:
                    order_id = place_order(symbol, "buy", quantity)
                    if order_id:
                        position_open = True
                        entry_price = current_price
                        highest_price = entry_price
                        exit_level = next_level
                        performance_logger.log_trade("buy", 0, account_balance)

            elif position_open and current_price is not None:
                trailing_stop_hit, highest_price = check_trailing_stop(
                    entry_price, current_price, highest_price)
              
                if current_price >= exit_level or trailing_stop_hit or sell_signal:
                    order_id = place_order(symbol, "sell", quantity)
                    if order_id:
                        position_open = False
                        profit = (current_price - entry_price) * quantity
                        performance_logger.log_trade("sell", profit, account_balance + profit)
                        trading_state = TradingState()  # Reset state

            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()