カーブフィッティングは簡単に発生する
株やFX、先物取引で「過去に儲かった戦略」が、未来でも通用するとは限りません。
カーブフィッティング,つまり有意性のないトレードロジックを有意性があると誤認識する現象は,普通のバックテストだと下記のように簡単に発生します。
💡 実例的な違い(目安)
分析手法 | フィッティングのリスク | 実運用成績との乖離 |
---|---|---|
通常のバックテスト | 高い(70~90%が過剰最適化) | 大きく乖離しやすい |
ウォークフォワード分析 | 中~低(30~50%に減少) | 実運用に近い成績 |
※これは目安であり、戦略の複雑さや市場のノイズによって変動します。
この記事では、PythonとFlask、Optunaを使って、トレード戦略をウォークフォワード分析で検証できる無料Webアプリをご紹介します。
ウォークフォワード分析とは?
ウォークフォワード分析(Walk Forward Analysis)は、過去のデータを訓練期間とテスト期間に分けて、戦略の「本番での再現性」をチェックする方法です。
このアプリでできること
- ブラウザ上で簡単にパラメータ入力
- 戦略を自動で最適化(Optuna使用)
- 成績をリアルタイムで表示
- CSVに自動保存
無料で誰でも使用可能なWeb アプリですので,ぜひお試しを。
Qiitaでもシステムの技術的な側面を紹介をしています。

Noteでもアプリの使用方法などをまとめています。
実際の検証結果
前提条件
スタートの資産は1、損切りは価格の1/15、ポジションサイズは損切り時に資産が-5%になるように、スプレッドは価格の0.1%、日足、Long方向のみ。log10資産の最終値(青バー)、決定係数(オレンジバー)をグラフで出力している
指標名 | 買いエントリー条件 | 条件式(Entry) | エグジット条件 | 条件式(Exit) |
---|---|---|---|---|
Random | 20%の確率でランダムに | random.randint(1,10)>8 | 20%の確率でランダムに | random.randint(1,10)>8 |
Dow理論 | 期間k1の高値上抜け | max(high[i-k1:i-1]) < close[i] | 期間k1の底値下抜け | min(low[i-k1:i-1]) > close[i] |
RSI | RSIが30以下から上抜け | RSI(k1, i-1) < 30 and RSI(k1, i) > 30 | RSIが70以上から下抜け | RSI(k1, i-1) > 70 and RSI(k1, i) < 70 |
SMA | closeがSMAを下から上抜け | close[i-1] < SMA(k1, i-1) and close[i] > SMA(k1, i) | closeがSMAを上から下抜け | close[i-1] > SMA(k1, i-1) and close[i] < SMA(k1, i) |
EMA | EMA短期 > EMA長期(ゴールデンクロス) | EMA(k1, i-1) < EMA(k1*2, i-1) and EMA(k1, i) > EMA(k1*2, i) | EMA短期 < EMA長期(デッドクロス) | EMA(k1, i-1) > EMA(k1*2, i-1) and EMA(k1, i) < EMA(k1*2, i) |
MACD | MACDがSIGNALを上抜け | MACD(k1, i-1) < SIGNAL(k1, i-1) and MACD(k1, i) > SIGNAL(k1, i) | MACDがSIGNALを下抜け | MACD(k1, i-1) > SIGNAL(k1, i-1) and MACD(k1, i) < SIGNAL(k1, i) |
BBANDS | closeがBBLで反発しBBMを上抜け | close[i-1] < BBL(k1, i-1) and close[i-1] < BBM(k1, i-1) and close[i] > BBM(k1, i) | closeがBBUに接触または上抜け | close[i-1] < BBU(k1, i-1) and close[i] >= BBU(k1, i) |
ATR | ATR上昇+高値ブレイク | ATR(k1, i) > ATR(k1, i-1) and close[i] > max(close[i-k1:i]) | ATR減少 or 高値割れ | ATR(k1, i) < ATR(k1, i-1) or close[i] < close[i-1] |
ADX | ADXが20→25を上抜け + 価格上昇 | ADX(k1, i-1) < 25 and ADX(k1, i) > 25 and close[i] > close[i-1] | ADXが低下 or 価格下落 | ADX(k1, i) < ADX(k1, i-1) or close[i] < close[i-1] |
STOCH | %Kが%Dを下から上抜け + %K<30 | STOCHK(k1, i-1) < STOCHD(k1, i-1) and STOCHK(k1, i) > STOCHD(k1, i) and STOCHK(k1, i) < 30 | %Kが%Dを上から下抜け + %K>70 | STOCHK(k1, i-1) > STOCHD(k1, i-1) and STOCHK(k1, i) < STOCHD(k1, i) and STOCHK(k1, i) > 70 |
HIST | HISTがマイナスからゼロを上抜け | HIST(k1, i-1) < 0 and HIST(k1, i) > 0 | HISTがプラスからゼロを下抜け | HIST(k1, i-1) > 0 and HIST(k1, i) < 0 |
エントリー&エグジット条件と検証結果
(1)Randomでのエントリー & Randomでのエグジット
実はこれだけでも勝てるという非常に重要な事実。当然通貨によるが。ちなみに為替は勝てないので除外している。

(2)Randomでのエントリー & Trailing stopエグジット
Trailing stop(ダウ理論)は非常に有意性がある という発見。~システムトレード 基本と原則(実践編)~ でも同様の結論だったため,信憑性はありそう。損小利大 is ジャスティス

(3)Golden crossのエントリー & Dead crossエグジット
意外といまいち。決済の回数が少ないのが原因か。

(4)RSIでのエントリー & エグジット
いまいち。決済の回数が少ないのが原因か。

(5)価格のバウンドでエントリー& Trailing stopエグジット
Close[i-k1]>Close[i] and Close[i]>Close[i-k1//3-1] でエントリー。とりあえず現状一番これがよい。なぜかはわからん。

使ってみる(無料)
まとめ
ウォークフォワード分析を通じて、より「実践で通用する戦略」を作ることが可能になります。 本アプリは、PythonとFlaskを用いた個人開発ですが、どなたでも自由にご利用いただけます