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

PyQt5集成mplfinance绘图时设置volume=True报错的解决求助

问题说明

在PyQt5窗口中使用mplfinance绘制K线图时,设置volume=True以显示成交量时触发错误:ValueError: volumemust be of typematplotlib.axis.Axes`。仅绘制K线图时功能正常,工具栏与画布联动无问题。

原因分析

当手动向mpf.plot()传入自定义的ax参数时,mplfinance要求volume参数不能是布尔值True,必须指定一个专门用于渲染成交量的Matplotlib Axes对象——因为此时mplfinance不会自动创建成交量子图,需要开发者提前准备好对应的Axes。

解决步骤

  1. 调整画布的Axes布局:初始化时创建两个Axes,分别用于K线和成交量,通过gridspec设置上下布局比例。
  2. 更新绘图方法:每次绘图前清除两个Axes的内容,调用mpf.plot()时将volume参数指向成交量Axes。
  3. 确保工具栏同步更新:绘图完成后刷新工具栏,保证导航功能正常。

修改后的完整代码

import sys
import pandas as pd
import mplfinance as mpf
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton
from matplotlib.backends.backend_qt5agg import (
    FigureCanvasQTAgg as FigureCanvas,
    NavigationToolbar2QT as NavigationToolbar)
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec


class MyMplCanvas(FigureCanvas):
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        self.fig = plt.figure(figsize=(width, height), dpi=dpi)
        # 创建GridSpec,设置K线图占3份,成交量占1份
        gs = GridSpec(2, 1, height_ratios=[3, 1])
        self.ax_kline = self.fig.add_subplot(gs[0])
        self.ax_volume = self.fig.add_subplot(gs[1], sharex=self.ax_kline)
        super().__init__(self.fig)
        self.setParent(parent)


class MyDynamicMplCanvas(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.plot1_button = QPushButton("Plot 1")
        self.plot1_button.clicked.connect(self.plot1)
        self.plot2_button = QPushButton("Plot 2")
        self.plot2_button.clicked.connect(self.plot2)

        self.canvas = MyMplCanvas(self, width=5, height=4, dpi=100)
        self.toolbar = NavigationToolbar(self.canvas, self)

        vbox = QVBoxLayout()
        vbox.addWidget(self.toolbar)
        vbox.addWidget(self.canvas)
        vbox.addWidget(self.plot1_button)
        vbox.addWidget(self.plot2_button)

        self.setLayout(vbox)
        
        
    def getData(self, iisin):
        if iisin == 'A':
            pfad = '/path/to/file/Qt/DE000A0DJ6J9_4qs.csv'
        else:
            pfad = '/path/to/file/Qt/DE000A0DJ6J9_2qs.csv'
            
        data = pd.read_csv(pfad, header=0, sep='|', encoding='utf-8')
        data.index = pd.to_datetime(data['Datum'])
        data.rename(columns={'TradesSum': 'Volume'}, inplace=True)
        return data
    
        
    def plot1(self):
        # 清除两个Axes的内容
        self.canvas.ax_kline.clear()
        self.canvas.ax_volume.clear()
    
        mpf.plot(data=self.getData('A'), 
                  ax=self.canvas.ax_kline,
                  volume=self.canvas.ax_volume,
                  type='candle', style='yahoo',
                  mav=(20, 38, 50), returnfig=True)
        
        # 重新关联导航工具栏
        self.toolbar.update()
    
        # 在画布上显示绘图
        self.canvas.draw()
    
    
    def plot2(self):
        # 清除两个Axes的内容
        self.canvas.ax_kline.clear()
        self.canvas.ax_volume.clear()
    
        # 从CSV文件加载数据并绘图
        data = self.getData('B')
        mpf.plot(data=data, 
                  ax=self.canvas.ax_kline,
                  volume=self.canvas.ax_volume,
                  type='candle', style='yahoo',
                  mav=(20, 38, 50), returnfig=True)
        
        # 重新关联导航工具栏
        self.toolbar.update()
    
        # 在画布上显示绘图
        self.canvas.draw()



if __name__ == '__main__':
    app = QApplication(sys.argv)

    main_window = QWidget()
    main_layout = QVBoxLayout()
    main_window.setLayout(main_layout)

    mpl_widget = MyDynamicMplCanvas()
    main_layout.addWidget(mpl_widget)

    main_window.show()

    sys.exit(app.exec_())

关键修改点说明

  • 画布初始化:使用GridSpec创建两个Axes,设置高度比例为3:1,保证K线图为主视图,成交量为辅助视图,同时通过sharex=self.ax_kline让两个子图共享X轴,联动缩放。
  • 绘图参数:将volume参数从True改为self.canvas.ax_volume,指定成交量的渲染Axes。
  • 清除逻辑:每次绘图前同时清除K线和成交量Axes的内容,避免残留旧数据。

内容的提问来源于stack exchange,提问作者finny

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 07:32:21