第 15 課:リスク管理と資金管理

目標: 「生き残る」ことが「より稼ぐ」ことより重要であることを理解し、Risk Agentの設計原則をマスターする。


実話(公開事例:LTCM、1998年)

注意:以下は公開された歴史的事例の簡略的なレビューであり、リスク管理のポイントを示すもの。詳細は公開情報に基づく。

1998年、Long-Term Capital Management(LTCM)はウォール街で最も輝かしいヘッジファンドだった。創業者には2人のノーベル経済学賞受賞者が含まれ、チームはトップクラスの数学者とトレーダーを集めていた。

彼らの戦略はシンプルだった:債券市場の微小な価格差を利用した裁定取引。バックテストは安定したリターンを示し、リスクは低く見えた。

問題は25倍のレバレッジを使用したことだった。

1998年にロシアの債務危機が勃発すると、市場パニックにより流動性が枯渇した。「微小な差」は収束しないどころか、劇的に拡大した。LTCMのモデルはこれを「100年に一度」のイベントと想定していたが、それが発生した。

結果:46億ドルの資本が数週間で消失。連邦準備制度理事会はシステム崩壊を防ぐため、ウォール街の主要14銀行を調整して緊急救済を行う必要があった。

教訓は何か?

  1. モデルの前提は破綻する、特に極端な状況では
  2. レバレッジはリターンを拡大するが、リスクも拡大する
  3. 流動性危機では、すべての資産相関が1に近づく
  4. リスク管理は戦略から独立し、拒否権を持つ必要がある

これが独立したRisk Agentが必要な理由である - 戦略がどれだけ稼げるかは気にせず、システムが生き残るかどうかだけを気にする。


15.1 リスクの3層

階層的リスク管理

リスク管理の3層
焦点制御メカニズムトリガー条件
ポジションリスク単一取引の損失ストップロス、ポジション制限単一取引損失が閾値に到達
ポートフォリオリスク戦略の積み重ね分散化、相関モニタリングポートフォリオドローダウンが閾値に到達
システムリスクアカウント全体の生存サーキットブレーカー、フルポジション削減アカウントドローダウンが閾値に到達

リスク予算の考え方

コアアイデア: まずどれだけ損失できるかを決定し、次にどれだけ稼げるかを決定する。

総リスク予算:20%(最大許容ドローダウン)
    |
    |-- 戦略A:8%(モメンタム戦略、高ボラティリティ)
    |-- 戦略B:6%(平均回帰、中程度ボラティリティ)
    |-- 戦略C:4%(裁定戦略、低ボラティリティ)
    +-- 予備バッファ:2%(極端な状況用)

ペーパー演習:リスク予算の配分

100万ドルの資本があり、最大許容ドローダウンは15%。3つの戦略:

戦略過去の最大ドローダウン年間リターンシャープレシオ
A25%35%1.4
B12%18%1.5
C8%12%1.5

質問: ポートフォリオドローダウンが15%を超えないようにウェイトをどう配分するか?

答えを展開する

方法1:等リスク貢献(リスクパリティ)

戦略ドローダウン1/ドローダウンウェイトリスク貢献
A25%0.040.04/0.215 = 18.6%25% x 18.6% = 4.6%
B12%0.0830.083/0.215 = 38.6%12% x 38.6% = 4.6%
C8%0.1250.125/0.215 = 58.1%8% x 58.1% = 4.6%
合計0.215115.3%(スケーリングが必要)13.8%

スケーリング後のウェイト:A=16%、B=34%、C=50%、期待ポートフォリオドローダウン約12%(15%未満)

方法2:簡略計算

戦略が無相関と仮定すると、ポートフォリオドローダウン ~ sqrt(sum((ウェイト x ドローダウン)^2))

Aのウェイト = x とすると、sqrt((0.25x)^2 + (0.12x0.4)^2 + (0.08x0.5)^2) <= 15% を解く

解:x <= 20%、したがってAの最大配分は20%

重要な洞察: 高ボラティリティ戦略はアンダーウェイトする必要がある。そうしないとポートフォリオリスクを支配する。


15.2 ポジション管理

Kelly式:理論的に最適なポジション

