English Deutsch
preview
エキスパートアドバイザーの堅牢性テスト

エキスパートアドバイザーの堅牢性テスト

MetaTrader 5 | 16 6月 2025, 14:36
19 6
Zhuo Kai Chen
Zhuo Kai Chen

はじめに

戦略開発には、多くの複雑な要素が含まれていますが、これらの多くは初心者トレーダーには十分に伝えられていません。その結果、私自身を含め多くのトレーダーが、こうした教訓を痛みを伴う経験を通じて学ぶことになりました。この記事では、MQL5で戦略を開発する際に初心者トレーダーが直面しがちな一般的な落とし穴について、私の観察に基づいて解説します。EAの信頼性を見極め、簡単に実践できる方法で自作EAの堅牢性を検証するための、さまざまなヒントやコツ、具体例を紹介します。本記事の目的は、読者がEA購入時の詐欺を回避し、自身の戦略開発での失敗を未然に防げるよう支援することです。


EA市場の危険信号

MQL5市場をざっと見渡すと、ChatGPTやGemini AIなどの人気の大規模言語モデル(LLM)を利用したAI取引システムを宣伝する販売者が多数を占めていることが分かります。しかし、これらの主張は正当ではないと私は考えています。なぜなら、商用LLMを用いて先読みバイアスなしにバックテストをおこなうことは不可能だからです。さらに、一般的なLLMとMQL5との連携にはWebリクエスト機能が用いられます。そのため、販売者がEAにインターネット接続やプロンプト入力が必要であることを明示していない場合、そのEAが本当にLLMを利用している可能性は低いでしょう。LLMを取引に応用する、より堅実な方法は、ライブテストや、BERTのようなより基本的なモデルを基盤として活用することです。最近の研究論文でもこのようなアプローチが紹介されています。

ただし、ここで一つ明確にしておきたいのは、「AI」という言葉は必ずしもLLMだけを意味するわけではないという点です。多くの人はそう思いがちですが、教師あり学習、教師なし学習、強化学習といった高度な機械学習手法も、AIを使ったEAとして分類されます。そのため、販売者がニューラルネットワークを用いている場合に「AI EA」と主張しても、必ずしも虚偽のマーケティングとは言えません。しかし残念ながら、現実には「AI EA」と称される製品の多くが、実際には基本的なニューラルネットワークさえ使用していないのが実情です。これを見分ける一つの手段として、ONNXファイルなどの外部モデルファイルの有無を確認することが挙げられます。もし製品が実行ファイル(EAファイル)のみで構成されている場合、モデルのパラメータは全てEA内部にハードコードされていると考えられ、その結果、ファイルサイズが1メガバイトを超える傾向があります。

EA市場におけるその他の危険信号としては、次のものがあります。

  • 損切り幅が利益確定幅に比べて極端に大きいEA:このようなEAは、インジケーターによって負けトレードを除外することで、バックテスト上では高勝率を実現しているように見せかけます。しかし実際には、たった1回の損失で多くの利益を帳消しにしてしまうリスクがあります。
  • 開発者が自分のシグナルに少額しか投資していない:たとえば、1,000ドル以上で販売しているEAに対して、わずか10〜100ドル程度しか自己投資していない場合、口座がいずれ破綻することを開発者自身が見越している可能性があります。小口口座で得た大きな割合の利益をアピール材料として、販売を促進しようとしているのです。
  • 新しい口座で、取引回数が非常に少なく、勝率が100%である
  • マーチンゲール、ヘッジ、ドルコスト平均法、グリッド戦略の使用:これらの古典的な手法は、損失後にポジションを増やしたり、ドローダウン中にポジションを追加したりすることでリスクを増大させます。20世紀から存在するこれらの戦略は、理論上も長期的な期待収益はゼロ以下であるため、「隠れた聖杯戦略」とは言い難いのです。

ここに簡単な数学的証明があります。

数学の証明

彼らのバックボーンとなる戦略に、すでに明確な優位性(たとえば、成功確率pが0.5を大きく上回る)がない場合、期待収益はゼロ以下になります。つまり、長期的には損失が発生し、その損失がまだ表面化していないだけということです。たとえ収益性のあるエントリー戦略の上にマーチンゲールやグリッドシステムを組み合わせたとしても、ほとんどのリスク管理手法が推奨する「資金の一部のみをリスクに晒す」アプローチとは異なり、実質的には各取引でポートフォリオ全体をリスクに晒すことになります。大きなドローダウン時に追加資金を投入し続ける自信がないのであれば、こうした手法の使用は控えるべきです。

