import sys
import gc  # దీన్ని మర్చిపోకుండా ఉంచండి
import os
import logging
import time
import csv
import threading
from datetime import datetime, timedelta

# గార్బేజ్ కలెక్షన్‌ను వెంటనే ఎనేబుల్ చేయండి
gc.enable() 
sys.dont_write_bytecode = True

# అన్ని లైబ్రరీల థ్రెడ్స్ మరియు మెమరీని 1 కి పరిమితం చేయండి
os.environ["OMP_NUM_THREADS"] = "1"
os.environ["MKL_NUM_THREADS"] = "1"
os.environ["OPENBLAS_NUM_THREADS"] = "1"
os.environ["XGB_NUM_THREADS"] = "1" # ఇది చాలా ముఖ్యం

logging.basicConfig(level=logging.INFO)
import pytz
import sys
import gc
import logging
import time
import csv
import threading
from datetime import datetime, timedelta

gc.disable()
sys.dont_write_bytecode = True

logging.basicConfig(level=logging.INFO)

pd = None
np = None
pytz = None
requests = None
joblib = None
CORS = None
Flask = None
jsonify = None
render_template = None
tradeapi = None
ta = None
feedparser = None

def load_dependencies():
    global pd, np, pytz, requests, joblib, CORS, Flask, jsonify, render_template, tradeapi, ta, feedparser
    import pytz as pytz_mod
    import requests as requests_mod
    import joblib as joblib_mod
    import pandas as pd_mod
    import numpy as np_mod
    from flask import Flask as Flask_cls, jsonify as jsonify_fn, render_template as render_template_fn
    from flask_cors import CORS as CORS_cls
    import alpaca_trade_api as tradeapi_mod
    import ta as ta_mod
    import feedparser as feedparser_mod
    
    pytz = pytz_mod
    requests = requests_mod
    joblib = joblib_mod
    pd = pd_mod
    np = np_mod
    Flask = Flask_cls
    jsonify = jsonify_fn
    render_template = render_template_fn
    CORS = CORS_cls
    tradeapi = tradeapi_mod
    ta = ta_mod
    feedparser = feedparser_mod
    gc.collect()

load_dependencies()

US_TZ = pytz.timezone('America/New_York')
IST = pytz.timezone('Asia/Kolkata')

BASE_DIR = "/home/luxonweb/luxon_usd_bot"
LOG_FILE = os.path.join(BASE_DIR, "trade_history.csv")
STATE_FILE = os.path.join(BASE_DIR, "luxon_state_v1.joblib")
MODEL_FILE = os.path.join(BASE_DIR, "luxon_us_ultimate_99_model.pkl")
FEATURES_FILE = os.path.join(BASE_DIR, "luxon_us_ultimate_99_features.pkl")
TRADING_SYMBOL = "AAPL"

ALPACA_API_KEY = "PKVDXPSN5TDEH2ZKJ7QGKBVDXD"
ALPACA_SECRET_KEY = "67hfyKxrn2VnUpv5pJ6P4uXXfUfMCXg1EkQoGfpj3bxH"
ALPACA_BASE_URL = "https://paper-api.alpaca.markets"

USD_TO_INR = 83.50
LEVERAGE = 20          
MIN_TP_INR = 500.0      
MAX_SL_INR = 600.0      
TRAIL_DROP_INR = 100.0   

GLOBAL_MODEL = None
GLOBAL_FEATURES = None
bot_state = {}
live_data = {
    "news_score": 0,
    "sentiment_val": 0.5,
    "news": "NEUTRAL"
}
alpaca = None
app = None

def setup_files_and_directories():
    if not os.path.exists(BASE_DIR):
        os.makedirs(BASE_DIR, exist_ok=True)
    if not os.path.exists(LOG_FILE):
        with open(LOG_FILE, 'w', newline='') as f:
            csv.writer(f).writerow(["date_time", "entry", "exit", "type", "gross_pnl", "brokerage", "net_pnl", "wallet"])

