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_mock_stock_data
# Configure page
st.set_page_config(page_title="Stock Analysis Dashboard", layout="wide")
# Initialize data
@st.cache_data
def load_data():
return generate_mock_stock_data()
df = load_data()
# Title
st.title("📈 Stock Analysis Dashboard")
st.markdown("Analyze tech stock performance with interactive charts and technical indicators")
# Sidebar controls
st.sidebar.header("📊 Analysis Controls")
# Stock selector
stocks = df['symbol'].unique()
selected_stock = st.sidebar.selectbox("Select Stock", stocks, index=0)
# Date range
min_date = df['date'].min()
max_date = df['date'].max()
date_range = st.sidebar.date_input(
"Date Range",
value=(min_date, max_date),
min_value=min_date,
max_value=max_date
)
# Chart type
chart_type = st.sidebar.selectbox(
"Chart Type",
["Candlestick", "Line", "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, 100],
default=[20, 50]
)
show_bollinger = st.sidebar.checkbox("Bollinger Bands")
show_volume = st.sidebar.checkbox("Volume", True)
# Stock comparison
st.sidebar.subheader("Stock Comparison")
comparison_stocks = st.sidebar.multiselect(
"Compare with",
[s for s in stocks if s != selected_stock],
default=[]
)
# Filter data
if len(date_range) == 2:
start_date, end_date = date_range
filtered_df = df[
(df['symbol'] == selected_stock) &
(df['date'] >= pd.to_datetime(start_date)) &
(df['date'] <= pd.to_datetime(end_date))
].copy()
else:
filtered_df = df[df['symbol'] == selected_stock].copy()
# Calculate technical indicators
def calculate_moving_average(data, period):
return data['close'].rolling(window=period).mean()
def calculate_bollinger_bands(data, period=20, std_dev=2):
sma = data['close'].rolling(window=period).mean()
std = data['close'].rolling(window=period).std()
upper_band = sma + (std * std_dev)
lower_band = sma - (std * std_dev)
return upper_band, lower_band
# Add technical indicators to data
for period in ma_periods:
filtered_df[f'MA_{period}'] = calculate_moving_average(filtered_df, period)
if show_bollinger:
filtered_df['BB_upper'], filtered_df['BB_lower'] = calculate_bollinger_bands(filtered_df)
# Main content
col1, col2 = st.columns([3, 1])
with col1:
# Price chart
fig = make_subplots(
rows=2 if show_volume else 1,
cols=1,
shared_xaxes=True,
vertical_spacing=0.1,
subplot_titles=[f"{selected_stock} Price Chart", "Volume"] if show_volume else [f"{selected_stock} Price Chart"],
row_heights=[0.7, 0.3] if show_volume else [1.0]
)
# Price chart
if chart_type == "Candlestick":
fig.add_trace(
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
),
row=1, col=1
)
elif chart_type == "Line":
fig.add_trace(
go.Scatter(
x=filtered_df['date'],
y=filtered_df['close'],
mode='lines',
name=f"{selected_stock} Close",
line=dict(width=2)
),
row=1, col=1
)
else: # OHLC
fig.add_trace(
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
),
row=1, col=1
)
# Add moving averages
if show_ma:
colors = ['orange', 'purple', 'green', 'red', 'blue']
for i, period in enumerate(ma_periods):
fig.add_trace(
go.Scatter(
x=filtered_df['date'],
y=filtered_df[f'MA_{period}'],
mode='lines',
name=f'MA {period}',
line=dict(color=colors[i % len(colors)], width=1)
),
row=1, col=1
)
# Add Bollinger Bands
if show_bollinger:
fig.add_trace(
go.Scatter(
x=filtered_df['date'],
y=filtered_df['BB_upper'],
mode='lines',
name='BB Upper',
line=dict(color='gray', width=1, dash='dash')
),
row=1, col=1
)
fig.add_trace(
go.Scatter(
x=filtered_df['date'],
y=filtered_df['BB_lower'],
mode='lines',
name='BB Lower',
line=dict(color='gray', width=1, dash='dash'),
fill='tonexty',
fillcolor='rgba(128,128,128,0.1)'
),
row=1, col=1
)
# Add volume chart
if show_volume:
colors = ['red' if close < open else 'green' for close, open in zip(filtered_df['close'], filtered_df['open'])]
fig.add_trace(
go.Bar(
x=filtered_df['date'],
y=filtered_df['volume'],
name='Volume',
marker_color=colors
),
row=2, col=1
)
fig.update_layout(
height=600 if show_volume else 500,
xaxis_rangeslider_visible=False,
showlegend=True
)
st.plotly_chart(fig, use_container_width=True)
with col2:
# Stock statistics
st.subheader("📊 Statistics")
current_price = filtered_df['close'].iloc[-1]
price_change = current_price - filtered_df['close'].iloc[-2] if len(filtered_df) > 1 else 0
price_change_pct = (price_change / filtered_df['close'].iloc[-2] * 100) if len(filtered_df) > 1 else 0
st.metric(
"Current Price",
f"${current_price:.2f}",
f"{price_change:+.2f} ({price_change_pct:+.1f}%)"
)
st.metric("52W High", f"${filtered_df['high'].max():.2f}")
st.metric("52W Low", f"${filtered_df['low'].min():.2f}")
# Calculate additional stats
returns = filtered_df['close'].pct_change().dropna()
volatility = returns.std() * np.sqrt(252) * 100 # Annualized volatility
st.metric("Volatility (Annual)", f"{volatility:.1f}%")
st.metric("Avg Volume", f"{filtered_df['volume'].mean():,.0f}")
# Price distribution
st.subheader("Price Distribution")
fig_hist = px.histogram(
filtered_df,
x='close',
nbins=20,
title="Price Distribution"
)
fig_hist.update_layout(height=250, showlegend=False)
st.plotly_chart(fig_hist, use_container_width=True)
# Stock comparison section
if comparison_stocks:
st.subheader("📊 Stock Comparison")
# Get comparison data
comparison_data = []
for stock in [selected_stock] + comparison_stocks:
stock_data = df[
(df['symbol'] == stock) &
(df['date'] >= pd.to_datetime(date_range[0])) &
(df['date'] <= pd.to_datetime(date_range[1]))
].copy()
# Normalize prices to start at 100
stock_data['normalized_price'] = (stock_data['close'] / stock_data['close'].iloc[0]) * 100
stock_data['stock'] = stock
comparison_data.append(stock_data[['date', 'normalized_price', 'stock']])
comparison_df = pd.concat(comparison_data)
# Create comparison chart
fig_comparison = px.line(
comparison_df,
x='date',
y='normalized_price',
color='stock',
title="Normalized Price Comparison (Base = 100)",
labels={'normalized_price': 'Normalized Price', 'date': 'Date'}
)
fig_comparison.update_layout(height=400)
st.plotly_chart(fig_comparison, use_container_width=True)
# Performance table
st.subheader("Performance Summary")
perf_data = []
for stock in [selected_stock] + comparison_stocks:
stock_data = df[
(df['symbol'] == stock) &
(df['date'] >= pd.to_datetime(date_range[0])) &
(df['date'] <= pd.to_datetime(date_range[1]))
]
if len(stock_data) > 1:
total_return = ((stock_data['close'].iloc[-1] / stock_data['close'].iloc[0]) - 1) * 100
returns = stock_data['close'].pct_change().dropna()
volatility = returns.std() * np.sqrt(252) * 100
perf_data.append({
'Stock': stock,
'Total Return (%)': f"{total_return:.1f}%",
'Volatility (%)': f"{volatility:.1f}%",
'Max Price': f"${stock_data['high'].max():.2f}",
'Min Price': f"${stock_data['low'].min():.2f}"
})
perf_df = pd.DataFrame(perf_data)
st.table(perf_df)
# Volume analysis
st.subheader("📊 Volume Analysis")
col1, col2 = st.columns(2)
with col1:
# Volume trend
fig_volume = px.line(
filtered_df,
x='date',
y='volume',
title="Volume Trend"
)
fig_volume.update_layout(height=300)
st.plotly_chart(fig_volume, use_container_width=True)
with col2:
# Volume vs Price correlation
fig_scatter = px.scatter(
filtered_df,
x='volume',
y='close',
title="Volume vs Price",
labels={'volume': 'Volume', 'close': 'Close Price'}
)
fig_scatter.update_layout(height=300)
st.plotly_chart(fig_scatter, use_container_width=True)
# Footer
st.markdown("---")
st.markdown("*This dashboard uses mock data for demonstration purposes. Real trading decisions should be based on actual market data.*")
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?