Kelly式は、勝率とオッズが与えられた場合、長期的な富の成長を最大化するためにどの割合を賭けるべきかを示す:

f* = (p x b - q) / b

ここで:
- f* = 最適ポジション割合
- p = 勝率
- q = 1 - p = 負け率
- b = オッズ(利益/損失比)

ペーパー演習:Kellyポジションの計算

シナリオ勝率pオッズbKelly f*解釈
A60%1.0(0.6x1-0.4)/1 = 20%毎回20%賭ける
B55%1.5(0.55x1.5-0.45)/1.5 = 25%高オッズ、より多く賭けられる
C50%1.0(0.5x1-0.5)/1 = 0%期待値ゼロ、賭けない
D45%2.0(0.45x2-0.55)/2 = 17.5%低勝率だが高オッズ
E70%0.5(0.7x0.5-0.3)/0.5 = 10%高勝率低オッズ

実践でなぜ「Half Kelly」を使うのか

問題説明解決策
推定誤差勝率とオッズは推定値で、不正確な可能性1/2 Kellyまたは1/4 Kellyを使用
ボラティリティが大きすぎるFull Kellyのボラティリティは耐えられない可能性快適さのためポジションを下げる
破産リスクFull Kellyでの連続損失で全滅する可能性最小ポジション制限を設定
相関Kellyは独立性を前提とするが、ポジションは相関する可能性ポートフォリオレベルで割引を適用

実践的推奨: Kelly/2をポジション上限とし、他の制約と組み合わせる。

Kellyとパラメータ不確実性

根本的な問題: Kelly式は真の勝率とオッズを知っていることを前提とするが、これらは実際には推定値である。

推定誤差の影響:

真の勝率:55%
推定勝率:60%(5%過大評価)
オッズ:1.0

真のKelly:(0.55x1 - 0.45)/1 = 10%
推定Kelly:(0.60x1 - 0.40)/1 = 20%(100%過大評価!)

10%にすべき戦略に20%のポジションを使用
-> リスクが倍増、破産の可能性

ベイジアンKelly式

パラメータ不確実性を考慮する方法はベイジアンフレームワークを使用する:

import numpy as np
from scipy import stats

def bayesian_kelly(wins: int, losses: int,
                   avg_win: float, avg_loss: float,
                   confidence: float = 0.9) -> dict:
    """
    ベイジアンKelly:勝率推定の不確実性を考慮

    wins: 過去の勝ち回数
    losses: 過去の負け回数
    avg_win: 平均勝ち率
    avg_loss: 平均負け率
    confidence: 信頼度
    """
    n = wins + losses

    # 勝率のベイジアン事後分布(ベータ分布)
    # 一様事前分布Beta(1,1)を使用
    alpha = wins + 1
    beta = losses + 1

    # 勝率の点推定と区間
    p_mean = alpha / (alpha + beta)
    p_lower = stats.beta.ppf((1 - confidence) / 2, alpha, beta)
    p_upper = stats.beta.ppf((1 + confidence) / 2, alpha, beta)

    # オッズ
    odds = avg_win / avg_loss

    # 異なる勝率仮定下でのKelly
    kelly_mean = (p_mean * odds - (1 - p_mean)) / odds
    kelly_lower = (p_lower * odds - (1 - p_lower)) / odds
    kelly_upper = (p_upper * odds - (1 - p_upper)) / odds

    # 保守的Kelly:信頼区間下限を使用
    kelly_conservative = max(0, kelly_lower)

    return {
        'p_estimate': p_mean,
        'p_interval': (p_lower, p_upper),
        'kelly_mean': max(0, kelly_mean),
        'kelly_conservative': kelly_conservative,
        'kelly_interval': (max(0, kelly_lower), max(0, kelly_upper)),
        'sample_size': n,
        'recommendation': kelly_conservative / 2  # さらに半分
    }


# 
result = bayesian_kelly(wins=60, losses=40, avg_win=0.02, avg_loss=0.015)

print(f"勝率推定: {result['p_estimate']:.1%}")
print(f"勝率90% CI: [{result['p_interval'][0]:.1%}, {result['p_interval'][1]:.1%}]")
print(f"Kelly(点推定): {result['kelly_mean']:.1%}")
print(f"Kelly(保守的): {result['kelly_conservative']:.1%}")
print(f"推奨ポジション: {result['recommendation']:.1%}")

