Dmitry Beresnev
feat: restructure to multi-page app with modular architecture
f7323a3
raw
history blame
2.81 kB
"""Data fetching and processing utilities for the financial dashboard."""
import pandas as pd
from openbb import sdk
import streamlit as st
@st.cache_data(ttl=3600)
def load_stock_data(symbol: str) -> pd.DataFrame:
"""Load historical stock price data with caching."""
df = sdk.equity.price.historical(symbol=symbol).to_dataframe()
return df
@st.cache_data(ttl=86400)
def load_company_profile(symbol: str):
"""Load company profile information with caching."""
profile_response = sdk.equity.profile(symbol=symbol)
profile_info = profile_response.results[0] if hasattr(profile_response, 'results') and profile_response.results else None
return profile_info
@st.cache_data(ttl=86400)
def load_income_statement(symbol: str) -> pd.DataFrame:
"""Load company income statement data with caching."""
income_stmt = sdk.equity.fundamental.income(symbol=symbol).to_dataframe()
return income_stmt
def calculate_technical_indicators(df: pd.DataFrame, period: int) -> pd.DataFrame:
"""Calculate SMA, EMA, and RSI indicators."""
df = df.copy()
df["SMA"] = df["close"].rolling(period).mean()
df["EMA"] = df["close"].ewm(span=period, adjust=False).mean()
# Calculate RSI
delta = df["close"].diff()
gain = delta.clip(lower=0)
loss = -1 * delta.clip(upper=0)
avg_gain = gain.rolling(period).mean()
avg_loss = loss.rolling(period).mean()
rs = avg_gain / avg_loss
df["RSI"] = 100 - (100 / (1 + rs))
return df
def get_price_metrics(df: pd.DataFrame) -> dict:
"""Calculate key price metrics."""
current_price = df["close"].iloc[-1]
prev_close = df["close"].iloc[-2] if len(df) > 1 else df["close"].iloc[0]
price_change = current_price - prev_close
price_change_pct = (price_change / prev_close) * 100 if prev_close != 0 else 0
return {
"current_price": current_price,
"price_change": price_change,
"price_change_pct": price_change_pct,
"high_52w": df['high'].max(),
"low_52w": df['low'].min(),
}
def get_profitability_metrics(income_data: pd.Series) -> dict:
"""Calculate profitability metrics from income statement."""
total_rev = income_data.get('total_revenue', 0)
gross_prof = income_data.get('gross_profit', 0)
net_inc = income_data.get('net_income', 0)
operating_inc = income_data.get('operating_income', 0)
metrics = {}
if total_rev and total_rev > 0:
metrics["gross_margin"] = (gross_prof / total_rev) * 100 if pd.notna(gross_prof) else 0
metrics["net_margin"] = (net_inc / total_rev) * 100 if pd.notna(net_inc) else 0
if operating_inc:
metrics["operating_margin"] = (operating_inc / total_rev) * 100
else:
metrics = {"gross_margin": 0, "net_margin": 0}
return metrics