Create an app for stock analysis with mock data. Generate mock daily price data for 5 tech stocks over the past year with standard fields (Open, Close, etc). Features: - Stock selector dropdown - Price trend charts - Basic stats (mean, volatility) - Moving averages - Volume analysis - Stock comparison Interactive elements: - Date range picker - Technical indicators - Chart type toggle Focus on clean visualization of realistic mock data.
To upload files, please first save the app
import streamlit as st
import pandas as pd
import numpy as np
import plotly.graph_objects as go
import plotly.express as px
from plotly.subplots import make_subplots
from datetime import datetime, timedelta
from data_generator import generate_stock_data
from utils import calculate_moving_averages, calculate_volatility, calculate_returns
st.set_page_config(page_title="Stock Analysis Dashboard", layout="wide")
# Load mock data
@st.cache_data
def load_data():
return generate_stock_data()
df = load_data()
st.title("📈 Stock Analysis Dashboard")
st.markdown("Interactive analysis of tech stock performance with technical indicators")
# Sidebar controls
st.sidebar.header("Configuration")
# Stock selector
stocks = df['Symbol'].unique()
selected_stock = st.sidebar.selectbox("Select Stock", stocks, index=0)
# Date range picker
min_date = df['Date'].min()
max_date = df['Date'].max()
start_date = st.sidebar.date_input("Start Date", min_date, min_value=min_date, max_value=max_date)
end_date = st.sidebar.date_input("End Date", max_date, min_value=min_date, max_value=max_date)
# Chart type
chart_type = st.sidebar.selectbox("Chart Type", ["Candlestick", "Line Chart", "OHLC"])
# Technical indicators
st.sidebar.subheader("Technical Indicators")
show_ma = st.sidebar.checkbox("Moving Averages", True)
ma_periods = st.sidebar.multiselect("MA Periods", [5, 10, 20, 50, 200], default=[20, 50])
show_volume = st.sidebar.checkbox("Volume", True)
show_volatility = st.sidebar.checkbox("Volatility Bands", False)
# Filter data
filtered_df = df[
(df['Symbol'] == selected_stock) &
(df['Date'] >= pd.to_datetime(start_date)) &
(df['Date'] <= pd.to_datetime(end_date))
].copy()
# Calculate technical indicators
if show_ma:
filtered_df = calculate_moving_averages(filtered_df, ma_periods)
if show_volatility:
filtered_df['Volatility'] = calculate_volatility(filtered_df['Close'])
filtered_df['Upper_Band'] = filtered_df['Close'] + 2 * filtered_df['Volatility']
filtered_df['Lower_Band'] = filtered_df['Close'] - 2 * filtered_df['Volatility']
# Main dashboard
col1, col2, col3, col4 = st.columns(4)
with col1:
current_price = filtered_df['Close'].iloc[-1] if len(filtered_df) > 0 else 0
st.metric("Current Price", f"${current_price:.2f}")
with col2:
if len(filtered_df) > 1:
price_change = filtered_df['Close'].iloc[-1] - filtered_df['Close'].iloc[-2]
pct_change = (price_change / filtered_df['Close'].iloc[-2]) * 100
st.metric("Daily Change", f"${price_change:.2f}", f"{pct_change:.2f}%")
with col3:
volume = filtered_df['Volume'].iloc[-1] if len(filtered_df) > 0 else 0
st.metric("Volume", f"{volume:,.0f}")
with col4:
volatility = filtered_df['Close'].std() if len(filtered_df) > 0 else 0
st.metric("Volatility (σ)", f"{volatility:.2f}")
# Price chart
st.subheader(f"{selected_stock} Price Chart")
if len(filtered_df) > 0:
if show_volume:
fig = make_subplots(
rows=2, cols=1,
subplot_titles=(f'{selected_stock} Price', 'Volume'),
row_width=[0.7, 0.3],
vertical_spacing=0.08,
specs=[[{"secondary_y": False}], [{"secondary_y": False}]]
)
else:
fig = go.Figure()
# Price chart based on type
if chart_type == "Candlestick":
candlestick = go.Candlestick(
x=filtered_df['Date'],
open=filtered_df['Open'],
high=filtered_df['High'],
low=filtered_df['Low'],
close=filtered_df['Close'],
name=selected_stock
)
if show_volume:
fig.add_trace(candlestick, row=1, col=1)
else:
fig.add_trace(candlestick)
elif chart_type == "Line Chart":
line = go.Scatter(
x=filtered_df['Date'],
y=filtered_df['Close'],
mode='lines',
name=f'{selected_stock} Close',
line=dict(width=2)
)
if show_volume:
fig.add_trace(line, row=1, col=1)
else:
fig.add_trace(line)
else: # OHLC
ohlc = go.Ohlc(
x=filtered_df['Date'],
open=filtered_df['Open'],
high=filtered_df['High'],
low=filtered_df['Low'],
close=filtered_df['Close'],
name=selected_stock
)
if show_volume:
fig.add_trace(ohlc, row=1, col=1)
else:
fig.add_trace(ohlc)
# Add moving averages
if show_ma:
colors = ['orange', 'red', 'blue', 'green', 'purple']
for i, period in enumerate(ma_periods):
ma_col = f'MA_{period}'
if ma_col in filtered_df.columns:
ma_trace = go.Scatter(
x=filtered_df['Date'],
y=filtered_df[ma_col],
mode='lines',
name=f'MA{period}',
line=dict(color=colors[i % len(colors)], width=1)
)
if show_volume:
fig.add_trace(ma_trace, row=1, col=1)
else:
fig.add_trace(ma_trace)
# Add volatility bands
if show_volatility and 'Upper_Band' in filtered_df.columns:
upper_band = go.Scatter(
x=filtered_df['Date'],
y=filtered_df['Upper_Band'],
mode='lines',
name='Upper Band',
line=dict(color='gray', dash='dash'),
opacity=0.5
)
lower_band = go.Scatter(
x=filtered_df['Date'],
y=filtered_df['Lower_Band'],
mode='lines',
name='Lower Band',
line=dict(color='gray', dash='dash'),
fill='tonexty',
opacity=0.3
)
if show_volume:
fig.add_trace(upper_band, row=1, col=1)
fig.add_trace(lower_band, row=1, col=1)
else:
fig.add_trace(upper_band)
fig.add_trace(lower_band)
# Add volume chart
if show_volume:
volume_trace = go.Bar(
x=filtered_df['Date'],
y=filtered_df['Volume'],
name='Volume',
marker_color='lightblue',
opacity=0.7
)
fig.add_trace(volume_trace, row=2, col=1)
# Update layout
fig.update_layout(
height=600 if show_volume else 500,
showlegend=True,
xaxis_rangeslider_visible=False,
title=f"{selected_stock} Stock Analysis"
)
if show_volume:
fig.update_xaxes(title_text="Date", row=2, col=1)
fig.update_yaxes(title_text="Price ($)", row=1, col=1)
fig.update_yaxes(title_text="Volume", row=2, col=1)
st.plotly_chart(fig, use_container_width=True)
# Statistics section
col1, col2 = st.columns(2)
with col1:
st.subheader("📊 Basic Statistics")
if len(filtered_df) > 0:
stats_data = {
"Metric": ["Mean Close", "Median Close", "Standard Deviation", "Min Price", "Max Price", "Price Range"],
"Value": [
f"${filtered_df['Close'].mean():.2f}",
f"${filtered_df['Close'].median():.2f}",
f"${filtered_df['Close'].std():.2f}",
f"${filtered_df['Close'].min():.2f}",
f"${filtered_df['Close'].max():.2f}",
f"${filtered_df['Close'].max() - filtered_df['Close'].min():.2f}"
]
}
stats_df = pd.DataFrame(stats_data)
st.table(stats_df)
with col2:
st.subheader("📈 Returns Analysis")
if len(filtered_df) > 1:
returns = calculate_returns(filtered_df['Close'])
returns_data = {
"Period": ["Daily Return", "Weekly Return", "Monthly Return", "Total Return"],
"Value": [
f"{returns['daily']:.2f}%",
f"{returns['weekly']:.2f}%",
f"{returns['monthly']:.2f}%",
f"{returns['total']:.2f}%"
]
}
returns_df = pd.DataFrame(returns_data)
st.table(returns_df)
# Stock comparison section
st.subheader("🔄 Stock Comparison")
comparison_stocks = st.multiselect(
"Select stocks to compare",
[stock for stock in stocks if stock != selected_stock],
default=[]
)
if comparison_stocks:
comparison_df = df[
(df['Symbol'].isin([selected_stock] + comparison_stocks)) &
(df['Date'] >= pd.to_datetime(start_date)) &
(df['Date'] <= pd.to_datetime(end_date))
].copy()
# Normalize prices for comparison
comparison_normalized = []
for stock in [selected_stock] + comparison_stocks:
stock_data = comparison_df[comparison_df['Symbol'] == stock].copy()
if len(stock_data) > 0:
stock_data['Normalized'] = (stock_data['Close'] / stock_data['Close'].iloc[0]) * 100
stock_data['Stock'] = stock
comparison_normalized.append(stock_data)
if comparison_normalized:
normalized_df = pd.concat(comparison_normalized)
fig_comparison = px.line(
normalized_df,
x='Date',
y='Normalized',
color='Stock',
title="Normalized Price Comparison (Base = 100)",
labels={'Normalized': 'Normalized Price', 'Date': 'Date'}
)
fig_comparison.update_layout(height=400)
st.plotly_chart(fig_comparison, use_container_width=True)
# Raw data section
with st.expander("📋 Raw Data"):
st.dataframe(filtered_df.sort_values('Date', ascending=False))
else:
st.warning("No data available for the selected date range.")
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?