出力例:

勝率推定: 60.0%
勝率90% CI: [51.1%, 68.4%]
Kelly(点推定): 26.7%
Kelly(保守的): 6.8%
推奨ポジション: 3.4%

重要な洞察:

  • 100回の取引で60%の勝率を推定、真の値は51%-68%の可能性
  • 点推定Kelly(26.7%)の使用は非常にリスクが高い
  • 勝率下限に基づく保守的Kelly(6.8%)、より安全
  • 推奨ポジションをさらに半分に(3.4%)、マージンを残す

サンプルサイズとKelly割引

過去の取引回数勝率推定誤差推奨Kelly割引
< 30推定が極めて信頼できないKellyを使用しない
30-100+/-10-15%Kelly x 0.25
100-300+/-5-10%Kelly x 0.5
300-1000+/-3-5%Kelly x 0.7
> 1000+/-1-3%Kelly x 0.8

ペーパー演習:Kelly割引

シナリオ取引回数推定勝率推定オッズ点Kelly割引実際のポジション
A5055%1.212.5%0.253.1%
B20055%1.212.5%0.56.3%
C50055%1.212.5%0.78.8%

結論: サンプルが少ないほど、Kelly割引は大きくする。不十分なデータでフルポジションは絶対にしない。

ポジション制限ルール

ポジション制限層

15.3 ストップロスとテイクプロフィット

3種類のストップロス

タイプ定義長所短所
固定ストップロス損失がX%に達したら退出シンプル、確実ボラティリティで振り落とされる可能性
トレーリングストップ高値からのリトレースメントがX%で退出利益を伸ばす利益を返す可能性
時間ストップN日後に利益がなければ退出資本拘束を回避その後の動きを逃す可能性

ストップロスレベル計算

方法1:ATR倍数

ストップロス価格 = エントリー価格 - N x ATR

ここで:
- ATR = Average True Range
- N = 倍数(通常1.5 - 3)

例:
- エントリー価格 = $100
- ATR = $2
- N = 2
- ストップロス価格 = $100 - 2 x $2 = $96(4%ストップロス)

方法2:ボラティリティ調整

ストップロス範囲 = k x sigma

ここで:
- sigma = 資産の日次ボラティリティ
- k = 倍数(通常2 - 3)

例:
- 日次ボラティリティ = 2%
- k = 2.5
- ストップロス範囲 = 2.5 x 2% = 5%

ペーパー演習:ストップロス戦略の設計

シンボルエントリー価格日次ボラティリティATR固定5%ストップATRx2ストップVolx2.5ストップ
AAPL$1801.5%$2.7$171$174.6$173.3
TSLA$2503.5%$8.8$237.5$232.4$228.1
SPY$4500.8%$3.6$427.5$442.8$441

観察:

  • 固定ストップロスは高ボラティリティ資産(TSLA)には狭すぎ、簡単に振り落とされる
  • ATR/ボラティリティストップは資産特性に基づいて自動調整
  • 低ボラティリティ資産(SPY)は狭いストップが可能

ストップロスの心理的罠

表れ結果
ストップしたくない「少し待てば戻る」小さな損失が大きな損失に
早すぎるストップ損失の最初の兆候で逃げる頻繁に振り落とされ、手数料で損失
トレーリングストップが狭すぎる小さな利益を固定大きな動きを捉えられない
損失後のナンピン「コストベースを下げる」間違った方向への賭けを増やす

核心原則: ストップロスは取引システムの一部であり、失敗の兆候ではない。

よくある誤解

誤解1:高レバレッジはリターンのみを拡大する

リスクと感情的プレッシャーも拡大する。LTCMは25倍のレバレッジを使用し、数週間で46億ドルを失った。レバレッジは正しいときにより稼がせるが、間違っているときにより早く死ぬ。

誤解2:分散化 = より多くのシンボルを保有

10のテック株を保有することは分散化ではない。分散化の核心は低相関であり、シンボルの数ではない。株式 + 債券 + コモディティは10株よりはるかに良い分散化である。

誤解3:リスク管理は後から追加できる

