GaiaEx AcademyGaiaEx Academy
用 Pandas、NumPy 与 Matplotlib 做数据分析
开发者编程12 min read

用 Pandas、NumPy 与 Matplotlib 做数据分析

像量化分析师一样清洗、转换并可视化金融数据

分享文章

NumPy:引擎盖下的发动机

在 Python 里,每一项严肃的金融计算最终都要经过 NumPy。Python 列表虽然灵活,却很慢——每个元素都是一个完整的 Python 对象,带有类型检查的开销。NumPy 数组把原始数字存储在连续的内存块里,使得运算速度比纯 Python 循环快 100 倍

下面是实际中的差别:

import numpy as np

# Create an array of 1 million random daily returns
returns = np.random.normal(0.0005, 0.02, 1_000_000)

# Vectorized operations — no loops needed
cumulative = np.cumprod(1 + returns)  # Growth of $1
sharpe = returns.mean() / returns.std() * np.sqrt(252)
max_drawdown = np.min(cumulative / np.maximum.accumulate(cumulative) - 1)

print(f"Sharpe Ratio: {sharpe:.3f}")
print(f"Max Drawdown: {max_drawdown:.2%}")

面向金融的关键 NumPy 概念:

  • 向量化运算 — 一次性把数学运算应用到整个数组,而不是逐个元素循环。
  • 广播(Broadcasting) — 自动对齐不同形状的数组以做算术运算(例如,从每个元素中减去一个标量均值)。
  • 线性代数np.linalg 提供矩阵乘法、特征值分解,以及投资组合优化中用到的求解器。
  • 随机抽样 — 蒙特卡洛模拟、自助抽样(bootstrap)和随机建模都依赖 np.random

性能提示:永远优先使用向量化的 NumPy 运算,而非 Python for 循环。一项涵盖 500 个资产的投资组合优化,用循环要跑 30 秒,用向量化的 NumPy 不到 50 毫秒就能完成——提速 600 倍。

NumPy:连续内存 + 向量化运算 ndarray — dtype、shape、strides(C 连续存储) 在 C/Fortran 里跑一个循环,而不是上百万步 Python 字节码 广播:对齐形状以做逐元素运算 例如收益率向量 − 标量均值,或 (n,) 与 (n, m) 矩阵各行运算 linalg:cov、eig、solve — 投资组合数学就在这里
数组是快速通道;广播则让你不写循环也能保持代码可读。

Pandas:用于金融数据的 DataFrame

如果说 NumPy 是发动机,那 pandas 就是仪表盘。它把 NumPy 数组包装进带标签、带索引的结构里,让金融数据的处理变得直观又富有表达力。

两个核心结构是:

  • Series — 带索引的单列数据(可以想象成一组收盘价的时间序列)。
  • DataFrame — 由多列组成的表格,每一列都是一个 Series,共享同一个索引(可以想象成 OHLCV 的 K 线数据)。

加载和查看数据非常直接:

import pandas as pd

# Read from CSV
df = pd.read_csv("btc_daily.csv", parse_dates=["date"], index_col="date")

# Or from JSON (common in API responses)
df = pd.read_json("https://api.example.com/candles?symbol=ETH")

# Quick inspection
print(df.shape)          # (365, 5)
print(df.dtypes)         # Column types
print(df.describe())     # Statistical summary
print(df.tail())         # Last 5 rows

让 pandas 在金融中不可或缺的,是它的 DatetimeIndex。一旦你的索引是日期时间类型,就能解锁强大的时间序列操作:

# Slice by date range
q1_data = df["2025-01":"2025-03"]

# Resample daily data to weekly OHLC
weekly = df["close"].resample("W").ohlc()

# Forward-fill missing data (weekends, holidays)
df = df.asfreq("D").ffill()

这些操作能处理金融数据中混乱的现实问题——缺口、时区差异、不规则的时间戳——让你能专注于分析,而不是数据管线的搭建。

滚动计算:移动平均线与波动率

金融分析天然是窗口化的。你很少会孤立地关注单个数据点——上下文来自它与近期历史的关系。pandas 的 .rolling() 方法就是这里的主力工具。

import pandas as pd
import numpy as np

# Assume df has a "close" column with DatetimeIndex
df["sma_20"] = df["close"].rolling(20).mean()
df["sma_50"] = df["close"].rolling(50).mean()
df["ema_12"] = df["close"].ewm(span=12).mean()

# Daily returns and rolling volatility
df["returns"] = df["close"].pct_change()
df["vol_30d"] = df["returns"].rolling(30).std() * np.sqrt(365)

# Bollinger Bands
df["bb_upper"] = df["sma_20"] + 2 * df["close"].rolling(20).std()
df["bb_lower"] = df["sma_20"] - 2 * df["close"].rolling(20).std()

# Rolling correlation between two assets
df["corr_btc_eth"] = df["btc_returns"].rolling(60).corr(df["eth_returns"])

每位交易者都该掌握的关键滚动计算:

  • 简单移动平均线(SMA) — 对 N 个周期做等权平均。滞后但稳定。
  • 指数移动平均线(EMA) — 通过 .ewm() 给近期数据更高的权重。对价格变化更敏感。
  • 滚动波动率 — 在一个窗口内对收益率取标准差,再年化。对仓位规模和风险预算至关重要。
  • 滚动相关性 — 衡量两个资产随时间一起波动的程度。对投资组合的分散投资至关重要。

GaiaEx 这样的平台上,你可以通过交易 API 拉取历史 K 线数据,加载进 pandas DataFrame,几秒钟就能算出这些指标——而你的资产始终安全地放在你的 MPC 钱包里。

