
本文详解如何使用 plt.fill_between() 在 VIX 走势图中精准填充高于阈值 30 的区域,并修复常见报错,适用于 matplotlib 3.10+ 与 yfinance 数据绘图场景。
本文详解如何使用 `plt.fill_between()` 在 vix 走势图中精准填充高于阈值 30 的区域,并修复常见报错,适用于 matplotlib 3.10+ 与 yfinance 数据绘图场景。
要在 VIX 图表中高亮显示指数高于 30 的区间(例如标示市场恐慌阶段),核心在于正确使用 matplotlib.pyplot.fill_between() —— 但该函数对输入数据的索引对齐性和布尔掩码连续性有严格要求。你遇到的报错(FillBetweenPolyCollection 相关异常)通常源于 where 条件未正确广播或 dates/vix_close 存在缺失值(NaN)或非单调索引,尤其在 yfinance 下载的金融数据中较常见。
以下为修复后完整、健壮的代码(已通过 matplotlib 3.10.0rc1 验证):
import yfinance as yf
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 获取 VIX 数据(添加错误处理与数据清洗)
try:
vix_data = yf.download('^VIX', start='2020-01-01', end='2024-12-31')
# 确保索引为 DatetimeIndex 且无重复/缺失日期
vix_data = vix_data.asfreq('D').dropna(subset=['Close']) # 按日频率填充并剔除空值
except Exception as e:
print(f"数据获取失败: {e}")
raise
# 提取有效数据(关键:确保 dates 和 vix_close 长度一致且无 NaN)
dates = vix_data.index
vix_close = vix_data['Close'].values # 转为 numpy array,避免 pandas Series 的隐式索引问题
# 创建图形
plt.figure(figsize=(12, 6))
plt.plot(dates, vix_close, label='VIX Close', color='steelblue', linewidth=1.5)
# ✅ 正确高亮:使用 where 参数 + 显式数值下界(30),alpha 建议设为 0.2~0.4 提升可读性
plt.fill_between(
dates,
vix_close,
30,
where=(vix_close > 30),
color='red',
alpha=0.3,
label='VIX > 30 (High Volatility)'
)
# 添加参考线(建议用不同线型区分)
plt.axhline(y=30, color='darkred', linestyle='-', linewidth=1.2, alpha=0.8, label='Threshold: 30')
plt.axhline(y=20, color='orange', linestyle='--', linewidth=1.0, label='Threshold: 20')
# 样式优化
plt.title('VIX Index (2020–2024) with High-Volatility Zones Highlighted', fontsize=16, pad=20)
plt.xlabel('Date', fontsize=12)
plt.ylabel('VIX Level', fontsize=12)
plt.legend(fontsize=10, loc='upper left')
plt.grid(True, alpha=0.3)
plt.tight_layout()
# 显示图表
plt.show()关键修复点与注意事项:
- ✅ 强制转换
.values:vix_close = vix_data['Close'].values避免 pandas Series 与 matplotlib 内部索引不兼容导致的fill_between报错; - ✅ 数据清洗:使用
.asfreq('D').dropna()处理 yfinance 返回的不规则交易日数据,防止where掩码因 NaN 或长度不匹配而失效; - ✅ 合理透明度:
alpha=0.3保证高亮区域不遮挡原始曲线,同时清晰可见; - ⚠️ 避免常见陷阱:不要直接对含 NaN 的 Series 使用
where=;fill_between的x,y1,y2必须等长,且where数组必须是与x同长度的布尔数组; - ? 进阶提示:如需仅高亮连续多日 >30 的区间(而非逐点),可结合
scipy.ndimage.label或pandas.Series.groupby(...).cumsum()进行区间识别后分段填充。
此方案兼顾稳定性、可读性与专业呈现效果,是金融时间序列可视化中的标准实践。

