リスク管理は事前に設計する必要がある。30%損失した後にリスク管理を考えるのは遅すぎる。正しいアプローチ:ポジションを開く前にストップロス、ポジション制限、ドローダウンサーキットブレーカーを設定する。

誤解4:Risk Agentの拒否権は「より良い理由」で上書きできる

絶対にできない。Risk Agentのハード制約はシステムの安全境界である - いかなる理由もこれらをバイパスできない。これは「1つの間違いがすべてを破壊する」ことを防ぐ最後の防衛である。


15.4 ポートフォリオリスク管理

相関の罠

問題: 分散化していると思っているが、していない。

ポートフォリオ見た目実際の相関危機時の相関
AAPL + MSFT + GOOGL3つの異なる企業0.70.9
株式 + 債券異なる資産クラス0.20.6
米国株 + 香港株異なる市場0.50.85
Bitcoin + Ethereum2つの暗号通貨0.850.95

重要な洞察: 危機時に相関が急上昇する。まさに分散化が最も必要なときに - しかし機能しない。

ポートフォリオドローダウン制御

ポートフォリオドローダウンモニタリングレベル:

警告(黄色):ドローダウン5%
- 新規ポジションサイズを削減
- ストップロス感度を増加

制御(赤色):ドローダウン10%
- 新規ポジションを停止
- ポジション削減を開始

サーキットブレーカー(黒色):ドローダウン15%
- 30%まで完全削減
- クーリング期間を開始(例:5日間)

ペーパー演習:ドローダウンシナリオシミュレーション

初期状態: 100万ドルの資本、80%ポジション

純資産価値ドローダウントリガーレベルアクション
0$1M0%-通常運用
5$970K3%-通常運用
10$940K6%黄色新規ポジション削減、ストップ引き上げ
15$910K9%黄色制御を継続
20$880K12%赤色新規停止、削減開始
25$850K15%黒色30%まで削減、クーリング期間
30$860K14%赤色30%ポジション維持
35$890K11%赤色ゆっくり追加を検討

15.5 Risk Agent設計

Risk Agent核心責任

Risk Agent責任

拒否権設計

シナリオSignal AgentリクエストRisk Agent判断理由
通常AAPL10%買い承認すべての制限を満たす
過剰AAPL15%買い10%に削減単一取引制限を超過
集中MSFT10%買い(既にAAPL15%保有)拒否テックが既にセクター制限を超過
ドローダウンポジション追加拒否ポートフォリオが赤色レベルをトリガー
サーキットブレーカー任意の買い拒否システムがクーリング期間中

Risk Agent実装原則

1. ハード制約は上書きできない
   - ポジション制限、ドローダウンサーキットブレーカーはハードコード
   - 他のAgentが「より良い理由」を持っていてもバイパスできない
   - 人間の介入には特別なプロセスが必要(例:二重確認)

2. 独立したデータソース
   - Risk Agentは独自の市場データソースを持つ
   - 他のAgentからのデータに完全に依存しない
   - リスク制御をバイパスするための「偽データ」を防ぐ

3. 完全な監査ログ
   - すべての判断をログ:時間、リクエスト、判断、理由
   - 事後レビューをサポート:「あの日なぜストップロスしなかったのか?」
   - ログは変更不可

4. デグラデーション戦略
   - Risk Agent自体が失敗した場合、システムはセーフモードに入る
   - セーフモード:新規ポジション不可、削減のみ
   - リスク制御が壊れているからといってリスク制御をスキップできない
コード実装(エンジニア向け)
from dataclasses import dataclass
from enum import Enum
from typing import Optional
import logging

class Decision(Enum):
    APPROVE = "approve"
    REDUCE = "reduce"
    REJECT = "reject"

@dataclass
class RiskCheckResult:
    decision: Decision
    reason: str
    adjusted_size: Optional[float] = None

