0

I am trying to change the axis titles and font size in multiple charts that are plotted using mpf.plot and fig.add_axes to place them on screen.

I have understood the process and examples given in this link How to change font size and font type in mplfinance title and on the github discussing the approach, but it will not work with my code. Anywhere I put "returnfig=True" it causes errors.

Here is my code snippet of the relevant section

fig = mpf.figure(figsize=(12,8),style='yahoo')

ax1 = fig.add_axes([0.05,0.70,0.3,0.25]) # ax = fig.add_axes([left,bottom,width,height])
ax2 = fig.add_axes([0.05,0.65,0.3,0.05])

ax3 = fig.add_axes([0.36,0.70,0.3,0.25])
ax4 = fig.add_axes([0.36,0.65,0.3,0.05])

ax5 = fig.add_axes([0.68,0.70,0.3,0.25])
ax6 = fig.add_axes([0.68,0.65,0.3,0.05])

ax7 = fig.add_axes([0.05,0.25,0.3,0.25])
ax8 = fig.add_axes([0.05,0.20,0.3,0.05])

ax9 = fig.add_axes([0.36,0.25,0.3,0.25])
ax10 = fig.add_axes([0.36,0.20,0.3,0.05])

ax11 = fig.add_axes([0.68,0.25,0.3,0.25])
ax12 = fig.add_axes([0.68,0.20,0.3,0.05])

mpf.plot(ausd,type='candle',ax=ax1,volume=ax2, mav=(9), show_nontrading=False, axtitle='M6A=F')
mpf.plot(gbpf,type='candle',ax=ax3,volume=ax4, mav=(9), show_nontrading=False, axtitle='M6B=F')
mpf.plot(cadf,type='candle',ax=ax5,volume=ax6, mav=(9), show_nontrading=False, axtitle='M6E=F')
mpf.plot(btcf,type='candle',ax=ax7,volume=ax8, mav=(9), show_nontrading=False, axtitle='M6C=F')
mpf.plot(gldf,type='candle',ax=ax9,volume=ax10, mav=(9), show_nontrading=False, axtitle='MBT=F')
mpf.plot(slvf,type='candle',ax=ax11,volume=ax12, mav=(9), show_nontrading=False, axtitle='MGC=F')
mdkb
  • 372
  • 1
  • 14

2 Answers2

2

The are two ways to gain access to the Figure and Axes objects that mplfinance uses. These two ways are documented here.

1. If you use returnfig=True it means that mpf.plot() is creating the Figure and Axes objects internally, and returning them to you for further manipulation before you eventually call mpf.show() or fig.savefig() to complete the plot.

2. However, if you create your own Figure and Axes objects externally to mpf.plot(), even if you use mpf.figure() to create the Figure object, then mpf.plot() does not own the Figure and Axes objects, and so cannot return them to you!
In fact, you already have them and own them so there is no point to returning them! This is why, when mpf.plot() detects that you have passed Axes into it (thus it is in "External Axes Mode") then it will reject the kwarg returnfig because in that context it doesn't make any sense to return a Figure and Axes that you already have.

