如何通过Flask在HTML页面展示mplfinance生成的股票蜡烛图?
问题:Flask中无法传递mplfinance生成的蜡烛图到前端页面
我正在完成一项学校项目,需使用Flask、在线表单和CSV文件搭建金融股票类网站。通过yfinance库获取股票数据,使用mplfinance绘制蜡烛图,单独测试绘图代码时功能正常,但无法将生成的图表传递至Flask渲染的resultat.html页面,除图表外其他功能均正常。
我的代码
import yfinance as yf import pandas as pd from matplotlib import pyplot as plt import datetime as dt import mplfinance as mpf import csv from flask import Flask, render_template, request with open('nasdaq.csv', 'r') as t: nasdaq_dict = list(csv.DictReader(t, delimiter=';')) stocks_list = [stock['company'] for stock in nasdaq_dict] app = Flask(__name__) @app.route('/') def index(): return render_template('index.html', arr = [stocks_list]) @app.route('/resultat',methods = ['GET', 'POST']) def resultat(): result = request.args stock = result['stock'] date = result['full_date'] index_stock = stocks_list.index(stock) ticker = [ticker['ticker'] for ticker in nasdaq_dict if ticker["company"] == stock] df = yf.download(ticker, period="max", actions=True) filename = stock + ".csv" df.to_csv(filename) file = filename data = pd.read_csv(file) data.Date = pd.to_datetime(data.Date) data = data.set_index('Date') graph = mpf.plot(data, type = 'candle', title = f'{stock}' + 'price', mav = 20, volume=True, tight_layout = True, style = 'yahoo') return render_template("resultat.html", stock = stock, full_date = date, ticker = ticker[0], graph = graph) app.run(debug=True)
问题核心代码片段
df = yf.download(ticker, period="max", actions=True) filename = stock + ".csv" df.to_csv(filename) file = filename data = pd.read_csv(file) data.Date = pd.to_datetime(data.Date) data = data.set_index('Date') graph = mpf.plot(data, type = 'candle', title = f'{stock}' + 'price', mav = 20, volume=True, tight_layout = True, style = 'yahoo') return render_template("resultat.html", stock = stock, full_date = date, ticker = ticker[0], graph = graph)
解决方案
1. 问题根源
mplfinance的plot()方法默认不会返回可直接传递给前端的图表对象,本地测试时它会调用GUI弹出窗口显示图表,但在Flask的无服务器环境中,这个操作不会生成前端能识别的资源,且graph变量实际为None,自然无法在页面渲染。
2. 解决步骤
步骤1:调整代码生成静态图片
- 直接使用yfinance返回的DataFrame,无需存为CSV再读取(冗余步骤)
- 使用mpf.plot的
savefig参数将图表保存到Flask的static目录下(必须,Flask仅允许访问该目录下的静态资源) - 为图片设置唯一文件名,避免不同请求的图表覆盖
修改后的resultat路由代码:
@app.route('/resultat',methods = ['GET', 'POST']) def resultat(): result = request.args stock = result['stock'] date = result['full_date'] ticker = [ticker['ticker'] for ticker in nasdaq_dict if ticker["company"] == stock][0] # 直接使用yfinance返回的df,跳过存CSV再读取的步骤 df = yf.download(ticker, period="max", actions=True) df.index = pd.to_datetime(df.index) # 确保索引是datetime类型 # 生成唯一图片文件名,避免冲突 img_filename = f"{stock}_{dt.datetime.now().strftime('%Y%m%d%H%M%S')}.png" img_path = f"static/{img_filename}" # 绘制图表并保存到static目录 mpf.plot(df, type='candle', title=f'{stock} Price', mav=20, volume=True, tight_layout=True, style='yahoo', savefig=img_path) # 关键:保存为静态图片 return render_template("resultat.html", stock=stock, full_date=date, ticker=ticker, img_filename=img_filename)
步骤2:修改前端模板resultat.html
在模板中添加<img>标签,通过Flask的url_for引用静态图片:
<!DOCTYPE html> <html> <head> <title>Stock Result</title> </head> <body> <h1>{{ stock }} ({{ ticker }})</h1> <p>Date selected: {{ full_date }}</p> <!-- 显示蜡烛图 --> <img src="{{ url_for('static', filename=img_filename) }}" alt="{{ stock }} Candle Chart"> </body> </html>
3. 注意事项
- 确保Flask项目根目录下存在
static文件夹(如果没有,手动创建) - 若请求量较大,可定期清理
static目录下的旧图片,避免占用过多存储空间 - 生产环境中建议使用更高效的存储方式,而非本地静态目录
内容的提问来源于stack exchange,提问作者N43Ltto
相关产品推荐
相关产品推荐

