Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions quantstats/reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -1545,12 +1545,12 @@ def metrics(
metrics["1Y %"] = _np.sum(df[df.index >= y1], axis=0) * pct

# Multi-year annualized returns
d = today - relativedelta(months=35)
d = today - relativedelta(years=3)
metrics["3Y (ann.) %"] = (
_get_stats().cagr(df[df.index >= d], 0.0, compounded, win_year) * pct
)

d = today - relativedelta(months=59)
d = today - relativedelta(years=5)
metrics["5Y (ann.) %"] = (
_get_stats().cagr(df[df.index >= d], 0.0, compounded, win_year) * pct
)
Expand Down
24 changes: 24 additions & 0 deletions tests/test_reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import quantstats as qs
from quantstats import reports
from dateutil.relativedelta import relativedelta


@pytest.fixture
Expand Down Expand Up @@ -174,6 +175,29 @@ def test_metrics_with_rf(self, sample_returns):
# Results should be different
assert not result_no_rf.equals(result_with_rf)

def test_metrics_use_full_three_and_five_year_windows(self):
"""Test that multi-year annualized metrics use full labeled windows."""
dates = pd.date_range("2020-01-31", "2026-01-31", freq="ME")
returns = pd.Series(0.0, index=dates, name="Strategy")
returns.loc[pd.Timestamp("2021-01-31")] = 0.25
returns.loc[pd.Timestamp("2023-01-31")] = 0.15

result = reports.metrics(returns, display=False)

expected_3y = qs.stats.cagr(
returns[returns.index >= dates[-1] - relativedelta(years=3)],
rf=0.0,
compounded=True,
).iloc[0]
expected_5y = qs.stats.cagr(
returns[returns.index >= dates[-1] - relativedelta(years=5)],
rf=0.0,
compounded=True,
).iloc[0]

assert result.loc["3Y (ann.)", "Strategy"] == pytest.approx(round(expected_3y, 2))
assert result.loc["5Y (ann.)", "Strategy"] == pytest.approx(round(expected_5y, 2))


class TestMatchDates:
"""Test date matching functionality."""
Expand Down