Matplotlib股票均线图条件背景色偏移问题原因排查
问题原因与修复方案
核心问题分析
你的代码出现背景色偏移、错误渲染的原因有三个:
- x轴坐标不匹配:matplotlib处理时间序列时会把datetime索引转为内部浮点值,但
pcolorfast默认从x=0开始映射数据,和实际x轴的日期坐标完全错位,导致颜色块和数据点偏移半个区间,末尾颜色对应错误。 - NaN的错误渲染:
pcolorfast不会自动忽略NaN值,而是用颜色映射的邻接值或中间值填充NaN区域,前9个无EMA的NaN数据被错误渲染成红色。 - 区间映射逻辑不匹配:
pcolorfast是为二维网格设计的,每个数据值对应一个矩形区间(x从i到i+1),但你的折线图是基于离散点绘制的,两者的位置逻辑不兼容。
修复后的代码
from yahoo_fin import stock_info as si import talib import numpy as np import matplotlib.pyplot as plt import matplotlib.dates as mdates sym = 'SBUX' data = si.get_data(sym, start_date='01/01/2022') data['ma10'] = talib.EMA(data['close'], 10) conditions = [(data['close'] / data['ma10'] - 1 > 0.05), (data['close'] / data['ma10'] - 1 < -0.05)] values = [1, -1] data['above_below'] = np.select(conditions, values, default=0) # 用0替换NaN,对应黄色中间色 fig, ax = plt.subplots() # 绘制收盘价和均线 ax.plot(data.close, label='Close') ax.plot(data.ma10, label='10-day EMA') # 将datetime索引转为matplotlib的数值坐标 x = mdates.date2num(data.index) # 生成pcolorfast需要的x区间边界(n个点对应n+1个边界) x_bounds = np.concatenate([x, [x[-1] + (x[1] - x[0])]]) # 获取y轴的上下限 y_bounds = ax.get_ylim() # 绘制背景色,确保x区间和数据点对齐,设置vmin/vmax固定颜色映射 ax.pcolorfast(x_bounds, y_bounds, data['above_below'].values[np.newaxis], cmap='RdYlGn', vmin=-1, vmax=1, alpha=0.3) # 添加图例和格式化x轴日期 ax.legend() ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m')) plt.xticks(rotation=45) plt.tight_layout() plt.show()
关键修改说明
- 替换NaN为0:把
default=np.nan改成default=0,这样无EMA的区域会显示黄色(RdYlGn的中间色),避免错误填充邻接颜色。如果想让这些区域透明,可以用np.ma.masked_invalid(data['above_below'])生成掩码数组,pcolorfast会忽略掩码区域。 - 匹配x轴坐标:用
mdates.date2num把日期转为matplotlib的数值坐标,再生成包含区间边界的x_bounds,确保每个颜色块对应两个相邻日期之间的区间,和折线图的点位置完全对齐。 - 固定颜色映射范围:设置
vmin=-1和vmax=1,保证1对应绿色、-1对应红色,不会因为数据分布变化导致颜色偏移。
内容的提问来源于stack exchange,提问作者RazzleDazzle
相关产品推荐
相关产品推荐