ここで明確にしておきたいのは、このセクションの目的が、現在のMQL5市場で蔓延している典型的な誇大・虚偽マーケティング手法に対する注意喚起であり、MQL5上でのEAの売買そのものに反対しているわけではないということです。実際のところ、私は信頼性のあるマーケティングと真に堅牢な戦略に基づいたEAの開発・販売を、より多くの人々に促したいと考えています。そうすることで、MQL5市場がより健全で信頼性の高い環境へと成長していくことを願っています。


過剰適合

過剰適合は取引モデルによく見られる問題で、ある戦略が過去のデータでは良好な成績を示していても、新たな未知のデータに対してはうまく一般化できないことがあります。この実験では、Pythonコードを使用して、取引モデルにおけるパラメータ選択がどのように過剰適合を引き起こすかを示します。具体的には、複数の特徴量を持つランダムな取引シナリオを生成し、選択的なフィルタリングが結果にどのような影響を与えるかを可視化します。また、特定のデータのサブセットに対してパラメータを過度に最適化した場合に、パフォーマンスがどのように変化するかを観察します。

まず、1,000個のランダムな取引サンプルからなるデータセットをシミュレートします。各サンプルは、以下の3つの特徴量を持つ取引判断に対応します。

  • 特徴量1:市場環境を表し、「a」「b」「c」などの値を取ります。
  • 特徴量2:資産のボラティリティや市場センチメントなどを表し、「d」「e」「f」などの値を取ります。
  • 特徴量3:その他の取引指標を表し、「g」「h」「i」などの値を持ちます。
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# Step 1: Generate random samples
np.random.seed(42)  # For reproducibility

# Possible feature values
feature_1_values = ['a', 'b', 'c']
feature_2_values = ['d', 'e', 'f']
feature_3_values = ['g', 'h', 'i']

# Generate random data
n_samples = 1000
feature_1 = np.random.choice(feature_1_values, n_samples)
feature_2 = np.random.choice(feature_2_values, n_samples)
feature_3 = np.random.choice(feature_3_values, n_samples)
outcome = np.random.choice([0, 1], n_samples)  # Random binary outcome

# Create a DataFrame
df = pd.DataFrame({
    'feature_1': feature_1,
    'feature_2': feature_2,
    'feature_3': feature_3,
    'outcome': outcome
})

各サンプルには、それぞれ「勝ち」または「負け」の結果がランダムに割り当てられており、0または1の値で表されます。これらの結果は、与えられた特徴量に基づく仮想的な取引の成果を表しており、各特徴量は異なるパラメータ設定を意味します。

現実の取引においては、市場インジケーター、取引時間帯、売買シグナルの閾値など、適切なパラメータを選択することがモデルの成績に大きく影響します。しかし、モデルが過去データに現れた特定のパターンに過度に適合してしまい、新しいデータにはうまく対応できなくなる場合、これが過剰適合と呼ばれます。

この現象を示すために、まずは特徴量1が「b」、特徴量2が「d」、特徴量3が「g」のサンプルのみを抽出して分析をおこないます。

def plot_filtered_distribution(df, feature_filters):
    # Filter the DataFrame based on the specified feature values
    filtered_df = df
    for feature, value in feature_filters.items():
        filtered_df = filtered_df[filtered_df[feature] == value]
    
    # Check if filtered dataframe is empty
    if filtered_df.empty:
        print("No data available for the selected feature combination.")
        return

    # Plot the distribution of outcomes based on the filtered data
    sns.countplot(x='outcome', data=filtered_df, palette='Set2')
    plt.title(f'Distribution of Outcomes (filtered by {", ".join([f"{key}={value}" for key, value in feature_filters.items()])})')
    plt.show()

# Example usage: Visualize the distribution of outcomes when filtering by feature_1 = 'a', feature_2 = 'd', feature_3 = 'g'
plot_filtered_distribution(df, {'feature_1': 'b', 'feature_2': 'd', 'feature_3': 'g'})

過剰適合の例1

次に、特徴量1が「c」かつ特徴量2が「f」、特徴量3が「h」のサンプルに限定して、その結果の分布をプロットします。

過剰適合の例2