用 GroupBy 与聚合做投资组合分析

当你管理多个资产时,.groupby() 就变得不可或缺。它让你按类别拆分数据、应用计算、再合并结果——也就是拆分-应用-合并(split-apply-combine)模式。

# DataFrame with multiple assets
trades = pd.DataFrame({
    "symbol": ["BTC", "ETH", "BTC", "SOL", "ETH", "BTC"],
    "side": ["buy", "buy", "sell", "buy", "sell", "buy"],
    "pnl": [120.5, -45.2, 89.0, 210.3, 55.8, -30.1],
    "volume": [5000, 3200, 4800, 1500, 2900, 5100],
})

# Performance by asset
summary = trades.groupby("symbol").agg(
    total_pnl=("pnl", "sum"),
    avg_pnl=("pnl", "mean"),
    trade_count=("pnl", "count"),
    total_volume=("volume", "sum"),
    win_rate=("pnl", lambda x: (x > 0).mean()),
)

print(summary.sort_values("total_pnl", ascending=False))

用于投资组合工作的进阶聚合模式:

  • 多级 groupby — 同时按 symbol side 分组,查看每个资产的多头与空头表现。
  • 自定义聚合函数 — 为每个资产组计算夏普比率、索提诺比率或最大回撤。
  • 透视表 — 用 pd.pivot_table() 重塑数据,以便于热力图展示的格式查看各资产的月度收益率。
  • 结合 groupby 的重采样 — 把基于时间的重采样与分类分组结合,做多资产的时间序列分析。

Matplotlib:绘制价格走势与信号

没有可视化的数据,就只是一堆数字。Matplotlib 把你的分析变成图表,揭示那些在原始数据中看不见的形态。

import matplotlib.pyplot as plt
import matplotlib.dates as mdates

fig, axes = plt.subplots(3, 1, figsize=(14, 10),
                         sharex=True, gridspec_kw={"height_ratios": [3, 1, 1]})

# Price + Moving Averages
axes[0].plot(df.index, df["close"], label="Close", linewidth=1.2)
axes[0].plot(df.index, df["sma_20"], label="SMA 20", linestyle="--")
axes[0].fill_between(df.index, df["bb_upper"], df["bb_lower"],
                     alpha=0.1, color="blue", label="Bollinger Bands")
axes[0].set_ylabel("Price (USD)")
axes[0].legend(loc="upper left")

# Volume bars
colors = ["green" if c > o else "red"
          for c, o in zip(df["close"], df["open"])]
axes[1].bar(df.index, df["volume"], color=colors, alpha=0.7)
axes[1].set_ylabel("Volume")

# Rolling Volatility
axes[2].plot(df.index, df["vol_30d"], color="purple")
axes[2].set_ylabel("30d Volatility")
axes[2].axhline(y=0.8, color="red", linestyle=":", alpha=0.5)

axes[2].xaxis.set_major_formatter(mdates.DateFormatter("%b %Y"))
plt.tight_layout()
plt.savefig("analysis_dashboard.png", dpi=150)
plt.show()

这会生成一个专业的三面板仪表盘:顶部是带布林带的价格走势,中间是成交量,底部是波动率。这种布局与你在专业交易终端上看到的别无二致。

做统计可视化时,seaborn 在 Matplotlib 之上提供了更高层的函数:

import seaborn as sns

# Return distribution
sns.histplot(df["returns"].dropna(), bins=100, kde=True)

# Correlation heatmap across assets
corr_matrix = portfolio_returns.corr()
sns.heatmap(corr_matrix, annot=True, cmap="RdYlGn", center=0)
Pandas → 分析;Matplotlib → 洞察 DataFrame index + columns rolling resample groupby Series 指标 收益率、波动率、Sharpe matplotlib.pyplot — figure、axes、artists 价格 成交量 指标 seaborn 可选 — 同一套 Artist 层,默认样式更美观
Pandas 负责整理出整洁的表格;Matplotlib 把它们映射到你可以标注和分享的坐标轴上。

把它们串起来:一条完整的分析管线

当你把这些工具串成一条可重复的管线时,真正的威力才显现出来。下面是专业量化分析师每天都在用的工作流:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

def analyze_asset(symbol: str, df: pd.DataFrame) -> dict:
    """Full analysis pipeline for a single asset."""
    df["returns"] = df["close"].pct_change()
    df["log_returns"] = np.log(df["close"] / df["close"].shift(1))

    return {
        "symbol": symbol,
        "total_return": (df["close"].iloc[-1] / df["close"].iloc[0]) - 1,
        "annual_vol": df["returns"].std() * np.sqrt(365),
        "sharpe": df["returns"].mean() / df["returns"].std() * np.sqrt(365),
        "max_drawdown": (df["close"] / df["close"].cummax() - 1).min(),
        "skewness": df["returns"].skew(),
        "kurtosis": df["returns"].kurtosis(),
    }

# Analyze multiple assets
results = [analyze_asset(sym, data) for sym, data in assets.items()]
summary = pd.DataFrame(results).set_index("symbol")
print(summary.round(4))

这条管线接收原始价格数据,为每个资产生成一份完整的风险-收益画像。从这里开始,你可以把这些指标喂给投资组合优化器、生成配置建议,或触发再平衡信号。

pandas-NumPy-Matplotlib 这套技术栈,是 Python 金融中其他一切的基石。掌握这三个库,你就有能力分析任何市场、构建任何指标、可视化任何策略——无论你是在 NYSE 交易股票、在 GaiaEx 交易加密货币,还是在 CME 交易衍生品。