def load_bot_state():
    global IST
    if os.path.exists(STATE_FILE):
        try: 
            state = joblib.load(STATE_FILE)
            if "consecutive_losses" not in state: state["consecutive_losses"] = 0
            if "sleep_until" not in state: state["sleep_until"] = None
            if "last_price" not in state: state["last_price"] = 0.0
            if "last_adx" not in state: state["last_adx"] = 0.0
            if "last_news" not in state: state["last_news"] = "SCANNING..."
            if "last_sync" not in state: state["last_sync"] = "00:00:00"
            if "last_status" not in state: state["last_status"] = "SCANNING"
            if "last_bull" not in state: state["last_bull"] = 50
            if "last_bear" not in state: state["last_bear"] = 50
            if "last_pnl" not in state: state["last_pnl"] = 0.0
            if "last_news_time" not in state: state["last_news_time"] = 0
            if "last_reset_date" not in state: state["last_reset_date"] = datetime.now(IST).strftime("%Y-%m-%d")
            return state
        except: 
            pass
            
    return {
        "total_wallet": 119.76, 
        "today_profit": 0.0, 
        "wins": 0, 
        "losses": 0, 
        "trades": 0, 
        "in_pos": False, 
        "pos_type": "NONE", 
        "entry_p": 0.0, 
        "qty": 0.0, 
        "max_pnl_reached": 0.0,
        "consecutive_losses": 0,    
        "sleep_until": None,
        "last_price": 0.0,
        "last_adx": 0.0,
        "last_news": "SCANNING...",
        "last_sync": "00:00:00",
        "last_status": "SCANNING",
        "last_bull": 50,
        "last_bear": 50,
        "last_pnl": 0.0,
        "last_news_time": 0,
        "last_reset_date": datetime.now(IST).strftime("%Y-%m-%d")
    }

def save_bot_state(): 
    global bot_state
    if bot_state:
        joblib.dump(bot_state, STATE_FILE)

def check_us_market_status():
    global US_TZ
    now_est = datetime.now(US_TZ)
    current_date_str = now_est.strftime("%Y-%m-%d")
    
    holidays_2026 = {
        "2026-01-01": "Market Closed: New Year's Day",
        "2026-01-19": "Market Closed: Martin Luther King, Jr. Day",
        "2026-02-16": "Market Closed: Washington's Birthday",
        "2026-04-03": "Market Closed: Good Friday",
        "2026-05-25": "Market Closed: Memorial Day",
        "2026-06-19": "Market Closed: Juneteenth National Independence Day",
        "2026-07-03": "Market Closed: Independence Day Observed",
        "2026-09-07": "Market Closed: Labor Day",
        "2026-11-26": "Market Closed: Thanksgiving Day",
        "2026-12-25": "Market Closed: Christmas Day"
    }

    if now_est.weekday() >= 5:
        return False, "Market Closed: WEEKEND"

    if current_date_str in holidays_2026:
        return False, holidays_2026[current_date_str]

    market_open = now_est.replace(hour=9, minute=30, second=0, microsecond=0)
    market_close = now_est.replace(hour=16, minute=0, second=0, microsecond=0)

    if market_open <= now_est <= market_close:
        return True, "MARKET OPEN"
    elif now_est < market_open:
        return False, "Market Closed: PRE-MARKET HOURS"
    else:
        return False, "Market Closed: AFTER-MARKET HOURS"

