Update app.py
Browse files
app.py
CHANGED
@@ -1,123 +1,167 @@
|
|
|
|
1 |
import yfinance as yf
|
2 |
-
import gradio as gr
|
3 |
-
import numpy as np
|
4 |
import pandas as pd
|
|
|
|
|
|
|
|
|
5 |
import matplotlib.pyplot as plt
|
6 |
-
|
7 |
-
from
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
scaler = MinMaxScaler(feature_range=(0, 1))
|
20 |
-
scaled_data = scaler.fit_transform(
|
21 |
-
|
22 |
-
|
23 |
-
for i in range(60, len(scaled_data)):
|
24 |
-
x_train.append(scaled_data[i-60:i, 0])
|
25 |
-
y_train.append(scaled_data[i, 0])
|
26 |
-
|
27 |
-
x_train, y_train = np.array(x_train), np.array(y_train)
|
28 |
-
x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))
|
29 |
-
|
30 |
-
return x_train, y_train, scaler
|
31 |
|
32 |
-
#
|
33 |
def build_model():
|
34 |
model = Sequential()
|
35 |
model.add(LSTM(units=50, return_sequences=True, input_shape=(60, 1)))
|
|
|
36 |
model.add(LSTM(units=50, return_sequences=False))
|
37 |
-
model.add(
|
38 |
-
model.add(Dense(units=1))
|
39 |
-
|
40 |
model.compile(optimizer='adam', loss='mean_squared_error')
|
41 |
return model
|
42 |
|
43 |
-
#
|
44 |
-
def
|
45 |
-
|
46 |
-
|
47 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
# Preprocess the data
|
49 |
-
|
50 |
-
|
51 |
-
# Build and train the model
|
52 |
-
model = build_model()
|
53 |
-
model.fit(x_train, y_train, batch_size=1, epochs=1)
|
54 |
-
|
55 |
-
return model, scaler, stock_data
|
56 |
-
|
57 |
-
# Function to predict stock prices
|
58 |
-
def predict_stock(model, scaler, stock_data):
|
59 |
-
# Use the last 60 days of data for predictions
|
60 |
-
test_data = stock_data[['Close']][-60:].values
|
61 |
-
test_data_scaled = scaler.transform(test_data)
|
62 |
-
|
63 |
-
x_test = []
|
64 |
-
x_test.append(test_data_scaled)
|
65 |
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
plt.xlabel('Date')
|
80 |
plt.ylabel('Price')
|
81 |
plt.legend()
|
82 |
plt.show()
|
83 |
|
84 |
-
return
|
85 |
-
|
86 |
-
# Gradio interface function
|
87 |
-
def stock_prediction(ticker, start, end):
|
88 |
-
model, scaler, stock_data = train_model(ticker, start, end)
|
89 |
-
prediction = predict_stock(model, scaler, stock_data)
|
90 |
-
|
91 |
-
start_price = stock_data['Close'].iloc[0]
|
92 |
-
end_price = stock_data['Close'].iloc[-1]
|
93 |
-
percent_change = ((end_price - start_price) / start_price) * 100
|
94 |
-
highest_price = stock_data['Close'].max()
|
95 |
-
lowest_price = stock_data['Close'].min()
|
96 |
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
],
|
117 |
-
outputs=gr.JSON(label="Prediction and Analysis"),
|
118 |
-
live=True
|
119 |
-
)
|
120 |
-
|
121 |
-
# Launch the Gradio app
|
122 |
-
if __name__ == "__main__":
|
123 |
-
iface.launch()
|
|
|
1 |
+
import os
|
2 |
import yfinance as yf
|
|
|
|
|
3 |
import pandas as pd
|
4 |
+
import numpy as np
|
5 |
+
import tensorflow as tf
|
6 |
+
from tensorflow.keras.models import Sequential, load_model
|
7 |
+
from tensorflow.keras.layers import LSTM, Dense, Dropout
|
8 |
import matplotlib.pyplot as plt
|
9 |
+
import gradio as gr
|
10 |
+
from datetime import datetime
|
11 |
+
|
12 |
+
# Disable GPU usage and oneDNN optimizations
|
13 |
+
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
|
14 |
+
os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'
|
15 |
+
|
16 |
+
# Helper function to handle date adjustments and retries if data not found
|
17 |
+
def adjust_date_range_if_needed(stock_data, ticker, start_date, end_date):
|
18 |
+
retries = 3 # Number of retries for fetching data
|
19 |
+
while stock_data.empty and retries > 0:
|
20 |
+
start_date = (datetime.strptime(start_date, '%Y-%m-%d') - timedelta(days=1)).strftime('%Y-%m-%d')
|
21 |
+
end_date = (datetime.strptime(end_date, '%Y-%m-%d') - timedelta(days=1)).strftime('%Y-%m-%d')
|
22 |
+
print(f"Retrying with adjusted dates: {start_date} to {end_date}") # Debugging output
|
23 |
+
stock_data = yf.download(ticker, start=start_date, end=end_date)
|
24 |
+
retries -= 1
|
25 |
+
return stock_data, start_date, end_date
|
26 |
+
|
27 |
+
# Define function to validate stock ticker and get stock data
|
28 |
+
def get_stock_data(ticker, start_date, end_date):
|
29 |
+
try:
|
30 |
+
stock_data = yf.download(ticker, start=start_date, end=end_date)
|
31 |
+
print(f"Stock data downloaded: {stock_data.shape}") # Debugging output to check data download
|
32 |
+
except Exception as e:
|
33 |
+
print(f"Error fetching data: {e}") # Debugging output for data download error
|
34 |
+
return None, None, None
|
35 |
+
|
36 |
+
# If stock data is empty, attempt to adjust the date range
|
37 |
+
if stock_data.empty:
|
38 |
+
print("No data found for the original date range.") # Debugging output
|
39 |
+
stock_data, adjusted_start, adjusted_end = adjust_date_range_if_needed(stock_data, ticker, start_date, end_date)
|
40 |
+
if stock_data.empty:
|
41 |
+
return None, None, None # If still empty after retries, return None
|
42 |
+
return stock_data, adjusted_start, adjusted_end
|
43 |
+
return stock_data, start_date, end_date
|
44 |
+
|
45 |
+
# Preprocess the data for the LSTM model
|
46 |
+
def preprocess_data(stock_data):
|
47 |
+
# Closing prices
|
48 |
+
close_prices = stock_data['Close'].values
|
49 |
+
close_prices = close_prices.reshape(-1, 1)
|
50 |
+
|
51 |
+
# Normalize the data
|
52 |
+
from sklearn.preprocessing import MinMaxScaler
|
53 |
scaler = MinMaxScaler(feature_range=(0, 1))
|
54 |
+
scaled_data = scaler.fit_transform(close_prices)
|
55 |
+
|
56 |
+
return scaled_data, scaler
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
|
58 |
+
# Build the LSTM model
|
59 |
def build_model():
|
60 |
model = Sequential()
|
61 |
model.add(LSTM(units=50, return_sequences=True, input_shape=(60, 1)))
|
62 |
+
model.add(Dropout(0.2))
|
63 |
model.add(LSTM(units=50, return_sequences=False))
|
64 |
+
model.add(Dropout(0.2))
|
65 |
+
model.add(Dense(units=1)) # Predicting the next closing price
|
|
|
66 |
model.compile(optimizer='adam', loss='mean_squared_error')
|
67 |
return model
|
68 |
|
69 |
+
# Save and load models to avoid re-training
|
70 |
+
def save_model(model, file_name):
|
71 |
+
model.save(file_name)
|
72 |
+
|
73 |
+
def load_trained_model(file_name):
|
74 |
+
if os.path.exists(file_name):
|
75 |
+
return load_model(file_name)
|
76 |
+
else:
|
77 |
+
return None
|
78 |
+
|
79 |
+
# Train and make predictions
|
80 |
+
def predict_stock(stock_data, scaler, model):
|
81 |
+
# Get the last 60 days of stock data for prediction
|
82 |
+
last_60_days = stock_data[-60:]
|
83 |
+
last_60_days_scaled = scaler.transform(last_60_days)
|
84 |
+
|
85 |
+
# Prepare the input for prediction
|
86 |
+
X_test = []
|
87 |
+
X_test.append(last_60_days_scaled)
|
88 |
+
X_test = np.array(X_test)
|
89 |
+
X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1))
|
90 |
+
|
91 |
+
# Predict
|
92 |
+
predicted_price = model.predict(X_test)
|
93 |
+
predicted_price = scaler.inverse_transform(predicted_price)
|
94 |
+
|
95 |
+
print(f"Predicted price: {predicted_price}") # Debugging output to verify predictions
|
96 |
+
return predicted_price
|
97 |
+
|
98 |
+
# Main app function
|
99 |
+
def stock_predictor(ticker, start_date, end_date):
|
100 |
+
# Validate if the ticker is available on Yahoo Finance
|
101 |
+
if not ticker:
|
102 |
+
return f"Invalid stock ticker: {ticker}"
|
103 |
+
|
104 |
+
# Get stock data
|
105 |
+
stock_data, adjusted_start, adjusted_end = get_stock_data(ticker, start_date, end_date)
|
106 |
+
|
107 |
+
if stock_data is None or stock_data.empty:
|
108 |
+
return f"No data found for {ticker} in the selected or adjusted date range."
|
109 |
+
|
110 |
# Preprocess the data
|
111 |
+
scaled_data, scaler = preprocess_data(stock_data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
|
113 |
+
# Try to load a pre-trained model
|
114 |
+
model_file = f"{ticker}_model.h5"
|
115 |
+
model = load_trained_model(model_file)
|
116 |
+
|
117 |
+
if model is None:
|
118 |
+
# Train the model if pre-trained model is not found
|
119 |
+
print("Training the model...") # Debugging output for training
|
120 |
+
model = build_model()
|
121 |
+
X_train, y_train = [], []
|
122 |
+
for i in range(60, len(scaled_data)):
|
123 |
+
X_train.append(scaled_data[i-60:i, 0])
|
124 |
+
y_train.append(scaled_data[i, 0])
|
125 |
+
X_train, y_train = np.array(X_train), np.array(y_train)
|
126 |
+
X_train = np.reshape(X_train, (X_train.shape[0], X_train.shape[1], 1))
|
127 |
+
|
128 |
+
# Train the model (reduced epochs for faster processing)
|
129 |
+
model.fit(X_train, y_train, epochs=2, batch_size=32) # Reduced epochs
|
130 |
+
|
131 |
+
# Save the trained model
|
132 |
+
save_model(model, model_file)
|
133 |
+
|
134 |
+
# Predict stock price for tomorrow
|
135 |
+
predicted_price = predict_stock(scaled_data, scaler, model)
|
136 |
+
|
137 |
+
# Historical vs Predicted
|
138 |
+
plt.figure(figsize=(14, 7))
|
139 |
+
plt.plot(stock_data['Close'], color="blue", label="Historical Prices")
|
140 |
+
plt.scatter(len(stock_data), predicted_price, color="red", label="Predicted Price for Tomorrow")
|
141 |
+
plt.title(f"{ticker} Stock Price Prediction")
|
142 |
plt.xlabel('Date')
|
143 |
plt.ylabel('Price')
|
144 |
plt.legend()
|
145 |
plt.show()
|
146 |
|
147 |
+
return f"Predicted Stock Price for {ticker} tomorrow: ${predicted_price[0][0]:.2f}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
|
149 |
+
# Gradio UI
|
150 |
+
def build_ui():
|
151 |
+
stock_tickers = ["AAPL", "TSLA", "AMZN", "MSFT", "GOOGL", "FB", "NFLX", "NVDA", "BABA", "JPM"]
|
152 |
+
|
153 |
+
# Use Textbox for manual date input (format: YYYY-MM-DD)
|
154 |
+
gr_interface = gr.Interface(
|
155 |
+
fn=stock_predictor,
|
156 |
+
inputs=[
|
157 |
+
gr.Dropdown(stock_tickers, label="Stock Ticker"),
|
158 |
+
gr.Textbox(label="Start Date (YYYY-MM-DD)", value="2022-01-01"), # Manual start date
|
159 |
+
gr.Textbox(label="End Date (YYYY-MM-DD)", value=datetime.today().strftime("%Y-%m-%d")) # Manual end date
|
160 |
+
],
|
161 |
+
outputs="text",
|
162 |
+
title="Stock Price Prediction for Tomorrow"
|
163 |
+
)
|
164 |
+
gr_interface.launch()
|
165 |
+
|
166 |
+
# Run the app
|
167 |
+
build_ui()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|