diff --git a/app.py b/app.py index 17ba920..54a7094 100644 --- a/app.py +++ b/app.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Dict, Tuple +from typing import Dict, Optional, Tuple import pandas as pd import streamlit as st @@ -70,6 +70,112 @@ def format_number(value: float, decimals: int = 2) -> str: return f"{value:,.{decimals}f}" +def inject_metric_card_styles() -> None: + st.markdown( + """ + + """, + unsafe_allow_html=True, + ) + + +def render_metric_card(label: str, value: str, *, delta: Optional[str] = None, close_value: bool = False) -> str: + value_class = "aw-metric-value aw-metric-value--close" if close_value else "aw-metric-value" + + delta_html = "" + if delta: + delta_class = "aw-metric-delta--flat" + delta_symbol = "" + if delta.startswith("-"): + delta_class = "aw-metric-delta--down" + delta_symbol = "↓" + elif delta != "0.00%": + delta_class = "aw-metric-delta--up" + delta_symbol = "↑" + + delta_html = ( + f'
{delta_symbol} {delta}
' + ) + + return ( + '
' + f'
{label}
' + f'
{value}
' + f"{delta_html}" + "
" + ) + + def render_summary_cards( requested_count: int, ranked_results: pd.DataFrame, @@ -111,17 +217,26 @@ def filter_rankings( def render_metric_cards(latest_row: pd.Series) -> None: - columns = st.columns(6) - columns[0].metric("Close", f"INR {format_number(latest_row['Close'])}") - columns[1].metric( - "Daily return", - format_percent(latest_row["daily_return"]), - delta=format_percent(latest_row["daily_return"]), + cards = [ + render_metric_card( + "Close", + f"INR {format_number(latest_row['Close'])}", + close_value=True, + ), + render_metric_card( + "Daily return", + format_percent(latest_row["daily_return"]), + delta=format_percent(latest_row["daily_return"]), + ), + render_metric_card("Excess return", format_percent(latest_row.get("excess_return"))), + render_metric_card("Anomaly score", format_number(latest_row["anomaly_score"], 1)), + render_metric_card("Confidence", str(latest_row.get("confidence_level", "Low"))), + render_metric_card("Risk", str(latest_row.get("risk_level", "Normal"))), + ] + st.markdown( + f'
{"".join(cards)}
', + unsafe_allow_html=True, ) - columns[2].metric("Excess return", format_percent(latest_row.get("excess_return"))) - columns[3].metric("Anomaly score", format_number(latest_row["anomaly_score"], 1)) - columns[4].metric("Confidence", latest_row.get("confidence_level", "Low")) - columns[5].metric("Risk", latest_row.get("risk_level", "Normal")) def render_ranked_table(ranked_results: pd.DataFrame) -> None: @@ -335,6 +450,7 @@ def render_analyst_report( def main() -> None: st.set_page_config(page_title="AlphaWatch", layout="wide") + inject_metric_card_styles() st.title(APP_TITLE) st.caption(APP_DESCRIPTION)