diff --git a/quantstats/_plotting/core.py b/quantstats/_plotting/core.py index 8390d283..822bd502 100644 --- a/quantstats/_plotting/core.py +++ b/quantstats/_plotting/core.py @@ -260,22 +260,21 @@ def plot_returns_bars( # Format x-axis labels try: - ax.set_xticklabels(df.index.year) - years = sorted(list(set(df.index.year))) + years = [str(year) for year in df.index.year] except AttributeError: - ax.set_xticklabels(df.index) - years = sorted(list(set(df.index))) + years = [str(label) for label in df.index] + + tick_labels = years # ax.fmt_xdata = _mdates.DateFormatter('%Y-%m-%d') # years = sorted(list(set(df.index.year))) # Reduce label density for long time series if len(years) > 10: - mod = int(len(years) / 10) - _plt.xticks( - _np.arange(len(years)), - [str(year) if not i % mod else "" for i, year in enumerate(years)], - ) + step = max(1, int(_np.ceil(len(years) / 10))) + tick_labels = [label if not i % step else "" for i, label in enumerate(years)] + + ax.set_xticklabels(tick_labels) # rotate and align the tick labels so they look better fig.autofmt_xdate() diff --git a/tests/test_plots.py b/tests/test_plots.py index 8fa5b509..d51a43a8 100644 --- a/tests/test_plots.py +++ b/tests/test_plots.py @@ -54,6 +54,21 @@ def test_yearly_returns(self, sample_returns): fig = plots.yearly_returns(sample_returns, show=False) assert fig is not None + def test_yearly_returns_sparsifies_labels_for_long_ranges(self): + """Test yearly returns uses sparser year labels once the range exceeds 10 years.""" + np.random.seed(7) + dates = pd.date_range("2010-01-01", periods=365 * 12, freq="D") + returns = pd.Series(np.random.randn(len(dates)) * 0.01, index=dates, name="Strategy") + benchmark = pd.Series(np.random.randn(len(dates)) * 0.008, index=dates, name="Benchmark") + + fig = plots.yearly_returns(returns, benchmark=benchmark, show=False) + labels = [tick.get_text() for tick in fig.axes[0].get_xticklabels()] + non_empty_labels = [label for label in labels if label] + + assert len(labels) == 12 + assert len(non_empty_labels) == 6 + assert non_empty_labels == ["2010", "2012", "2014", "2016", "2018", "2020"] + def test_histogram(self, sample_returns, sample_benchmark): """Test histogram plot.""" fig = plots.histogram(sample_returns, sample_benchmark, show=False)