def update_news_loop():
    global live_data, bot_state, feedparser
    while True:
        try:
            rss_url = f"https://news.google.com/rss/search?q={TRADING_SYMBOL}+stock+market+trend+OR+breaking+news+when:1d&hl=en-US&gl=US&ceid=US:en"
            feed = feedparser.parse(rss_url)
            
            score = 0
            bullish_keywords = ['rally', 'bullish', 'surge', 'breakout', 'all-time high', 'positive', 'gain', 'buying', 'earnings', 'upgraded']
            bearish_keywords = ['crash', 'bearish', 'slump', 'sell-off', 'declining', 'dump', 'plunge', 'weak', 'loss', 'downgraded']

            for news in feed.entries[:15]:
                t = news.title.lower()
                news_impact = 0
                if any(x in t for x in bullish_keywords): news_impact += 1
                if any(x in t for x in bearish_keywords): news_impact -= 1.5 
                score += news_impact

            live_data["news_score"] = score
            live_data["sentiment_val"] = max(0, min(1, 0.5 + (score * 0.1)))
            
            if score >= 4: live_data["news"] = "STRONG BULLISH"
            elif score >= 1.5: live_data["news"] = "BULLISH"
            elif score <= -4: live_data["news"] = "STRONG BEARISH"
            elif score <= -1.5: live_data["news"] = "BEARISH"
            else: live_data["news"] = "NEUTRAL"

            bot_state["last_news"] = live_data["news"]
            bot_state["last_news_time"] = time.time()
            save_bot_state()

        except Exception as e:
            logging.error(f"RSS News Loop Error: {e}")
        time.sleep(300)

