import streamlit as st import yfinance as yf import pandas as pd import plotly.graph_objects as go from plotly.subplots import make_subplots import datetime as dt # Page config st.set_page_config( page_title="Stock Analysis Dashboard", page_icon="📈", layout="wide" ) # Sidebar st.sidebar.header("Settings") ticker = st.sidebar.text_input("Ticker Symbol", "AAPL").upper() start = st.sidebar.date_input("Start Date", dt.date.today() - dt.timedelta(days=365)) end = st.sidebar.date_input("End Date", dt.date.today()) # Cache data @st.cache_data def fetch_data(ticker, start, end): return yf.download(ticker, start=start, end=end) # Main st.title("📈 Stock Analysis Dashboard") st.subheader(f"{ticker} ({start} – {end})") # Fetch data = fetch_data(ticker, start, end) if data.empty: st.error("No data found. Check ticker or date range.") st.stop() # KPIs latest_close = data["Adj Close"].iloc[-1] prev_close = data["Adj Close"].iloc[-2] change = latest_close - prev_close pct_change = (change / prev_close) * 100 col1, col2, col3, col4 = st.columns(4) col1.metric("Latest Close", f"${latest_close:,.2f}", f"{pct_change:+.2f}%") col2.metric("Volume", f"{data['Volume'].iloc[-1]:,.0f}") col3.metric("High", f"${data['High'].max():,.2f}") col4.metric("Low", f"${data['Low'].min():,.2f}") # Chart fig = make_subplots( rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.03, subplot_titles=("Price & Volume", "Volume"), row_heights=[0.7, 0.3] ) fig.add_trace( go.Candlestick( x=data.index, open=data["Open"], high=data["High"], low=data["Low"], close=data["Close"], name="Candle" ), row=1, col=1 ) fig.add_trace( go.Bar( x=data.index, y=data["Volume"], name="Volume", marker_color="#636EFA" ), row=2, col=1 ) fig.update_layout( title=f"{ticker} Price & Volume", xaxis_rangeslider_visible=False, template="plotly_dark", height=600, showlegend=False ) st.plotly_chart(fig, use_container_width=True) # Moving averages ma_window = st.sidebar.slider("Moving Average Window", 5, 200, 20) data[f"MA{ma_window}"] = data["Close"].rolling(ma_window).mean() st.subheader("Moving Average") ma_fig = go.Figure() ma_fig.add_trace(go.Scatter(x=data.index, y=data["Close"], name="Close")) ma_fig.add_trace(go.Scatter(x=data.index, y=data[f"MA{ma_window}"], name=f"MA{ma_window}")) ma_fig.update_layout(title=f"{ticker} Close vs MA{ma_window}", height=400) st.plotly_chart(ma_fig, use_container_width=True) # Download @st.cache_data def convert_df(df): return df.to_csv().encode("utf-8") csv = convert_df(data) st.sidebar.download_button( label="Download CSV", data=csv, file_name=f"{ticker}_{start}_{end}.csv", mime="text/csv" )