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)