看净值与回撤
用 snapshot + drawdown 组合,先看整体净值走势,再定位最大回撤出现在哪个阶段、跌了多深,是复盘策略的第一组图。
QuantStats · plots 模块
quantstats.plots 提供约 17 种绘图:snapshot 综合快照、drawdown 回撤、monthly_heatmap 月度热力图、rolling_beta/sharpe/sortino/volatility 滚动指标、distribution/histogram 分布等,帮你可视化绩效结构。
QuantStats plots 绘图分类示意;基于官方 README,非实测图表。
quantstats.plots 的完整方法列表可用 [f for f in dir(qs.plots) if f[0] != '_'] 查看;以下按展示内容与使用场景展开,具体以官方 README 为准。
| 绘图 | 方法 | 展示内容 | 使用场景 |
|---|---|---|---|
| 综合快照 | qs.plots.snapshot(stock) | 净值曲线 + 回撤 + 核心指标总览 | 快速了解策略整体表现,作为第一张图 |
| 回撤 | qs.plots.drawdown(stock) | 历史回撤水下曲线 | 评估策略的亏损深度与修复时间 |
| 回撤区间 | qs.plots.drawdowns_periods(stock) | 标注每次回撤的起止区间 | 定位哪些阶段发生了显著回撤 |
| 月度热力图 | qs.plots.monthly_heatmap(stock) | 按年月排列的收益热力矩阵 | 识别季节性/哪些月份赚或亏 |
| 年度收益 | qs.plots.yearly_returns(stock) | 各年度收益率柱状 | 比较不同年份的绩效强弱 |
| 滚动 beta | qs.plots.rolling_beta(stock, benchmark) | 相对基准的滚动敏感度曲线 | 观察策略对市场/基准的暴露是否漂移 |
| 滚动夏普/索提诺/波动 | qs.plots.rolling_sharpe / rolling_sortino / rolling_volatility | 风险调整收益与波动的时间序列 | 评估绩效是否稳定,避免只看单点指标 |
| 收益分布 | qs.plots.distribution(stock) | 收益率的分布曲线 | 判断收益是否正态、尾部是否肥厚 |
| 直方图 | qs.plots.histogram(stock) | 收益率频数直方图 | 直观查看收益集中在哪些区间 |
| 收益/对数收益 | qs.plots.returns / log_returns / daily_returns | 累计收益、对数收益、日收益曲线 | 查看收益的时间演化与日度波动 |
| 蒙特卡洛图 | qs.plots.montecarlo / montecarlo_distribution | 模拟路径与模拟分布 | 可视化风险的概率分布(详见蒙特卡洛页) |
[f for f in dir(qs.plots) if f[0] != '_']),再对照官方仓库 README 与更新日志确认;本页按官方 README 的分类整理,安装版本不同时以你本机打印出的结果为准。1. 导入并扩展 pandas:import quantstats as qs; qs.extend_pandas() —— 扩展后可 stock.plot_snapshot() 直接调用。
2. 获取收益序列:stock = qs.utils.download_returns('META') —— 或传入你自己的日/周/月收益率 Series。
3. 画综合快照:qs.plots.snapshot(stock, title='Meta Performance', show=True) —— 生成净值+回撤+指标总览图。
4. 画回撤与热力图:qs.plots.drawdown(stock)、qs.plots.monthly_heatmap(stock) —— 分别看亏损深度与月度分布。
| 分类 | 包含绘图 | 分析目的 |
|---|---|---|
| 走势类 | snapshot / returns / log_returns / daily_returns / earnings | 看净值与收益如何随时间累积、日度如何波动 |
| 回撤类 | drawdown / drawdowns_periods | 量化亏损深度与回撤发生的时间区间 |
| 分布类 | distribution / histogram | 检查收益分布形态与尾部风险 |
| 滚动类 | rolling_beta / rolling_sharpe / rolling_sortino / rolling_volatility | 看风险调整收益与基准暴露是否随市场漂移 |
| 周期/汇总类 | monthly_heatmap / yearly_returns | 看月度/年度表现,识别季节性与强弱年份 |
| 蒙特卡洛类 | montecarlo / montecarlo_distribution | 用模拟分布做概率化风险分析 |
1. 安装可选依赖:pip install plotly>=5.0 —— plotly 为可选项,不装不影响其他绘图。
2. 转交互图:qs.plots.to_plotly() —— 把当前静态图转成可缩放/悬停的 Plotly 图。
3. 适用场景:需要交互式查看数据点、嵌入网页或 Notebook 展示时使用。
| 维度 | 静态图(matplotlib) | 交互图(Plotly) |
|---|---|---|
| 额外依赖 | 装库即带(matplotlib 是必需依赖) | 需另装 plotly>=5.0 |
| 适合场景 | 报告、归档、批量出图 | 自己探索数据、Notebook 内逐步讲解 |
| 输出形式 | PNG / SVG 等图片文件 | 可缩放、可悬停的 HTML 组件 |
| 保存与分享 | savefig 落盘后当附件发 | 导出 HTML 后嵌网页或内网页面 |
| 文件体量 | 小,适合塞进文档与邮件 | 大,数据点多时文件明显变大 |
| 与报告的关系 | HTML 报告里内嵌的就是静态图 | 报告默认不出交互图,需单独转换(以官方实现为准) |
用 snapshot + drawdown 组合,先看整体净值走势,再定位最大回撤出现在哪个阶段、跌了多深,是复盘策略的第一组图。
monthly_heatmap 一眼看清哪些月份赚钱/亏损,yearly_returns 比较各年强弱,帮助识别策略的季节性或某年失效。
rolling_sharpe/sortino 观察风险调整收益是否随时间稳定,rolling_beta 看基准暴露是否漂移,避免被单点指标误导。
下面几类问题在用 quantstats.plots 出图时最常见,官方 README 只记录了其中一部分,其余需要自己按顺序排查。
| 现象 / 报错特征 | 触发条件 | 原因 | 处置 |
|---|---|---|---|
| no display name and no $DISPLAY environment variable | 在服务器 / 容器 / 无桌面环境跑绘图 | matplotlib 默认后端要连图形界面 | 在 import quantstats 之前先 import matplotlib; matplotlib.use('Agg'),并把图落盘而不是依赖 show=True |
| 图上中文变成方框或乱码 | title / 标签里写了中文 | matplotlib 默认字体不含中文字形 | 指定中文字体(plt.rcParams['font.sans-serif'])或标题改用英文;QuantStats 默认标题是 ticker,一般不触发 |
| ModuleNotFoundError: No module named 'plotly' | 调用 qs.plots.to_plotly() | plotly 是可选依赖,装 quantstats 时不会自动带上 | pip install plotly>=5.0,或继续用静态 matplotlib 图 |
| AttributeError: module 'quantstats.plots' has no attribute ... | 照抄网上示例里的方法名 | 实际版本与示例版本不一致 | 先 [f for f in dir(qs.plots) if f[0] != '_'] 列出现有方法,再对照官方文档确认 |
| 图是空白 / 没有曲线 | 收益序列含大量 NaN,或索引不是时间索引 | 绘图依赖 DatetimeIndex 与有效数值 | 检查 stock.isna().sum() 与 stock.index;先补齐或去噪再画 |
| 第二次出图把第一次的图覆盖了 | 连续出图没改文件名 | 落盘路径同名直接覆盖 | 文件名带策略名与日期;Windows 下路径含中文或空格时加引号或用 pathlib 拼 |
| Notebook 里图不显示或显示了两次 | 交互后端与 show=True 混用 | 同一份图被内联与弹窗各渲染一次 | 明确只用一种方式:要么内联显示,要么 savefig 落盘;批量任务统一用落盘 |
图不是越多越好:一张图只讲一件事,先定场景再选图。
| 场景 | 优先看哪类图 | 为什么 | 注意点 |
|---|---|---|---|
| 给客户或同事汇报 | snapshot + yearly_returns | 一屏讲清整体表现,再用年度柱状讲长期强弱 | 只放 1–2 张主图,其余进附录;项目自带的 HTML 报告里已内嵌同款图 |
| 自查回撤深浅 | drawdown + drawdowns_periods | 前者看水下深度,后者定位回撤发生在哪段行情 | 回撤由收益率序列算出,与逐笔成交亏损口径不同 |
| 判断收益是否接近正态 | distribution + histogram | 看偏度与尾部是否肥厚,决定要不要看尾部风险指标 | 样本期太短时分布形态不可信 |
| 看风险调整收益是否稳定 | rolling_sharpe / rolling_sortino / rolling_volatility | 滚动窗口能暴露「单一期末指标好看」的假象 | 窗口长度会改变结论,汇报时要写明窗口口径 |
| 看季节性、哪些月份赚亏 | monthly_heatmap | 年×月矩阵一眼看出收益分布与集中亏损月 | 年份少时所谓规律可能只是偶然 |
| 看对市场的暴露是否漂移 | rolling_beta(需传基准序列) | beta 漂移说明策略风格或杠杆变了,不是原来的策略 | 没有基准收益序列时这张图没有意义 |
| 概率化地看待风险 | montecarlo / montecarlo_distribution | 用模拟分布估计破产与达标概率,补足单条净值曲线的不足 | 模拟概率不等于真实概率,详见蒙特卡洛页 |
把图一次落盘并按规范命名,省掉反复手工截图。
1. 先切无界面后端:import matplotlib; matplotlib.use('Agg') —— 服务器或定时任务里避免尝试调用图形界面;应在 import quantstats 之前执行。
2. 出单张图并落盘:qs.plots.snapshot(stock, title='META', savefig='out/meta_snapshot.png') —— plots 下多数方法带 savefig 参数(支持情况与参数名以官方 README 为准),预期在 out/ 目录看到 PNG 文件。
3. 一次出整套图:qs.reports.plots(stock, mode='full') —— 批量绘图模式,mode 可切 basic / full,适合一次性生成图集。
4. 出完释放资源:import matplotlib.pyplot as plt; plt.close('all') —— 连续跑几十张图时避免内存持续上涨。
| 图 | 建议落盘文件名 | 归档用途 |
|---|---|---|
| snapshot | 策略名_snapshot_日期.png | 月度复盘封面、汇报首页 |
| drawdown | 策略名_drawdown_日期.png | 回撤复盘与风控留档 |
| monthly_heatmap | 策略名_monthly_年份.png | 年度总结里的月度表现页 |
| rolling_sharpe | 策略名_rolling_sharpe_窗口.png | 稳定性说明,需同时备注窗口长度 |
| yearly_returns | 策略名_yearly_截止年.png | 多年绩效对比 |
| distribution | 策略名_dist_日期.png | 尾部风险讨论与策略对比 |
约 17 种:snapshot、drawdown、monthly_heatmap、rolling_beta/sharpe/sortino/volatility、distribution、histogram、returns、yearly_returns、montecarlo 等,完整列表以 dir(qs.plots) 与官方 README 为准。
安装可选依赖 plotly≥5.0 后,可用 qs.plots.to_plotly() 转为交互式 Plotly 图;未安装 plotly 不影响静态图功能,具体以官方 README 为准。
可用 savefig 参数控制保存;部分图(如 monthly_heatmap)在保存时可能仍会弹出显示,属官方 README Known Issues 记录的已知问题,以官方文档为准。
EasyClaw 的 stock-technical-mastery 技能画的是 A股 K 线/技术指标图(MACD/RSI/布林带),面向 A股技术分析;它画的是任意收益序列的绩效图(回撤/热力图/滚动指标)。两者覆盖的市场与分析对象不同,输出也不能互相替代(集成状态见页脚披露)。
不能。图仅可视化历史收益序列,不构成收益保证或投资建议;实盘需自行核验数据与风险。
可以。先把后端切到 Agg(import matplotlib; matplotlib.use('Agg')),再正常调用绘图方法并用 savefig 落盘,全程不需要显示器;这是把它接进定时任务或数据管道的前提。
常见。图上算的是你喂进去那条收益序列的区间收益,是否含手续费与滑点、是否复权、分红如何计入都由数据口径决定,与绘图本身无关。先对齐数据口径再对比图,否则容易把口径差异当成策略差异。