4. 数据可视化基础

数据可视化,说白了就是给枯燥的数字穿上漂亮的外衣。我刚开始做量化的时候,整天对着密密麻麻的行情数据,眼睛都快瞎了。后来才明白——你没法靠肉眼从一万个数字里找出规律,但一张图就能让你秒懂趋势。

这一章,咱们就聊聊怎么把数据变成图表。我会从最基础的 Matplotlib 讲起,再到专业的 K 线图绘制,最后聊聊交互式图表。嗯,都是我在实战中反复用到的工具。

4.1 Matplotlib 基础绘图

Matplotlib 是 Python 可视化的老大哥。几乎所有其他可视化库,底层都离不开它。我个人习惯把它当作「画板」,其他库都是「画笔」。

先看一个最简单的折线图:

import matplotlib.pyplot as plt
import numpy as np

# 模拟收盘价
days = np.arange(1, 31)
prices = 100 + np.cumsum(np.random.randn(30) * 2)

plt.plot(days, prices)
plt.title('模拟收盘价走势')
plt.xlabel('交易日')
plt.ylabel('价格')
plt.show()

这段代码跑出来,你会看到一条上下波动的曲线。但说实话,这种图在量化里用处不大——太粗糙了。

我的小技巧: 在 Jupyter Notebook 里,记得加一行 %matplotlib inline,否则图可能不显示。我当年被这个坑过,折腾了半小时。

Matplotlib 的核心概念就三个:Figure(画布)、Axes(坐标系)、Axis(坐标轴)。你可以把 Figure 想象成一张白纸,Axes 是纸上画图的位置,Axis 就是横轴纵轴上的刻度。

来个多子图的例子:

fig, axes = plt.subplots(2, 2, figsize=(10, 6))

axes[0, 0].plot(days, prices, 'b-')
axes[0, 0].set_title('收盘价')

axes[0, 1].hist(prices, bins=15, color='green', alpha=0.7)
axes[0, 1].set_title('价格分布')

axes[1, 0].plot(days, prices.cumsum(), 'r--')
axes[1, 0].set_title('累计收益')

axes[1, 1].scatter(days, prices, s=20, c='purple')
axes[1, 1].set_title('散点图')

plt.tight_layout()
plt.show()

你看,一个画布上放四个图,对比起来特别方便。我在做策略回测时,经常把净值曲线、回撤曲线、持仓比例放在一起看。

4.2 K 线图绘制(mplfinance)

做量化交易,K 线图是绕不开的。Matplotlib 原生画 K 线很麻烦,得自己画矩形和线条。好在有个专门的库——mplfinance,一行代码就能搞定。

先安装:

pip install mplfinance

然后准备数据。mplfinance 要求数据格式是 pandas DataFrame,索引是日期,列名必须包含 Open、High、Low、Close、Volume:

import pandas as pd
import mplfinance as mpf

# 模拟数据
dates = pd.date_range('2024-01-01', periods=100, freq='D')
data = pd.DataFrame({
    'Open':   np.random.uniform(100, 110, 100),
    'High':   np.random.uniform(105, 115, 100),
    'Low':    np.random.uniform(95, 105, 100),
    'Close':  np.random.uniform(100, 110, 100),
    'Volume': np.random.randint(1000, 5000, 100)
}, index=dates)

# 画K线
mpf.plot(data, type='candle', volume=True, style='charles')
注意: 实际数据中,High 必须大于等于 Open 和 Close,Low 必须小于等于。我遇到过数据源有误,导致 K 线图出现「倒挂」的情况,排查了半天才发现是数据问题。

mplfinance 支持多种样式。我个人喜欢用 style='yahoo',红绿配色看着舒服。你还可以加均线:

mpf.plot(data, type='candle', volume=True, 
         mav=(5, 10, 20), style='yahoo')

mav 参数就是移动平均线,传入一个元组,分别表示 5 日、10 日、20 日均线。嗯,这个在技术分析里太常用了。

4.3 技术指标可视化

光看 K 线还不够,咱们得把技术指标叠加上去。这里以均线和布林带为例。

4.3.1 均线叠加

其实 mplfinance 自带的 mav 参数就能画均线。但如果你想自定义颜色、线型,就得自己算:

# 自己计算均线
data['MA5'] = data['Close'].rolling(5).mean()
data['MA20'] = data['Close'].rolling(20).mean()

# 用 Matplotlib 画
plt.figure(figsize=(12, 6))
plt.plot(data.index, data['Close'], label='收盘价', alpha=0.6)
plt.plot(data.index, data['MA5'], label='5日均线', linewidth=1.5)
plt.plot(data.index, data['MA20'], label='20日均线', linewidth=1.5)
plt.legend()
plt.title('收盘价与均线')
plt.show()

