Jack022
Jack022

Reputation: 1257

How to add a patch on a Matplotlib/Matplotlib finance chart?

I created a candlestick chart using the following:

fig, axlist = mpf.plot(df, type='candle', returnfig=True)

Now i'm trying to add a rectangle that goes from a certain point of the x axis to another point of the x axis at y position. Now, the data on the x axis is dates, while the data on the y axis are prices.

I tried the following:

ax1 = axlist[0]

new_patch = Rectangle(xy=(0, 9300), width=0.8, height=0.3, angle=0, color='orange')
ax1.add_patch(new_patch)
ax1.autoscale_view()

Which works, the problem is that i don't want to use a number to choose the position of X. In Rectangle(xy=(0, 9300), insted of using 0, i want to use a date, like Rectangle(xy=('2020-06-17 10:30', 9300), but that will throw me an error: x must be an int.

Here is a sample of the dataframe i'm using to chart:

                                   Date     Open     High      Low    Close      Volume
Date
2020-06-17 19:10:00 2020-06-17 19:10:00  9402.02  9411.03  9400.00  9403.59  215.630925
2020-06-17 19:15:00 2020-06-17 19:15:00  9403.59  9412.54  9403.01  9410.57  108.958008
2020-06-17 19:20:00 2020-06-17 19:20:00  9410.16  9413.66  9409.06  9411.88  107.795579

To summarise: i need to plot a patch on my chart, i can place this patch on the x axis using a number, but instead i want to use a date. Is there any way to do so?

Edit: i tried the solution suggested here, but it didn't work:

date = datetime.datetime(2020, 6, 19, 10, 30)
testDate = mdates.date2num(date)
print(testDate)

new_patch = Rectangle(xy=(testDate, 9370), width=1, height=0.3, angle=0, color='orange')
ax1.add_patch(new_patch)
ax1.autoscale_view()

As it gave me an absurd result:

Upvotes: 1

Views: 541

Answers (1)

micmalti
micmalti

Reputation: 571

Different libraries, different implementations

mplfinance can only generate a plot if the dataframe uses a DatetimeIndex; that's why it's necessary to use pd.to_datetime beforehand. When you fitted this plot into a matplotlib figure to apply a patch to it, matplotlib couldn't process the x values as dates since they weren't presented to it as such.

What it did instead was to replace them with a list of integer values starting with 0. That's why when you've assigned the x-value of the patch to testDate i.e. 737595.4375, everything was squashed once you auto-scaled the x-axis.

The solution

One way to resolve this issue is to store the dataframe Date column in an indexed array and then retrieve the index of the matching date:

unique_index = pd.Index(df["Date"])
start_x = unique_index.get_loc('2020-06-17 19:10:00')

In case you'd want to draw the patch at a date that's missing in the dataframe, you'd have to locate the index that's directly before the starting point and add to any number between 0 and 1.

Upvotes: 2

Related Questions