Source code for kaxanuk.attribution_analysis.dashboard.components
"""
Reusable dashboard components (cards, tables, headers).
"""
import math
from dash import html, dash_table
from kaxanuk.attribution_analysis.dashboard.constants import (
CURRENCY_KEYWORDS,
PERCENTAGE_KEYWORDS,
RATIO_KEYWORDS,
DATE_KEYWORDS,
)
from kaxanuk.attribution_analysis.dashboard.styles import (
get_data_table_style,
get_data_table_header_style,
get_table_container_style,
)
[docs]
def format_metric_value(metric_name: str, value: object) -> str:
"""
Format a metric value for display based on its name and type.
The formatting rule is inferred from keywords found in `metric_name`:
currency (``$#,##0.00``), percentage (``0.00%``), ratio (4 decimal
places), or date (``YYYY-MM-DD``). Falls back to 4 decimal places for
other numeric values, or ``str(value)`` otherwise.
Parameters
----------
metric_name : str
Name of the metric, matched case-insensitively against
`CURRENCY_KEYWORDS`, `PERCENTAGE_KEYWORDS`, `RATIO_KEYWORDS`, and
`DATE_KEYWORDS` to select the formatting rule.
value : object
The value to format. Typically an ``int``, ``float``, date-like
object (with a ``strftime`` method), or None.
Returns
-------
str
The formatted value, or ``"N/A"`` if `value` is None or NaN.
"""
if value is None or (isinstance(value, float) and math.isnan(value)):
return "N/A"
metric_lower = metric_name.lower()
if any(keyword in metric_lower for keyword in CURRENCY_KEYWORDS):
if isinstance(value, (int, float)):
return f"${value:,.2f}"
return str(value)
if any(keyword in metric_lower for keyword in PERCENTAGE_KEYWORDS):
if isinstance(value, (int, float)):
return f"{value:.2%}"
return str(value)
if any(keyword in metric_lower for keyword in RATIO_KEYWORDS):
if isinstance(value, (int, float)):
return f"{value:.4f}"
return str(value)
if any(keyword in metric_lower for keyword in DATE_KEYWORDS):
if hasattr(value, 'strftime'):
return value.strftime('%Y-%m-%d')
return str(value)
if isinstance(value, (int, float)):
return f"{value:.4f}"
return str(value)
[docs]
def create_metric_card(title: str, value: str, card_type: str = "primary") -> html.Div:
"""
Build a single metric card (title + value) for the dashboard's KPI row.
Parameters
----------
title : str
Metric label displayed above the value (e.g. ``"Sharpe Ratio"``).
value : str
Pre-formatted metric value to display (e.g. ``"1.234"``).
card_type : str, default "primary"
Style variant appended as a CSS class to the value element (e.g.
``"success"``, ``"warning"``, ``"danger"``), used to color-code
the card.
Returns
-------
dash.html.Div
A ``Div`` containing the title (``H4``) and value (``H2``)
elements, styled with the ``metric-card`` class.
"""
return html.Div([
html.H4(title, className="metric-title"),
html.H2(value, className=f"metric-value {card_type}")
], className="metric-card")
[docs]
def create_header_with_logo(
logo_src: str | None,
portfolio_name: str,
start_date: str,
end_date: str,
) -> list:
"""
Build the dashboard header, optionally including a logo.
Parameters
----------
logo_src : str or None
Image source for the logo (e.g. a base64 data URI). If None, the
header is rendered without a logo section.
portfolio_name : str
Portfolio name displayed as the header's subtitle.
start_date : str
Start date of the analysis period, displayed as-is
(e.g. ``"2023-01-01"``).
end_date : str
End date of the analysis period, displayed as-is.
Returns
-------
list
A list of Dash HTML components making up the header content,
suitable for passing directly as `children` to a container
component.
"""
if logo_src:
return [
html.Div([
html.Div([
html.Img(
src=logo_src,
style={
'height': '60px',
'width': 'auto',
'margin-right': '20px'
}
)
], className="logo-section"),
html.Div([
html.H1("Attribution Analysis Dashboard", className="dashboard-main-title"),
html.H2(f"{portfolio_name}", className="dashboard-subtitle"),
html.P(
f"Analysis Period: {start_date} to {end_date}",
className="date-range"
)
], className="title-section")
], className="header-content")
]
return [
html.H1("Attribution Analysis Dashboard", className="dashboard-main-title"),
html.H2(f"{portfolio_name}", className="dashboard-subtitle"),
html.P(
f"Analysis Period: {start_date} to {end_date}",
className="date-range"
)
]
[docs]
def create_statistics_table(
stats_data: list[dict],
portfolio_name: str,
) -> html.Div:
"""
Build a sortable Dash DataTable of performance statistics.
Parameters
----------
stats_data : list of dict
Row data for the table, where each dict has ``"Metric"`` and
``"Value"`` keys.
portfolio_name : str
Portfolio name used as the header label for the value column.
Returns
-------
dash.html.Div
A ``Div`` wrapping a ``dash_table.DataTable`` with columns
``Metric`` and `portfolio_name`, sortable natively and paginated
at 25 rows per page.
"""
return html.Div([
dash_table.DataTable(
data=stats_data,
columns=[
{"name": "Metric", "id": "Metric"},
{"name": f"{portfolio_name}", "id": "Value"},
],
style_cell=get_data_table_style(),
style_header=get_data_table_header_style(),
style_table=get_table_container_style(),
page_size=25,
sort_action="native",
style_as_list_view=True
)
], style={'margin': '20px 0'})