GaiaExGaiaEx
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 の概念:

  • ベクトル化演算 — 要素ごとにループするのではなく、配列全体にまとめて数学を適用する。
  • ブロードキャスティング — 異なる形状の配列を自動的に揃えて演算する(例:すべての要素からスカラーの平均を引く)。
  • 線形代数np.linalg は、ポートフォリオ最適化で使われる行列積、固有値分解、ソルバーを提供する。
  • ランダムサンプリング — モンテカルロシミュレーション、ブートストラップサンプリング、確率的モデリングはすべて np.random に依存する。

パフォーマンスのヒント:常に Python の for ループより、ベクトル化された NumPy 演算を優先してください。500 資産のポートフォリオ最適化がループでは30秒かかるのに対し、ベクトル化された NumPy なら50ミリ秒以下で終わります——600倍の高速化です。

NumPy: contiguous memory + vectorized ops ndarray — dtype, shape, strides (C-contiguous) one loop in C/Fortran, not a million Python bytecode steps broadcasting: align shapes for element-wise math e.g. returns vector − scalar mean, or (n,) with (n, m) matrix rows linalg: cov, eig, solve — portfolio math lives here
配列は高速な経路であり、ブロードキャスティングはループなしでコードを読みやすく保つ方法です。

pandas:金融データのための DataFrame

NumPy がエンジンなら、pandasはダッシュボードです。NumPy 配列をラベル付き・インデックス付きの構造でラップし、金融データの操作を直感的で表現力のあるものにします。

二つの中核構造があります。

  • Series — インデックス付きの単一列データ(終値の時系列のようなもの)。
  • DataFrame — 共通のインデックスを共有する、それぞれが Series である列のテーブル(OHLCV のローソク足データのようなもの)。

データの読み込みと確認は簡単です。

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 を通じて過去のキャンドルデータを取得し、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))

ポートフォリオ作業のための高度な集計パターン:

  • 多階層グループ化 — シンボルサイドでグループ化し、資産ごとのロング対ショートの成績を見る。
  • カスタム集計関数 — 資産グループごとのシャープレシオ、ソルティノレシオ、最大ドローダウンを計算する。
  • ピボットテーブルpd.pivot_table()を使い、資産別の月次リターンをヒートマップに適した形式に再構成する。
  • グループ化を伴うリサンプリング — 時間ベースのリサンプリングとカテゴリ別グループ化を組み合わせ、複数資産の時系列分析を行う。

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()

これによって、プロフェッショナルな3パネルのダッシュボードが生成されます。上にボリンジャーバンド付きのプライスアクション、中央にボリューム、下にボラティリティ。このレイアウトは、プロ向けトレーディングターミナルで目にするものを反映しています。

統計的な可視化のためには、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 → analysis; Matplotlib → insight DataFrame index + columns rolling resample groupby Series metrics returns, vol, Sharpe matplotlib.pyplot — figure, axes, artists price volume indicators seaborn optional — same Artist layer, prettier defaults
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 でデリバティブを取引していても、それは変わりません。