import pandas as pd
import numpy as np
import yfinance as yf
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.metrics import mean_squared_error, r2_score
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import EarlyStopping
import tensorflow as tf
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
import requests
from tqdm.notebook import tqdm
import warnings
import pandas_ta as ta

warnings.filterwarnings('ignore')
tf.random.set_seed(42)
np.random.seed(42)

# Function to get list of Indian stocks
def get_indian_stocks():
    nse_url = "https://archives.nseindia.com/content/equities/EQUITY_L.csv"
    nse_df = pd.read_csv(nse_url)
    return [f"{symbol}.NS" for symbol in nse_df['SYMBOL'].tolist()]

# Function to fetch stock data with retries
def get_stock_data(symbol, period="1mo", retries=3):
    for attempt in range(retries):
        try:
            stock = yf.Ticker(symbol)
            df = stock.history(period=period)
            if len(df) < 400:  # Ensure we have enough data
                return None
            return df
        except Exception as e:
            if attempt == retries - 1:
                print(f"Error fetching data for {symbol}: {str(e)}")
                return None
            time.sleep(1)

# Function to create features
def create_features(df):
    df['Returns'] = df['Close'].pct_change()
    df['SMA_50'] = df['Close'].rolling(window=50).mean()
    df['SMA_200'] = df['Close'].rolling(window=200).mean()
    df['Volatility'] = df['Returns'].rolling(window=20).std() * np.sqrt(252)
    
    # Adding more technical indicators
    df['RSI'] = ta.momentum.RSIIndicator(df['Close']).rsi()
    df['MACD'] = ta.trend.MACD(df['Close']).macd()
    df['MACD_Signal'] = ta.trend.MACD(df['Close']).macd_signal()
    df['BB_High'] = ta.volatility.BollingerBands(df['Close']).bollinger_hband()
    df['BB_Low'] = ta.volatility.BollingerBands(df['Close']).bollinger_lband()
    df['OBV'] = ta.volume.OnBalanceVolumeIndicator(df['Close'], df['Volume']).on_balance_volume()
    
    df = df.dropna()
    return df

# Function to prepare data for LSTM
def prepare_data_for_lstm(data, look_back=60):
    scaler = MinMaxScaler(feature_range=(0, 1))
    scaled_data = scaler.fit_transform(data)
    
    X, y = [], []
    for i in range(look_back, len(scaled_data)):
        X.append(scaled_data[i-look_back:i])
        y.append(scaled_data[i, 0])  # 0 index represents 'Close' price
    
    return np.array(X), np.array(y), scaler

# Function to create and train LSTM model
def create_lstm_model(input_shape):
    model = Sequential([
        LSTM(100, return_sequences=True, input_shape=input_shape),
        Dropout(0.2),
        LSTM(100, return_sequences=False),
        Dropout(0.2),
        Dense(50),
        Dense(1)
    ])
    model.compile(optimizer=Adam(learning_rate=0.001), loss='mse')
    return model

# Function to train model and make prediction
def analyze_stock(symbol):
    df = get_stock_data(symbol)
    if df is None or len(df) < 400:
        return None

    df = create_features(df)
    
    features = ['Open', 'High', 'Low', 'Close', 'Volume', 'Returns', 'SMA_50', 'SMA_200', 
                'Volatility', 'RSI', 'MACD', 'MACD_Signal', 'BB_High', 'BB_Low', 'OBV']
    X = df[features]
    y = df['Close']
    
    # Prepare data for LSTM
    X_lstm, y_lstm, scaler = prepare_data_for_lstm(df[features].values)
    X_train_lstm, X_test_lstm, y_train_lstm, y_test_lstm = train_test_split(X_lstm, y_lstm, test_size=0.2, random_state=42)
    
    # Train LSTM model
    lstm_model = create_lstm_model((X_train_lstm.shape[1], X_train_lstm.shape[2]))
    early_stopping = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True)
    lstm_model.fit(X_train_lstm, y_train_lstm, epochs=100, batch_size=32, validation_split=0.2, 
                   callbacks=[early_stopping], verbose=0)
    
    # Train Random Forest and Gradient Boosting models
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
    
    rf_model = RandomForestRegressor(n_estimators=200, random_state=42, n_jobs=-1)
    rf_model.fit(X_train, y_train)
    
    gb_model = GradientBoostingRegressor(n_estimators=200, random_state=42)
    gb_model.fit(X_train, y_train)
    
    # Make predictions
    lstm_pred = lstm_model.predict(X_test_lstm)
    lstm_pred = scaler.inverse_transform(np.concatenate((lstm_pred, np.zeros((len(lstm_pred), len(features)-1))), axis=1))[:, 0]
    rf_pred = rf_model.predict(X_test)
    gb_pred = gb_model.predict(X_test)
    
    # Ensemble prediction
    ensemble_pred = (lstm_pred + rf_pred + gb_pred) / 3
    
    # Calculate metrics
    mse = mean_squared_error(y_test, ensemble_pred)
    r2 = r2_score(y_test, ensemble_pred)
    
    # Make future prediction
    last_60_days = scaler.transform(X.iloc[-60:].values)
    last_60_days_reshaped = last_60_days.reshape(1, 60, len(features))
    lstm_future = lstm_model.predict(last_60_days_reshaped)
    lstm_future = scaler.inverse_transform(np.concatenate((lstm_future, np.zeros((1, len(features)-1))), axis=1))[0, 0]
    
    rf_future = rf_model.predict(X.iloc[-1:])
    gb_future = gb_model.predict(X.iloc[-1:])
    
    ensemble_future = (lstm_future + rf_future[0] + gb_future[0]) / 3
    
    current_price = df['Close'].iloc[-1]
    potential_return = (ensemble_future - current_price) / current_price
    
    avg_volume = df['Volume'].mean()
    volatility = df['Volatility'].iloc[-1]
    
    return {
        'symbol': symbol,
        'current_price': current_price,
        'predicted_price': ensemble_future,
        'potential_return': potential_return,
        'mse': mse,
        'r2': r2,
        'avg_volume': avg_volume,
        'volatility': volatility
    }

