| | """Data fetching and processing utilities for the financial dashboard.""" |
| |
|
| | import pandas as pd |
| | from openbb import sdk |
| |
|
| |
|
| | def load_stock_data(symbol: str) -> pd.DataFrame: |
| | """Load historical stock price data.""" |
| | df = sdk.equity.price.historical(symbol=symbol).to_dataframe() |
| | return df |
| |
|
| |
|
| | def load_company_profile(symbol: str): |
| | """Load company profile information.""" |
| | 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 |
| |
|
| |
|
| | def load_income_statement(symbol: str) -> pd.DataFrame: |
| | """Load company income statement data.""" |
| | 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["SMA"] = df["close"].rolling(period).mean() |
| | df["EMA"] = df["close"].ewm(span=period, adjust=False).mean() |
| |
|
| | |
| | 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 format_financial_value(value) -> str: |
| | """Format financial values with appropriate units.""" |
| | if pd.isna(value): |
| | return "N/A" |
| | if abs(value) >= 1e9: |
| | return f"${value/1e9:.2f}B" |
| | elif abs(value) >= 1e6: |
| | return f"${value/1e6:.2f}M" |
| | else: |
| | return f"${value:.2f}" |
| |
|
| |
|
| | 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 |
| |
|