import numpy as np
import pandas as pd
import yfinance as yf
import datetime as dt
import matplotlib.pyplot as plt
import math

start_date = dt.datetime(2020, 4, 1)
end_date = dt.datetime(2023, 4, 1)

data = yf.download("GOOGL", start_date, end_date)

pd.set_option('display.max_rows', 4)
pd.set_option('display.max_columns', 5)
print(data)

training_data_len = math.ceil(len(data) * 0.8)
training_data_len

train_data = data[:training_data_len]
test_data = data[training_data_len:]
print(train_data.shape, test_data.shape)

dataset_train = train_data.Open.values

dataset_train = np.reshape(dataset_train, (-1, 1))
dataset_train.shape

from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler(feature_range=(0, 1))

scaled_train = scaler.fit_transform(dataset_train)
print(scaled_train[:5])

dataset_test = test_data.Open.values

dataset_test = np.reshape(dataset_test, (-1, 1))

scaled_test = scaler.fit_transform(dataset_test)
print(*scaled_test[:5])
X_train = []
y_train = []
for i in range(50, len(scaled_train)):
    X_train.append(scaled_train[i-50:i, 0])
    y_train.append(scaled_train[i, 0])
    if i <= 51:
        print(X_train)
        print(y_train)
        print()
X_test = []
y_test = []
for i in range(50, len(scaled_test)):
    X_test.append(scaled_test[i-50:i, 0])
    y_test.append(scaled_test[i, 0])

X_train, y_train = np.array(X_train), np.array(y_train)

X_train = np.reshape(X_train, (X_train.shape[0], X_train.shape[1], 1))
y_train = np.reshape(y_train, (y_train.shape[0], 1))
print("X_train :", X_train.shape, "y_train :", y_train.shape)

X_test, y_test = np.array(X_test), np.array(y_test)

X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1))

y_test = np.reshape(y_test, (y_test.shape[0], 1))
print("X_test :", X_test.shape, "y_test :", y_test.shape)

from keras.models import Sequential
from keras.layers import LSTM, Dense, SimpleRNN, Dropout, GRU, Bidirectional
from keras.optimizers import SGD
from sklearn import metrics
from sklearn.metrics import mean_squared_error

regressor = Sequential()

regressor.add(SimpleRNN(units=50, activation="tanh", return_sequences=True, input_shape=(X_train.shape[1], 1)))
regressor.add(Dropout(0.2))

regressor.add(SimpleRNN(units=50, activation="tanh", return_sequences=True))

regressor.add(SimpleRNN(units=50, activation="tanh", return_sequences=True))
regressor.add(SimpleRNN(units=50))
regressor.add(Dense(units=1, activation='sigmoid'))

regressor.compile(optimizer=SGD(learning_rate=0.01, decay=1e-6, momentum=0.9, nesterov=True), loss="mean_squared_error")

regressor.fit(X_train, y_train, epochs=20, batch_size=2)
regressor.summary()

regressorLSTM = Sequential()

regressorLSTM.add(LSTM(50, return_sequences=True, input_shape=(X_train.shape[1], 1)))
regressorLSTM.add(LSTM(50, return_sequences=False))
regressorLSTM.add(Dense(25))

regressorLSTM.add(Dense(1))

regressorLSTM.compile(optimizer='adam', loss='mean_squared_error', metrics=["accuracy"])

regressorLSTM.fit(X_train, y_train, batch_size=1, epochs=12)
regressorLSTM.summary()

regressorGRU = Sequential()

regressorGRU.add(GRU(units=50, return_sequences=True, input_shape=(X_train.shape[1], 1), activation='tanh'))
regressorGRU.add(Dropout(0.2))

regressorGRU.add(GRU(units=50, return_sequences=True, activation='tanh'))

regressorGRU.add(GRU(units=50, return_sequences=True, activation='tanh'))

regressorGRU.add(GRU(units=50, activation='tanh'))

regressorGRU.add(Dense(units=1, activation='relu'))
regressorGRU.compile(optimizer=SGD(learning_rate=0.01, decay=1e-7, momentum=0.9, nesterov=False), loss='mean_squared_error')

regressorGRU.fit(X_train, y_train, epochs=20, batch_size=1)
regressorGRU.summary()

y_RNN = regressor.predict(X_test)
y_LSTM = regressorLSTM.predict(X_test)
y_GRU = regressorGRU.predict(X_test)

y_RNN_O = scaler.inverse_transform(y_RNN)
y_LSTM_O = scaler.inverse_transform(y_LSTM)
y_GRU_O = scaler.inverse_transform(y_GRU)
fig, axs = plt.subplots(3, figsize=(18, 12), sharex=True, sharey=True)
fig.suptitle('Model Predictions')

axs[0].plot(train_data.index[150:], train_data.Open[150:], label="train_data", color="b")
axs[0].plot(test_data.index, test_data.Open, label="test_data", color="g")

axs[0].plot(test_data.index[50:], y_RNN_O, label="y_RNN", color="brown")
axs[0].legend()
axs[0].title.set_text("Basic RNN")

axs[1].plot(train_data.index[150:], train_data.Open[150:], label="train_data", color="b")
axs[1].plot(test_data.index, test_data.Open, label="test_data", color="g")
axs[1].plot(test_data.index[50:], y_LSTM_O, label="y_LSTM", color="orange")
axs[1].legend()
axs[1].title.set_text("LSTM")

axs[2].plot(train_data.index[150:], train_data.Open[150:], label="train_data", color="b")
axs[2].plot(test_data.index, test_data.Open, label="test_data", color="g")
axs[2].plot(test_data.index[50:], y_GRU_O, label="y_GRU", color="red")
axs[2].legend()
axs[2].title.set_text("GRU")

plt.xlabel("Days")
plt.ylabel("Open price")

plt.show()