Daniel Goldfarb
  • 6,937
  • 5
  • 29
  • 61
  • Your explanation gave me a deeper understanding of the external axis. – r-beginners Jul 05 '22 at 13:45
  • I had worked to that linked document originally, but found by using `fig.add_subplot` I was unable to get multiple charts to work in the way you see in the code above, but by using `fig.add_axes` it did work. In the comments above I noted that I found a workaround to styling and all but the ability to remove labels from axes. At this point my choice is to scrap the entire code and go back to trying to use `fig.add.subplot` which I spent a day failing to get working, or solve that last puzzle of how to remove axes labels with my current code, albeit the "discouraged" method. – mdkb Jul 06 '22 at 00:35
  • You said "returning them to you for further manipulation before you eventually call mpf.show() or fig.savefig() to complete the plot." - I was using `plt.show()`, I assume this is the same thing when coding outside of notebooks? – mdkb Jul 06 '22 at 00:40
  • 1
    Yes, `mpf.show()` is the same as `plt.show()` as you can [see here](https://github.com/matplotlib/mplfinance/blob/master/src/mplfinance/_mplwraps.py#L31-L33). The idea is that, by providing `mpf` versions of some of the pyplot functions, then many mplfinance users are able to do a variety of manipulations without ever having to `import matplotlib.pyplot` – Daniel Goldfarb Jul 06 '22 at 03:47
1

I understand that returnfig=True is required if you want to access each of the panels when they are set up. My understanding may still be lacking. If you set up a subplot with additional axes, I don't think you need returnfig=True. Completing the graph with the ticker in the previous question would result in the following code. I introduced loop processing, shortened the long date format, and reduced the orientation of the ticker.

myTickers = ['M6A=F','M6B=F','M6C=F','M6E=F','MBT=F','MGC=F']
fig = mpf.figure(figsize=(12,12), style='yahoo')

ax1 = fig.add_axes([0.05,0.70,0.25,0.25]) 
ax2 = fig.add_axes([0.05,0.60,0.25,0.08])

ax3 = fig.add_axes([0.36,0.70,0.25,0.25])
ax4 = fig.add_axes([0.36,0.60,0.25,0.08])

ax5 = fig.add_axes([0.68,0.70,0.25,0.25])
ax6 = fig.add_axes([0.68,0.60,0.25,0.08])

ax7 = fig.add_axes([0.05,0.25,0.25,0.25])
ax8 = fig.add_axes([0.05,0.15,0.25,0.08])

ax9 = fig.add_axes([0.36,0.25,0.25,0.25])
ax10 = fig.add_axes([0.36,0.15,0.25,0.07])

ax11 = fig.add_axes([0.68,0.25,0.25,0.25])
ax12 = fig.add_axes([0.68,0.15,0.25,0.08])

for i,(t,ax) in enumerate(zip(myTickers,[[ax1,ax2],[ax3,ax4],[ax5,ax6],[ax7,ax8],[ax9,ax10],[ax11,ax12]])):
    dff = df.loc[:,t]
    mpf.plot(dff, type='candle',
             ax=ax[0],
             volume=ax[1],
             mav=(9),
             show_nontrading=False,
             axtitle=t,
             datetime_format='%b %d',
             xrotation=30)
    
for ax in [ax1,ax3,ax5,ax7,ax9,ax11]:
    ax.set_xticklabels([])

enter image description here

r-beginners
  • 31,170
  • 3
  • 14
  • 32
  • That solves what was going to be my next question of how to loop the code better and how to format the date (my 5-min charts have time as well), so thank you. I was actually looking for ways to format the styling e.g. font, size, color and plot background color, etc... – mdkb Jul 05 '22 at 07:04
  • in the code where you write "for i,(t,ax) in enumerate(zip(myTickers...." how would you change that if you had 12 myTickers but only wanted the first 6? – mdkb Jul 05 '22 at 07:20
  • 1
    I use a list limited to 6 tickers out of 12 tickers to handle the tickers and the axis to be expanded in a loop process, but to handle them in a loop process, you can do the following. `for i,(t,ax) in enumerate(zip(myTickers[:6],[[ax1,ax2],...)` – r-beginners Jul 05 '22 at 07:51
  • 1
    See here for a [detailed description](https://github.com/matplotlib/mplfinance/blob/master/examples/styles.ipynb) of how to customize graph styles. – r-beginners Jul 05 '22 at 07:54
  • That link helped with some additional changes. I also found a workaround through using bespoke chartstyles and rcparam like this - `myrcparams={'axes.labelsize':'x-small','axes.titlesize':'small'}` and then `mystyle = mpf.make_mpf_style(base_mpf_style='yahoo', marketcolors=chartColors, rc=myrcparams)` I was then able to add style in using `fig = mpf.figure(figsize=(12,8), style=mystyle)` The only thing left to figure out how to do is remove the duplicate date info from the x-axis of the charts. – mdkb Jul 05 '22 at 11:27
  • 1
    In response to comments from the mplfinance developer, we have also addressed how to remove the date of the remaining issues. This is now complete, including your additional modifications. code and graph updated – r-beginners Jul 06 '22 at 07:35
  • thanks was perfect. one little tweak... I added this bit of code to lock in the x-axis as the volume charts tended to drift ```ax1 = fig.add_axes([0.05,0.70,0.3,0.25])``` ```ax2 = fig.add_axes([0.05,0.60,0.3,0.05], sharex=ax1)``` unfortunately with the additional code to remove the labels that you added, the ```sharex=ax1``` also forces the effect on both ax1 and ax2 even if specify only removing the labels from one. ```for ax in [ax1,ax3,ax5,ax7,ax9,ax11]: ax.set_xticklabels([])``` – mdkb Jul 06 '22 at 22:43