Overcome this error in the code:
Error:
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
/usr/local/lib/python3.10/dist-packages/pandas/core/indexes/base.py in get_loc(self, key, method, tolerance)
   3801             try:
-> 3802                 return self._engine.get_loc(casted_key)
   3803             except KeyError as err:

7 frames
pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

KeyError: 'High'

The above exception was the direct cause of the following exception:

KeyError                                  Traceback (most recent call last)
/usr/local/lib/python3.10/dist-packages/pandas/core/indexes/base.py in get_loc(self, key, method, tolerance)
   3802                 return self._engine.get_loc(casted_key)
   3803             except KeyError as err:
-> 3804                 raise KeyError(key) from err
   3805             except TypeError:
   3806                 # If we have a listlike key, _check_indexing_error will raise

KeyError: 'High'
Code:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import yfinance as yf
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import Dense, LSTM, Dropout


def calculate_atr(data, period):
    data['H-L'] = data['High'] - data['Low']
    data['H-PC'] = abs(data['High'] - data['Close'].shift(1))
    data['L-PC'] = abs(data['Low'] - data['Close'].shift(1))
    data['TR'] = data[['H-L', 'H-PC', 'L-PC']].max(axis=1)
    data['ATR'] = data['TR'].rolling(window=period).mean()
    return data

def calculate_super_trend(data, period, multiplier):
    data = calculate_atr(data, period)
    data['Upper Basic'] = (data['High'] + data['Low']) / 2 + multiplier * data['ATR']
    data['Lower Basic'] = (data['High'] + data['Low']) / 2 - multiplier * data['ATR']
    data['Upper Band'] = data.apply(lambda x: x['Upper Basic'] if x['Close'] > x['Upper Basic'] else x['Lower Basic'], axis=1)
    data['Lower Band'] = data.apply(lambda x: x['Lower Basic'] if x['Close'] < x['Lower Basic'] else x['Upper Basic'], axis=1)
    data['Super Trend'] = np.where(data['Close'] > data['Upper Band'], data['Lower Band'], data['Upper Band'])
    return data.dropna()


def load_preprocess_data(ticker, start_date, end_date, window_size, period=14, multiplier=3):
    stock_data = yf.download(ticker, start=start_date, end=end_date)
    stock_data.columns = [col.lower() for col in stock_data.columns]
    stock_data_with_super_trend = calculate_super_trend(stock_data, period, multiplier)

    columns_to_use = stock_data_with_super_trend[['Open', 'High', 'Low', 'Close', 'Super Trend']].values
    scaler = MinMaxScaler(feature_range=(0, 1))
    data_normalized = scaler.fit_transform(columns_to_use)

    X, y = [], []
    for i in range(window_size, len(data_normalized)):
        X.append(data_normalized[i - window_size:i])
        y.append(data_normalized[i, 3])  # Use Close prices directly as labels

    train_len = int(0.8 * len(X))
    X_train, y_train = np.array(X[:train_len]), np.array(y[:train_len])
    X_test, y_test = np.array(X[train_len:]), np.array(y[train_len:])

    return X_train, y_train, X_test, y_test

def create_lstm_model(input_shape):
    model = Sequential()
    model.add(LSTM(units=50, return_sequences=True, input_shape=input_shape))
    model.add(Dropout(0.2))
    model.add(LSTM(units=50, return_sequences=True))
    model.add(Dropout(0.2))
    model.add(LSTM(units=50))
    model.add(Dropout(0.2))
    model.add(Dense(units=1))

    model.compile(optimizer='adam', loss='mean_squared_error')
    return model

def train_model(model, X_train, y_train, batch_size, epochs):
    history = model.fit(X_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_split=0.1)
    return model, history

def evaluate_model(model, X_test, y_test, scaler):
    y_pred = model.predict(X_test)
    y_pred_inverse = scaler.inverse_transform(np.column_stack((np.zeros(y_pred.shape), y_pred)))[:, 1]  # Inverse transform for Close prices
    y_test_inverse = scaler.inverse_transform(np.column_stack((np.zeros(y_test.shape), y_test)))[:, 1]

    mae = np.mean(np.abs(y_pred_inverse - y_test_inverse))
    mse = np.mean(np.square(y_pred_inverse - y_test_inverse))
    return mae, mse

def plot_prediction(model, X_test, y_test, scaler):
    y_pred = model.predict(X_test)
    y_pred_inverse = scaler.inverse_transform(np.column_stack((np.zeros(y_pred.shape), y_pred)))[:, 1]  # Inverse transform for Close prices
    y_test_inverse = scaler.inverse_transform(np.column_stack((np.zeros(y_test.shape), y_test)))[:, 1]

    plt.figure(figsize=(14, 6))
    plt.plot(y_test_inverse, label='Actual')
    plt.plot(y_pred_inverse, label='Predicted')
    plt.xlabel('Days')
    plt.ylabel('Close Price')
    plt.title('Stock Price Prediction (Actual vs Predicted)')
    plt.legend()
    plt.show()


# Define the parameters
ticker = '^NSEI'  # Ticker symbol for Nifty
start_date = '2010-01-01'
end_date = '2023-06-01'
window_size = 60  # Number of previous days' data to consider
period = 14  # ATR period
multiplier = 3  # ATR multiplier
batch_size = 32
epochs = 100

# Load and preprocess the data
X_train, y_train, X_test, y_test = load_preprocess_data(ticker, start_date, end_date, window_size, period, multiplier)

# Create the LSTM model
input_shape = (X_train.shape[1], X_train.shape[2])
model = create_lstm_model(input_shape)

# Train the model
model, history = train_model(model, X_train, y_train, batch_size, epochs)

# Evaluate the model
scaler = MinMaxScaler(feature_range=(0, 1))
scaler.fit_transform(y_train.reshape(-1, 1))  # Fit scaler on training labels
mae, mse = evaluate_model(model, X_test, y_test, scaler)
print(f"Mean Absolute Error: {mae}“)
print(f"Mean Squared Error: {mse}”)

# Plot the predictions
plot_prediction(model, X_test, y_test, scaler)

# Predict the closing price for the upcoming 5 days and plot them
upcoming_days = 5
predictions = []

for i in range(upcoming_days):
    next_day_input = np.array([X_test[-1, 1:, :]])  # Use the last window data from X_test and exclude the first element
    next_day_pred = model.predict(next_day_input)
    predictions.append(next_day_pred[0, 0])

    new_row = np.column_stack((next_day_input[0, 1:, :], next_day_pred))  # Create a new row with the predicted value
    X_test = np.append(X_test, [new_row], axis=0)  # Append the new row to X_test

predictions = np.array(predictions).reshape(-1, 1)
predictions_inverse = scaler.inverse_transform(np.column_stack((np.zeros(predictions.shape), predictions)))[:, 1]  # Inverse transform for Close prices

# Plot the upcoming 5 days predictions
plt.figure(figsize=(14, 6))
plt.plot(predictions_inverse, marker="o", label='Predicted')
plt.xlabel('Days')
plt.ylabel('Close Price')
plt.title('NIFTY Stock Price Prediction for Upcoming 5 Days')
plt.legend()
plt.show()