class RiskAgent:
    """リスク管理Agent - 拒否権を持つ"""

    def __init__(self, config: dict):
        self.max_single_position = config.get("max_single_position", 0.10)
        self.max_symbol_exposure = config.get("max_symbol_exposure", 0.20)
        self.max_sector_exposure = config.get("max_sector_exposure", 0.30)
        self.max_total_exposure = config.get("max_total_exposure", 0.80)
        self.drawdown_warning = config.get("drawdown_warning", 0.05)
        self.drawdown_stop = config.get("drawdown_stop", 0.10)
        self.drawdown_circuit = config.get("drawdown_circuit", 0.15)

        self.is_circuit_breaker_active = False
        self.logger = logging.getLogger("RiskAgent")

    def check_order(
        self,
        symbol: str,
        size: float,  # 総資本の割合
        current_portfolio: dict,
        current_drawdown: float
    ) -> RiskCheckResult:
        """
        注文リクエストをレビュー

        戻り値:承認/削減/拒否
        """

        # サーキットブレーカー状態をチェック
        if self.is_circuit_breaker_active:
            return RiskCheckResult(
                Decision.REJECT,
                "サーキットブレーカー作動中 - 新規ポジション不可"
            )

        # ドローダウン状態をチェック
        if current_drawdown >= self.drawdown_stop:
            return RiskCheckResult(
                Decision.REJECT,
                f"ドローダウン {current_drawdown:.1%} >= ストップ閾値"
            )

        # 単一取引制限をチェック
        if size > self.max_single_position:
            return RiskCheckResult(
                Decision.REDUCE,
                f"サイズ {size:.1%} > 最大 {self.max_single_position:.1%}",
                adjusted_size=self.max_single_position
            )

        # シンボル集中をチェック
        current_symbol_exposure = current_portfolio.get(symbol, 0)
        if current_symbol_exposure + size > self.max_symbol_exposure:
            allowed = self.max_symbol_exposure - current_symbol_exposure
            if allowed <= 0:
                return RiskCheckResult(
                    Decision.REJECT,
                    f"シンボル {symbol} は既に最大エクスポージャー"
                )
            return RiskCheckResult(
                Decision.REDUCE,
                f"シンボル制限内に収めるため削減",
                adjusted_size=allowed
            )

        # 総ポジションをチェック
        total_exposure = sum(current_portfolio.values()) + size
        if total_exposure > self.max_total_exposure:
            return RiskCheckResult(
                Decision.REJECT,
                f"総エクスポージャー {total_exposure:.1%} が制限を超過"
            )

        return RiskCheckResult(Decision.APPROVE, "すべてのチェックに合格")

    def check_drawdown(self, current_drawdown: float) -> str:
        """ドローダウン状態をチェックして推奨を返す"""

        if current_drawdown >= self.drawdown_circuit:
            self.is_circuit_breaker_active = True
            self.logger.critical(f"サーキットブレーカー作動: {current_drawdown:.1%}")
            return "circuit_breaker"

        if current_drawdown >= self.drawdown_stop:
            self.logger.warning(f"ストップレベル: {current_drawdown:.1%}")
            return "stop_new_positions"

        if current_drawdown >= self.drawdown_warning:
            self.logger.info(f"警告レベル: {current_drawdown:.1%}")
            return "reduce_risk"

        return "normal"

15.6 マルチエージェント協調におけるリスク制御

Risk Agentと他のAgentの関係

Risk Agentレビューフロー

危機時の協調

状態Regime AgentSignal AgentRisk AgentExecution Agent
通常トレンド/レンジを識別通常シグナル通常レビュー通常執行
警告「危機の可能性」フラグシグナル頻度削減レビュー基準引き上げ注文サイズ削減
危機「危機確認」フラグロングシグナル停止削減開始クローズを優先
サーキットブレーカー-すべてのシグナル停止ターゲットまで強制削減クローズのみ執行

リスク帰属

帰属次元問題改善方向
シンボル選択1つのシンボルがドローダウンの50%を占めるそのシンボルのウェイト制限を下げる
戦略選択トレンド戦略がレンジで大損失Regime検出を強化
タイミング選択高ボラティリティ時にポジション開始高ボラティリティ時にポジション下げる
ポジションが大きすぎる単一取引損失が予想を超過ポジション制限を厳格化
ストップロス失敗ストップロスが執行されなかったストップロスメカニズムをチェック

受け入れ基準

このレッスンを完了した後、これらの基準を使用して学習を検証:

チェックポイント基準自己テスト方法
リスク層の理解ポジション/ポートフォリオ/システムリスクを区別できる各制御メカニズムの例を挙げる
Kellyポジション計算式を使用して最適ポジションを計算できるペーパー演習を完了
ストップロス戦略設計ATR/ボラティリティを使用してストップを設計できる自分の戦略のストップルールを設計
相関の罠の理解なぜ分散化が失敗する可能性があるかを説明できる危機時の相関変化を説明
Risk Agent設計Risk Agentの4つの責任を説明できるリスクレビューフローチャートを描く

総合演習

自分のリスク制御システムを設計:

  1. リスク予算を定義(最大許容ドローダウン)
  2. ポジション制限ルールを設計(単一取引/単一シンボル/セクター/合計)
  3. ストップロス戦略を設計(タイプ、パラメータ)
  4. ドローダウントリガーメカニズムを設計(警告/制御/サーキットブレーカーレベル)
  5. Risk Agentが他のAgentとどう協調するかを説明

レッスン成果物

このレッスンを完了すると、以下を得られます:

  1. リスク予算フレームワーク - まずどれだけ損失できるかを決定し、次に戦略を配分
  2. ポジション管理ルール - Kelly式 + 多層制限
  3. ストップロス設計方法 - ATR/ボラティリティストップ計算
  4. Risk Agent設計テンプレート - 4つの責任 + 拒否メカニズム

レッスンまとめ

  • リスク管理の3層を理解:ポジション、ポートフォリオ、システム
  • Kelly式と実践的調整をマスター
  • ストップロスのタイプとパラメータ選択を理解
  • 相関の罠とポートフォリオリスクを理解
  • Risk Agent設計原則をマスター:独立、拒否権、上書き不可

付録:リスク指標クイックリファレンス

この表はクオンツ取引で使用される一般的なリスク指標とその業界基準をまとめたもの。

核心リスク指標

リスク指標優秀な基準許容可能な基準制御方法
最大ドローダウン< 10%(市場中立)/ < 15%(インデックス強化)< 20%(市場中立)/ < 25%(インデックス強化)動的ストップロス、ポジション制御
シャープレシオ>2.0>1.0リターン対ボラティリティ比を最適化
年間ボラティリティ< 8%(市場中立)/ < 15%(インデックス強化)< 12%(市場中立)/ < 20%(インデックス強化)ボラティリティターゲティング戦略
ダウンサイドリスク< 5%< 10%非対称リスク管理
勝率>55%>50%シグナル品質改善
損益比>2.0>1.5利益を伸ばし、損失を抑える
カルマーレシオ>1.5>0.5年間リターン / 最大ドローダウン

ポジション制御基準

制限タイプ保守的基準積極的基準説明
単一取引リスク1%2%総資本に対する取引毎の最大損失%
単一シンボルポジション5%10%総資本に対する単一株式%
セクター集中20%30%総資本に対する単一セクター%
総ポジション60-80%80-100%総資本に対する株式%
レバレッジ1x1.5xプロの機関でない限り>1xは推奨しない

ドローダウントリガーメカニズム

ドローダウンレベルアクション説明
5%警告モニタリング開始、ポジションチェック
10%削減ポジションを20-30%下げる
15%制御新規ポジション停止、削減継続
20%サーキットブレーカー最小レベルまで強制削減

さらに読む


次のレッスン予告

レッスン16:ポートフォリオ構築とエクスポージャー管理

複数の戦略シグナルがある場合、どのようにポートフォリオに組み合わせるか?ポジションをどう配分するか?ファクターエクスポージャーをどうモニタリングするか?次のレッスンではポートフォリオ層に飛び込む - SignalからPortfolioへの重要なステップ。

この章を引用する
Zhang, Wayland (2026). 第 15 課:リスク管理と資金管理. In AIクオンツ取引:ゼロからイチへ. https://waylandz.com/quant-book-ja/Lesson-15-Risk-Control-and-Money-Management
@incollection{zhang2026quant_Lesson_15_Risk_Control_and_Money_Management,
  author = {Zhang, Wayland},
  title = {第 15 課:リスク管理と資金管理},
  booktitle = {AIクオンツ取引:ゼロからイチへ},
  year = {2026},
  url = {https://waylandz.com/quant-book-ja/Lesson-15-Risk-Control-and-Money-Management}
}