hi, here is my code. # Import necessary libraries
import os
import pickle
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout
from tensorflow.keras.callbacks import EarlyStopping
from tensorflow.keras.optimizers import Adam

# Load the data
# Replace 'spy_data.csv' with the path to your actual data file
data = pd.read_csv('clean_spy_data_with_rsi.csv', parse_dates=['Date'], index_col='Date')

# Ensure data is sorted by date
data.sort_index(inplace=True)

# Feature selection
features = ['Open', 'High', 'Low', 'Close', 'Volume', 'RSI']
data = data[features]

# Handle missing values if any
data.dropna(inplace=True)

# Feature scaling
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_data = scaler.fit_transform(data)

# Convert the scaled data back to a DataFrame
scaled_data = pd.DataFrame(scaled_data, columns=features, index=data.index)

# Function to create sequences
def create_sequences(data, seq_length):
    X = []
    y = []
    for i in range(seq_length, len(data)):
        X.append(data.iloc[i - seq_length:i].values)
        y.append(data.iloc[i]['Close'])
    return np.array(X), np.array(y)

# Define sequence length
sequence_length = 60  # Using 60 past days to predict the next day

# Create sequences
X, y = create_sequences(scaled_data, sequence_length)

# Split data into training and testing sets (e.g., 80% training, 20% testing)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, shuffle=False
)

# Build the LSTM model with additional complexity and modifications
model = Sequential()

# First LSTM layer with increased units and Dropout regularization
model.add(
    LSTM(
        units=128,  # Increased units for better feature extraction
        return_sequences=True,
        input_shape=(X_train.shape[1], X_train.shape[2]),
    )
)
model.add(Dropout(0.3))  # Increased dropout

# Second LSTM layer with Dropout
model.add(LSTM(units=64, return_sequences=True))
model.add(Dropout(0.3))

# Third LSTM layer with Dropout
model.add(LSTM(units=32))
model.add(Dropout(0.2))

# Output layer
model.add(Dense(units=1))

# Compile the model with a lower learning rate
optimizer = Adam(learning_rate=0.0005)
model.compile(optimizer=optimizer, loss='mean_squared_error')

# Early stopping callback with more patience
early_stopping = EarlyStopping(
    monitor='val_loss', patience=15, restore_best_weights=True
)

# Train the model with smaller batch size
history = model.fit(
    X_train,
    y_train,
    epochs=150,  # Increased epochs to give more learning time
    batch_size=16,  # Smaller batch size for better gradient updates
    validation_data=(X_test, y_test),
    callbacks=[early_stopping],
    verbose=1,
)

# Evaluate the model
loss = model.evaluate(X_test, y_test)
print(f'Test Loss: {loss}')

# Make predictions
predicted_prices = model.predict(X_test)

# Inverse transform the predicted and actual prices
scaler_for_close = MinMaxScaler(feature_range=(0, 1))
scaler_for_close.fit(data[['Close']])

predicted_prices = scaler_for_close.inverse_transform(
    predicted_prices.reshape(-1, 1)
)
actual_prices = scaler_for_close.inverse_transform(y_test.reshape(-1, 1))

# Additional metrics

# Calculate RMSE
rmse = np.sqrt(mean_squared_error(actual_prices, predicted_prices))
print(f'Root Mean Squared Error (RMSE): {rmse}')

# Calculate MAE
mae = mean_absolute_error(actual_prices, predicted_prices)
print(f'Mean Absolute Error (MAE): {mae}')

# Calculate R-squared
r2 = r2_score(actual_prices, predicted_prices)
print(f'R-squared (R²): {r2}')

# Visualize the results
plt.figure(figsize=(14, 5))
plt.plot(
    data.index[-len(actual_prices) :],
    actual_prices,
    color='blue',
    label='Actual Close Price',
)
plt.plot(
    data.index[-len(predicted_prices) :],
    predicted_prices,
    color='red',
    label='Predicted Close Price',
)
plt.title('SPY Stock Closing Price Prediction vs Actual')
plt.xlabel('Date')
plt.ylabel('Price')
plt.legend()
plt.show()

# Plot the residuals
residuals = actual_prices - predicted_prices
plt.figure(figsize=(14, 5))
plt.plot(residuals, color='purple')
plt.title('Residuals (Actual - Predicted)')
plt.xlabel('Time')
plt.ylabel('Residuals')
plt.show()

# Save the model and scaler
if not os.path.exists('newlstmmodel'):
    os.makedirs('newlstmmodel')

# Save the LSTM model
model.save('newlstmmodel/lstm_model_finetuned.keras')

# Save the scaler using pickle
with open('newlstmmodel/scaler.pkl', 'wb') as f:
    pickle.dump(scaler, f)

# Create a DataFrame with predicted and actual prices
results_df = pd.DataFrame({
    'Date': data.index[-len(actual_prices):],
    'Actual_Price': actual_prices.flatten(),
    'Predicted_Price': predicted_prices.flatten()
})

# Save the results
results_df.to_csv('newlstmmodel/predictions_vs_actual_finetuned.csv', index=False)

print("Fine-tuned model, scaler, and predictions saved successfully.")
 and here are the results.. Root Mean Squared Error (RMSE): 7.656313781014085
Mean Absolute Error (MAE): 5.855185604970265
R-squared (R²): 0.9770283963805861
Fine-tuned model, scaler, and predictions saved successfully... i need to make it better. Please use the most enhanced coding you know of to try and produce better results.. and then send me the full updated code please.