这里有个坑:rolling 窗口期内的前几个值会是 NaN。比如 5 日均线,前 4 天没有值。画图时 Matplotlib 会自动跳过 NaN,但如果你要做计算,记得用 dropna() 处理。

4.3.2 布林带

布林带由中轨(20日均线)、上轨(中轨+2倍标准差)、下轨(中轨-2倍标准差)组成。代码实现:

# 计算布林带
data['Middle'] = data['Close'].rolling(20).mean()
data['Std'] = data['Close'].rolling(20).std()
data['Upper'] = data['Middle'] + 2 * data['Std']
data['Lower'] = data['Middle'] - 2 * data['Std']

# 画图
plt.figure(figsize=(12, 6))
plt.plot(data.index, data['Close'], label='收盘价', color='blue', alpha=0.5)
plt.plot(data.index, data['Middle'], label='中轨', color='orange', linestyle='--')
plt.plot(data.index, data['Upper'], label='上轨', color='red', linestyle=':')
plt.plot(data.index, data['Lower'], label='下轨', color='green', linestyle=':')
plt.fill_between(data.index, data['Upper'], data['Lower'], alpha=0.1, color='gray')
plt.legend()
plt.title('布林带')
plt.show()
避坑指南: 我曾经在实盘策略里直接用默认参数(20, 2),结果发现某些波动率极高的品种,价格频繁突破上下轨。后来我改成用 21 日均线和 2.5 倍标准差,效果好了很多。参数不是死的,得根据品种调整。

4.4 交互式图表(Plotly 基础)

静态图有个问题——你没法缩放、悬停看数值。尤其是做回测分析时,我想看某一天的详细数据,静态图就无能为力了。这时候 Plotly 就派上用场了。

Plotly 生成的图表是 HTML 格式,可以在浏览器里交互。安装:

pip install plotly

来个交互式 K 线图:

import plotly.graph_objects as go

fig = go.Figure(data=[go.Candlestick(
    x=data.index,
    open=data['Open'],
    high=data['High'],
    low=data['Low'],
    close=data['Close'],
    name='K线'
)])

fig.update_layout(
    title='交互式K线图',
    xaxis_title='日期',
    yaxis_title='价格',
    xaxis_rangeslider_visible=False  # 去掉底部滑块
)

fig.show()

鼠标悬停在 K 线上,会显示当天的 O、H、L、C 数据。还能用滚轮缩放,拖拽平移。说实话,自从用了 Plotly,我回测时基本不用静态图了。

再加个均线:

fig.add_trace(go.Scatter(
    x=data.index, y=data['MA5'],
    mode='lines', name='5日均线',
    line=dict(color='orange', width=1)
))

fig.add_trace(go.Scatter(
    x=data.index, y=data['MA20'],
    mode='lines', name='20日均线',
    line=dict(color='purple', width=1)
))

fig.show()
我的习惯: 在 Jupyter Notebook 里用 fig.show() 会直接显示交互图。如果要在网页上展示,可以用 fig.write_html('chart.html') 保存成独立文件。我经常把回测结果生成 HTML 图表,发给团队同事看,他们不用装 Python 也能打开。

4.5 本章知识体系

下面这张图,帮你理清数据可视化的核心脉络:

数据可视化知识体系 数据可视化 Matplotlib 基础 Figure / Axes / Axis 折线图 / 直方图 / 散点图 多子图布局 mplfinance K线图 蜡烛图 / 成交量 内置均线 (mav参数) 多种样式 (yahoo/charles) 技术指标可视化 均线 (MA5/MA20) 布林带 (中轨/上下轨) 自定义参数调整 Plotly 交互式图表 悬停显示 / 缩放 / 拖拽 导出独立HTML文件

从这张图能看出来,四个分支层层递进。先掌握 Matplotlib 的基础概念,再学专业的 K 线绘制,然后叠加技术指标,最后用交互式图表提升分析效率。我个人建议的学习顺序也是这样——别一上来就搞 Plotly,先把静态图玩明白。


好了,数据可视化的基础就聊到这儿。记住一句话:图表是给人类看的,不是给机器看的。做量化交易,你首先要让自己看懂数据,然后才能让策略跑起来。下一章咱们会聊更高级的可视化技巧,但今天这些内容,足够你应付大部分日常分析了。

课后练习: 找一段真实的股票日线数据(比如从 Tushare 或 AKShare 获取),用 mplfinance 画出带 10 日和 30 日均线的 K 线图,再用 Plotly 生成交互版本。对比一下两种方式的优缺点。
专注资料整理