Upload main.py
Browse filesupdating the file
main.py
ADDED
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import yfinance as yf
|
3 |
+
import plotly.graph_objects as go
|
4 |
+
from prophet import Prophet
|
5 |
+
import pandas as pd
|
6 |
+
import matplotlib.pyplot as plt
|
7 |
+
from statsmodels.tsa.seasonal import seasonal_decompose
|
8 |
+
|
9 |
+
from statsmodels.graphics.gofplots import qqplot
|
10 |
+
|
11 |
+
# Set Streamlit options
|
12 |
+
st.set_page_config(layout="wide") # Use wide page layout
|
13 |
+
st.set_option('deprecation.showPyplotGlobalUse', False)
|
14 |
+
|
15 |
+
|
16 |
+
# Header section with enhanced aesthetics
|
17 |
+
def display_header():
|
18 |
+
st.sidebar.title("Navigation")
|
19 |
+
st.sidebar.info("""
|
20 |
+
This application is designed to provide users with financial insights and predictive analysis
|
21 |
+
on various stocks using real-time data from Yahoo Finance. Created by Gokul Palanisamy.
|
22 |
+
""")
|
23 |
+
st.sidebar.title("About Us")
|
24 |
+
st.sidebar.info("""
|
25 |
+
Developed by Gokul Palanisamy, this tool helps users make informed investment decisions by
|
26 |
+
analyzing historical data and predicting future stock trends.
|
27 |
+
""")
|
28 |
+
st.sidebar.title("Contact Us")
|
29 |
+
st.sidebar.info("""
|
30 |
+
Email: [gokulp@bu.edu](mailto:gokulp@bu.edu)
|
31 |
+
Phone: +1 (857) 832-0441
|
32 |
+
More Information: [Gokul Palanisamy](https://www.linkedin.com/in/gokulp/)
|
33 |
+
""")
|
34 |
+
|
35 |
+
|
36 |
+
display_header()
|
37 |
+
|
38 |
+
# Input widgets for stock symbols and settings
|
39 |
+
st.markdown("## StocX AI")
|
40 |
+
col1, col2, col3 = st.columns(3)
|
41 |
+
with col1:
|
42 |
+
stock1 = st.text_input('Enter Stock Ticker Symbol 1', value='', key='stock1_input')
|
43 |
+
with col2:
|
44 |
+
stock2 = st.text_input('Enter Stock Ticker Symbol 2', value='', key='stock2_input')
|
45 |
+
with col3:
|
46 |
+
daysago = st.text_input('Select Time Frame in Days (write "max" for maximum time)', value='1y', key='daysago_input')
|
47 |
+
forecast_out = st.slider('Predicted Days Ahead', 1, 180, 30)
|
48 |
+
|
49 |
+
|
50 |
+
# Fetch and display stock data
|
51 |
+
def fetch_data(ticker, period):
|
52 |
+
return yf.Ticker(ticker).history(period=period)
|
53 |
+
|
54 |
+
|
55 |
+
data1, data2 = None, None
|
56 |
+
if stock1:
|
57 |
+
data1 = fetch_data(stock1, daysago)
|
58 |
+
st.write(f'### {stock1} Stock Data')
|
59 |
+
st.write(data1)
|
60 |
+
|
61 |
+
if stock2:
|
62 |
+
data2 = fetch_data(stock2, daysago)
|
63 |
+
st.write(f'### {stock2} Stock Data')
|
64 |
+
st.write(data2)
|
65 |
+
|
66 |
+
|
67 |
+
# Function to analyze and compare stocks
|
68 |
+
def compare_stocks(stock1, data1, stock2, data2):
|
69 |
+
if data1 is not None and data2 is not None:
|
70 |
+
# Calculate percentage change for each stock
|
71 |
+
pct_change1 = (data1['Close'].iloc[-1] - data1['Close'].iloc[0]) / data1['Close'].iloc[0] * 100
|
72 |
+
pct_change2 = (data2['Close'].iloc[-1] - data2['Close'].iloc[0]) / data2['Close'].iloc[0] * 100
|
73 |
+
|
74 |
+
better_stock = stock1 if pct_change1 > pct_change2 else stock2
|
75 |
+
reason = f"{better_stock} had a higher percentage change ({max(pct_change1, pct_change2):.2f}%) over the period."
|
76 |
+
|
77 |
+
st.write("## Stock Performance Comparison")
|
78 |
+
st.write(f"**{stock1}** percentage change: {pct_change1:.2f}%")
|
79 |
+
st.write(f"**{stock2}** percentage change: {pct_change2:.2f}%")
|
80 |
+
st.write(f"**Better Performing Stock:** {better_stock}")
|
81 |
+
st.write(f"**Reason:** {reason}")
|
82 |
+
|
83 |
+
|
84 |
+
if stock1 and stock2 and data1 is not None and data2 is not None:
|
85 |
+
compare_stocks(stock1, data1, stock2, data2)
|
86 |
+
|
87 |
+
|
88 |
+
# Comprehensive analysis functions
|
89 |
+
def perform_analysis(stock, data):
|
90 |
+
if data is not None and not data.empty:
|
91 |
+
st.write(f"### {stock} Detailed Analysis")
|
92 |
+
|
93 |
+
# Time Series Decomposition
|
94 |
+
st.write(f"#### Time Series Decomposition")
|
95 |
+
decomposition = seasonal_decompose(data['Close'], period=30, model='additive')
|
96 |
+
fig, (ax1, ax2, ax3, ax4) = plt.subplots(4, 1, figsize=(10, 8))
|
97 |
+
decomposition.observed.plot(ax=ax1, title='Observed')
|
98 |
+
decomposition.trend.plot(ax=ax2, title='Trend')
|
99 |
+
decomposition.seasonal.plot(ax=ax3, title='Seasonal')
|
100 |
+
decomposition.resid.plot(ax=ax4, title='Residual')
|
101 |
+
plt.tight_layout()
|
102 |
+
st.pyplot()
|
103 |
+
|
104 |
+
# Prophet Prediction
|
105 |
+
st.write(f"#### Prophet Forecast")
|
106 |
+
df_prophet = pd.DataFrame(data={'ds': data.index, 'y': data['Close']})
|
107 |
+
df_prophet['ds'] = pd.to_datetime(df_prophet['ds']).dt.tz_localize(None) # Make timezone naive
|
108 |
+
model = Prophet()
|
109 |
+
model.fit(df_prophet)
|
110 |
+
future = model.make_future_dataframe(periods=forecast_out)
|
111 |
+
forecast = model.predict(future)
|
112 |
+
fig = plot_prophet_forecast(model, forecast)
|
113 |
+
st.plotly_chart(fig)
|
114 |
+
|
115 |
+
|
116 |
+
# Helper function for Plotly forecast visualization
|
117 |
+
def plot_prophet_forecast(model, forecast):
|
118 |
+
fig = go.Figure()
|
119 |
+
fig.add_trace(go.Scatter(x=model.history['ds'], y=model.history['y'], mode='lines', name='Actual'))
|
120 |
+
fig.add_trace(go.Scatter(x=forecast['ds'], y=forecast['yhat'], mode='lines+markers', name='Forecast'))
|
121 |
+
fig.add_trace(go.Scatter(x=forecast['ds'], y=forecast['yhat_upper'], fill=None, mode='lines',
|
122 |
+
line=dict(color='gray', dash='dash'), name='Upper Confidence Interval'))
|
123 |
+
fig.add_trace(go.Scatter(x=forecast['ds'], y=forecast['yhat_lower'], fill='tonexty', mode='lines',
|
124 |
+
line=dict(color='gray', dash='dash'), name='Lower Confidence Interval'))
|
125 |
+
fig.update_layout(title='Prophet Forecast and Confidence Intervals', xaxis_title='Date', yaxis_title='Values',
|
126 |
+
hovermode='x')
|
127 |
+
return fig
|
128 |
+
|
129 |
+
|
130 |
+
# Call analysis functions if data is available
|
131 |
+
if stock1 and data1 is not None:
|
132 |
+
perform_analysis(stock1, data1)
|
133 |
+
if stock2 and data2 is not None:
|
134 |
+
perform_analysis(stock2, data2)
|