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"""
"""
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}
"""