このランダムに生成されたデータにおいて、わずか3つのパラメータを変更するだけで、勝ちに偏ったサンプル群や負けに偏ったサンプル群を簡単に抽出できることが分かります。これは、過剰適合の力を如実に示しています。特定の特徴量の組み合わせに偏ることで、モデルがデータの一部に過度に適合し、誤解を招く結論につながる可能性があります。特徴量に基づいてデータを選択的にフィルタリングすればするほど、結果のパフォーマンス(勝率など)が人工的に高く見える傾向が強くなります。これは、まさに過剰適合の典型的な兆候です。どんなに適当な戦略であっても、十分な数のパラメータを使って過剰適合させれば、あたかも有益な結果が得られたかのように見せることが可能になってしまいます。

この点は、特定のパラメータに基づいて精密に調整された戦略に依存しているトレーダーにとって、非常に重要な警告となります。なぜなら、そのような戦略は将来の市場環境に対してうまく一般化されない可能性が高いからです。本当に重要なのは、広範なデータ範囲にわたって一貫したパフォーマンスを示すモデルの堅牢性であり、狭いパラメータ領域に対して最適化された戦略ではありません。


MetaTrader 5ターミナルの最適化

特定のEAの、ある期間におけるパフォーマンスを最大化するパラメータを選択しようとする行為は、「最適化」と呼ばれます。前のセクションで示したように、少数のパラメータをわずかに調整するだけで、ランダムな小規模サンプルのデータに対して過剰適合が簡単に起こります。では、最適化におけるこのような誤りをどのように回避し、バックテスト結果の信頼性を高めることができるのでしょうか。このセクションでは、MetaTrader 5ターミナルでの最適化時に過剰適合のリスクを最小限に抑え、より堅牢な結果を得るための方法について解説します。

1.長期にわたる多数のサンプルを使用する

大数の法則によれば、戦略のリターンがある確率分布に従うと仮定すると、サンプル数が増えるにつれて、そのサンプルの平均リターンは母集団の平均に近づいていきます。デイトレードやスキャルピングのような高頻度取引でない戦略であれば、少なくとも10年分のデータを用い、数千件の取引を含むテストを行うのが理想的です。マクロ経済のレジーム変化に敏感な戦略であれば、最近の数年のデータのみでテストすることも許容されます。ただし、どれだけのサンプル数が十分かの普遍的なルールは存在せず、最終的には戦略の有効性を検証するのに十分なサンプル数が必要です。目標は、金融市場で活用可能な歴史的かつ繰り返されるパターンが存在することを示すことです。 

EAが長期時間枠で動作する場合は、複数の銘柄にまたがってテストをおこなうことでサンプル数を増やし、マルチアセット戦略へと昇華させることが可能です。このように資産を分散してテストすることで、過剰適合のリスクは大幅に下がり、戦略の堅牢性と市場への適応力が高まります。資産の多様化によって、戦略の堅牢性が向上し、異なる市場環境への適応能力も強化されます。

2.調整可能なパラメータを少なくする

前述の実験で示した通り、パラメータの数が多ければ多いほど、最適化によって勝率の高いサンプル群を選び出せてしまう可能性が高まります最初にランダムで決められたパラメータでも、簡単に成功した結果のグループに分類されてしまうことがあり、それが必ずしもサンプル全体の有効性を示すわけではありません。David Aronsonは、Evidence-Based Technical Analysisにてデータマイニング技術を検証し、調整可能なパラメータが1つの戦略は存在する可能性が低いものの、そのほうが過剰適合のリスクは低いと結論付けています。したがって、調整可能なパラメータは5個未満に抑えることが推奨されます。また、マジックナンバーのように結果に影響しないパラメータは調整可能とみなすべきではありません。インジケーターのルックバック期間など広く使われている値に固定可能なパラメータは、最適化中に調整可能なパラメータとしてカウントしないほうが良いです。

3. バックテストと最適化で手数料・スプレッド・スワップを考慮する

ストラテジーテスターを使う際には、必ず画面上のマネーサイン($マーク)をクリックして、手数料、スプレッド、スワップが実際の取引環境に即した条件で設定されているかどうかを確認してください。これらを考慮しない最適化結果は、実取引のパフォーマンスを正しく反映しません。 

最適化設定

スプレッド

多くのトレーダーは、自分の戦略が一貫して負けている場合、それは「勝てる戦略とは逆のことをしている」ことを意味していると誤解しがちです。そして、取引方向を反転させれば勝てるはずだと考えるかもしれません。しかし、これは現実から大きくかけ離れています。取引は、小口トレーダーにとってマイナスサムゲームです。一貫して負けているトレーダーというのは、多くの場合、すでに優位性を失った戦略を使っており、その結果は勝ち負けがランダムに分布するようになります。そうした場合の損失の多くは、スプレッド、手数料、スワップポイントといった、取引ごとに発生するコストが原因です。

