第 09 課:クオンツにおける教師あり学習の応用

機械学習は魔法ではなく、統計的パターンを拡大する虫眼鏡だ。データにパターンがなければ、どんな強力なモデルでもアルファは抽出できない。


「聖杯」から「ツール」へ

2017年、あるヘッジファンドがトップAI研究者のチームを採用し、ディープラーニングでクオンツ取引を「革命」すると約束した。

彼らは10層のLSTMネットワークを構築し、20年分の分レベルデータで学習させ、GPUクラスターで3ヶ月間実行した。

バックテスト結果:年率150%のリターン、シャープレシオ4.0。

創業者は興奮して発表した:「聖杯を見つけた!」

ライブ運用開始から3ヶ月後:

  • 1ヶ月目: +5% (期待通り)
  • 2ヶ月目: -8% (心配し始める)
  • 3ヶ月目: -15% (パニック)

累積損失18%、同時期にS&P 500は8%上昇。

何が起きたのか?

  1. 過去のノイズへの過学習: 10層のLSTMは数百万のパラメータを持ち、過去のデータを完璧に「記憶」したが、そのパターンは単なるノイズだった
  2. 予測と利益は別物: モデルの精度は52%で、まあまあに聞こえるが、取引コストを差し引くと純損失
  3. 分布ドリフト: 2017年の市場構造は学習データ(1997-2016)とすでに異なっていた

教訓: クオンツ取引における機械学習の正しい役割は「価格変動の予測」ではなく、ノイズから弱いが堅牢なシグナルを抽出すること。このレッスンでは教師あり学習の正しい使い方を教える。


9.1 教師あり学習のクオンツ視点

教師あり学習とは?

既知の答えを持つデータを使ってモデルを「学習」させ、未知のデータの答えを予測できるようにする。

学習データ:
  入力 X (特徴量)          ->  出力 Y (ラベル)
  [昨日のリターン, 出来高, RSI]  ->  [明日上昇/下降]
  [0.02, 1.5M, 65]            ->  [上昇]
  [-0.01, 2.0M, 35]           ->  [下降]

モデルが学習すること:
  「RSI > 60で出来高増加なら、明日上昇する確率が高い」

予測フェーズ:
  新しい入力 [0.01, 1.8M, 70]  ->  モデル予測 [上昇?]

クオンツ取引における「ラベリング」のジレンマ

従来の機械学習: ラベルは明確 (猫/犬、スパム/非スパム)

クオンツ問題: ラベルはどう定義すべきか?

ラベリング手法問題点
「明日上昇 = 1, 下降 = 0」0.01%の上昇も5%の上昇も両方「上昇」?
「5日リターン > 1%」その5日間で、最初に10%下落してから回復するかも
「リターンそのもの」ノイズが多すぎて、モデルがパターンを見つけにくい
「シャープ > 1のポジション」保有期間全体を見る必要があり、先読みバイアスのリスク

正しいアプローチ: ラベルは実行可能な取引判断を反映すべきで、抽象的な予測ターゲットではない。

よくある誤解

誤解現実
「精度が高いほど良い」3:1の勝率損失比率で52%の精度は、1:1の比率で70%の精度よりはるかに良い
「複雑なモデルほど強い」金融データは低S/N比、シンプルなモデルの方がしばしば堅牢
「特徴量が多いほど良い」特徴量が多すぎると次元の呪いと過学習を招く
「ディープラーニングは万能」ディープラーニングには大量のデータが必要で、クオンツ取引では通常不足

9.2 特徴量エンジニアリング: クオンツ取引のコア戦場

アルファの80%は特徴量エンジニアリングから来る、モデル選択ではない。

特徴量の種類

特徴量タイプ情報源
価格特徴量リターン、ボラティリティ、モメンタムOHLCV
テクニカル指標RSI、MACD、ボリンジャーバンド価格由来
統計的特徴量歪度、尖度、自己相関分布特性
クロスアセット特徴量セクターモメンタム、市場センチメント関連資産
オルタナティブデータ衛星画像、ソーシャルメディア外部データ

特徴量構築例

AAPLの日次データがあるとして、以下の特徴量を構築する:

