バックテストで年利25%なのに実運用で損失。。。過学習を避ける3つのチェックポイント

Python実装・コード

先日、自作のBOTを動かしてみたんですが、バックテストでは年利25%だったのに最初の2週間で損失が出てちょっと焦りました笑。なぜこんなことが起きるのか調べていたら、バックテストと実運用の乖離について理解が深まったので記事にします。

なぜ僕がこの問題に向き合うことになったか

僕は普段、日本株の製造メーカー(日立や三菱重工あたり)を中心に投資しているのですが、IT会社に転職してからPythonをいじり始めて、「これは自動売買いけるんじゃない?」と勘違いしてしまいました。。。

結果、過去5年分のデータで「最高の戦略」を作り上げ、リアル口座に投入。2週間で含み損→ロスカット→反省、というよくある流れになりました。原因はシンプルで、「過学習(カーブフィッティング)」です。

過学習とは何か(30秒で説明)

過学習を一言でいうと「過去のデータにだけ合わせすぎて、未来に通用しない戦略」のことです。たとえば、移動平均を21日にしたら過去データで一番儲かったから採用、というのは典型的な罠です。

パラメータをいじり倒すと、過去には完璧にフィットするんですが、市場が少し変わると一気に崩れます。僕の場合、まさにそれでした。

過学習を避ける3つのチェックポイント

1. アウト・オブ・サンプル検証を必ずする

過去データを「学習用」と「検証用」に分けて、検証用のデータでパフォーマンスが半分以下に落ちないかチェックします。コード例はこちらです。

import pandas as pd
import yfinance as yf

# 日立製作所のデータを取得
df = yf.download("6501.T", start="2020-01-01", end="2025-12-31")

# 学習期間と検証期間を分ける
train = df[:"2024-06-30"]
test  = df["2024-07-01":]

print(f"学習期間: {len(train)}日 / 検証期間: {len(test)}日")

2. パラメータをいじりすぎない

移動平均の日数、RSIの閾値、ボラティリティのフィルタ。。。あれもこれも最適化していくと、ほぼ確実に過学習します。僕の場合「最適化するのは最大2つまで」をルールにしました。

3. ウォークフォワード分析を導入する

「直近6ヶ月で学習 → 次の1ヶ月で検証」を繰り返し、戦略が時間経過に強いか確認します。実運用のリアリティに近い検証方法だと思います。

import pandas as pd

def walk_forward(df, train_months=6, test_months=1):
    results = []
    start = df.index[0]
    while start < df.index[-1]:
        train_end = start + pd.DateOffset(months=train_months)
        test_end  = train_end + pd.DateOffset(months=test_months)
        train_data = df[start:train_end]
        test_data  = df[train_end:test_end]
        if len(test_data) < 5:
            break
        # ここで戦略を学習・検証
        results.append((train_end, test_end))
        start = train_end
    return results

まとめ:バックテストは「夢を見る道具」になりがち

過去データでうまくいった戦略は、たぶん3〜4割は過学習だと僕は感じています。検証用データで再チェックして、それでも残るやつだけ実運用に持っていく、というのが今の僕のスタンスです。

個人的には、次は「製造メーカー株でウォークフォワードを回した結果」を試してまた記事にしようと思います。同じように損失で焦った人がいたら、ぜひ一緒に勉強していけたらと思います。。。

関連サービス

この記事で紹介した手法を実際に試す際におすすめのサービスです。

タイトルとURLをコピーしました