利益を生み出す戦略とまったく逆のシグナルを安定的に出す戦略を作ることは、自分で利益の出る戦略を作るよりも、実際にはずっと困難です。後者の場合は勝つことを目的に戦略を設計していますが、前者では意図的に負ける戦略を作ろうとしているわけではないからです。

これが、私が初心者トレーダーにスキャルピング戦略を勧めない理由です。統計的に見た不利な条件があまりにも大きいからです。例を挙げましょう。EUR/USDを取引するとして、b-bookブローカーであれば手数料はゼロでも、通常スプレッドは約1ピップあります。一方、ECN型のa-bookブローカーであれば、スプレッドは0.1ピップ程度ですが、1ロットあたり約7ドルの手数料がかかります。どちらの場合でも、たとえば10ピップの利益確定(TP)だけを狙うスキャルピング戦略を使うと、勝っても負けても毎回およそ10%近いコストを支払っている計算になります。これは高頻度で取引を繰り返すトレーダーにとって非常に大きな問題です。なぜなら、そうした取引コストは時間の経過とともに確実に利益を削っていくからです。

ここで、勝率が55%、リスクリワードが1:1の堅牢な戦略があると仮定しましょう。もしスプレッドや手数料を無視できるとしたら、そのエクイティカーブはプロの基準から見ても非常に優秀なものとなるでしょう。

手数料なし

しかし、スキャルピングによって小さな利益を狙う一方で、手数料・スプレッド・スワップなどによる取引コストが実質的に1回の取引ごとに約10%かかることを考慮に入れると、各取引の相対的なコストが増加するため、先ほどの堅牢な戦略であっても、エクイティカーブはほとんど利益が出ない状態にまで押し下げられてしまいます。以下の図がその一例です。

手数料あり

シミュレーションPythonコード:

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# Parameters
n_trades = 1000  # Number of trades
win_rate = 0.55  # 55% win rate
commission_rate = 0.1  # 10% commission per trade
initial_balance = 10000  # Starting balance
trade_amount = 100  # Amount per trade

# Simulate the trades
np.random.seed(42)  # For reproducibility

# Generate random outcomes (1 for win, 0 for loss)
outcomes = np.random.choice([1, 0], size=n_trades, p=[win_rate, 1 - win_rate])

# Initialize balance and equity curve
balance = initial_balance
equity_curve = [balance]

# Simulate each trade
for outcome in outcomes:
    # Calculate the result of the trade
    if outcome == 1:
        # Win: add profit (trade_amount) and subtract commission
        balance += trade_amount - (trade_amount * commission_rate)
    else:
        # Loss: subtract loss (trade_amount) and subtract commission
        balance -= trade_amount + (trade_amount * commission_rate)
    
    # Append the updated balance to the equity curve
    equity_curve.append(balance)

# Plot the equity curve
plt.figure(figsize=(7, 4))
plt.plot(equity_curve)
plt.title('Equity Curve with 10% Commission on Each Trade')
plt.xlabel('Number of Trades')
plt.ylabel('Balance')
plt.grid(True)
plt.show()

