0

I have a simple matplotlib line chart displaying four timeseries. What I'd like to do is annotate it in two ways:

  1. Change the background color of a region of the plot where there's a different regime, e.g. high volatility period has a light blue rectangle behind the plot
  2. add a green up arrow and a red down arrow at key points in the graph (showing where orders are placed)

I think I know how to add the arrows (see below) but have no idea how to do the "on/off" regions. Any recommendations?

plt.plot(datetime.datetime(2020, 9, 13, 5, 0, 0), 10400, marker=r'$\uparrow$')
  • I think you want something like `axhspan` or `axvspan` like [here](https://stackoverflow.com/questions/9957637/how-can-i-set-the-background-color-on-specific-areas-of-a-pyplot-figure/9957832#9957832). – tom10 Oct 09 '20 at 00:08

1 Answers1

1

As mentioned in the comments, you can use ax.axhspan() and ax.axvspan() to add color to a specific background range. Arrows are set with ax.arrow(x,y,dx,dy), which draws an arrow alone. The sample solution is a customized version of the official reference. matplotlib.axes.Axes.arrow

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.cbook as cbook

years = mdates.YearLocator()   # every year
months = mdates.MonthLocator()  # every month
years_fmt = mdates.DateFormatter('%Y')

data = cbook.get_sample_data('goog.npz', np_load=True)['price_data']

fig, ax = plt.subplots(figsize=(12,9))
ax.plot('date', 'adj_close', data=data, color='g', lw=2.0)

ax.xaxis.set_major_locator(years)
ax.xaxis.set_major_formatter(years_fmt)
ax.xaxis.set_minor_locator(months)

datemin = np.datetime64(data['date'][0], 'Y')
datemax = np.datetime64(data['date'][-1], 'Y') + np.timedelta64(1, 'Y')
ax.set_xlim(datemin, datemax)

ax.format_xdata = mdates.DateFormatter('%Y-%m-%d')
ax.format_ydata = lambda x: '$%1.2f' % x  # format the price.
# update
ax.axvspan(13514,13879, color='skyblue', alpha=0.2)
ax.arrow(13650,550,55,55, zorder=10, width=10, fc='b', ec='b')
ax.arrow(13930,630,25,-55, zorder=10, width=10, fc='red',ec='red')

fig.autofmt_xdate()

plt.show()

enter image description here

r-beginners
  • 31,170
  • 3
  • 14
  • 32
  • @KyleDowney: Since this answers your question, it would be helpful, and a good way to say thanks, to accept the answer (click the checkmark below the number on the upper left) and to up-vote (click the ^ above the number). This is an important part of SO, and is helpful to not only you and the answerer, but to everyone else who reads the question. – tom10 Oct 10 '20 at 00:48
  • My reputation on SO is not high enough to rate your answer in public, but I assure you I have done so. Thank you! – Kyle Downey Jan 03 '21 at 22:02