def execute_trading_engine():
    global bot_state, GLOBAL_MODEL, GLOBAL_FEATURES, alpaca, IST, ta, pd, tradeapi
    try:
        now_ist = datetime.now(IST)
        bot_state["last_sync"] = now_ist.strftime("%H:%M:%S")
        
        current_date_str = now_ist.strftime("%Y-%m-%d")
        if bot_state.get("last_reset_date") != current_date_str:
            bot_state["today_profit"] = 0.0
            bot_state["last_reset_date"] = current_date_str
            save_bot_state()
        
        is_open, market_reason = check_us_market_status()
        
        live_price_fetched = 0.0
        try:
            trade_snapshot = alpaca.get_latest_trade(TRADING_SYMBOL)
            live_price_fetched = float(trade_snapshot.price)
            bot_state["last_price"] = live_price_fetched
        except Exception:
            try:
                bar_snapshot = alpaca.get_latest_bar(TRADING_SYMBOL)
                live_price_fetched = float(bar_snapshot.close)
                bot_state["last_price"] = live_price_fetched
            except Exception:
                pass

        if not is_open and not bot_state["in_pos"]:
            bot_state["last_status"] = market_reason
            save_bot_state()
            return
        
        bars = alpaca.get_bars(TRADING_SYMBOL, tradeapi.TimeFrame(15, tradeapi.TimeFrameUnit.Minute), limit=100).df
        if bars.empty:
            return

        df = bars.copy()
        df.columns = [c.lower() for c in df.columns]
        
        df['ema_50'] = ta.trend.ema_indicator(df['close'], window=50)
        df['ema_200'] = ta.trend.ema_indicator(df['close'], window=200)
        df['rsi'] = ta.momentum.rsi(df['close'])
        df['macd'] = ta.trend.macd_diff(df['close'])
        df['adx'] = ta.trend.adx(df['high'], df['low'], df['close'])
        df['bb_high'] = ta.volatility.bollinger_hband(df["close"], window=20, window_dev=2)
        df['bb_low'] = ta.volatility.bollinger_lband(df["close"], window=20, window_dev=2)
        
        df['body_size'] = (df['close'] - df['open']).abs()
        for i in range(1, 6): 
            df[f'ret_{i}'] = df['close'].pct_change(i)

        if live_price_fetched > 0:
            curr_p = live_price_fetched
        else:
            curr_p = float(df['close'].iloc[-1])
            bot_state["last_price"] = curr_p

        adx_v = float(df['adx'].fillna(0).iloc[-1])
        bot_state["last_adx"] = round(adx_v, 2)

        if GLOBAL_MODEL is not None and GLOBAL_FEATURES is not None:
            try:
                inference_df = df.copy().ffill().bfill().fillna(0)
                for col in GLOBAL_FEATURES:
                    if col not in inference_df.columns and col.lower() in inference_df.columns:
                        inference_df[col] = inference_df[col.lower()]
                    elif col not in inference_df.columns and col.upper() in inference_df.columns:
                        inference_df[col] = inference_df[col.upper()]
                for missing_col in GLOBAL_FEATURES:
                    if missing_col not in inference_df.columns:
                        inference_df[missing_col] = 0.0

                X = inference_df[GLOBAL_FEATURES].tail(1)
                probs = GLOBAL_MODEL.predict_proba(X)[0]
                bot_state["last_bull"] = int(probs[1] * 100)
                bot_state["last_bear"] = 100 - bot_state["last_bull"]
                del X, inference_df
            except Exception as e:
                logging.warning(f"Inference Logic Warning: {e}")

        is_sleeping = False
        if bot_state.get("sleep_until"):
            sleep_dt = bot_state["sleep_until"]
            if isinstance(sleep_dt, str):
                sleep_dt = datetime.strptime(sleep_dt, "%Y-%m-%d %H:%M:%S").replace(tzinfo=IST)
            if now_ist < sleep_dt:
                remaining_time = (sleep_dt - now_ist).seconds // 60
                bot_state["last_status"] = f"SLEEPING MODE ({remaining_time} Mins Left)"
                bot_state["last_pnl"] = 0.0
                is_sleeping = True
                save_bot_state()
            else:
                bot_state["sleep_until"] = None
                bot_state["consecutive_losses"] = 0
                bot_state["last_status"] = "SCANNING"
                save_bot_state()

        if is_sleeping:
            del df; gc.collect()
            return 

        if not bot_state["in_pos"]:
            bot_state["last_pnl"] = 0.0
            bot_state["last_status"] = "SCANNING"
            
            if adx_v >= 25:
                exchange_has_position = False
                try:
                    position = alpaca.get_position(TRADING_SYMBOL)
                    if int(position.qty) != 0:
                        exchange_has_position = True
                except Exception:
                    pass
                
                if exchange_has_position:
                    bot_state["in_pos"] = True 
                    bot_state["last_status"] = "SYNCING WITH ALPACA..."
                    save_bot_state()
                    del df; gc.collect()
                    return

                compounded_wallet_usdt = bot_state["total_wallet"]
                allocated_qty = (compounded_wallet_usdt * LEVERAGE) / curr_p

                current_news = bot_state["last_news"]
                is_news_bearish = current_news in ["BEARISH", "STRONG BEARISH"]
                is_news_bullish = current_news in ["BULLISH", "STRONG BULLISH"]

                pos_triggered = False
                pos_type = "NONE"

                if bot_state["last_bull"] >= 85 and not is_news_bearish:
                    pos_triggered = True
                    pos_type = "LONG"
                elif bot_state["last_bull"] <= 15 and not is_news_bullish:
                    pos_triggered = True
                    pos_type = "SHORT"

                if pos_triggered:
                    side_order = "buy" if pos_type == "LONG" else "sell"
                    sl_side = "sell" if pos_type == "LONG" else "buy"
                    
                    try:
                        try:
                            alpaca.cancel_all_orders()
                            time.sleep(0.5)
                        except Exception:
                            pass

                        order = alpaca.submit_order(
                            symbol=TRADING_SYMBOL, qty=round(allocated_qty, 2),
                            side=side_order, type='market', time_in_force='day'
                        )
                        
                        sl_dist_usdt = (MAX_SL_INR / USD_TO_INR) / allocated_qty
                        sl_trigger_price = round(curr_p - sl_dist_usdt, 2) if pos_type == "LONG" else round(curr_p + sl_dist_usdt, 2)
                        
                        sl_order = alpaca.submit_order(
                            symbol=TRADING_SYMBOL, qty=round(allocated_qty, 2),
                            side=sl_side, type='stop', stop_price=sl_trigger_price, time_in_force='day'
                        )
                        sl_order_id = sl_order.id
                    except Exception as order_err:
                        logging.error(f"Order Placement Failure: {order_err}")
                        del df; gc.collect()
                        return

                    bot_state.update({
                        "in_pos": True, "pos_type": pos_type, "entry_p": curr_p, 
                        "qty": allocated_qty, "max_pnl_reached": 0.0, 
                        "entry_time": now_ist.strftime("%Y-%m-%d %H:%M:%S"),
                        "sl_order_id": sl_order_id, "sl_mode": "HARD_600", 
                        "last_status": f"RUNNING: {pos_type}"
                    })
        
        else:
            if bot_state["pos_type"] == "LONG":
                gross_pnl_inr = (curr_p - bot_state["entry_p"]) * bot_state["qty"] * USD_TO_INR
            else:
                gross_pnl_inr = (bot_state["entry_p"] - curr_p) * bot_state["qty"] * USD_TO_INR
            
            bot_state["last_pnl"] = round(gross_pnl_inr, 2)
            bot_state["last_status"] = f"RUNNING: {bot_state['pos_type']}"
            
            if gross_pnl_inr > bot_state["max_pnl_reached"]: 
                bot_state["max_pnl_reached"] = gross_pnl_inr
            
            should_exit = False
            exit_reason = ""
            
            if gross_pnl_inr >= 300.0 and bot_state.get("sl_mode") == "HARD_600":
                try:
                    if bot_state.get("sl_order_id"):
                        alpaca.cancel_order(bot_state["sl_order_id"])
                    fee_buffer_usdt = (120.0 / USD_TO_INR) / bot_state["qty"]
                    be_trigger_price = round(bot_state["entry_p"] + fee_buffer_usdt, 2) if bot_state["pos_type"] == "LONG" else round(bot_state["entry_p"] - fee_buffer_usdt, 2)
                    
                    new_sl_order = alpaca.submit_order(
                        symbol=TRADING_SYMBOL, qty=round(bot_state["qty"], 2),
                        side="sell" if bot_state["pos_type"] == "LONG" else "buy",
                        type='stop', stop_price=be_trigger_price, time_in_force='day'
                    )
                    bot_state["sl_order_id"] = new_sl_order.id
                    bot_state["sl_mode"] = "BREAKEVEN_0"
                    bot_state["last_status"] = "SL MOVED TO FEE-COVER"
                except Exception:
                    pass
            
            try:
                if bot_state.get("sl_order_id"):
                    check_order = alpaca.get_order(bot_state["sl_order_id"])
                    if check_order.status in ["filled", "expired", "canceled"]:
                        should_exit = True
                        exit_reason = "EXIT: BREAKEVEN HIT" if bot_state.get("sl_mode") == "BREAKEVEN_0" else "EXIT: STOP LOSS HIT"
            except Exception:
                pass

            if not should_exit:
                current_sl_limit = MAX_SL_INR if bot_state.get("sl_mode") == "HARD_600" else 0.0
                if gross_pnl_inr <= -current_sl_limit:
                    should_exit = True
                    exit_reason = "EXIT: STOP LOSS HIT (BACKUP)" if current_sl_limit > 0 else "EXIT: BREAKEVEN HIT (BACKUP)"

            if not should_exit and bot_state["max_pnl_reached"] >= MIN_TP_INR:
                if gross_pnl_inr <= (bot_state["max_pnl_reached"] - TRAIL_DROP_INR):
                    should_exit = True
                    exit_reason = "EXIT: TRAILING GUARD HIT"
            
            if should_exit:
                bot_state["in_pos"] = False 
                bot_state["last_status"] = exit_reason
                
                try:
                    alpaca.close_position(TRADING_SYMBOL)
                    if bot_state.get("sl_order_id"):
                        alpaca.cancel_order(bot_state["sl_order_id"])
                except Exception:
                    pass

                brokerage_inr = (curr_p * bot_state["qty"] * 0.0004) * USD_TO_INR  
                net_pnl_inr = gross_pnl_inr - brokerage_inr
                
                bot_state["total_wallet"] += (net_pnl_inr / USD_TO_INR)
                bot_state["today_profit"] += net_pnl_inr
                bot_state["trades"] += 1
                
                if net_pnl_inr > 0: 
                    bot_state["wins"] += 1
                    bot_state["consecutive_losses"] = 0
                else: 
                    bot_state["losses"] += 1
                    if "STOP LOSS" in exit_reason:
                        bot_state["consecutive_losses"] += 1

                if bot_state["consecutive_losses"] >= 2:
                    bot_state["sleep_until"] = (now_ist + timedelta(minutes=45)).strftime("%Y-%m-%d %H:%M:%S")
                    bot_state["last_status"] = "SLEEPING MODE (45 Mins Left)"

                final_wallet_inr = (bot_state["total_wallet"] * USD_TO_INR)
                with open(LOG_FILE, 'a', newline='') as f:
                    csv.writer(f).writerow([
                        datetime.now(IST).strftime("%Y-%m-%d %H:%M"), 
                        round(bot_state["entry_p"], 2), round(curr_p, 2), 
                        bot_state["pos_type"], round(gross_pnl_inr, 2), 
                        round(brokerage_inr, 2), round(net_pnl_inr, 2), 
                        round(final_wallet_inr, 2)
                    ])
                
                bot_state.update({
                    "entry_p": 0.0, "qty": 0.0, "last_pnl": 0.0,
                    "entry_time": None, "sl_order_id": None, "sl_mode": None,
                    "pos_type": "NONE", "max_pnl_reached": 0.0
                })
                if not bot_state["sleep_until"]:
                    bot_state["sleep_until"] = (now_ist + timedelta(minutes=1)).strftime("%Y-%m-%d %H:%M:%S")
                    bot_state["last_status"] = "ANTI-DUPLICATE COOL DOWN (1 Min)"
        
        save_bot_state()
        del df; gc.collect()
    except Exception as e:
        logging.error(f"Trading Engine Exception: {e}")