4. 最適化ではステップ幅を大きく設定し、パラメータの感度に注意する

    MetaTrader 5の最適化ターミナルでは、各パラメータの試行時に使用するステップ幅を調整できます。通常のパラメータ値に対して相対的に大きめのステップ幅を設定することが推奨されます。非常に特定の値に焦点を当てると、過剰適合や市場環境の変化に対する感度が高くなりやすくなります。たとえば、昨年はRSIのルックバック期間が11のときにリバーション戦略が最もうまく機能していたとしても、今年はそれが13に変わっているかもしれません。小刻みな値ばかりを試すと、パラメータに対する広範なパフォーマンス傾向を見落としやすく、非効率的な最適化に時間を浪費する可能性があります。

    最適化ステップ

    個人的には、パフォーマンスを示す指標としてプロフィットファクターを使用するのが好みです。これは総利益と総損失の比率であり、トータルリターンのような絶対値ではなく相対的な尺度であるためです。

    プロフィットファクター = 総利益 ÷ 総損失

    また、パラメータ感度も非常に重要です。各パラメータについて、可能な値の範囲を広くカバーするように試行をおこなうべきです。理想的には、最適な値の周辺が凹型分布を描くことが望ましく、パラメータが最適値からずれるにつれて、パフォーマンスが緩やかに低下していくような形です。これにより、パラメータ値が変動しても戦略の優位性が維持され、最高のパフォーマンスパラメータが戦略の最適な設定を表すことが保証されます。

    最適化結果


    アウトオブサンプル

    パラメータの最適化や、EAを異なる時間枠や銘柄でテストする際には、最近のデータをテスト対象から除外することが望ましいです。これらのデータは、元のEAに一切手を加える前の時点では未知であるべきであり、この手法はインサンプル/アウトオブサンプルテストとして知られています。

    このテスト手法の目的は、将来の情報をもとに戦略を調整してしまう「先読みバイアス」を回避することです。また、最適化によって戦略が過剰適合してしまうリスクの軽減にもつながります。

    この手法を実践するには、まずテスト対象とするデータ全体のサンプルサイズを決めます。その上で、テスト回数に応じて7:3、8:2、9:1といったインサンプルとアウトオブサンプルの比率を選びます。インサンプルデータを用いて、すべての観察、仮説、パラメータ調整、シグナルルールの改良を行ったうえで、最終的なEAをアウトオブサンプルデータに適用し、仮説が安定して通用するかを検証します。もし、インサンプルで優れた結果を出すように最適化されたEAが、アウトオブサンプルではほとんど利益を出さない、あるいは損失になるといった場合、それは過剰適合か、あるいは最近の市場環境の変化によって優位性が失われた可能性があります。

    EAの一貫性がインサンプルとアウトオブサンプルの両方で維持されているかを評価する際には、注目すべきいくつかの主要な指標があります。

    まず、レバレッジによる複利効果を除いたEAのバージョンを作成すべきです。これがあるとテスト結果が歪み、サンプル期間の終盤に過度な重みがかかってしまうためです。

    主に確認すべき指標は以下の通りです。

    1. プロフィットファクター:プロフィットファクターは1を超えている必要があり、理想的には1.2〜1.5の範囲が望ましいです。1.2未満では収益性が十分でない可能性があり、1.5を超える場合はサンプルサイズが小さすぎるか、取引コストが考慮されていない可能性があります。もちろん、これが戦略の不正を意味するわけではありませんが、数値が現実的かどうかには注意を払うべきです。

    2. 最大エクイティドローダウン:すでに起きた損失ではなく、潜在的リスクを表す「最大エクイティドローダウン」に着目します。この値は、自分自身が許容できる最大ドローダウンよりも10%以上小さいのが望ましく、低すぎる場合はEAのリスクを高めることを検討できますし、高すぎる場合は戦略全体のリスク設計を見直す必要があります。

    3. LR相関:線形回帰(LR)による相関係数を見れば、EAの収益カーブの一貫性を測ることができます。相関係数が0.9を超えていれば、テスト期間を通じて安定したパフォーマンスが得られていたことを示します。極端なブレや偏りがないかの判断材料になります。

    4. ロングとショートの勝率と取引量:EAがロングとショートの両方を取引する場合、それぞれの勝率と取引量が大きく偏っていないかを確認すべきです。もし大きな差があれば、戦略内部で構造的なバランスの崩れが生じている可能性があります。

    もちろん、他にも見るべき指標はありますが、EAの信頼性をインサンプル・アウトオブサンプルの両面から評価する際に、これらの項目は特に重要です。

    バックテストの例

    一部の伝統的なトレーダーはウォークフォワード分析を好みます。これは、インサンプル/アウトオブサンプルテストを一定期間ごとに繰り返し、「現在」に向かって一歩ずつ進めていく手法です。しかし私は、パラメータの数が少なく、特定の値に過度に適合していないことをすでに確認できている場合、このような分析は多くの場合不要だと考えています。そのような場合、最適なパラメータ値は時間の経過とともに一貫している可能性が高いです。さらに、戦略の優位性の本質はパラメータの値ではなく、シグナルルールにあるという点もすでに強調しました。そのため、通常は一度のインサンプル/アウトオブサンプルテストで十分に結果の妥当性を確認することができます。

    とはいえ、機械学習に基づいた戦略では話が異なります。これらの戦略では、戦略の優位性がしばしばモデル内部のパラメータ設定に依存しており、その値は学習に使用した期間によって大きく変動する可能性があります。このような場合には、異なるデータセットに対してモデルの性能がどのように変化するかを検証するために、ウォークフォワード分析が必要になります。この分析の実装方法については、別の記事で詳しく説明しています。最終的なポイントは、そのEAが直近の期間でもある程度の利益を維持していることが、その戦略が引き続き有効であることを確認する上で不可欠だということです。


    外れ値テスト

    外れ値テストでは、利益の大部分がごく少数の外れ値的な取引によって生じているのではなく、より一貫したバランスの取れた損益の積み重ねによって得られているかを確認します。これは、もし利益が主に数件の外れ値取引によるものである場合、平均リターンを推定するためのサンプル数の意義が薄れるため、重要な検証ポイントです。これを確認するには、まずバックテストのエクイティカーブを見て、上昇がいくつかの大きな急騰によるものではなく、安定的かつ一貫した成長によるものであることを確認します。加えて、バックテストレポート内で最大利益と平均利益を比較することで、それを数値的にも裏付けることができます。

    また、利益が特定の短期間に集中していないかどうかも確認する必要があります。短期間に偏って利益が出ている場合、一時的な相場環境による影響が疑われるためです。これをチェックするには、月次リターンの分布を確認して、全体としての一貫性が保たれているかを見ます。まずは、バックテストレポートを右クリックして保存し、その中の月次収益分布を確認してください。 

    Excelレポートの保存

    次に、そのファイルを開き、「Deals」と書かれた行の行番号を確認します(この例では9342行目です)。

    行を検索

    最後に、Jupyter Notebookで以下のPythonコードを実行することで、月次リターン(%)の表を出力できます。
    import pandas as pd
    import matplotlib.pyplot as plt
    # Replace 'your_file.xlsx' with the path to your file
    input_file = 'your_backtest.xlsx'
    # Load the Excel file and skip the first {skiprows} rows, skiprows = the row of "DEAL"
    data = pd.read_excel(input_file, skiprows=9342)
    # Select the 'profit' column (assumed to be 'Unnamed: 10') and filter rows as per your instructions
    profit_data = data[['Time','Symbol','Profit','Balance']][1:-1] 
    profit_data = profit_data[profit_data.index % 2 == 0]  # Filter for rows with odd indices
    profit_data = profit_data.reset_index(drop=True)  # Reset index
    # Convert to float, then apply the condition to set values to 1 if > 0, otherwise to 0
    profit_data[['Profit','Balance']] = profit_data[['Profit','Balance']].apply(pd.to_numeric, errors='coerce').fillna(0)  # Convert to float, replacing NaN with 0
    
    # Load the data
    data = profit_data
    
    # Calculate percentage gain compared to the previous balance
    data['percentage_gain'] = data['Profit'] / data['Balance'].shift(1) * 100
    
    # Drop the first row because it doesn't have a previous balance to compare
    data = data.dropna()
    
    # Ensure 'time' is in datetime format
    data['Time'] = pd.to_datetime(data['Time'])
    
    # Extract the year and month from the 'time' column
    data['year'] = data['Time'].dt.year
    data['month'] = data['Time'].dt.month_name()
    
    # Ensure months are ordered correctly (January to December)
    month_order = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
    data['month'] = pd.Categorical(data['month'], categories=month_order, ordered=True)
    
    # Calculate the total return for each year-month combination
    monthly_return = data.groupby(['year', 'month'])['percentage_gain'].sum().unstack(fill_value=0)
    
    # Function to apply color formatting based on return value
    def colorize(val):
        color = 'green' if val > 0 else 'red'
        return f'background-color: {color}'
    
    # Display the table with color coding
    styled_table = monthly_return.style.applymap(colorize, subset=pd.IndexSlice[:, :])
    
    # Show the table
    styled_table

    月次リターンの例

    長期のバックテストではドローダウンのある月はほぼ避けられませんが、ここで注目すべきはリターンのパーセンテージであり、ドローダウンが全サンプルの平均リターンと比較して著しく大きくないことを確認する必要があります。

    最後に、EAが複数の銘柄を取引する場合は、特定の銘柄に利益が偏っていて、他の銘柄がほとんど寄与していないという事態を避けなければなりません。これを確認するために、先ほどのPythonコードに数行追加して、各銘柄ごとのリターン分布を円グラフで可視化することができます。

    import seaborn as sns
    # Group by symbol and calculate the total profit/loss for each symbol
    symbol_return = data.groupby('Symbol')['percentage_gain'].sum()
    
    # Plot the pie chart
    plt.figure(figsize=(7, 3))
    plt.pie(symbol_return, labels=symbol_return.index, autopct='%1.1f%%', startangle=90, colors=sns.color_palette("Set2", len(symbol_return)))
    
    # Title and display
    plt.title('Total Return by Symbol')
    plt.show()

    円グラフ

    円グラフ上で単一の資産が支配的にならないよう確認するだけです。


    高度な提案

    ここでは、より高度な堅牢性テストを4つ紹介します。これらは、ある程度の専門知識と時間を要する場合があります。

    1. 実取引でのテスト

    実際の市場環境で、小さなロットサイズを用いて戦略をリアルまたはデモ口座で運用し、そのパフォーマンスを一定期間観察します。実取引ではスリッページ、スプレッド、約定遅延などの現実的な市場ダイナミクスに戦略が耐えられるかを検証できます。

    これは、バックテストやシミュレーションだけではわからない、実際の市場環境と感情的なプレッシャーの下で戦略が期待通りに機能するかを判断するのに役立ちます。

    2. モンテカルロシミュレーション

    勝ち・負けの順序をランダムにシャッフルし、複数の可能性あるエクイティカーブを生成するモンテカルロ法を用います。これには、エントリーポイントやストップロスに対してランダムな調整を加えることも含まれます。

    モンテカルロ・シミュレーションは、戦略がどの程度ランダムな市場条件に耐えられるかを評価し、最悪のケースに備えた理解を深めるのに役立ちます。これにより、過去データへの過剰最適化を見抜く手助けになります。

    3. ドローダウンと破産確率分析

    最大ドローダウン(エクイティが最も大きくピークから谷に落ち込んだ幅)を分析し、現行のリスクリワード設定に基づいて、口座残高がゼロになる確率(破産確率)を計算します。

    これらの指標は、戦略のリスクプロファイルをより深く理解するのに役立ち、最大ドローダウンが許容範囲内であるか、また特定の市場状況下で口座が枯渇する可能性がどれほどあるかを把握できます。長期的な運用の持続可能性を評価する上で特に重要です。

    4. スリッページと実行シミュレーション

    想定されるエントリー/エグジットと実際の市場約定の間にランダムなズレを導入することで、スリッページや現実の執行遅延をシミュレートします。スリッページは、市場のボラティリティ、取引サイズ、流動性などの要因に基づいてモデル化できます。MetaTrader 5のストラテジーテスターにはストレステスト機能があり、この用途に役立ちます。

    約定は、実際の収益性に大きく影響する重要な要素です。このテストにより、戦略がスリッページに対してどの程度敏感か、また理想的でない約定状況でも利益を維持できるかを評価できます。特にスリッページが影響を与えやすいのは、ニュースイベントなど高ボラティリティ時を狙う戦略です。そうでなければ、スリッページは正負が相殺し合う傾向があり、他の取引コストと比べると影響は比較的小さいと考えられます。ほとんどの場合、プラスのスリッページとマイナスのスリッページは互いに相殺し合い、他の取引コストと比較して影響は比較的小さくなります。


    結論

    この記事では、自作のEAや、他者から販売されたEAの堅牢性を厳密に検証する方法について解説しました。はじめに、MQL5マーケットプレイスにおいて、販売者がデータを不正に操作するために使う可能性のあるマーケティング手法について説明し、それらの手法が本質的に効果を持たない理由を示しました。次に、Pythonを用いた実験を通じて、過剰適合の概念を紹介しました。その後、MetaTrader 5におけるバックテストや最適化を実施する際に考慮すべき重要なポイントについて説明し、それぞれのヒントの背景にある目的を明確にしました。続いて、アウト・オブ・サンプルテストについて詳述し、レポートの各種指標を評価する方法を提示しました。また、取引、時間、銘柄という3つの観点からの外れ値テストについても取り上げ、それぞれの検証方法を具体的に紹介しました。最後に、より高度な堅牢性テストに関する追加の提案を述べて、この記事を締めくくりました。

    MetaQuotes Ltdにより英語から翻訳されました。
    元の記事: https://www.mql5.com/en/articles/16957

    添付されたファイル |
    最後のコメント | ディスカッションに移動 (6)
    Zhuo Kai Chen
    Zhuo Kai Chen | 21 2月 2025 において 06:55
    Omega J Msigwa #:
    素晴らしい記事だ。

    ありがとう!

    Daniel Opoku
    Daniel Opoku | 10 3月 2025 において 16:37

    珠緒は素晴らしい仕事をしたし、読み応えのある記事だった。 ポイント4にはこうある:

    4.ロングポジションとショートポジションの勝率と取引量:EAがロングポジションとショートポジションの両方を取引する場合、その勝率と取引量が適度に似ていることを確認してください。

    両者の間に大きな相違がある場合、ストラテジーのバランスが崩れている可能性があり、対処が必要な場合があります。

    これは、トレンドの方向が偏っている場合に当てはまりますか(買いトレンドが売りトレンドよりも長い期間支配しています。EA の勝率と取引量は同じようなものですか?

    Zhuo Kai Chen
    Zhuo Kai Chen | 11 3月 2025 において 02:38
    Daniel Opoku 取引量:EAがロングポジションとショートポジションの両方を取引する場合、それらの勝率と取引量が適度に類似していることを確認してください。

    両者の間に大きな相違がある場合は、ストラテジーのバランスが崩れている可能性があり、対処が必要な場合があります。

    これは、トレンドの方向が偏っている場合にも当てはまります(買いトレンドの方が売りトレンドよりも長い期間優勢です。EA の勝率と取引量は同じようなものですか?

    コメントありがとうございます。

    ストラテジーにどの程度のベータが 含まれているかによって異なります。単一資産のストラテジーがより高い時間枠とより高い保有期間で取引される場合、ストラテジーの結果はマクロトレンドに従っていくらかバイアスがかかる可能性が高いでしょう。そのため、取引頻度の高いストラテジーや、相関のない複数の資産に分散してストラテジーをトレードすることで、取引量(ボリューム)の多いストラテジーをトレードするようにアドバイスしている。もし、ストラテジーの長所がトレンドのバイアスを前提とせず、買いも売りも対称的なルールを持っているのであれば、サンプル数が多くても同じような取引量と勝率が期待できるはずです。

    もちろん、指数のロング・オンリー戦略のように、トレンドのバイアスを前提とする戦略もある。この種の戦略では、トレーダーは片側だけを取引すべきである。ただ、バイアスの仮定を使い過ぎないようにすれば問題ないだろう。

    linfo2
    linfo2 | 26 3月 2025 において 03:10
    結果を分析するためにPythonを使うことに目を開かせてくれました。私にとっての主な課題は、EAが原因なのか、それともトレンドが原因なのかということです。)おそらく、確率メトリックを含めるべきでしょう
    Zhuo Kai Chen
    Zhuo Kai Chen | 26 3月 2025 において 06:29
    linfo2 #:
    結果を分析するためにPythonを使うことに目を開かせてくれました。私にとっての主な課題は、EAが原因なのか、それともトレンドが原因なのかということです。)おそらく、確率メトリックを含めるべきでしょう。

    取引された市場とバックテスト結果との間の月次リターンの相関チェックを行うことを検討してください。もし相関が0.2以上のように高い場合、市場トレンドがバックテスト結果の大部分を占めていることを示唆している可能性があります。

    MQL5入門(第12回):初心者のためのカスタムインジケーター作成ガイド MQL5入門(第12回):初心者のためのカスタムインジケーター作成ガイド
    MQL5でカスタムインジケーターを構築する方法を学びます。プロジェクトベースのアプローチを採用します。この初心者向けガイドでは、インジケーターバッファ、プロパティ、トレンドの視覚化について解説し、段階的に学習を進めることができます。
    ログレコードをマスターする(第5回):キャッシュとローテーションによるハンドラの最適化 ログレコードをマスターする(第5回):キャッシュとローテーションによるハンドラの最適化
    この記事では、ハンドラへのフォーマッタ追加、実行サイクルを管理するためのCIntervalWatcherクラスの導入、キャッシュとファイルローテーションによる最適化、さらにパフォーマンステストおよび実用的な使用例を通じて、ログライブラリをさらに改善します。これらの機能強化により、さまざまな開発シナリオに柔軟に対応可能な、効率的でスケーラブルなロギングシステムが実現します。
    プライスアクション分析ツールキットの開発(第12回):External Flow (III)トレンドマップ プライスアクション分析ツールキットの開発(第12回):External Flow (III)トレンドマップ
    市場の流れは、ブル(買い手)とベア(売り手)の力関係によって決まります。市場が反応する特定の水準には、そうした力が作用しています。中でも、フィボナッチとVWAPの水準は、市場の動きに強い影響を与える傾向があります。この記事では、VWAPとフィボナッチ水準に基づいたシグナル生成の戦略を一緒に探っていきましょう。
    MQL5で取引管理者パネルを作成する(第9回):コード編成(I) MQL5で取引管理者パネルを作成する(第9回):コード編成(I)
    このディスカッションでは、大規模なコードベースを扱う際に直面する課題について掘り下げます。MQL5におけるコード構成のベストプラクティスを紹介し、取引管理パネルのソースコードの可読性と拡張性を向上させるための実践的なアプローチを実装します。また、他の開発者がアルゴリズム開発で活用できる再利用可能なコードコンポーネントの開発も目指しています。ぜひ最後までお読みいただき、ご意見をお寄せください。