show_nontrading=False in mplfinance ruins my chart [EDITED

131 views Asked by At

Im creating plots using mplfinance library to plot financial graphs with technical indicators. But I need to hide the gaps coming from weekends or holidays. When trying to hide them by using the argument show_nontrading=False the graph goes out of scale and the x-axis breaks. Here is my code:

def plot_mplfinance(self, path):
        from matplotlib.ticker import MaxNLocator
        from matplotlib.dates import MonthLocator, DateFormatter
        from matplotlib.ticker import FixedLocator
        from matplotlib.gridspec import GridSpec
        import os
        import warnings
        warnings.filterwarnings("ignore")
        try:
            cmf= self.CMF().dropna()
            sma_cmf= self.sma_aux(20, cmf).SMA
            sma_cmf= sma_cmf.iloc[19:]
            fallacmf=False
        except: #Esto ocurrirá cuando Eikon no traiga datos de volumen
            fallacmf=True
        macd = self.MACD(12,26,9)
        rsi = self.RSI(14)
        rsi=rsi.iloc[13:]
        macd= macd[['MACD','Signal','Histogram']]
        sma_df= self.SMA(20)
        sma_df= sma_df.iloc[19:]
        psar_df= self.PSAR()
        psarbull= psar_df["PSAR_BULL"]
        psarbear= psar_df["PSAR_BEAR"]
        os.chdir(path)
        prices= self.prices[['Open','High','Low','Adj Close','Volume']]
        prices.columns= ['Open','High','Low','Close','Volume']
        last_price = prices['Close'].iloc[-1]
        fig = plt.figure(figsize=(11.692913385826772, 8))  # Ajusta el tamaño según tus necesidades
        if fallacmf==False:
            gs = GridSpec(5, 1, height_ratios=[3, 1, 1, 1, 1])
        
            # Subplot superior para el gráfico de precios con PSAR y SMA
            ax1 = plt.subplot(gs[0])
            ax0 = plt.subplot(gs[1], sharex=ax1)
            mpf.plot(prices, type='candle', style='yahoo', figscale=1.5, volume=ax0, show_nontrading=True, tight_layout=False, returnfig=True, ax=ax1)
            ax1.set_title(f'{self.ticker} - Último precio ${last_price:.2f}', fontsize=15, loc='center')
        
            ax1.plot(psarbull.index, psarbull, 'o', markersize=1, color="blue", label='Up Trend')
            ax1.plot(psarbear.index, psarbear, 'o', markersize=1, color="red", label='Down Trend')
            ax1.plot(sma_df.index, sma_df.SMA, color="green", label='SMA 20', linewidth=1.0)
            ax1.axhline(y=last_price, color='gray', linestyle='--', linewidth=1.0, label='Último precio')
    
            ax2 = plt.subplot(gs[2], sharex=ax1)  # Compartir el mismo eje X con el subplot superior
            ax2.plot(macd.index, macd['MACD'], color="green", label="MACD (12,26)")
            ax2.plot(macd.index, macd['Signal'], color="lightgreen", label="Signal Line (9)")
            ax2.fill_between(macd.index, macd['Histogram'], color='g', alpha=0.5, label="Histogram")
            
            ax3 = plt.subplot(gs[3], sharex=ax1)  # Compartir el mismo eje X con el subplot superior
            ax3.plot(rsi.index, rsi['RSI'], color="purple", label="RSI (14)")
            ax3.set_ylim(0, 100)
            ax3.axhline(y=30, color='gray', linestyle='--', linewidth=1.0)
            ax3.axhline(y=70, color='gray', linestyle='--', linewidth=1.0)
        
            ax4 = plt.subplot(gs[4], sharex=ax1)  # Compartir el mismo eje X con el subplot superior
            ax4.plot(cmf.index, cmf, color="orange", label="CMF")
            ax4.plot(sma_cmf.index, sma_cmf, color="brown", label='SMA 20')
        # Configurar etiquetas, leyendas, etc. para ambos subplots según tus necesidades
        # Remove x-axis from ax1
            ax1.get_xaxis().set_visible(False)  # Eliminar la etiqueta del eje X del subplot superior
            ax0.get_xaxis().set_visible(False)
            ax2.get_xaxis().set_visible(False)
            ax3.get_xaxis().set_visible(False)
            
            ax1.tick_params(axis='y', labelleft=True, labelright=False)
            ax1.yaxis.set_ticks_position('left')
            ax1.yaxis.set_label_position("left")
            
            ax1.set_ylabel('Precios')
            ax2.set_ylabel('MACD')
            ax3.set_ylabel('RSI')
            ax4.set_ylabel('CMF')
            
            ax1.grid(True)
            ax2.grid(True)
            ax3.grid(True)
            ax4.grid(axis='y')
            
            for ax in [ax1, ax0, ax2, ax3, ax4]:
                for spine in ax.spines.values():
                    spine.set_visible(False)
                
            lines1, labels1 = ax1.get_legend_handles_labels()
            lines2, labels2 = ax2.get_legend_handles_labels()
            lines3, labels3 = ax3.get_legend_handles_labels()
            lines4, labels4 = ax4.get_legend_handles_labels()
            
            ax1.legend(lines1, labels1, loc='upper left', fontsize=8)
            ax2.legend(lines2, labels2, loc='upper left', fontsize=8)
            ax3.legend(lines3, labels3, loc='upper left', fontsize=8)
            ax4.legend(lines4, labels4, loc='upper left', fontsize=8)

Then this graph comes out:

When changing the argument to show_nontrading=False, the image completely breaks and i don't know how to fix it so I can hide non-trading days... does anyone know? Here is what happens when I put the non-trading days as False: non-trading=False

UPDATE: Now i changed some of the code, changed the way I plot:

prices= self.prices[['Open','High','Low','Adj Close','Volume']]
prices.columns= ['Open','High','Low','Close','Volume']
last_price = prices['Close'].iloc[-1]
try:
    cmf= self.CMF().dropna()
    sma_cmf= self.sma_aux(20, cmf).SMA
    sma_cmf= sma_cmf.iloc[19:]
    prices['CMF']= cmf
    prices['SMA_CMF']= sma_cmf
    fallacmf=False
except: #Esto ocurrirá cuando Eikon no traiga datos de volumen
    fallacmf=True
macd = self.MACD(12,26,9)
rsi = self.RSI(14)
rsi=rsi.iloc[13:]
prices['RSI']= rsi["RSI"]
macd= macd[['MACD','Signal','Histogram']]
prices= pd.merge(prices, macd, left_index=False, right_index=False, on='Date',how='left')
sma_df= self.SMA(20)
sma_df= sma_df.iloc[19:]
prices= pd.merge(prices, sma_df, left_index=False, right_index=False, on='Date',how='left')

psar_df= self.PSAR()
psarbull= psar_df["PSAR_BULL"]
psarbear= psar_df["PSAR_BEAR"]
prices['PSAR_BULL']= psarbull
prices['PSAR_BEAR']= psarbear



# Agregar elementos adicionales a los subgráficos
ap = [
      mpf.make_addplot(prices['PSAR_BULL'], type='scatter', panel=0, markersize=0.5, color='blue',label='PSAR Bull'),
      mpf.make_addplot(prices['PSAR_BEAR'], type='scatter', panel=0, markersize=0.5, color='red',label='PSAR Bear'),
      mpf.make_addplot(prices['SMA'],panel=0,color='green', label='SMA (20)'),
      
      mpf.make_addplot(prices['MACD'],panel=2,color='green', label='MACD (12,26)',secondary_y=False,ylabel='MACD'),
      mpf.make_addplot(prices['Signal'],panel=2,color='lightgreen', label='Signal Line (9)',secondary_y=False),
      mpf.make_addplot(prices['Histogram'],type='bar',width=0.7,panel=2, color='g',alpha=1,secondary_y=False),
      
      mpf.make_addplot(prices['RSI'], panel=3, color='violet', label='RSI (14)', ylabel='RSI'),
      
      mpf.make_addplot(prices['CMF'],panel=4,color='orange', label='CMF (21)',secondary_y=False,ylabel='CMF'),
      mpf.make_addplot(prices['SMA_CMF'],panel=4,color='brown', label='SMA (20)',secondary_y=False)
]

save = dict(fname='ypf.png', dpi=300, pad_inches=0.25)
# Graficar los precios con los elementos adicionales
mpf.plot(prices, volume=True, addplot=ap, xrotation=0, type='candle',style='yahoo',ylabel_lower='Shares\nTraded', figratio=(12,8), 
figscale=1.2, tight_layout=True, show_nontrading=False, panel_ratios=(4,2,2,2,2), savefig=save) #title=f'{self.ticker} - Último precio ${last_price:.2f}'

And now this is the image I have, much better! New_Plot

My only question now is how to change the y-axis in the subplots, how to change the size of the RSI y-axis for instance from 0 to 100, and to add horizontal lines in the 30 and 70 level, etc. Also im seeing in the MACD graph that the legend goes to the right, is there any way of specifying legend location?

2

There are 2 answers

1
Daniel Goldfarb On

My only question now is how to change the y-axis in the subplots, how to change the size of the RSI y-axis for instance from 0 to 100, and to add horizontal lines in the 30 and 70 level, etc. Also im seeing in the MACD graph that the legend goes to the right, is there any way of specifying legend location?

See mplfinance plot customizations for various simple plot customizations. What may not be there, that you may also need is kwarg ylim= which you may need for the RSI (for example, set ylim=(0,100)).

See also using lines for information about placing horizontal and vertical lines on the plot.

Are you saying that loc='upper left' is not working for the MACD subplot?

0
Agustin Amador Ehrman On

I solved this by using plt.subplots and, just in case, I reset the index and saved it again as DatetimeIndex. Here is the final code:

prices= self.prices[['Open','High','Low','Adj Close','Volume']]
        prices.columns= ['Open','High','Low','Close','Volume']
        last_price = prices['Close'].iloc[-1]
        try:
            cmf= self.CMF().dropna()
            sma_cmf= self.sma_aux(20, cmf).SMA
            sma_cmf= sma_cmf.iloc[19:]
            prices['CMF']= cmf
            prices['SMA_CMF']= sma_cmf
            fallacmf=False
        except: #Esto ocurrirá cuando Eikon no traiga datos de volumen
            fallacmf=True
        macd = self.MACD(12,26,9)
        rsi = self.RSI(14)
        rsi=rsi.iloc[13:]
        prices['RSI']= rsi["RSI"]
        macd= macd[['MACD','Signal','Histogram']]
        prices= pd.merge(prices, macd, left_index=False, right_index=False, on='Date',how='left')
        sma_df= self.SMA(20)
        sma_df= sma_df.iloc[19:]
        prices= pd.merge(prices, sma_df, left_index=False, right_index=False, on='Date',how='left')

        psar_df= self.PSAR()
        psarbull= psar_df["PSAR_BULL"]
        psarbear= psar_df["PSAR_BEAR"]
        prices['PSAR_BULL']= psarbull
        prices['PSAR_BEAR']= psarbear
        prices= prices.reset_index(drop=False)
        prices.index= pd.DatetimeIndex(prices['Date'])
        
        if fallacmf==False:
            fig , ax =plt.subplots(5,1,sharex=True,figsize=(11.692913385826772, 8),gridspec_kw= {'height_ratios':[3,1,1,1,1]})

            ap = [
                  mpf.make_addplot(prices['PSAR_BULL'], type='scatter', ax=ax[0], markersize=0.5, color='blue',label='PSAR Bull'),
                  mpf.make_addplot(prices['PSAR_BEAR'], type='scatter', ax=ax[0], markersize=0.5, color='red',label='PSAR Bear'),
                  mpf.make_addplot(prices['SMA'],ax=ax[0],color='green', label='SMA (20)'),
                  
                  mpf.make_addplot(prices['MACD'],ax=ax[2],color='green', label='MACD (12,26)',secondary_y=False,ylabel='MACD'),
                  mpf.make_addplot(prices['Signal'],ax=ax[2],color='lightgreen', label='Signal Line (9)',secondary_y=False),
                  mpf.make_addplot(prices['Histogram'],type='bar',width=0.7,ax=ax[2], color='g',alpha=1,secondary_y=False),
                  
                  mpf.make_addplot(prices['RSI'], ax=ax[3], color='violet', label='RSI (14)', ylabel='RSI',ylim=(0, 100)),
                  
                  mpf.make_addplot(prices['CMF'], ax=ax[4],color='orange', label='CMF (21)',secondary_y=False,ylabel='CMF'),
                  mpf.make_addplot(prices['SMA_CMF'], ax=ax[4],color='brown', label='SMA (20)',secondary_y=False)
            ]
            mpf.plot(prices, type='candle',ax=ax[0],addplot=ap, volume=ax[1],xrotation=0,style='yahoo')
            ax[0].axhline(y=last_price, color='gray', linestyle='--', linewidth=1.0, label='Last Price')
            ax[0].set_title(f'{self.ticker} - Último precio ${last_price:.2f}', fontsize=15, loc='center')
            ax[3].set_ylim(0, 100)
            ax[3].axhline(y=30, color='gray', linestyle='--', linewidth=1.0)
            ax[3].axhline(y=50, color='gray', linestyle='--', linewidth=1.0)
            ax[3].axhline(y=70, color='gray', linestyle='--', linewidth=1.0)
            ax[0].legend(loc='upper left', fontsize=8)
            ax[2].legend(loc='upper left', fontsize=8)
            ax[3].legend(loc='upper left', fontsize=8)
            ax[4].legend(loc='upper left', fontsize=8)
plt.savefig(f'{self.ticker}.png', bbox_inches='tight', dpi=300)
        plt.close()