Learning Scientific Programming with Python (2nd edition)

E7.14: An annotated plot of a share price

Another example of an annotated plot, this time of the share price of BP plc (LSE: BP) with a couple of notable events added to it. The necessary data for this example can be downloaded as bp-share-prices.csv.

import datetime
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime


def date_to_int(s):
    epoch = datetime(year=1970, month=1, day=1)
    date = datetime.strptime(s, "%Y-%m-%d")
    return (date - epoch).days


dt = np.dtype([("daynum", "i8"), ("close", "f8")])
share_price = np.loadtxt(
    "bp-share-prices.csv",
    skiprows=1,
    delimiter=",",
    usecols=(0, 4),
    converters={0: date_to_int},
    dtype=dt,
)
fig, ax = plt.subplots()
ax.plot(share_price["daynum"], share_price["close"], c="g")
ax.fill_between(
    share_price["daynum"], 0, share_price["close"], facecolor="g", alpha=0.5
)

daymin, daymax = share_price["daynum"].min(), share_price["daynum"].max()
ax.set_xlim(daymin, daymax)

price_max = share_price["close"].max()


def get_xy(date):
    """Return the (x,y) coordinates of the share price on a given date."""
    x = date_to_int(date)
    return share_price[np.where(share_price["daynum"] == x)][0]


# A vertical arrows and labels.
x, y = get_xy("2002-04-30")
ax.annotate(
    "Global oil market\ndownturn",
    (x, y),
    xytext=(x, 725),
    arrowprops=dict(facecolor="black", shrink=0.05, linewidth=0.1),
    ha="center",
)
x, y = get_xy("2010-04-20")
ax.annotate(
    "Deepwater Horizon\noil spill",
    (x, y),
    xytext=(x, 775),
    arrowprops=dict(facecolor="black", shrink=0.05, linewidth=0.1),
    ha="center",
)
x, y = get_xy("2020-03-05")
ax.annotate(
    "Covid pandemic",
    (x, y),
    xytext=(x, 700),
    arrowprops=dict(facecolor="black", shrink=0.05, linewidth=0.1),
    ha="center",
)

years = range(1989, 2026, 2)
ax.set_xticks([date_to_int("{:4d}-01-01".format(year)) for year in years])
ax.set_xticklabels(years, rotation=90)
ax.set_ylim(0, 875)

plt.show()
BP's share price on an annotated chart

BP's share price on an annotated chart.