# Function to calculate confidence score
def calculate_confidence(stock_data):
    r2_weight = 0.4
    volume_weight = 0.3
    volatility_weight = 0.3
    
    r2_score = max(min(stock_data['r2'], 1), 0)  # Clip R2 score between 0 and 1
    volume_score = min(stock_data['avg_volume'] / 1e6, 1)  # Normalize volume, cap at 1
    volatility_score = 1 - min(stock_data['volatility'], 1)  # Lower volatility is better, cap at 1
    
    confidence = (r2_weight * r2_score +
                  volume_weight * volume_score +
                  volatility_weight * volatility_score)
    
    return confidence * 100  # Convert to percentage

# Function to scan all stocks
def scan_stocks(stocks):
    results = []
    
    with ThreadPoolExecutor(max_workers=5) as executor:
        future_to_stock = {executor.submit(analyze_stock, symbol): symbol for symbol in stocks}
        for future in tqdm(as_completed(future_to_stock), total=len(stocks), desc="Analyzing Stocks"):
            result = future.result()
            if result:
                confidence = calculate_confidence(result)
                result['confidence'] = confidence
                results.append(result)
    
    return sorted(results, key=lambda x: x['confidence'], reverse=True)

# Main function
def main():
    print("Fetching list of Indian stocks...")
    stocks = get_indian_stocks()
    print(f"Found {len(stocks)} stocks. Starting analysis...")
    
    results = scan_stocks(stocks[:100])  # Analyze top 100 stocks for demonstration
    
    print("\nTop 10 suggested stocks for investment:")
    for i, stock in enumerate(results[:10], 1):
        print(f"{i}. {stock['symbol']}:")
        print(f"   Current Price: ₹{stock['current_price']:.2f}")
        print(f"   Predicted Price: ₹{stock['predicted_price']:.2f}")
        print(f"   Potential Return: {stock['potential_return']:.2%}")
        print(f"   Confidence: {stock['confidence']:.2f}%")
        print(f"   R2 Score: {stock['r2']:.4f}")
        print(f"   MSE: {stock['mse']:.4f}")
        print(f"   Average Daily Volume: {stock['avg_volume']:,.0f}")
        print(f"   Volatility: {stock['volatility']:.2%}")
        print()
    
    print(f"Total stocks analyzed: {len(results)}")
    print("Note: This analysis is based on historical data and should not be the sole basis for investment decisions.")
    print("Always conduct thorough research and consult with a qualified financial advisor before investing.")

if __name__ == "__main__":
    main()

This is a code but it is giving me a bad output:

Fetching list of Indian stocks...
Found 2022 stocks. Starting analysis...
Analyzing Stocks: 100%
 100/100 [00:02<00:00, 36.07it/s]
ERROR:yfinance:ABREL.NS: Period '1mo' is invalid, must be one of ['1d', '5d']

Top 10 suggested stocks for investment:
Total stocks analyzed: 0
Note: This analysis is based on historical data and should not be the sole basis for investment decisions.
Always conduct thorough research and consult with a qualified financial advisor before investing.

Can you fix this?