""" Tab 8 — Standardized Financial Statements Sub-tabs for Highlights, Income Statement, Balance Sheet, Cash Flow with YoY growth rates, conditional color coding (green/red), and AI summary. """ import streamlit as st import pandas as pd from config.constants import MARKET_OPTIONS from utils.ticker import get_global_ticker from data.financials import _get_annual_financials_balance_cashflow from data.fundamentals import get_sector_industry from views.financial_ai_summary import render_ai_summary # ───────── Formatting ───────── def _fmt_val(val) -> str: """Format raw number. Parentheses for negatives.""" if val is None: return "N/A" try: f = float(val) if f != f: return "N/A" neg = f < 0 af = abs(f) if af >= 1e9: s = f"{af / 1e9:,.1f}" elif af >= 1e6: s = f"{af / 1e6:,.1f}" elif af >= 1e3: s = f"{af / 1e3:,.1f}" else: s = f"{af:,.0f}" return f"({s})" if neg else s except (ValueError, TypeError): return "N/A" def _calc_yoy(df: pd.DataFrame) -> pd.DataFrame: """Calculate YoY growth rates between consecutive columns.""" if df is None or df.empty or len(df.columns) < 2: return pd.DataFrame() yoy = pd.DataFrame(index=df.index) for i in range(len(df.columns) - 1): curr_col, prev_col = df.columns[i], df.columns[i + 1] vals = [] for idx in df.index: try: c, p = float(df.loc[idx, curr_col]), float(df.loc[idx, prev_col]) vals.append((c - p) / abs(p) * 100 if p != 0 and c == c and p == p else None) except (ValueError, TypeError): vals.append(None) yoy[f"{str(curr_col)[:10]} YoY"] = vals return yoy def _build_display_df(raw_df: pd.DataFrame) -> pd.DataFrame: """Build display DF with interleaved YoY growth rows.""" if raw_df is None or raw_df.empty: return pd.DataFrame() cols = raw_df.columns[:5] df = raw_df[cols].copy() yoy = _calc_yoy(df) rows = [] for idx in df.index: row = {"Item": idx} for c in cols: row[str(c)[:10]] = _fmt_val(df.loc[idx, c]) rows.append(row) yoy_row = {"Item": " YoY Growth (%)"} has_yoy = False for yc in yoy.columns: period = yc.replace(" YoY", "") val = yoy.loc[idx, yc] if idx in yoy.index else None if val is not None and val == val: yoy_row[period] = f"{val:+.2f}%" has_yoy = True else: yoy_row[period] = "" if has_yoy: rows.append(yoy_row) result = pd.DataFrame(rows) if "Item" in result.columns: result = result.set_index("Item") return result def _render_styled_table(df: pd.DataFrame): """Render financial statement as HTML with color-coded YoY rows.""" if df is None or df.empty: st.warning("No data available.") return html = '
| Item | ' for c in df.columns: html += f'{c} | ' html += '||
|---|---|---|---|
| {idx} | ' for c in df.columns: val = str(df.loc[idx, c]) if is_yoy and "%" in val: try: num = float(val.replace("%", "").replace("+", "")) cbg = "rgba(52,211,153,0.12)" if num > 0 else ("rgba(248,113,113,0.12)" if num < 0 else "transparent") cc = "#34D399" if num > 0 else ("#F87171" if num < 0 else "#9CA3AF") except ValueError: cbg, cc = "transparent", "#9CA3AF" html += f'{val} | ' elif not is_yoy and "(" in val: html += f'{val} | ' else: html += f'{val} | ' html += '