|
import streamlit as st
|
|
import pandas as pd
|
|
import numpy as np
|
|
import yfinance as yf
|
|
from datetime import date, timedelta
|
|
import matplotlib.pyplot as plt
|
|
from pmdarima.arima import auto_arima
|
|
|
|
|
|
st.markdown("""
|
|
<style>
|
|
.main {
|
|
background-color: #f5f5f5;
|
|
padding: 20px;
|
|
}
|
|
.sidebar .sidebar-content {
|
|
background-color: #fafafa;
|
|
}
|
|
.stButton>button {
|
|
background-color: #2e7d32;
|
|
color: white;
|
|
border-radius: 5px;
|
|
font-weight: bold;
|
|
}
|
|
.stButton>button:hover {
|
|
background-color: #388e3c;
|
|
}
|
|
h1, h2, h3 {
|
|
color: #333;
|
|
}
|
|
.stDataFrame {
|
|
background-color: #ffffff;
|
|
}
|
|
.stTable {
|
|
color: #333;
|
|
}
|
|
.stPlotlyChart {
|
|
background-color: #ffffff;
|
|
}
|
|
</style>
|
|
""", unsafe_allow_html=True)
|
|
|
|
|
|
st.title("π Stock Market Forecasting")
|
|
|
|
|
|
st.sidebar.header("User Input")
|
|
|
|
|
|
ticker = st.sidebar.text_input("Enter stock ticker:", value="GOOGL")
|
|
end_date = st.sidebar.date_input("End Date", value=date.today())
|
|
start_date = st.sidebar.date_input("Start Date", value=date.today() - timedelta(days=365))
|
|
forecast_days = st.sidebar.slider("Forecast days", min_value=10, max_value=30, value=15)
|
|
|
|
|
|
if start_date > end_date:
|
|
st.sidebar.error("β Start date cannot be later than end date.")
|
|
st.stop()
|
|
|
|
|
|
feature_select = st.sidebar.multiselect(
|
|
label="Select Stock Features to Forecast",
|
|
options=["Close", "High", "Low", "Open"],
|
|
default=["Close"]
|
|
)
|
|
|
|
|
|
feature_descriptions = {
|
|
"Close": "The closing price of the stock at the end of the trading day.",
|
|
"High": "The highest price at which the stock traded during the day.",
|
|
"Low": "The lowest price at which the stock traded during the day.",
|
|
"Open": "The price at which the stock opened at the beginning of the trading day."
|
|
}
|
|
|
|
|
|
if st.sidebar.button("Fetch Data"):
|
|
st.subheader(f"Stock Data for {ticker.upper()} ({start_date} to {end_date})")
|
|
|
|
try:
|
|
|
|
df = yf.download(ticker, start=start_date, end=end_date, progress=False)
|
|
|
|
|
|
if df.empty:
|
|
st.error("β No data found for the selected ticker or date range.")
|
|
st.stop()
|
|
|
|
st.success("β
Data fetched successfully!")
|
|
|
|
|
|
df.insert(0, "Date", df.index)
|
|
df.reset_index(drop=True, inplace=True)
|
|
|
|
st.dataframe(df.head())
|
|
|
|
|
|
combined_forecast_df = pd.DataFrame()
|
|
|
|
|
|
for feature in feature_select:
|
|
st.write(f"### π Forecasting: {feature}")
|
|
st.write(feature_descriptions[feature])
|
|
|
|
|
|
series = df[feature].dropna()
|
|
|
|
|
|
model = auto_arima(series,
|
|
start_p=1, start_q=1,
|
|
max_p=2, max_q=2,
|
|
m=12,
|
|
start_P=0,
|
|
seasonal=True,
|
|
d=1, D=1,
|
|
trace=True,
|
|
error_action='ignore',
|
|
suppress_warnings=True)
|
|
|
|
|
|
forecast = model.predict(n_periods=forecast_days)
|
|
future_dates = pd.date_range(start=df["Date"].iloc[-1] + timedelta(days=1), periods=forecast_days)
|
|
|
|
|
|
forecast_df = pd.DataFrame({
|
|
"Date": future_dates,
|
|
feature: forecast
|
|
})
|
|
|
|
|
|
combined_forecast_df = pd.merge(combined_forecast_df, forecast_df, on="Date", how="outer") if not combined_forecast_df.empty else forecast_df
|
|
|
|
|
|
fig, ax = plt.subplots(figsize=(10, 4))
|
|
ax.plot(df["Date"], series, label="Historical", color='blue')
|
|
ax.plot(forecast_df["Date"], forecast_df[feature], label="Forecast", color='orange')
|
|
ax.set_title(f"{feature} Forecast for {ticker.upper()}")
|
|
ax.set_xlabel("Date")
|
|
ax.set_ylabel(feature)
|
|
ax.legend()
|
|
|
|
|
|
st.pyplot(fig)
|
|
|
|
|
|
st.subheader("Combined Forecasted Data")
|
|
st.dataframe(combined_forecast_df.head())
|
|
|
|
except Exception as e:
|
|
st.error(f"β An error occurred: {str(e)}")
|
|
st.stop()
|
|
|