Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import yfinance as yf | |
| import pandas as pd | |
| import numpy as np | |
| from sklearn.preprocessing import MinMaxScaler | |
| from tensorflow.keras.models import Sequential | |
| from tensorflow.keras.layers import LSTM, Dense, GRU | |
| from datetime import datetime, timedelta | |
| import matplotlib.pyplot as plt | |
| # Function to convert string to datetime object | |
| def str_to_datetime(s): | |
| return datetime.strptime(s, '%Y-%m-%d') | |
| # Function to create a windowed dataframe | |
| def df_to_windowed_df(dataframe, first_date_str, last_date_str, n=3): | |
| dataframe.index = pd.to_datetime(dataframe.index) | |
| first_date = str_to_datetime(first_date_str) | |
| last_date = str_to_datetime(last_date_str) | |
| target_date = first_date | |
| dates = [] | |
| X, Y =[],[] | |
| last_time = False | |
| while True: | |
| df_subset = dataframe.loc[:target_date.strftime('%Y-%m-%d')].tail(n + 1) | |
| if len(df_subset)!= n + 1: | |
| print(f'Error: Window of size {n} is too large for date {target_date}') | |
| return | |
| values = df_subset['Close'].to_numpy() | |
| x, y = values[:-1], values[-1] | |
| dates.append(target_date) | |
| X.append(x) | |
| Y.append(y) | |
| next_week = dataframe.loc[target_date.strftime('%Y-%m-%d'):].head(2) | |
| if len(next_week) < 2: | |
| print(f'Insufficient future data for {target_date}. Ending process.') | |
| break | |
| next_date_str = next_week.index.strftime('%Y-%m-%d') | |
| next_date = str_to_datetime(next_date_str) | |
| if last_time: | |
| break | |
| target_date = next_date | |
| if target_date == last_date: | |
| last_time = True | |
| ret_df = pd.DataFrame({'Target Date': dates}) | |
| X = np.array(X) | |
| for i in range(n): | |
| ret_df[f'Target-{n-i}'] = X[:, i] | |
| ret_df['Target'] = Y | |
| return ret_df | |
| look_back = 3 | |
| num_features = 7 | |
| # Load pre-trained models and scalers | |
| lstm_model = Sequential() | |
| lstm_model.add(LSTM(50, activation='relu', input_shape=(look_back, num_features))) | |
| lstm_model.add(Dense(1)) | |
| lstm_model.compile(optimizer='adam', loss='mse') | |
| lstm_model.load_weights('lstm_model_weights.weights.h5') | |
| gru_model = Sequential() | |
| gru_model.add(GRU(50, activation='relu', input_shape=(look_back, num_features))) # Replace with your actual GRU architecture | |
| gru_model.add(Dense(1)) | |
| gru_model.compile(optimizer='adam', loss='mse') | |
| gru_model.load_weights('gru_model_weights.weights.h5') | |
| lstm_scaler = pd.read_pickle('lstm_scaler.pkl') | |
| gru_scaler = pd.read_pickle('gru_scaler.pkl') | |
| def predict_stock_price(ticker, num_days): | |
| # Fetch stock data | |
| stock_data = yf.Ticker(ticker) | |
| stock_data = stock_data.history(period='5y') | |
| stock_data.reset_index(inplace=True) | |
| stock_data['Date'] = pd.to_datetime(stock_data['Date']).dt.date | |
| stock_data = stock_data[['Date', 'Close']] | |
| stock_data.index = stock_data.pop('Date') | |
| # Prepare data for prediction | |
| windowed_df = df_to_windowed_df(stock_data, '2021-03-25', '2023-11-20', n=3) | |
| windowed_df['MA7'] = windowed_df['Target'].rolling(window=7).mean() | |
| windowed_df['MA21'] = windowed_df['Target'].rolling(window=21).mean() | |
| windowed_df['Volatility'] = windowed_df['Target'].pct_change().rolling(window=21).std() | |
| windowed_df['Close-MA7_Diff'] = windowed_df['Target'] - windowed_df['MA7'] | |
| windowed_df = windowed_df.dropna() | |
| X = windowed_df[['Target-3', 'Target-2', 'Target-1', 'MA7', 'MA21', 'Volatility', 'Close-MA7_Diff']] | |
| X = np.array(X) | |
| X = X.reshape(X.shape[0], X.shape[1], 1) | |
| # Scale the data using separate scalers | |
| X_lstm = lstm_scaler.transform(X.reshape(X.shape, -1)).reshape(X.shape) | |
| X_gru = gru_scaler.transform(X.reshape(X.shape, -1)).reshape(X.shape) | |
| # Predict using LSTM and GRU | |
| lstm_predictions = lstm_model.predict(X_lstm) | |
| gru_predictions = gru_model.predict(X_gru) | |
| # Inverse transform to get actual prices | |
| lstm_predictions = lstm_scaler.inverse_transform(np.concatenate([X.reshape(X.shape, -1)[:,:3], lstm_predictions], axis=1))[:, -1] | |
| gru_predictions = gru_scaler.inverse_transform(np.concatenate([X.reshape(X.shape, -1)[:,:3], gru_predictions], axis=1))[:, -1] | |
| # Future predictions | |
| future_dates = [windowed_df['Target Date'].iloc[-1] + timedelta(days=i) for i in range(1, num_days + 1)] | |
| last_window_lstm = X_lstm[-1].reshape(1, 1, X_lstm.shape) | |
| last_window_gru = X_gru[-1].reshape(1, 1, X_gru.shape) | |
| future_predictions_lstm = [] | |
| future_predictions_gru = [] | |
| for _ in range(num_days): | |
| next_price_lstm = lstm_model.predict(last_window_lstm) | |
| future_predictions_lstm.append(next_price_lstm) | |
| last_window_lstm = np.roll(last_window_lstm, -1, axis=1) | |
| last_window_lstm[0, -1,:3] = next_price_lstm | |
| next_price_gru = gru_model.predict(last_window_gru) | |
| future_predictions_gru.append(next_price_gru) | |
| last_window_gru = np.roll(last_window_gru, -1, axis=1) | |
| last_window_gru[0, -1,:3] = next_price_gru | |
| future_predictions_lstm = lstm_scaler.inverse_transform(np.concatenate([np.array(future_predictions_lstm).reshape(-1, 1)] * 4, axis=1))[:, -1] | |
| future_predictions_gru = gru_scaler.inverse_transform(np.concatenate([np.array(future_predictions_gru).reshape(-1, 1)] * 4, axis=1))[:, -1] | |
| # Create plots with confidence intervals | |
| plt.figure(figsize=(14, 7)) | |
| plt.plot(windowed_df['Target Date'], windowed_df['Target'], label='Actual') | |
| plt.plot(windowed_df['Target Date'], lstm_predictions, label='LSTM Predictions') | |
| plt.plot(windowed_df['Target Date'], gru_predictions, label='GRU Predictions') | |
| # Calculate and plot confidence intervals (example - you'll need to adjust the logic) | |
| std_dev = np.std(lstm_predictions) # Calculate standard deviation | |
| plt.fill_between(windowed_df['Target Date'], lstm_predictions - std_dev, lstm_predictions + std_dev, color='blue', alpha=0.2, label='LSTM Confidence Interval') | |
| std_dev = np.std(gru_predictions) | |
| plt.fill_between(windowed_df['Target Date'], gru_predictions - std_dev, gru_predictions + std_dev, color='orange', alpha=0.2, label='GRU Confidence Interval') | |
| plt.plot(future_dates, future_predictions_lstm, label='Future LSTM Predictions', linestyle='dashed') | |
| plt.plot(future_dates, future_predictions_gru, label='Future GRU Predictions', linestyle='dashed') | |
| # Identify and annotate potential buying/selling opportunities | |
| # (This is a simplified example, you'll need to implement your own logic) | |
| for i in range(1, len(future_predictions_lstm)): | |
| if future_predictions_lstm[i] > future_predictions_lstm[i-1] + std_dev: | |
| plt.annotate('Buy', (future_dates[i], future_predictions_lstm[i]), textcoords="offset points", xytext=(0,10), ha='center', color='green') | |
| elif future_predictions_lstm[i] < future_predictions_lstm[i-1] - std_dev: | |
| plt.annotate('Sell', (future_dates[i], future_predictions_lstm[i]), textcoords="offset points", xytext=(0,10), ha='center', color='red') | |
| plt.xlabel('Date') | |
| plt.ylabel('Closing Price') | |
| plt.title(f'{ticker} Stock Price Prediction') | |
| plt.legend() | |
| plt.grid(True) | |
| return plt | |
| # Gradio interface | |
| iface = gr.Interface( | |
| fn=predict_stock_price, | |
| inputs=[ | |
| gr.Textbox(lines=1, placeholder="Enter stock ticker (e.g., AMZN)", value="AMZN"), | |
| gr.Slider(minimum=1, maximum=365, step=1, value=30, label="Number of days to predict") | |
| ], | |
| outputs=gr.Plot(), | |
| title="Stock Price Prediction with LSTM and GRU", | |
| description="Enter a stock ticker symbol and the number of days to predict." | |
| ) | |
| iface.launch() |