使用mplfinance绘制共享X轴的多子图时,子图无数据、标题不显示的问题咨询
解决mplfinance多子图带成交量不显示的问题
这个问题我之前折腾过好一会儿,核心原因是:当你开启volume=True时,mplfinance会自动创建两个坐标轴(上方的价格轴+下方的成交量轴),而你之前只传递了一个ax参数,mplfinance没办法正确把内容映射到你手动创建的子图里,最后就导致轴范围被重置成默认的0-1,数据和标题都没显示出来。
下面给你两种靠谱的解决方案,都是我实际用过的:
方案1:用GridSpec手动分配双轴位置(推荐,更灵活)
这种方式直接在matplotlib的画布上给每个币种分配两行空间,分别放价格轴和成交量轴,然后明确告诉mplfinance该用哪个轴:
import mplfinance as mpf from matplotlib import pyplot as plt from matplotlib.gridspec import GridSpec N = len(df_coins) # 创建主画布,高度按子图数量比例设置 fig = plt.figure(figsize=(20, 5*N)) # 生成网格:每个币种占2行(价格+成交量),整列宽度 gs = GridSpec(2*N, 1, figure=fig) for idx, (coin, df) in enumerate(df_coins.items()): # 给当前币种创建价格轴和成交量轴,共享X轴避免重复标签 ax_price = fig.add_subplot(gs[2*idx, 0]) ax_volume = fig.add_subplot(gs[2*idx+1, 0], sharex=ax_price) # 绘制时明确指定价格轴和成交量轴 mpf.plot(df, ax=ax_price, volume_ax=ax_volume, title=coin, type='line', volume=True, show_nontrading=True) # 自动调整子图间距,防止标题和轴标签重叠 plt.tight_layout() plt.show()
方案2:利用mplfinance的returnfig参数整合轴
如果不想手动管理网格,可以让mplfinance自己生成每个图表的轴,再把这些轴移植到主画布上:
import mplfinance as mpf from matplotlib import pyplot as plt N = len(df_coins) fig = plt.figure(figsize=(20, 5*N)) for idx, (coin, df) in enumerate(df_coins.items()): # 让mplfinance返回它生成的图形和坐标轴对象 mpf_fig, mpf_axes = mpf.plot(df, title=coin, type='line', volume=True, show_nontrading=True, returnfig=True) # 取出mplfinance生成的价格轴和成交量轴 ax_price, ax_volume = mpf_axes # 将这两个轴绑定到我们的主画布上 ax_price.figure = fig ax_volume.figure = fig fig.axes.append(ax_price) fig.axes.append(ax_volume) # 设置轴的位置:每个币种占5单位高度,成交量轴高度设为价格轴的1/3 # 这里的坐标是画布的相对位置(0-1) price_pos = [0.1, 1 - (idx+1)*5/fig.get_figheight(), 0.8, 3.5/fig.get_figheight()] vol_pos = [0.1, 1 - (idx+1)*5/fig.get_figheight() + 0.2, 0.8, 1.3/fig.get_figheight()] ax_price.set_position(price_pos) ax_volume.set_position(vol_pos) plt.tight_layout() plt.show()
额外提示
- 如果你不需要成交量图,只传
ax=ax就可以正常工作,但只要开了volume=True,就必须指定volume_ax或者用returnfig=True的方式处理双轴。 - 方案1里的
sharex=ax_price已经帮你实现了共享X轴,不会再出现重复的X标签啦。
内容的提问来源于stack exchange,提问作者P i