基礎データ (5日間):
日付      始値    高値    安値    終値   出来高
Day 1    $180   $182   $178   $181   10M
Day 2    $181   $185   $180   $184   12M
Day 3    $184   $186   $183   $183   11M
Day 4    $183   $184   $180   $181   15M
Day 5    $181   $183   $179   $182   13M

特徴量計算 (Day 5終値後):

1. モメンタム特徴量
   5日リターン = (182 - 181) / 181 = 0.55%
   3日リターン = (182 - 184) / 184 = -1.09%

2. ボラティリティ特徴量
   5日リターンシーケンス: [1.66%, -0.54%, -1.09%, 0.55%]
   日次ボラティリティ = std() = 1.11%
   年率ボラティリティ = 1.11% x sqrt(252) = 17.6%

3. 出来高特徴量
   5日平均出来高 = (10+12+11+15+13)/5 = 12.2M
   今日の出来高 / 平均 = 13/12.2 = 1.07 (やや平均以上)

4. 価格ポジション
   5日高値 = $186, 安値 = $178
   現在のポジション = (182-178)/(186-178) = 50% (中間位置)

良い特徴量の基準

基準検証方法満たさない場合の結果
予測力単変量テスト IC > 0.03計算リソースの無駄
安定性期間全体でICの変動が小さい特定期間への過学習
低相関既存特徴量との相関 < 0.7情報の冗長性
解釈可能ロジックを明確に説明できるデバッグが困難

特徴量選択の実践的手法

手法1: 単変量スクリーニング

各特徴量とラベルの相関を計算する (IC, Information Coefficient):

IC = corr(特徴量ランキング, リターンランキング)

良い特徴量: IC平均 > 0.03, IC安定性 (IC/std(IC)) > 0.5

手法2: 重要度プルーニング

シンプルなモデル(Random Forestなど)を学習させ、特徴量重要度を確認:

上位5特徴量が重要度の80%以上を占める場合:
  -> 上位5-10特徴量のみ保持
  -> その他の特徴量はノイズの可能性

手法3: 再帰的除去

最も重要度の低い特徴量を段階的に削除し、モデルパフォーマンスを観察:

開始: 50特徴量, シャープ 1.2
30に削減: シャープ 1.3 (実際に改善!)
10に削減: シャープ 1.4 (さらに改善)
5に削減: シャープ 1.1 (低下し始める)

-> 最適な特徴量数は約10

9.3 一般的なモデルとその使用例

モデル比較

モデル長所短所使用例
線形回帰シンプル、解釈可能、過学習に強い線形関係のみ捉えるファクター投資、リスクモデル
Random Forest非線形、過学習に強い、特徴量重要度遅い、外挿が苦手分類、特徴量選択
XGBoost/LightGBM強力、高速、欠損値処理過学習しやすい、ブラックボックス一般的な分類/回帰
LSTM時系列依存性を捉える大量データが必要、遅いデータが豊富なシナリオのみ
Transformer強力なアテンションメカニズムさらに大量データ必要、学習困難研究フロンティア、本番では稀

モデル失敗条件

線形モデルの失敗:

  • 特徴量-リターン関係が非線形
  • 強い相互作用効果が存在(例:「低バリュエーション + 高モメンタム」)

ツリーモデルの失敗:

  • 外挿が必要(学習範囲外の値を予測)
  • 特徴量が連続的に変化(ツリーモデルは階段状の予測)

ディープラーニングの失敗:

  • データサイズ < 100,000サンプル(通常過学習)
  • 特徴量品質が低い(ゴミ入力、ゴミ出力)
  • 深刻な分布ドリフト(過去が未来を代表しない)

クオンツ取引における実践的選択

自問: どれくらいのデータがあるか?

データ < 5,000サンプル (: 20年の日次データ)
  -> 線形モデル、Ridge回帰
  -> 特徴量 < 20

データ 5,000-50,000サンプル (: 1年の分データ)
  -> Random Forest、XGBoost
  -> 特徴量 20-50

データ > 50,000サンプル (: ティックデータ)
  -> LSTM/Transformerを試せる
  -> ただしシンプルなモデルを上回るか検証が必要

9.4 金融データの特殊な課題

低S/N比

金融シグナルは極めて弱い:

データタイプS/N比達成可能な予測力
画像認識精度95%+
自然言語精度80%+
金融予測極めて低52-55%の精度でもトップクラス