def define_routes():
    global app, bot_state, IST
    
    @app.route('/get_data')
    def get_data():
        is_open, market_reason = check_us_market_status()
        calculated_trades = 0
        calculated_wins = 0
        calculated_losses = 0
        calculated_today_profit = 0.0
        last_wallet_from_csv = 0.0 
        
        now_ist = datetime.now(IST)
        today_str = now_ist.strftime("%Y-%m-%d")

        history_rows = []
        if os.path.exists(LOG_FILE):
            try:
                with open(LOG_FILE, 'r', encoding='utf-8') as f:
                    reader = csv.reader(f)
                    next(reader)  
                    for row in reader:
                        if len(row) >= 8:
                            history_rows.append({
                                "date_time": row[0], "entry": row[1], "exit": row[2],
                                "type": row[3], "gross_pnl": row[4], "brokerage": row[5],
                                "net_pnl": row[6], "wallet": row[7]
                            })
                            net_pnl_val = float(row[6])
                            calculated_trades += 1
                            if net_pnl_val > 0: calculated_wins += 1
                            else: calculated_losses += 1
                            if today_str in row[0]: calculated_today_profit += net_pnl_val
                            last_wallet_from_csv = float(row[7])
            except Exception: pass

        bot_state["trades"] = calculated_trades
        bot_state["wins"] = calculated_wins
        bot_state["losses"] = calculated_losses
        bot_state["today_profit"] = calculated_today_profit
        
        if calculated_trades > 0 and last_wallet_from_csv > 0:
            raw_wallet = last_wallet_from_csv if last_wallet_from_csv >= 13000 else (10000.0 + calculated_today_profit)
        else:
            raw_wallet = float(bot_state.get('total_wallet', 119.76)) * USD_TO_INR

        wr = (calculated_wins / calculated_trades * 100) if calculated_trades > 0 else 0.0
        pos_type = bot_state.get('pos_type', 'NONE').upper()
        entry_p = float(bot_state.get('entry_p', 0.0))
        qty = float(bot_state.get('qty', 0.0))
        
        margin_str = f"{((entry_p * qty) / LEVERAGE) * USD_TO_INR:.2f}" if pos_type in ["LONG", "SHORT"] else "0.00"
        raw_price = float(bot_state.get('last_price', 0.0))
        raw_pnl = float(bot_state.get('last_pnl', 0.0))
        display_wallet = raw_wallet + raw_pnl if pos_type in ["LONG", "SHORT"] else raw_wallet

        return jsonify({
            "price": f"{raw_price:.2f}", "total_wallet": f"{display_wallet:.2f}",  
            "today_profit": f"{calculated_today_profit:.2f}", "adx": f"{float(bot_state.get('last_adx', 0.0)):.2f}",
            "bull": str(bot_state.get('last_bull', 50)), "bear": str(bot_state.get('last_bear', 50)),
            "status": str(bot_state.get("last_status", "SCANNING")), "sync": str(bot_state.get('last_sync', '00:00:00')), 
            "news": str(bot_state.get('last_news', 'NEUTRAL')), "pnl": f"{raw_pnl:.2f}", "pos": pos_type,
            "entry": f"{entry_p:.2f}", "qty": f"{qty:.5f}", "margin": margin_str, "win_rate": f"{wr:.1f}%", 
            "total_trades": int(calculated_trades), "wins": int(calculated_wins), "losses": int(calculated_losses),
            "tp": f"{float(MIN_TP_INR):.1f}", "sl": f"{float(MAX_SL_INR):.1f}", "market_open_status": is_open,                
            "market_reason": market_reason, "past_trades": list(reversed(history_rows))[:10]
        })

    @app.route('/')
    def home():
        return render_template('index.html')

