Spaces:
Sleeping
Sleeping
Commit
·
5a72e87
1
Parent(s):
fec9609
Added initial project files
Browse files- .gitignore +1 -0
- app.py +120 -0
- model/NVDA_lr_model.pkl +0 -0
- requirements.txt +6 -0
.gitignore
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
.DS_Store
|
app.py
ADDED
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#+--------------------------------------------------------------------------------------------+
|
2 |
+
# Model for Stock Price Prediction via Linear Regression
|
3 |
+
# Using today vs tomorrow analysis
|
4 |
+
# app.py for deployment on Hugging Face
|
5 |
+
#
|
6 |
+
# Written by: Prakash R. Kota
|
7 |
+
# Location: East Greenbush, NY
|
8 |
+
#
|
9 |
+
#
|
10 |
+
# Based on: 2a_HF_linear_model_app.ipynb
|
11 |
+
# and Based on: 1a_HF_linear_model.ipynb
|
12 |
+
#
|
13 |
+
# Written on: 25 Mar 2025
|
14 |
+
# Last update: 25 Mar 2025
|
15 |
+
#+--------------------------------------------------------------------------------------------+
|
16 |
+
|
17 |
+
import os
|
18 |
+
import joblib
|
19 |
+
import yfinance as yf
|
20 |
+
import pandas as pd
|
21 |
+
import numpy as np
|
22 |
+
from datetime import datetime
|
23 |
+
from sklearn.metrics import mean_absolute_percentage_error
|
24 |
+
from sklearn.linear_model import LinearRegression
|
25 |
+
import gradio as gr
|
26 |
+
|
27 |
+
# --- Global Variables --- #
|
28 |
+
Stock = "NVDA"
|
29 |
+
model_path = f"./model/{Stock}_lr_model.pkl"
|
30 |
+
start_date = "2020-01-01"
|
31 |
+
test_start_date = "2025-01-01"
|
32 |
+
today = datetime.today().strftime('%Y-%m-%d')
|
33 |
+
|
34 |
+
# --- Load Model --- #
|
35 |
+
if not os.path.exists(model_path):
|
36 |
+
raise FileNotFoundError(f"Model not found at {model_path}. Please train and save it first.")
|
37 |
+
|
38 |
+
model = joblib.load(model_path)
|
39 |
+
|
40 |
+
def run_prediction():
|
41 |
+
# --- Download Data --- #
|
42 |
+
data = yf.download(Stock, start=start_date, end=today)[["Close"]]
|
43 |
+
data.dropna(inplace=True)
|
44 |
+
data.index = pd.to_datetime(data.index)
|
45 |
+
|
46 |
+
# --- Create X and y for prediction --- #
|
47 |
+
xactual = data[:-1]["Close"].values.reshape(-1, 1) # Today's close
|
48 |
+
ytrue = data[1:]["Close"] # Tomorrow's close (Series)
|
49 |
+
dates = data[1:].index
|
50 |
+
|
51 |
+
# Keep only test range (2025+)
|
52 |
+
mask = dates >= test_start_date
|
53 |
+
xactual = xactual[mask]
|
54 |
+
ytrue = ytrue[mask]
|
55 |
+
dates = dates[mask]
|
56 |
+
|
57 |
+
# Predict
|
58 |
+
typred = model.predict(xactual)
|
59 |
+
|
60 |
+
# --- Build DataFrame --- #
|
61 |
+
pred_df = pd.DataFrame({
|
62 |
+
"Date": dates,
|
63 |
+
"Actual Close": ytrue.values,
|
64 |
+
"Predicted Close": typred.flatten()
|
65 |
+
})
|
66 |
+
|
67 |
+
# --- Calculate Metrics --- #
|
68 |
+
pred_df["% Error"] = ((pred_df["Predicted Close"] - pred_df["Actual Close"]) / pred_df["Actual Close"]) * 100
|
69 |
+
mape = np.mean(np.abs(pred_df["% Error"]))
|
70 |
+
sape = np.std(np.abs(pred_df["% Error"]))
|
71 |
+
|
72 |
+
# Add MAPE Range per row to table
|
73 |
+
pred_df["±MAPE Range"] = pred_df["Predicted Close"].apply(
|
74 |
+
lambda x: f"${x * (1 - mape/100):.2f} to ${x * (1 + mape/100):.2f}"
|
75 |
+
)
|
76 |
+
|
77 |
+
# --- Next Day Prediction --- #
|
78 |
+
latest_close = float(data["Close"].iloc[-1])
|
79 |
+
latest_date = data.index[-1].strftime("%Y-%m-%d")
|
80 |
+
next_pred = float(model.predict(np.array([[latest_close]]))[0])
|
81 |
+
next_date = (data.index[-1] + pd.tseries.offsets.BDay(1)).strftime("%Y-%m-%d")
|
82 |
+
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
83 |
+
|
84 |
+
# Expected Ranges
|
85 |
+
mape_range = (next_pred * (1 - mape/100), next_pred * (1 + mape/100))
|
86 |
+
sape_range = (next_pred * (1 - sape/100), next_pred * (1 + sape/100))
|
87 |
+
|
88 |
+
summary = f"""
|
89 |
+
Prediction for {Stock} made at {now}:
|
90 |
+
Last available date: {latest_date}, Close = ${latest_close:.2f}
|
91 |
+
Predicted closing price for next trading day ({next_date}): ${next_pred:.2f}
|
92 |
+
Expected range (±MAPE): ${mape_range[0]:.2f} to ${mape_range[1]:.2f}
|
93 |
+
Expected range (±SAPE): ${sape_range[0]:.2f} to ${sape_range[1]:.2f}
|
94 |
+
"""
|
95 |
+
|
96 |
+
# Sort and format
|
97 |
+
pred_df = pred_df.sort_values("Date", ascending=False)
|
98 |
+
pred_df["Date"] = pred_df["Date"].dt.strftime("%Y-%m-%d")
|
99 |
+
|
100 |
+
return summary, pred_df
|
101 |
+
|
102 |
+
# --- Gradio Interface --- #
|
103 |
+
description = f"""<h3>Linear Regression Stock Prediction</h3>
|
104 |
+
<p>This app loads a trained linear regression model for <b>{Stock}</b> and predicts the next trading day's close based on the last available price.
|
105 |
+
It also shows historical prediction accuracy from 2025 onward.</p>"""
|
106 |
+
|
107 |
+
demo = gr.Interface(
|
108 |
+
fn=run_prediction,
|
109 |
+
inputs=[],
|
110 |
+
outputs=[
|
111 |
+
gr.Textbox(label="Prediction Summary", lines=6),
|
112 |
+
gr.Dataframe(label="Prediction Table (2025+)", wrap=True)
|
113 |
+
],
|
114 |
+
title="Stock Prediction using Linear Regression",
|
115 |
+
description=description,
|
116 |
+
allow_flagging="never"
|
117 |
+
)
|
118 |
+
|
119 |
+
if __name__ == "__main__":
|
120 |
+
demo.launch()
|
model/NVDA_lr_model.pkl
ADDED
Binary file (575 Bytes). View file
|
|
requirements.txt
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
gradio
|
2 |
+
scikit-learn
|
3 |
+
yfinance
|
4 |
+
pandas
|
5 |
+
numpy
|
6 |
+
joblib
|