matplotlib / mplfinance

Financial Markets Data Visualization using Matplotlib
https://pypi.org/project/mplfinance/
Other
3.7k stars 634 forks source link

Side-by-Side Plots #318

Open debjyotiarr opened 3 years ago

debjyotiarr commented 3 years ago

Hello, I'm quite new to mplfinance, but I am enjoying using it. I can plot the stock data, macd data, rsi and volume for one stock in a plot. However, I would like it if I could plot 4 or 5 similar plots side-by-side, so that they can be glanced at one go.

I am attaching two plots I made of two Indian stocks. It would be nice if I could arrange these sideways in one large plot.

Thanks in advance.

axis_bank download

DanielGoldfarb commented 3 years ago

Hi @debjyotiarr

Nice job on those plots.

I have considered, in addition to kwarg panel, adding a kwarg for panel_column to be able to create multiple side-by-side plots, but presently this is not availble.

However there are two workarounds:

The first workaround is is to use external axes mode. The advantage of this method is that you have full control over all aspects of the plot. The main disadvantage is that you will have to write extra code if you want to line up the panels nicely as in your examples, since you will not be able to benefit from mplfinance doing that for you. (The reason mplfinance can't do that when in external axes mode is because, since the axes are passed in, mplfinance has no control over where the axes are placed on the figure. See, for example, cell Out[16]: of the above mentioned external axes mode notebook where the volume panels are separate plots from the candlestick plots; however it is possible to line up the axes nicely, similar to what mplfinance does in panels mode, but you would have the write the code to do that yourself.).

The second workaround is simpler, but still involves a bit of code. The idea is to save each plot as an image, and then create a matplotlib Figure with side-by-side Axes, and display each plot image on each of the Axes. Here is a an example where, instead of writing to disk, the plots are saved in memory as BytesIO objects:

import pandas            as pd
import mplfinance        as mpf
import matplotlib.pyplot as plt
import matplotlib.image  as m_img
import io

# Read the data:
df = pd.read_csv('data/SP500_NOV2019_Hist.csv',index_col=0,parse_dates=True)

# Save three plots to in-memory files:
sav1 = io.BytesIO()
sav2 = io.BytesIO()
sav3 = io.BytesIO()
mpf.plot(df,volume=True,style='checkers',savefig=sav1)
mpf.plot(df,volume=True,style='default',savefig=sav2)
mpf.plot(df,volume=True,style='yahoo',savefig=sav3)

# Rewind the files:
_ = sav1.seek(0)
_ = sav2.seek(0)
_ = sav3.seek(0)

# Read the files as images:
img1 = m_img.imread(sav1)
img2 = m_img.imread(sav2)
img3 = m_img.imread(sav3)

# Create three side-by-side Axes:
fig = plt.figure(figsize=(21,7))
ax1 = fig.add_subplot(131)
ax2 = fig.add_subplot(132)
ax3 = fig.add_subplot(133)

# Turn the axis lines and labels off since the images will already contain them
ax1.set_axis_off()
ax2.set_axis_off()
ax3.set_axis_off()

# Plot each image on a separate axes:
ax1.imshow(img1)
ax2.imshow(img2)
ax3.imshow(img3)
plt.show()

The result looks like this: Figure_1

HTH. All the best. --Daniel

DanielGoldfarb commented 3 years ago

And ... using your images as files on disk:

img1 = m_img.imread('axisbank.png')
img2 = m_img.imread('hdfcbank.png')
fig = plt.figure(figsize=(14,7))
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
ax1.set_axis_off()
ax2.set_axis_off()
ax1.imshow(img1)
ax2.imshow(img2)
plt.show()

The result:

Figure_2

debjyotiarr commented 3 years ago

Hi @DanielGoldfarb Thank you for your detailed reply and for the mplfinance package as a whole. I had kind of hit upon the second of your solutions and I am glad to see you suggest the same. This works fine for me right now.

Thanks again.

smjure commented 2 years ago

@debjyotiarr @DanielGoldfarb much needed feature :+1: