如何用mplfinance将OHLC图X轴设置为固定季度刻度?
问题与解决方案
问题
编写程序为指定资产生成OHLC价格图时,需要将X轴刻度设置为每年固定月份的季度形式(如1、4、7、10月),但遇到以下问题:
- 使用
MonthLocator(interval=3)时,刻度起始月份不固定,无法满足需求; - 使用
DateFormatter('%b %Y')时,出现日期标签重叠,甚至显示1969年错误日期的问题。
解决方案
关键修复点
- 固定季度刻度位置:使用
MonthLocator(bymonth=[1,4,7,10])直接指定每年的季度起始月份,替代interval=3的方式,确保刻度始终落在1、4、7、10月。 - 解决标签重叠与错误日期:
- 应用
DateFormatter('%b %Y')格式化日期标签,并通过旋转标签、调整对齐方式避免重叠; - 确保数据索引为有效datetime类型,同时限定刻度生成范围在数据的起始与结束日期之间,避免无效时间戳导致的1969年错误。
- 应用
修改后的完整代码
import mplfinance as mpf import yfinance as yf import matplotlib.pyplot as plt from datetime import datetime from matplotlib.ticker import MaxNLocator from matplotlib.dates import MonthLocator, DateFormatter import pandas as pd import os # 补充缺失的os导入 #%% Creamos la clase que grafica la lista de activos que desee ver, desde la fecha que querramos. class Grafico: def __init__(self, assets, start_date): self.assets = assets self.start_date = start_date self.end= datetime.now() self.start=datetime.strptime(self.start_date, '%Y-%m-%d') self.days=(self.end-self.start).days self.CCL= self.CCL_f() def CCL_f(self): GGAL=yf.download('GGAL', start=self.start_date) GGAL_BA=yf.download('GGAL.BA',start=self.start_date) CCL=(GGAL_BA/GGAL)*10 return CCL def plot(self): for file in os.listdir(): #Esto borrará los archivos viejos, para que cada vez que se ejecute el programa aparezcan en carpeta los gráficos que se quieren descargar if file.endswith('.png'): try: os.remove(file) except Exception as e: print(f'Error deleting {file}: {e}') for asset in self.assets: if ".BA" in asset: data = yf.download(asset, start=self.start_date, end=self.end) data= data/self.CCL self.data=data if asset=="BYMA.BA": self.data= self.data.drop("2018-12-31") else: data = yf.download(asset, start=self.start_date, end=self.end) self.data=data fig, ax = mpf.plot(self.data, type='candle', style='classic',figscale=1.5, tight_layout=False, returnfig=True) fig.set_size_inches(11.692913385826772,8) ax[0].yaxis.set_major_locator(MaxNLocator(nbins=30)) # --- 修复X轴刻度的核心代码 --- # 指定固定季度月份的刻度定位器 locator = MonthLocator(bymonth=[1,4,7,10]) # 设置刻度显示范围为数据的起止日期 locator.set_axis(ax[0].xaxis) locator.set_view_interval(*ax[0].get_xlim()) # 设置日期格式 formatter = DateFormatter('%b %Y') ax[0].xaxis.set_major_locator(locator) ax[0].xaxis.set_major_formatter(formatter) # 旋转X轴标签,避免重叠 plt.setp(ax[0].get_xticklabels(), rotation=45, ha='right', fontsize=5) # --- 核心代码结束 --- ax[0].tick_params(axis='y', labelsize=5) last_price = self.data['Close'].iloc[-1] ax[0].axhline(y=last_price, linestyle='--', color='k',linewidth=0.5) ax[0].set_title(f'{asset} - (Last {self.days} days)',fontsize=15, loc='center') plt.savefig(f'{asset}.png',bbox_inches='tight', dpi=300)
说明
MonthLocator(bymonth=[1,4,7,10])强制刻度仅出现在每年的1、4、7、10月,彻底解决起始月份不固定的问题;plt.setp(ax[0].get_xticklabels(), rotation=45, ha='right')将标签旋转45度并右对齐,有效避免日期重叠;- 通过
locator.set_view_interval(*ax[0].get_xlim())限定刻度生成范围,避免无效时间戳导致的1969年错误日期显示。
内容的提问来源于stack exchange,提问作者Agustín Ehrman
相关产品推荐
相关产品推荐