def background_loop():
    global GLOBAL_MODEL, GLOBAL_FEATURES
    
    # బ్యాక్‌గ్రౌండ్ త్రెడ్‌లో మోడల్‌ను నెమ్మదిగా లోడ్ చేయండి
    logging.info("Loading ML Model in background thread to save startup RAM...")
    try:
        if os.path.exists(MODEL_FILE) and os.path.exists(FEATURES_FILE):
            GLOBAL_MODEL = joblib.load(MODEL_FILE)
            GLOBAL_FEATURES = joblib.load(FEATURES_FILE)
            logging.info("ML Model loaded successfully inside background thread!")
    except Exception as e:
        logging.error(f"Failed to load model in background: {e}")

    while True:
        try:
            execute_trading_engine()
            time.sleep(3)
        except Exception as e:
            logging.error(f"Background Engine Exception: {e}")
            time.sleep(5)


if __name__ == "__main__":
    setup_files_and_directories()
    
    # Alpaca ని మాత్రమే మొదట కనెక్ట్ చేయండి
    alpaca = tradeapi.REST(ALPACA_API_KEY, ALPACA_SECRET_KEY, ALPACA_BASE_URL, api_version='v2')
    bot_state = load_bot_state()
    
    # మోడల్ లోడింగ్‌ను ఇక్కడి నుండి తీసేసి, బ్యాక్‌గ్రౌండ్ లూప్‌లోకి మారుస్తున్నాం
    # దీనివల్ల ఫ్లాస్క్ యాప్ సులభంగా స్టార్ట్ అవుతుంది
    
    app = Flask(__name__)
    CORS(app)
    define_routes()
    
    threading.Thread(target=update_news_loop, daemon=True).start()
    threading.Thread(target=background_loop, daemon=True).start()
    
    # సర్వర్‌ను లైట్ వెయిట్‌గా రన్ చేయండి
    app.run(host='0.0.0.0', port=5003, debug=False, use_reloader=False)