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
from plotly.subplots import make_subplots
from datetime import datetime, timedelta
import random
# Set page config
st.set_page_config(page_title="Stock Analysis Dashboard", layout="wide")
# Import data generation functions
from data_generator import generate_stock_data, calculate_technical_indicators
# Initialize session state
if 'stock_data' not in st.session_state:
st.session_state.stock_data = generate_stock_data()
def main():
st.title("📈 Stock Analysis Dashboard")
st.markdown("Interactive analysis of tech stock data with technical indicators")
# Sidebar controls
st.sidebar.header("Analysis Controls")
# Stock selector
stocks = list(st.session_state.stock_data.keys())
selected_stock = st.sidebar.selectbox("Select Stock", stocks)
# Date range picker
df = st.session_state.stock_data[selected_stock]
min_date = df.index.min().date()
max_date = df.index.max().date()
start_date, end_date = st.sidebar.date_input(
"Select Date Range",
value=(min_date, max_date),
min_value=min_date,
max_value=max_date
)
# Filter data by date range
filtered_df = df.loc[start_date:end_date]
# Technical indicators
st.sidebar.subheader("Technical Indicators")
show_ma = st.sidebar.checkbox("Moving Averages", value=True)
ma_period_1 = st.sidebar.slider("MA Period 1", 5, 50, 20)
ma_period_2 = st.sidebar.slider("MA Period 2", 20, 100, 50)
show_bollinger = st.sidebar.checkbox("Bollinger Bands", value=False)
bb_period = st.sidebar.slider("Bollinger Period", 10, 30, 20)
bb_std = st.sidebar.slider("Bollinger Std Dev", 1.0, 3.0, 2.0)
# Chart type
chart_type = st.sidebar.selectbox("Chart Type", ["Candlestick", "Line", "OHLC"])
# Calculate technical indicators
tech_data = calculate_technical_indicators(
filtered_df, ma_period_1, ma_period_2, bb_period, bb_std
)
# Main content area
col1, col2 = st.columns([3, 1])
with col1:
# Price chart
st.subheader(f"{selected_stock} Price Chart")
fig = make_subplots(
rows=2, cols=1,
subplot_titles=[f'{selected_stock} Price', 'Volume'],
vertical_spacing=0.1,
row_heights=[0.7, 0.3]
)
# Price chart
if chart_type == "Candlestick":
fig.add_trace(
go.Candlestick(
x=tech_data.index,
open=tech_data['Open'],
high=tech_data['High'],
low=tech_data['Low'],
close=tech_data['Close'],
name=selected_stock
),
row=1, col=1
)
elif chart_type == "Line":
fig.add_trace(
go.Scatter(
x=tech_data.index,
y=tech_data['Close'],
mode='lines',
name=f'{selected_stock} Close',
line=dict(color='blue')
),
row=1, col=1
)
else: # OHLC
fig.add_trace(
go.Ohlc(
x=tech_data.index,
open=tech_data['Open'],
high=tech_data['High'],
low=tech_data['Low'],
close=tech_data['Close'],
name=selected_stock
),
row=1, col=1
)
# Add moving averages
if show_ma:
fig.add_trace(
go.Scatter(
x=tech_data.index,
y=tech_data[f'MA_{ma_period_1}'],
mode='lines',
name=f'MA {ma_period_1}',
line=dict(color='orange', width=1)
),
row=1, col=1
)
fig.add_trace(
go.Scatter(
x=tech_data.index,
y=tech_data[f'MA_{ma_period_2}'],
mode='lines',
name=f'MA {ma_period_2}',
line=dict(color='red', width=1)
),
row=1, col=1
)
# Add Bollinger Bands
if show_bollinger:
fig.add_trace(
go.Scatter(
x=tech_data.index,
y=tech_data['BB_Upper'],
mode='lines',
name='BB Upper',
line=dict(color='gray', width=1, dash='dash'),
showlegend=False
),
row=1, col=1
)
fig.add_trace(
go.Scatter(
x=tech_data.index,
y=tech_data['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
)
# Volume chart
colors = ['red' if close < open else 'green'
for close, open in zip(tech_data['Close'], tech_data['Open'])]
fig.add_trace(
go.Bar(
x=tech_data.index,
y=tech_data['Volume'],
name='Volume',
marker_color=colors
),
row=2, col=1
)
fig.update_layout(
height=600,
xaxis_rangeslider_visible=False,
showlegend=True
)
st.plotly_chart(fig, use_container_width=True)
with col2:
# Stock statistics
st.subheader("Statistics")
current_price = tech_data['Close'].iloc[-1]
prev_price = tech_data['Close'].iloc[-2]
price_change = current_price - prev_price
price_change_pct = (price_change / prev_price) * 100
st.metric(
"Current Price",
f"${current_price:.2f}",
f"{price_change:+.2f} ({price_change_pct:+.2f}%)"
)
st.write("**Price Statistics**")
st.write(f"• High: ${tech_data['High'].max():.2f}")
st.write(f"• Low: ${tech_data['Low'].min():.2f}")
st.write(f"• Mean: ${tech_data['Close'].mean():.2f}")
st.write(f"• Volatility: {tech_data['Close'].std():.2f}")
st.write("**Volume Statistics**")
st.write(f"• Avg Volume: {tech_data['Volume'].mean():,.0f}")
st.write(f"• Max Volume: {tech_data['Volume'].max():,.0f}")
# Recent performance
st.subheader("Recent Performance")
returns_1d = (tech_data['Close'].iloc[-1] / tech_data['Close'].iloc[-2] - 1) * 100
returns_7d = (tech_data['Close'].iloc[-1] / tech_data['Close'].iloc[-8] - 1) * 100 if len(tech_data) >= 8 else 0
returns_30d = (tech_data['Close'].iloc[-1] / tech_data['Close'].iloc[-31] - 1) * 100 if len(tech_data) >= 31 else 0
st.metric("1 Day Return", f"{returns_1d:.2f}%")
st.metric("7 Day Return", f"{returns_7d:.2f}%")
st.metric("30 Day Return", f"{returns_30d:.2f}%")
# Stock comparison section
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_df = st.session_state.stock_data[stock].loc[start_date:end_date]
# Normalize to percentage change from first day
normalized = (stock_df['Close'] / stock_df['Close'].iloc[0] - 1) * 100
comparison_fig.add_trace(
go.Scatter(
x=stock_df.index,
y=normalized,
mode='lines',
name=stock,
line=dict(width=2)
)
)
comparison_fig.update_layout(
title="Stock Performance Comparison (Normalized %)",
xaxis_title="Date",
yaxis_title="Return (%)",
height=400
)
st.plotly_chart(comparison_fig, use_container_width=True)
# Comparison table
comparison_stats = []
for stock in comparison_stocks:
stock_df = st.session_state.stock_data[stock].loc[start_date:end_date]
stats = {
'Stock': stock,
'Current Price': f"${stock_df['Close'].iloc[-1]:.2f}",
'Total Return': f"{((stock_df['Close'].iloc[-1] / stock_df['Close'].iloc[0] - 1) * 100):.2f}%",
'Volatility': f"{stock_df['Close'].std():.2f}",
'Avg Volume': f"{stock_df['Volume'].mean():,.0f}"
}
comparison_stats.append(stats)
comparison_df = pd.DataFrame(comparison_stats)
st.table(comparison_df)
if __name__ == "__main__":
main()
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?