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 datetime import datetime, timedelta
import altair as alt
from data_generator import generate_stock_data
from calculations import calculate_moving_averages, calculate_volatility, calculate_rsi, calculate_macd
# Page config
st.set_page_config(
page_title="Stock Analysis Dashboard",
page_icon="📈",
layout="wide"
)
# Title
st.title("📈 Stock Analysis Dashboard")
st.markdown("Interactive analysis of tech stocks with technical indicators")
# Generate data
@st.cache_data
def load_data():
return generate_stock_data()
data = load_data()
# Sidebar controls
st.sidebar.header("Controls")
# Stock selector
stocks = list(data.keys())
selected_stock = st.sidebar.selectbox("Select Stock", stocks, index=0)
# Date range picker
stock_data = data[selected_stock]
min_date = stock_data['Date'].min().date()
max_date = stock_data['Date'].max().date()
date_range = st.sidebar.date_input(
"Date Range",
value=(min_date, max_date),
min_value=min_date,
max_value=max_date
)
if len(date_range) == 2:
start_date, end_date = date_range
filtered_data = stock_data[
(stock_data['Date'].dt.date >= start_date) &
(stock_data['Date'].dt.date <= end_date)
].copy()
else:
filtered_data = stock_data.copy()
# Technical indicators
st.sidebar.subheader("Technical Indicators")
show_ma = st.sidebar.checkbox("Moving Averages", value=True)
ma_periods = st.sidebar.multiselect("MA Periods", [5, 10, 20, 50], default=[20, 50])
show_rsi = st.sidebar.checkbox("RSI", value=False)
show_macd = st.sidebar.checkbox("MACD", value=False)
# Chart type
chart_type = st.sidebar.radio("Chart Type", ["Candlestick", "Line", "Area"])
# Calculate indicators
if show_ma and ma_periods:
for period in ma_periods:
filtered_data[f'MA_{period}'] = calculate_moving_averages(filtered_data['Close'], period)
if show_rsi:
filtered_data['RSI'] = calculate_rsi(filtered_data['Close'])
if show_macd:
macd_data = calculate_macd(filtered_data['Close'])
filtered_data = pd.concat([filtered_data, macd_data], axis=1)
# Main dashboard
col1, col2, col3, col4 = st.columns(4)
with col1:
current_price = filtered_data['Close'].iloc[-1]
st.metric("Current Price", f"${current_price:.2f}")
with col2:
price_change = filtered_data['Close'].iloc[-1] - filtered_data['Close'].iloc[-2]
change_pct = (price_change / filtered_data['Close'].iloc[-2]) * 100
st.metric("Daily Change", f"${price_change:.2f}", f"{change_pct:.2f}%")
with col3:
volatility = calculate_volatility(filtered_data['Close'])
st.metric("Volatility (30d)", f"{volatility:.2f}%")
with col4:
avg_volume = filtered_data['Volume'].mean()
st.metric("Avg Volume", f"{avg_volume:,.0f}")
# Price chart
st.subheader(f"{selected_stock} Price Chart")
fig = go.Figure()
if chart_type == "Candlestick":
fig.add_trace(go.Candlestick(
x=filtered_data['Date'],
open=filtered_data['Open'],
high=filtered_data['High'],
low=filtered_data['Low'],
close=filtered_data['Close'],
name=selected_stock
))
elif chart_type == "Line":
fig.add_trace(go.Scatter(
x=filtered_data['Date'],
y=filtered_data['Close'],
mode='lines',
name='Close Price',
line=dict(width=2)
))
else: # Area
fig.add_trace(go.Scatter(
x=filtered_data['Date'],
y=filtered_data['Close'],
fill='tonexty',
mode='lines',
name='Close Price',
line=dict(width=1)
))
# Add moving averages
if show_ma and ma_periods:
colors = ['orange', 'red', 'purple', 'brown']
for i, period in enumerate(ma_periods):
fig.add_trace(go.Scatter(
x=filtered_data['Date'],
y=filtered_data[f'MA_{period}'],
mode='lines',
name=f'MA{period}',
line=dict(color=colors[i % len(colors)], width=1)
))
fig.update_layout(
title=f"{selected_stock} Stock Price",
xaxis_title="Date",
yaxis_title="Price ($)",
height=500,
showlegend=True
)
st.plotly_chart(fig, use_container_width=True)
# Volume chart
st.subheader("Volume Analysis")
volume_fig = go.Figure()
volume_fig.add_trace(go.Bar(
x=filtered_data['Date'],
y=filtered_data['Volume'],
name='Volume',
marker_color='lightblue'
))
volume_fig.update_layout(
title=f"{selected_stock} Trading Volume",
xaxis_title="Date",
yaxis_title="Volume",
height=300
)
st.plotly_chart(volume_fig, use_container_width=True)
# Technical indicators charts
if show_rsi or show_macd:
st.subheader("Technical Indicators")
if show_rsi and show_macd:
indicator_col1, indicator_col2 = st.columns(2)
else:
indicator_col1 = st.container()
indicator_col2 = None
if show_rsi:
with indicator_col1:
rsi_fig = go.Figure()
rsi_fig.add_trace(go.Scatter(
x=filtered_data['Date'],
y=filtered_data['RSI'],
mode='lines',
name='RSI',
line=dict(color='purple')
))
rsi_fig.add_hline(y=70, line_dash="dash", line_color="red", annotation_text="Overbought")
rsi_fig.add_hline(y=30, line_dash="dash", line_color="green", annotation_text="Oversold")
rsi_fig.update_layout(
title="RSI (14)",
xaxis_title="Date",
yaxis_title="RSI",
height=300,
yaxis=dict(range=[0, 100])
)
st.plotly_chart(rsi_fig, use_container_width=True)
if show_macd:
with (indicator_col2 if indicator_col2 else indicator_col1):
macd_fig = go.Figure()
macd_fig.add_trace(go.Scatter(
x=filtered_data['Date'],
y=filtered_data['MACD'],
mode='lines',
name='MACD',
line=dict(color='blue')
))
macd_fig.add_trace(go.Scatter(
x=filtered_data['Date'],
y=filtered_data['Signal'],
mode='lines',
name='Signal',
line=dict(color='red')
))
macd_fig.add_trace(go.Bar(
x=filtered_data['Date'],
y=filtered_data['Histogram'],
name='Histogram',
marker_color='gray',
opacity=0.6
))
macd_fig.update_layout(
title="MACD",
xaxis_title="Date",
yaxis_title="MACD",
height=300
)
st.plotly_chart(macd_fig, use_container_width=True)
# Stock comparison
st.subheader("Stock Comparison")
comparison_stocks = st.multiselect(
"Select stocks to compare",
stocks,
default=[selected_stock]
)
if len(comparison_stocks) > 1:
comparison_fig = go.Figure()
for stock in comparison_stocks:
stock_data_comp = data[stock]
# Filter by date range
stock_filtered = stock_data_comp[
(stock_data_comp['Date'].dt.date >= start_date) &
(stock_data_comp['Date'].dt.date <= end_date)
] if len(date_range) == 2 else stock_data_comp
# Normalize to percentage change from first value
normalized_prices = (stock_filtered['Close'] / stock_filtered['Close'].iloc[0] - 1) * 100
comparison_fig.add_trace(go.Scatter(
x=stock_filtered['Date'],
y=normalized_prices,
mode='lines',
name=stock,
line=dict(width=2)
))
comparison_fig.update_layout(
title="Stock Performance Comparison (% Change)",
xaxis_title="Date",
yaxis_title="Percentage Change (%)",
height=400
)
st.plotly_chart(comparison_fig, use_container_width=True)
# Statistics table
st.subheader("Statistics")
stats_data = []
for stock in (comparison_stocks if len(comparison_stocks) > 1 else [selected_stock]):
stock_data_stats = data[stock]
if len(date_range) == 2:
stock_data_stats = stock_data_stats[
(stock_data_stats['Date'].dt.date >= start_date) &
(stock_data_stats['Date'].dt.date <= end_date)
]
stats_data.append({
'Stock': stock,
'Current Price': f"${stock_data_stats['Close'].iloc[-1]:.2f}",
'Mean Price': f"${stock_data_stats['Close'].mean():.2f}",
'Volatility': f"{calculate_volatility(stock_data_stats['Close']):.2f}%",
'Max Price': f"${stock_data_stats['High'].max():.2f}",
'Min Price': f"${stock_data_stats['Low'].min():.2f}",
'Avg Volume': f"{stock_data_stats['Volume'].mean():,.0f}"
})
stats_df = pd.DataFrame(stats_data)
st.table(stats_df)
# Raw data
with st.expander("Raw Data"):
st.dataframe(filtered_data)
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?