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 交易衍生品。