skip to content

遺伝的アルゴリズムで閾値探索

/ 6 min read

Table of Contents

機械学習モデルの出力に対して「どの値ならエントリーするか」を決める閾値(threshold)を、探索する。

単一モデルであれば、手動で少しずつ値を変えながら試すこともできる。しかし、複数モデルを組み合わせたアンサンブル戦略では話が変わる。

閾値の組み合わせ数が爆発するからだ。

例えば、以下のように複数の条件がある場合。

  • sub_thr
  • mean_thr
  • low_thr

それぞれを細かく探索しようとすると、総当たり(グリッドサーチ)は現実的ではなくなる。

そこで使うのが 遺伝的アルゴリズム(Genetic Algorithm / GA)

なぜGAなのか

GAの利点は、広い探索空間の中から「良いパラメーター」を効率的に見つけられることにある。

特に、閾値同士の相互作用が強い場合に有効だ。

例えば、

  • mean_thr を少し緩める
  • その代わり sub_thr を厳しくする

といった「組み合わせ最適化」が自然に行われる。

手動チューニングでは見つけづらい領域を探索できるのが強い。

Fitness関数が戦略の方向性を決める

GAでは、何を「良い個体」とするかを決めるために Fitness関数 を設計する。

今回は、単純な総利益ではなく、

  • 平均 pips を重視
  • トレード数が少なすぎる場合はペナルティ

という方向で設計した。

実際の式は以下。

fitness = (
avg
* np.sqrt(trades)
* min(1.0, trades / 220)
)

考え方としては、

  • avg → 1トレードあたりの質を重視

  • sqrt(trades) → トレード数が多いほど評価するが、過剰に効きすぎないように緩やかに増加

  • min(1.0, trades / 220) → 220トレード未満を軽くペナルティ

平均利益だけを最適化すると、

数回しかトレードしない超高勝率戦略

が生まれやすい。

例えば、5回だけトレードして全部勝つ設定は、バックテストでは強く見えてもライブでは再現性が低い。

そのため、最低限のサンプル数を要求する目的で、220トレード未満にペナルティを入れた。

最適化は「何を勝者と定義するか」で結果が大きく変わる。

GAそのものより、Fitness設計の方が重要だと思う。

最適化結果

30世代で収束し、以下のパラメーターが選ばれた。

=== GEN 1 ===
Best Fitness: 57.52974
Trades: 259
Pips: 925.85
Avg: 3.575
...
=== GEN 30 ===
Best Fitness: 60.60548
Trades: 243
Pips: 944.75
Avg: 3.888
sub_thr = 0.10562
mean_thr = 0.04674
low_thr = -0.04310

結果として、

指標
Trades243
Total Pips944.75
Avg Pips / Trade3.888
Fitness60.61

となった。

ただし、オーバーフィットは常に疑う

GAは強力な最適化手法だが、そのぶん 「探索に使った期間」に過剰適合しやすい

過去データに、綺麗に都合よく合わせたパラメーターを作ってしまう。

バックテストで綺麗な右肩上がりになっても、それだけでは信用できない。

対策

1. 探索期間を長く取る

短期間だけだと、偶然の相場環境に最適化されやすい。

2. 期間分割

データを前半・後半に分ける。

例えば、前半でパラメーター探索を行い、後半で検証する。

探索に使っていない期間でも成績が維持されるかを見る。

3. 複数期間のサンプリング

期間を切り出して複数回評価する。

いわゆる Bootstrap Sampling / Bagging 的な考え方で、特定期間にだけ強いという設定を避ける。

ライブ向けの位置付け

最終的にGAは、ライブ投入前の微調整として使うのが良い。

  1. Trainでモデル作成
  2. Validationで戦略確認
  3. Unknown Forwardで耐性確認
  4. 最後にGAで閾値微調整

ライブトレードでは、成績は劣化するので、

バックテスト結果の 40%〜120%程度

で考えれば良い。

下振れも上振れもある。

逆に、40%以下などだと、過学習を疑った方が良いだろう。