import pandas as pd import mplfinance as mpf from io import BytesIO import base64 import matplotlib.pyplot as plt def create_mplfinance_chart(df, ticker, predictions=None): """ Creates a custom mplfinance candlestick chart and returns it as a base64 encoded image. Implements the exact layout: Candlestick + Volume + MACD + Stochastic. """ if df.empty: return None # Define style - Yahoo style as requested mc = mpf.make_marketcolors( up='#00ff00', down='#ff0000', # Green/Red candles wick='black', edge='black', volume='#00bfff', inherit=True ) s = mpf.make_mpf_style( base_mpf_style='yahoo', marketcolors=mc, facecolor='white', edgecolor='black', gridcolor='lightgray', gridstyle='-', figcolor='white', rc={'axes.labelcolor': 'black', 'xtick.color': 'black', 'ytick.color': 'black', 'figure.titlesize': 16, 'axes.titlesize': 14, 'axes.titleweight': 'bold'} ) # Define panels: [Candlestick, Volume, MACD, Stochastic] apds = [] # MACD Panel (Panel 2 - index 1 for addplot) # MACD Line apds.append( mpf.make_addplot(df['MACD'], color='#606060', panel=2, ylabel='MACD', secondary_y=False) ) # Signal Line apds.append( mpf.make_addplot(df['MACD_signal'], color='#1f77b4', panel=2, secondary_y=False) ) # Positive Histogram Bars apds.append( mpf.make_addplot(df['MACD_bar_positive'], type='bar', color='#4dc790', panel=2, width=0.8) ) # Negative Histogram Bars apds.append( mpf.make_addplot(df['MACD_bar_negative'], type='bar', color='#fd6b6c', panel=2, width=0.8) ) # Stochastic Panel (Panel 3 - index 2 for addplot) apds.append( mpf.make_addplot(df[['%D', '%SD', 'UL', 'DL']], panel=3, ylabel='Stoch (14,3)', ylim=[0, 100]) ) # Prediction overlay on main chart if predictions is not None and predictions.any(): last_date = df.index[-1] future_index = pd.date_range(start=last_date, periods=len(predictions) + 1, freq=df.index.freq or 'D')[1:] future_series = pd.Series(predictions, index=future_index) apds.append( mpf.make_addplot(future_series, color='blue', linestyle='-.', width=2, marker='o', markersize=4) ) # Plotting fig, axes = mpf.plot( df, type='candle', style=s, title=f'{ticker} Price Chart and Analysis', ylabel='Price (USD)', volume=True, addplot=apds, mav=(5, 20), # Moving averages as requested figratio=(16, 9), figscale=1.5, panel_ratios=(3, 1, 3, 3), # Ratio as requested returnfig=True ) # Convert to Base64 buf = BytesIO() fig.savefig(buf, format='png', bbox_inches='tight', dpi=100) plt.close(fig) image_base64 = base64.b64encode(buf.getvalue()).decode('utf-8') return f''