なぜ金融のS/N比はこんなに低いのか?

  • 市場はほぼ効率的: 明らかなパターンはすぐに裁定される
  • 参加者が多い: あなたが見つけたパターンを他の人も使っている
  • ノイズが支配的: 短期価格変動の90%はランダムな変動

非定常分布

学習データと予測データは異なる分布を持つ:

学習セット (2015-2019):
  平均ボラティリティ 15%
  トレンド支配的

テストセット (2020):
  ボラティリティが80%に急上昇
  極端な急騰と暴落

-> 2020年にモデルが失敗

対処法:

  • ローリングウィンドウを使用し、常に再学習
  • ローリング統計を使った特徴量正規化
  • 異なるレジームを別々にモデル化

クラス不均衡

「大きな上昇(>3%) = 1, それ以外 = 0」を使う場合:

大きな上昇日: ~5%
通常日: ~95%

モデルは「常に0を予測」を学習、95%の精度だが完全に無用

対処法:

  • クラス重みを調整
  • 精度の代わりにAUCを評価に使用
  • 層別サンプリングで学習セットのクラスバランスを確保

9.5 モデル評価: 精度ではない

クオンツ特有の評価指標

指標計算良い基準
IC (Information Coefficient)corr(予測ランキング, 実際のリターンランキング)> 0.03
IR (Information Ratio)IC平均 / IC標準偏差> 0.5
ロング-ショートリターン上位五分位 - 下位五分位のリターン差有意に正
ターンオーバー調整後リターンリターン - 取引コストそれでも正

モデル評価例

モデルが100銘柄の明日のリターンランキングを予測するとして:

モデル予測ランキング (->):
  株A: 1 (最も上昇すると予測)
  株B: 2
  ...
  株Z: 100 (最も下落すると予測)

実際のリターンランキング (->):
  株A: 5
  株B: 10
  ...
  株Z: 95

IC = corr([1,2,...,100], [5,10,...,95])
   = 0.85 (予測ランキングは実際のランキングと高相関)

解釈:

  • IC = 0.85は予測ランキングが実際のランキングと非常に一致
  • 上位10をロング、下位10をショートすれば、有意な超過リターンが期待できる
  • ただし実市場では、ICは通常0.02-0.05のみ

現実世界の期待値

トップクオンツファンドのIC: 0.03-0.05
平均的なクオンツ戦略IC: 0.01-0.03
ランダム予測IC: 0

IC > 0.1を目指すな、それはほぼ確実に過学習

本番グレードのIC計算

先ほど示したシンプルなIC計算は簡易分析には適しているが、本番システムではエッジケースの堅牢な処理が必要。以下は本番対応の実装:

import numpy as np
from scipy.stats import spearmanr

def calculate_ic(
    signals: np.ndarray,
    returns: np.ndarray,
    method: str = "spearman"
) -> float:
    """Information Coefficient (IC) を計算 - シグナルとリターンの相関

    Args:
        signals: 予測シグナル配列
        returns: 実際のリターン配列
        method: "spearman" (推奨) または "pearson"

    Returns:
        IC値、範囲 [-1, 1]
    """
    if len(signals) != len(returns):
        raise ValueError("signals and returns must have same length")
    if len(signals) < 2:
        return 0.0

    # 欠損値処理 - 本番では必須
    mask = ~(np.isnan(signals) | np.isnan(returns))
    signals, returns = signals[mask], returns[mask]

    if len(signals) < 2:
        return 0.0

    if method == "spearman":
        ic, _ = spearmanr(signals, returns)
    else:
        ic = np.corrcoef(signals, returns)[0, 1]

    return float(ic) if not np.isnan(ic) else 0.0

なぜSpearmanがPearsonより好まれるか

側面SpearmanPearson
外れ値への感度堅牢 - ランクを使用非常に敏感 - 単一の外れ値が歪める
関係タイプ単調(非線形)を捉える線形のみ捉える
分布の仮定不要正規性を仮定
金融データへの適合より良い - リターンはファットテール悪い - 正規性仮定に違反

重要な洞察: 金融リターンはファットテールと外れ値で有名。単一の極端な日(市場クラッシュなど)がPearson相関を完全に歪める可能性がある。Spearmanは最初に値をランクに変換するため、外れ値の大きさに対して免疫がある。

使用例

基本IC計算:

# 日次シグナルと翌日リターン
signals = np.array([0.02, -0.01, 0.03, 0.01, -0.02])
returns = np.array([0.015, -0.005, 0.02, 0.008, -0.01])

ic = calculate_ic(signals, returns)
print(f"IC: {ic:.4f}")  # IC: 0.9000 (強い相関)

ローリングIC (時系列):

def rolling_ic(
    signals: pd.Series,
    returns: pd.Series,
    window: int = 20
) -> pd.Series:
    """スライディングウィンドウでローリングICを計算"""
    ic_series = pd.Series(index=signals.index, dtype=float)

    for i in range(window, len(signals)):
        sig_window = signals.iloc[i-window:i].values
        ret_window = returns.iloc[i-window:i].values
        ic_series.iloc[i] = calculate_ic(sig_window, ret_window)

    return ic_series

# : 20日ローリングIC
rolling_ic_values = rolling_ic(signal_series, return_series, window=20)

Information Ratio (IR) 計算:

def calculate_ir(ic_series: pd.Series) -> float:
    """Information Ratio を計算 = mean(IC) / std(IC)

    IR > 0.5 は堅牢なシグナルを示す
    """
    ic_clean = ic_series.dropna()
    if len(ic_clean) < 2 or ic_clean.std() == 0:
        return 0.0
    return ic_clean.mean() / ic_clean.std()

# 
ir = calculate_ir(rolling_ic_values)
print(f"IR: {ir:.2f}")  # IR > 0.5 は良い

本番での注意点

  1. データアライメント: シグナルとリターンが適切にアライメントされていることを確認。時刻Tのシグナルは、TからT+1(または予測ホライズン)のリターンに対応すべき。オフバイワンエラーは最も一般的なIC計算バグ。

  2. 最小サンプルサイズ: 意味のあるICには少なくとも30の観測が必要。サンプルが少ないと、相関推定は高分散で信頼できない。

  3. IC減衰モニタリング: 時間経過でICを追跡。IC傾向の低下は以下を示す:

    • アルファ減衰(シグナルが混雑してきた)
    • レジーム変化(市場構造が変化)
    • モデルドリフト(特徴量が予測力を失った)
# IC減衰検出
recent_ic = rolling_ic_values.tail(20).mean()
historical_ic = rolling_ic_values.tail(60).head(40).mean()

if recent_ic < historical_ic * 0.5:
    print("WARNING: ICが50%+減衰しました")
  1. クロスセクショナルvs時系列IC:

    • クロスセクショナルIC: ある時点での銘柄間の相関(銘柄選択に典型的)
    • 時系列IC: 1つの資産の時間経過での相関(タイミングシグナルに典型的)

    上記の実装は両方に機能する; データが正しく構造化されていることを確認するだけ。


9.6 マルチエージェントの視点

Signal Agentのモデル選択

マルチエージェントシステムでは、教師あり学習モデルはSignal Agentのコア:

Signal Agent Architecture

モデルが失敗したらどうする?

Signal Agentは自身のモデルが失敗しているかを検出する必要がある:

検出指標閾値トリガーされるアクション
ローリングIC < 0 が20日連続-シグナル重みを50%削減
予測分布の異常歪度 > 2シグナル出力を一時停止
モデル信頼度の低下予測分散が増加Meta Agentに通知

重要な設計: Signal Agentは常に正しいわけではない; 「自己疑念」メカニズムが必要。


コード実装 (オプション)

コード例を展開
import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import TimeSeriesSplit

def create_features(df: pd.DataFrame, lookback: int = 20) -> pd.DataFrame:
    """クオンツ特徴量を構築"""
    features = pd.DataFrame(index=df.index)

    # モメンタム特徴量
    features['ret_1d'] = df['close'].pct_change(1)
    features['ret_5d'] = df['close'].pct_change(5)
    features['ret_20d'] = df['close'].pct_change(20)

    # ボラティリティ特徴量
    features['vol_20d'] = df['close'].pct_change().rolling(20).std()

    # 出来高特徴量
    features['vol_ratio'] = df['volume'] / df['volume'].rolling(20).mean()

    # 価格ポジション
    features['price_pos'] = (
        (df['close'] - df['low'].rolling(20).min()) /
        (df['high'].rolling(20).max() - df['low'].rolling(20).min())
    )

    return features.shift(1)  # 先読みバイアスを回避

