一个 Figure、一个 Axes、一条线
图表是判断价格序列是否干净、有趋势或已损坏的最快方法。在 matplotlib 中,Figure 是整块画布,Axes 是画布上的一张图,带有线条、标签和图例。面向对象的写法是 fig, ax = plt.subplots(),之后调用 ax 的方法:ax.plot(x, y) 画线,ax.set_title、ax.set_xlabel 和 ax.set_ylabel 给图命名。在明确的 Axes 上绘图并返回它,会让绘图函数易于复用和测试。
import matplotlib
matplotlib.use("Agg") # draw without a window (no screen needed)
import matplotlib.pyplot as plt
import pandas as pd
prices = pd.Series([100.0, 102, 101, 105, 107, 106, 110], index=pd.bdate_range("2026-03-02", periods=7))
fig, ax = plt.subplots()
ax.plot(prices.index, prices.values, label="AAPL")
ax.set_title("Closing price")
ax.set_xlabel("Date")
ax.set_ylabel("Price (USD)")
print(ax.get_title(), "|", ax.get_xlabel(), "|", ax.get_ylabel()) # Closing price | Date | Price (USD)
print(len(ax.lines), ax.lines[0].get_ydata().tolist()) # 1 [100.0, 102.0, 101.0, 105.0, 107.0, 106.0, 110.0]标签与图例
一张图上有多条线时,每条都需要名字。给 ax.plot 传 label="...",最后调用一次 ax.legend():图例会按绘制顺序列出各标签。没有标签、标题和单位的图只是一幅图片,不是结果。线条也有样式:linestyle="--" 是虚线,适合不该遮住价格的均线,color、linewidth 和 marker 可以进一步调整。
ma = prices.rolling(3).mean()
ax.plot(ma.index, ma.values, label="MA3", linestyle="--")
ax.legend()
print([line.get_label() for line in ax.lines]) # ['AAPL', 'MA3']
print([text.get_text() for text in ax.get_legend().get_texts()]) # ['AAPL', 'MA3']
print(ax.lines[1].get_linestyle(), ax.lines[1].get_ydata().tolist()[:3]) # -- [nan, nan, 101.0] NaN points are simply not drawn参考线,以及看不见的图表
水平线用来标出执行价、止损位或平均值等水平:ax.axhline(105, linestyle="--") 会横贯整张图(axvline 则是竖线)。matplotlib 还能完全不开窗口绘图:使用 Agg 后端时,fig.savefig("chart.png") 把图写入文件,报告和服务器就是这样生成图表的。因为画出的一切都保存在 Axes 对象里,程序(或测试)可以读回来:用 ax.lines 取线条,get_ydata() 取数据,get_label() 取标签,get_title() 取标题。
ax.axhline(105, linestyle=":", label="level")
level_line = ax.lines[-1]
print(list(level_line.get_ydata()), level_line.get_linestyle(), level_line.get_label()) # [105, 105] : level
fig.savefig("prices.png") # writes the chart to a file; no window, no plt.show() needed
plt.close(fig) # release the figure when you are done with itdef plot_prices(prices):
fig, ax = plt.subplots()
ax.plot(prices.index, prices.values)
ax.set_title("Closing price")
return ax # the caller can add lines, save the chart or inspect it
ax = plot_prices(prices)
print(len(ax.lines), ax.get_title()) # 1 Closing price
plt.close("all")关闭你创建的图形每次
plt.subplots() 都会把图形保留在内存中,直到你调用 plt.close(fig)。在要画几百张图的循环或服务器里忘记这一点会泄漏内存,最终触发警告。在函数内创建 Figure,返回调用者需要的对象,并让调用者去关闭它。fig, ax = plt.subplots()然后ax.plot(x, y);用set_title、set_xlabel、set_ylabel给图命名。- 给每条线加
label=并调用ax.legend();linestyle="--"画虚线;ax.axhline(y)画水平线。 - 在 Axes 上绘图并返回它:
ax.lines、get_ydata()、get_label()可读回图表;程序中用savefig和plt.close代替show。
下一节:K线图,绘制每天的开盘、最高、最低和收盘。
实验:评分内容
- 用
plot_prices画出价格折线25 分 - 用
plot_comparison在一张图上比较两个序列25 分 - 用
plot_with_average加上虚线移动平均25 分 - 用
plot_with_level标出价格水平线25 分