How to send mplfinance candle stick chart to frontend using flask?

730 Views Asked by At

I'm working on the flask project where I use the mplfinance library to create candlestick charts and I need to pass this chart to the frontend.

@app.route('/chartdata', methods =['POST'])
def chart_data():
    if request.method == 'POST':
        
        body = request.json
        df = pd.read_csv('test_data.csv',index_col=0,parse_dates=True)
        df.index.name = 'Date'
        mplfinance.plot(df, type = 'candle',style ='yahoo',savefig ="sample.png")
        
        return "image to transferred" 

I tried this approach of saving the image and passing it to the front but here I can't avoid chart plot opening, Does anyone knows a better way to transfer these charts to the frontend Html page in this flask project

2

There are 2 best solutions below

3
On

You can save your figure to a io.BytesIO object and send it to the frontend, like here https://mellowd.dev/python/using-io-bytesio/

mplfinance.plot(...) has a savefig parameter for that, see https://github.com/matplotlib/mplfinance/blob/master/src/mplfinance/plotting.py#L171

Something like below, needs to be tested, as mplfinance.plot() does not have a keyword for image format.

import io

@app.route('/chartdata', methods =['POST'])
def chart_data():
    if request.method == 'POST':
        
        body = request.json
        df = pd.read_csv('test_data.csv',index_col=0,parse_dates=True)
        df.index.name = 'Date'
        b = io.BytesIO()
        mplfinance.plot(df, type = 'candle',style ='yahoo', savefig=b)
        return b 
0
On

I am sure this has been solved, but here for posterity.

The important part is to set the backend to use a non-gui method. Also make sure to use send_file do deal with sending back the buffer and filename. These same strategies for for normal matplotlib, just substitute the filename with the io.BytesIO and it will handle it automatically. It seems the python trend is to have it accept a filename, or some sort of stream interface.

This should be a rough approximation of what is desired.

# Use buffer to save object
from io import BytesIO

# Set the matplotlib to a no display backend
import matplotlib
matplotlib.use('agg')

import mplfinance

@app.route('/chartdata', methods =['POST'])
def chart_data():
    if request.method == 'POST':
        body = request.json
        df = pd.read_csv('test_data.csv',index_col=0,parse_dates=True)
        df.index.name = 'Date'

        # The buffer the figure will save to instead of a filename.
        memory_file = BytesIO()
        mplfinance.plot(df, type = 'candle',style ='yahoo',savefig=dict(fname=memory_file, format="png"))

        # seek to the beginning to the buffer because send_file will start at the current io position. 
        memory_file.seek(0)

        # send the file back to the user as an attachment 
        # so it will prompt to download.
        return send_file(memory_file, download_name="sample.png", as_attachment=True)