def create_label(df: pd.DataFrame, horizon: int = 5, threshold: float = 0.02):
    """ラベルを作成: 将来n日のリターンが閾値を超えるか"""
    future_ret = df['close'].pct_change(horizon).shift(-horizon)
    label = (future_ret > threshold).astype(int)
    return label

def calculate_ic(predictions: pd.Series, returns: pd.Series) -> float:
    """Information Coefficientを計算"""
    return predictions.corr(returns, method='spearman')

def walk_forward_train(df: pd.DataFrame, n_splits: int = 5):
    """Walk-Forward学習と評価"""
    features = create_features(df)
    labels = create_label(df)

    # データアライメント
    valid_idx = features.dropna().index.intersection(labels.dropna().index)
    X = features.loc[valid_idx]
    y = labels.loc[valid_idx]

    tscv = TimeSeriesSplit(n_splits=n_splits)
    results = []

    for train_idx, test_idx in tscv.split(X):
        X_train, X_test = X.iloc[train_idx], X.iloc[test_idx]
        y_train, y_test = y.iloc[train_idx], y.iloc[test_idx]

        model = RandomForestClassifier(n_estimators=100, max_depth=5, random_state=42)
        model.fit(X_train, y_train)

        predictions = model.predict_proba(X_test)[:, 1]
        # 将来リターン(次の5日)を計算、予測ホライズンとアライメント
        forward_returns = df.loc[X_test.index, 'close'].pct_change(5).shift(-5)
        ic = calculate_ic(pd.Series(predictions, index=X_test.index),
                         forward_returns)

        results.append({
            'test_start': X_test.index[0],
            'test_end': X_test.index[-1],
            'ic': ic,
            'accuracy': (model.predict(X_test) == y_test).mean()
        })

    return pd.DataFrame(results)

レッスンの成果物

このレッスン完了後、以下が得られます:

  1. クオンツ取引における教師あり学習の役割の理解 - 何ができて何ができないかを知る
  2. 実践的な特徴量エンジニアリングスキル - 効果的なクオンツ特徴量を構築・スクリーニングできる
  3. モデル選択フレームワーク - データサイズに基づいて適切なモデルを選択
  4. 正しい評価方法 - 精度ではなくIC/IRを使ってモデルを評価

受入基準

チェック項目受入基準自己テスト方法
特徴量構築OHLCVデータから5つの特徴量を構築できる価格データが与えられたら、手動で特徴量値を計算
モデル選択データサイズに基づいてモデルを推奨できる「3年の日次データ」シナリオで推奨を述べる
IC計算IC=0.03が何を意味するか説明できるメモなしで、ICのビジネス上の意味を説明
失敗検出3つのモデル失敗シグナルをリストできるSignal Agentの自己チェックロジックを設計

レッスンまとめ

  • クオンツ取引における教師あり学習の正しい役割を理解: 弱いシグナルの抽出、価格変動の予測ではない
  • コア特徴量エンジニアリング手法をマスター: 構築、スクリーニング、評価
  • 金融データの特殊な課題を認識: 低S/N比、非定常性、クラス不均衡
  • 精度ではなくIC/IRを使ってモデルを評価することを学ぶ
  • Signal Agentが教師あり学習モデルをどう統合するかを理解

さらなる読書


次のレッスンプレビュー

Lesson 10: モデルからエージェントへ

モデルは予測を出力するだけだが、取引には判断が必要。「予測モデル」を「判断を下せるAgent」にどうパッケージ化するか? 次のレッスンでは、モデルからAgentへの橋渡しを行う。

この章を引用する
Zhang, Wayland (2026). 第 09 課:クオンツ取引における教師あり学習. In AIクオンツ取引:ゼロからイチへ. https://waylandz.com/quant-book-ja/Lesson-09-Supervised-Learning-in-Quantitative-Trading
@incollection{zhang2026quant_Lesson_09_Supervised_Learning_in_Quantitative_Trading,
  author = {Zhang, Wayland},
  title = {第 09 課:クオンツ取引における教師あり学習},
  booktitle = {AIクオンツ取引:ゼロからイチへ},
  year = {2026},
  url = {https://waylandz.com/quant-book-ja/Lesson-09-Supervised-Learning-in-Quantitative-Trading}
}