{# Inputs: monthly_pl_points: list[MonthlyPnlPoint] -- chronological, may be empty period_label: str -- e.g. "YTD 2026", "2025", "Lifetime" #} {% set has_data = monthly_pl_points and (monthly_pl_points|map(attribute='trade_count')|sum) > 0 %}

Monthly realized P&L

{{ period_label }}
{% if not has_data %}
No realized closes in {{ period_label }}.
{% else %} {# Always wrap in an overflow-x container so the same CSS path covers both YTD/single-year (which fit) and Lifetime (which can scroll). The inner min-width keeps each bar at least 32px wide once the count exceeds the panel's natural width. #}
{# Wrap and inner chart container both pin to 105px — matches the Apex chart.height below. A previous mismatch (wrap=90, chart auto-grew to 105) caused Apex to emit `translate(NaN, ...)` SVG transforms in Lifetime view where category count outran available pixels. #}
{% if monthly_pl_lifetime %} {% set _best_neg = monthly_pl_lifetime[1]|float < 0 %} {% set _worst_neg = monthly_pl_lifetime[3]|float < 0 %}
Lifetime avg ${{ "{:,.0f}".format(monthly_pl_lifetime[0]|float) }}/mo · best {% if _best_neg %}−{% else %}+{% endif %}${{ "{:,.0f}".format(monthly_pl_lifetime[1]|float|abs) }} ({{ monthly_pl_lifetime[2] }}) · worst {% if _worst_neg %}−{% else %}+{% endif %}${{ "{:,.0f}".format(monthly_pl_lifetime[3]|float|abs) }} ({{ monthly_pl_lifetime[4] }}).
{% endif %} {% endif %}