import streamlit as st import yfinance as yf import plotly.graph_objects as go from prophet import Prophet import pandas as pd import matplotlib.pyplot as plt from statsmodels.tsa.seasonal import seasonal_decompose from statsmodels.graphics.gofplots import qqplot # Set Streamlit options st.set_page_config(layout="wide") # Use wide page layout st.set_option('deprecation.showPyplotGlobalUse', False) # Header section with enhanced aesthetics def display_header(): st.sidebar.title("Navigation") st.sidebar.info(""" This application is designed to provide users with financial insights and predictive analysis on various stocks using real-time data from Yahoo Finance. Created by Gokul Palanisamy. """) st.sidebar.title("About Us") st.sidebar.info(""" Developed by Gokul Palanisamy, this tool helps users make informed investment decisions by analyzing historical data and predicting future stock trends. """) st.sidebar.title("Contact Us") st.sidebar.info(""" Email: [gokulp@bu.edu](mailto:gokulp@bu.edu) Phone: +1 (857) 832-0441 More Information: [Gokul Palanisamy](https://www.linkedin.com/in/gokulp/) """) display_header() # Input widgets for stock symbols and settings st.markdown("## StocX AI") col1, col2, col3 = st.columns(3) with col1: stock1 = st.text_input('Enter Stock Ticker Symbol 1', value='', key='stock1_input') with col2: stock2 = st.text_input('Enter Stock Ticker Symbol 2', value='', key='stock2_input') with col3: daysago = st.text_input('Select Time Frame in Days (write "max" for maximum time)', value='1y', key='daysago_input') forecast_out = st.slider('Predicted Days Ahead', 1, 180, 30) # Fetch and display stock data def fetch_data(ticker, period): return yf.Ticker(ticker).history(period=period) data1, data2 = None, None if stock1: data1 = fetch_data(stock1, daysago) st.write(f'### {stock1} Stock Data') st.write(data1) if stock2: data2 = fetch_data(stock2, daysago) st.write(f'### {stock2} Stock Data') st.write(data2) # Function to analyze and compare stocks def compare_stocks(stock1, data1, stock2, data2): if data1 is not None and data2 is not None: # Calculate percentage change for each stock pct_change1 = (data1['Close'].iloc[-1] - data1['Close'].iloc[0]) / data1['Close'].iloc[0] * 100 pct_change2 = (data2['Close'].iloc[-1] - data2['Close'].iloc[0]) / data2['Close'].iloc[0] * 100 better_stock = stock1 if pct_change1 > pct_change2 else stock2 reason = f"{better_stock} had a higher percentage change ({max(pct_change1, pct_change2):.2f}%) over the period." st.write("## Stock Performance Comparison") st.write(f"**{stock1}** percentage change: {pct_change1:.2f}%") st.write(f"**{stock2}** percentage change: {pct_change2:.2f}%") st.write(f"**Better Performing Stock:** {better_stock}") st.write(f"**Reason:** {reason}") if stock1 and stock2 and data1 is not None and data2 is not None: compare_stocks(stock1, data1, stock2, data2) # Comprehensive analysis functions def perform_analysis(stock, data): if data is not None and not data.empty: st.write(f"### {stock} Detailed Analysis") # Time Series Decomposition st.write(f"#### Time Series Decomposition") decomposition = seasonal_decompose(data['Close'], period=30, model='additive') fig, (ax1, ax2, ax3, ax4) = plt.subplots(4, 1, figsize=(10, 8)) decomposition.observed.plot(ax=ax1, title='Observed') decomposition.trend.plot(ax=ax2, title='Trend') decomposition.seasonal.plot(ax=ax3, title='Seasonal') decomposition.resid.plot(ax=ax4, title='Residual') plt.tight_layout() st.pyplot() # Prophet Prediction st.write(f"#### Prophet Forecast") df_prophet = pd.DataFrame(data={'ds': data.index, 'y': data['Close']}) df_prophet['ds'] = pd.to_datetime(df_prophet['ds']).dt.tz_localize(None) # Make timezone naive model = Prophet() model.fit(df_prophet) future = model.make_future_dataframe(periods=forecast_out) forecast = model.predict(future) fig = plot_prophet_forecast(model, forecast) st.plotly_chart(fig) # Helper function for Plotly forecast visualization def plot_prophet_forecast(model, forecast): fig = go.Figure() fig.add_trace(go.Scatter(x=model.history['ds'], y=model.history['y'], mode='lines', name='Actual')) fig.add_trace(go.Scatter(x=forecast['ds'], y=forecast['yhat'], mode='lines+markers', name='Forecast')) fig.add_trace(go.Scatter(x=forecast['ds'], y=forecast['yhat_upper'], fill=None, mode='lines', line=dict(color='gray', dash='dash'), name='Upper Confidence Interval')) fig.add_trace(go.Scatter(x=forecast['ds'], y=forecast['yhat_lower'], fill='tonexty', mode='lines', line=dict(color='gray', dash='dash'), name='Lower Confidence Interval')) fig.update_layout(title='Prophet Forecast and Confidence Intervals', xaxis_title='Date', yaxis_title='Values', hovermode='x') return fig # Call analysis functions if data is available if stock1 and data1 is not None: perform_analysis(stock1, data1) if stock2 and data2 is not None: perform_analysis(stock2, data2)