import pandas as pd import numpy as np import datetime import traceback # ============================================================ # NUMBER FORMATTING HELPERS # ============================================================ def format_number(num): if num is None: return "-" try: return f"{float(num):,.2f}".rstrip("0").rstrip(".") except: return str(num) def format_large_number(num): if num is None: return "-" try: n = float(num) if abs(n) >= 1_00_00_000: # Crore return f"{n/1_00_00_000:.2f} Cr" elif abs(n) >= 1_00_000: # Lakh return f"{n/1_00_000:.2f} L" elif abs(n) >= 1_000: # Thousand return f"{n/1_000:.2f} K" else: return format_number(n) except: return str(num) # ============================================================ # HTML UI HELPERS # ============================================================ def html_card(title, content): return f"""

{title}

{content}
""" def html_section(title, content): return f"""

{title}

{content}
""" def html_error(msg): return f"""
Error: {msg}
""" # ============================================================ # DATAFRAME CLEANING # ============================================================ def clean_df(df): if isinstance(df.index, pd.DatetimeIndex): df.index = df.index.strftime("%Y-%m-%d") df.replace([np.inf, -np.inf], np.nan, inplace=True) df.fillna("-", inplace=True) return df # ============================================================ # TABLE STYLING # ============================================================ def make_table(df): try: df = df.copy() df = clean_df(df) html = df.to_html(classes="styled-table", escape=False, border=0) return f""" {html} """ except Exception as e: return html_error(f"Table render failed: {e}
{traceback.format_exc()}
") # ============================================================ # UNIVERSAL PLOT WRAPPER # ============================================================ def wrap_plotly_html(html_chart, table_html=None): extra = f"
{table_html}
" if table_html else "" return f"""
{html_card("Chart", html_chart)} {extra}
""" # ============================================================ # INDICATOR SAFE EXTRACTION HELPER # ============================================================ def safe_get(df, key, default_val="-"): try: return df.get(key, default_val) except: return default_val def format_timestamp_to_date(timestamp): if not isinstance(timestamp, (int, float)) or timestamp <= 0: return "N/A" try: return datetime.datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d') except: return "Invalid Date" # ============================================================ # HTML WRAPPER # ============================================================ STYLE_BLOCK = """ """ def wrap_html(content, title="Stock Data"): return f""" {title} {STYLE_BLOCK} {content} """