You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 09:02:07