File size: 6,568 Bytes
f7323a3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
"""UI component functions for the financial dashboard."""
import streamlit as st
import pandas as pd
import sys
import os
# Add parent directory to path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from utils.formatters import format_financial_value
from components.data_sources import get_profitability_metrics
def display_price_metrics(metrics: dict):
"""Display key price metrics in columns."""
st.markdown('<div class="section-title">π Price Metrics</div>', unsafe_allow_html=True)
col1, col2, col3, col4 = st.columns(4)
with col1:
st.metric("Current Price", f"${metrics['current_price']:.2f}",
f"{metrics['price_change']:+.2f}", delta_color="normal")
with col2:
st.metric("Day Change %", f"{metrics['price_change_pct']:+.2f}%",
None, delta_color="normal")
with col3:
st.metric("52W High", f"${metrics['high_52w']:.2f}")
with col4:
st.metric("52W Low", f"${metrics['low_52w']:.2f}")
def display_company_info(profile_info):
"""Display company information."""
st.markdown('<div class="section-title">π Company Information</div>', unsafe_allow_html=True)
if profile_info:
info_col1, info_col2 = st.columns(2)
with info_col1:
st.write(f"**Company Name:** {getattr(profile_info, 'name', 'N/A')}")
st.write(f"**Sector:** {getattr(profile_info, 'sector', 'N/A')}")
st.write(f"**Industry:** {getattr(profile_info, 'industry', 'N/A')}")
with info_col2:
st.write(f"**Country:** {getattr(profile_info, 'country', 'N/A')}")
st.write(f"**Exchange:** {getattr(profile_info, 'exchange', 'N/A')}")
st.write(f"**Website:** {getattr(profile_info, 'website', 'N/A')}")
def display_financial_metrics(income_stmt: pd.DataFrame):
"""Display financial metrics from income statement."""
st.markdown('<div class="section-title">π° Financial Metrics</div>', unsafe_allow_html=True)
latest_income = income_stmt.iloc[0] if len(income_stmt) > 0 else None
if latest_income is not None:
# First row of metrics
fin_col1, fin_col2, fin_col3, fin_col4 = st.columns(4)
with fin_col1:
revenue = latest_income.get('total_revenue', 0)
if pd.notna(revenue) and revenue > 0:
st.metric("Total Revenue", format_financial_value(revenue))
else:
st.metric("Total Revenue", "N/A")
with fin_col2:
net_income = latest_income.get('net_income', 0)
if pd.notna(net_income) and net_income > 0:
st.metric("Net Income", format_financial_value(net_income))
else:
st.metric("Net Income", "N/A")
with fin_col3:
gross_profit = latest_income.get('gross_profit', 0)
if pd.notna(gross_profit) and gross_profit > 0:
st.metric("Gross Profit", format_financial_value(gross_profit))
else:
st.metric("Gross Profit", "N/A")
with fin_col4:
operating_income = latest_income.get('operating_income', 0)
if pd.notna(operating_income) and operating_income > 0:
st.metric("Operating Income", format_financial_value(operating_income))
else:
st.metric("Operating Income", "N/A")
# Second row of metrics
fin_col5, fin_col6, fin_col7, fin_col8 = st.columns(4)
with fin_col5:
eps = latest_income.get('diluted_earnings_per_share', 0)
if pd.notna(eps):
st.metric("EPS (Diluted)", f"${eps:.2f}")
else:
st.metric("EPS (Diluted)", "N/A")
with fin_col6:
ebitda = latest_income.get('ebitda', 0)
if pd.notna(ebitda) and ebitda > 0:
st.metric("EBITDA", format_financial_value(ebitda))
else:
st.metric("EBITDA", "N/A")
with fin_col7:
cogs = latest_income.get('cost_of_revenue', 0)
if pd.notna(cogs) and cogs > 0:
st.metric("Cost of Revenue", format_financial_value(cogs))
else:
st.metric("Cost of Revenue", "N/A")
with fin_col8:
rd_expense = latest_income.get('research_and_development_expense', 0)
if pd.notna(rd_expense) and rd_expense > 0:
st.metric("R&D Expense", format_financial_value(rd_expense))
else:
st.metric("R&D Expense", "N/A")
def display_income_statement(income_stmt: pd.DataFrame):
"""Display formatted income statement table."""
st.markdown("### Income Statement")
if not income_stmt.empty:
display_columns = [
'period_ending',
'total_revenue',
'cost_of_revenue',
'gross_profit',
'operating_income',
'net_income',
'diluted_earnings_per_share',
'ebitda'
]
available_cols = [col for col in display_columns if col in income_stmt.columns]
financial_display = income_stmt[available_cols].copy()
for col in financial_display.columns:
if col != 'period_ending':
financial_display[col] = financial_display[col].apply(
lambda x: format_financial_value(x)
)
st.dataframe(financial_display, use_container_width=True, hide_index=True)
def display_profitability_metrics(income_stmt: pd.DataFrame):
"""Display profitability metrics."""
st.markdown("### Profitability Metrics")
prof_col1, prof_col2 = st.columns(2)
latest_data = income_stmt.iloc[0]
metrics = get_profitability_metrics(latest_data)
with prof_col1:
if "gross_margin" in metrics:
st.metric("Gross Margin", f"{metrics['gross_margin']:.2f}%")
if "net_margin" in metrics:
st.metric("Net Profit Margin", f"{metrics['net_margin']:.2f}%")
with prof_col2:
if "operating_margin" in metrics:
st.metric("Operating Margin", f"{metrics['operating_margin']:.2f}%")
if len(income_stmt) > 1:
prev_revenue = income_stmt.iloc[1].get('total_revenue', 0)
total_rev = latest_data.get('total_revenue', 0)
if prev_revenue and prev_revenue > 0:
revenue_growth = ((total_rev - prev_revenue) / prev_revenue) * 100
st.metric("Revenue Growth (YoY)", f"{revenue_growth:+.2f}%")
|