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
17 changes: 8 additions & 9 deletions quantstats/_plotting/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
15 changes: 15 additions & 0 deletions tests/test_plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down