{# Inputs: account_points: list[AccountValuePoint] -- selected-period series lifetime_account_points: list[AccountValuePoint] -- full lifetime series; falsy in Lifetime view defer_lifetime_brush: bool -- true → lazy-load via HTMX (the lifetime series costs ~1.8s to compute) benchmark_points: list[BenchmarkPoint] benchmark_symbol: str period_label: str -- e.g. "YTD 2025", "2024", "Lifetime" current_year: int -- for ytd snap detection available_years: list[int] -- snap targets for the brush selected_period: str -- echoed into the lazy-load URL selected_accounts: list[str] -- echoed into the lazy-load URL #} {% set has_data = account_points and account_points|length >= 2 %} {% set missing_dates_count = account_points|selectattr('account_value', 'none')|list|length if account_points else 0 %} {% set _lap = lifetime_account_points | default(none) %} {% set has_brush = _lap and _lap|length >= 2 %} {% set defer_brush = defer_lifetime_brush | default(false) %}

Equity curve

Account value · {{ period_label }} {% if missing_dates_count > 0 %} ⚠ {{ missing_dates_count }} date{{ 's' if missing_dates_count != 1 else '' }} missing prices {% endif %}
{% if not has_data %}
No deposits yet in {{ period_label }}.
{% else %}
{% if defer_brush %} {# Lazy-load the lifetime brush strip — see endpoint and template _portfolio_equity_brush.html for details. #}
{% elif has_brush %}
Lifetime shape · drag the selection to change period.
{% endif %}
Option positions are valued at cost basis on this chart; today's mark-to-market shows on the Holdings panel.
{% endif %}