MQL5標準ライブラリエクスプローラー(第5回):マルチシグナルEA
内容
はじめに
前回は、MQL5ウィザードと互換性のあるカスタムのローソク足パターンシグナルを構築しました。目的はカスタムシグナル開発を習得し、ウィザードの自動化機能を最大限に活用できるようにすることでした。
ここで疑問が生じます。ウィザードがこれほど強力であるにもかかわらず、なぜエキスパートアドバイザ(EA)の開発は依然として難しいのでしょうか。その答えは市場のダイナミクスにあります。MQL5ウィザードはプロフェッショナルで一貫性のあるEA構造を生成できますが、本質的な課題は取引ロジックそのものにあります。市場環境は常に変化し多様であるため、単一の固定ルールだけでは長期的に通用しないことが多いのです。
堅牢なEAを構築するためには、「シグナル」に焦点を当てる必要があります。多様なシグナルライブラリを開発し、既存のシグナルを改良できるようになることで、市場に適応可能なシステムを構築できます。このアプローチにより専門性の分担も可能となり、開発者は単一のシグナルモジュールの最適化に集中しつつ、より大きなエコシステムに貢献できます。
本記事では、「1つのEAに少数のシグナルしか組み込めない」という制約を克服します。複数の取引シグナルモジュールを管理・統合できるEAを構築します。このアプローチの最大の利点は耐久性(レジリエンス)です。市場が変化する中で、あるシグナルが機能しなくなっても、他のシグナルが取引機会を提供し続けることが可能になります。これにより、単一戦略のEAよりも長期的に生存しやすいシステムを構築できます。
このプロジェクトの一環として、フィボナッチ分析に基づくシグナルモジュールを作成し、MQL5標準ライブラリに含まれる既存シグナルと組み合わせます。
マルチシグナルシステムにおいては、すべてのシグナルがエントリーの主トリガーとして使われるわけではありません。一部のシグナルはフィルターとして機能し、メインシグナルによる取引判断を精査し、強化します。これにより、より洗練された取引戦略を構築することが可能になります。
次のセクションでは、本開発に必要なコアコンセプトを詳しく説明します。その後、実装フェーズに進み、実際のコードを通じて機能的かつ実用的なマルチシグナルEAの構築方法を解説します。
マルチシグナルエキスパートアドバイザー開発のためのコアコンセプト
市場に適応できるEAを構築するためには、発想の転換が必要です。単一の固定戦略に依存するのではなく、複数の戦略が連携する柔軟なシステム、いわば「戦略チーム」を構築します。MQL5標準ライブラリは、このアプローチを効率的に実現するための最適なフレームワークを提供します。本セクションでは、この仕組みを支える重要な概念を分解して解説します。
モジュール思考
このアプローチの基盤は「モジュール化」です。移動平均クロス、RSIシグナル、あるいは今回作成するフィボナッチパターンなど、それぞれの取引戦略を独立したモジュールとして扱います。各モジュールは、自身の判断に必要なロジックをすべて内包した「専門家」です。MQL5標準ライブラリの優れている点は、これらのモジュールを中央のEAに簡単に組み込めることです。このEAは、いわばポートフォリオマネージャの役割を果たします。これにより、各戦略を独立して開発、テスト、改善することが可能となり、その後、コア部分を書き換えることなく、シームレスに取引システムへ追加することができます。
意思決定の方法
複数のシグナルモジュールを持つようになった場合、それらはどのようにして合意に至るのでしょうか。ここで、洗練された投票および重み付けの仕組みが登場します。各モジュールは単に「買い」または「売り」と叫ぶのではなく、0から100の範囲の「重み」によって、自身の確信度を表明します。
明確で強いシグナルは80のような大きな票を投じる一方で、弱いシグナルは10程度の寄与にとどまります。EAはこれらすべての票を集計します。そして、合計された確信度が事前に定義された閾値を超えた場合にのみ、売買が実行されます。この仕組みは、強い確信を持つシグナルを自然に優先しつつ、弱いながらも補完的なシグナルが単独ではなく全体の判断を後押しすることを可能にします。
役割の割り当て:トリガーとフィルター
すべてのシグナルが同等であるわけではなく、また同等であるべきでもありません。高度なシステムにおいては、それぞれに明確な役割を割り当てます。
プライマリシグナル(トリガー)これらは主要な戦略であり、取引機会を見つけるために設計されています。高い重みを持ち、取引アイデアの大部分を生み出す責任を担います。
フィルターシグナル:これらは品質管理チームとして機能します。たとえば、ボラティリティフィルターは市場が混乱している期間に全体の重みを低下させることがあります。また、時間フィルターは特定の時間帯以外での取引を遮断します。これらは単独でエントリーを生成することはほとんどありませんが、不適切なエントリーを拒否することで、システム全体をより堅牢にします。
最終的な利点:組み込みの適応性
このアーキテクチャ全体は、自動売買における理想、すなわち適応性へとつながります。市場は進化し、昨日機能していた戦略が今日失敗することがあります。単一戦略のEAでは、これは致命的です。しかし、マルチシグナルシステムでは、これは管理可能なリスクとなります。
トレンド相場がレンジ相場へと移行すると、トレンドフォロー型のシグナルは静かになるかもしれませんが、平均回帰型やオシレーター系のシグナルがその役割を引き継ぐことができます。EAを書き換える必要はありません。それは自然に、その時点で機能している戦略へと依存度を移します。このような組み込みの耐性こそが、異なる市場環境においてEAが「生存」し、かつ成果を上げ続けることを可能にします。

マルチシグナルEAの概念的な処理フロー
システムの流れ:
- 市場データは継続的にマルチシグナルEAシステムへ入力されます。
- プライマリトリガーはエントリー機会を探索します。
- フィルターシグナルは判断の検証および精緻化をおこないます。
- すべてのモジュールは組み合わせ可能であり、組み込みシグナルと今回のフィボナッチのようなカスタムシグナルを併用できます。
- 重み付けシステムは、すべてのアクティブなシグナルから確信度を収集します。
- 意思決定エンジンは、合計確信度が取引閾値を超えているかを評価します。
- リスク管理はポジションサイズおよびリスク制御を担当します。
- すべての条件が一致した場合にのみ、取引が実行されます。
可視化される主な利点
- レジリエンス複数のシグナル経路があるため、一つが機能しなくても他がトリガーとなり得ます。
- 適応性:市場状況に応じて異なるシグナルが主導的役割を持ちます。
- 専門性:各モジュールは自身の得意分野に集中します。
- プロフェッショナルな基盤:MQL5標準ライブラリが堅牢なインフラストラクチャを提供します。
このアーキテクチャは「戦略的多様性」と呼べるものを生み出します。EAは単一の市場条件やパターンに依存することなく、進化する市場に適応し、生存する可能性が高くなります。また、MQL5ウィザードを活用して複雑な定型コードの処理を任せることで、開発者は最も重要な部分である、この多様なシグナル群の開発と改善に集中することができます。次のパートでは、これを実際に実装し、フィボナッチベースのシグナルモジュールのコーディングと、標準ライブラリのツールとの統合を開始します。
実装
MQL5ウィザード向けプロフェッショナルなフィボナッチ売買シグナルの構築
基盤:シグナルクラス構造のセットアップ
複雑なロジックに踏み込む前に、まずMQL5ウィザード上で私たちのシグナルを表示させるための「マジックコメント」について詳しく説明します。ウィザードの説明start/endブロックに注目してください。これは単なるドキュメントではありません。実際には、MQL5ウィザードが読み取るメタデータです。この情報をもとに、ウィザードは私たちのシグナルをドロップダウンメニューに表示します。titleはユーザーに表示される名称です。ShortNameは内部識別子として使用されます。pageはドキュメントへのリンクを指定します。
CExpertSignallを継承することで、MQL5標準ライブラリの大規模なインフラストラクチャを活用しています。これはいわば「巨人の肩の上に立つ」ようなものであり、リスク管理、ポジションサイジング、取引実行といった機能を自前で実装する必要はありません。その代わりに、私たちはフィボナッチに基づく売買ロジックそのものに専念できます。また、protectedメンバ変数として定義されているものは、設定パラメータとして機能します。これらはMQL5ウィザードのインターフェース上でユーザーが調整可能な値となります。
//+------------------------------------------------------------------+ //| SignalFibonacci | //| Copyright 2025 | //| Clemence Benjamin| //+------------------------------------------------------------------+ #ifndef SIGNAL_FIBONACCI_H #define SIGNAL_FIBONACCI_H #include <Expert\ExpertSignal.mqh> // wizard description start //+------------------------------------------------------------------+ //| Description of the class | //| Title=Signals of Fibonacci Retracement Levels | //| Type=SignalAdvanced | //| Name=Fibonacci Retracement | //| ShortName=Fib | //| Class=CSignalFibonacci | //| Page=signal_fibonacci | //+------------------------------------------------------------------+ // wizard description end //+------------------------------------------------------------------+ //| CSignalFibonacci class | //| Purpose: Complete Fibonacci-based trading signal module | //+------------------------------------------------------------------+ class CSignalFibonacci : public CExpertSignal { protected: // Configuration parameters int m_depth; // Lookback period for swing detection double m_min_retracement; // Minimum retracement percentage double m_max_retracement; // Maximum retracement percentage double m_weight_factor; // Weight multiplier for confidence bool m_use_as_filter; // Use as filter instead of primary double m_filter_weight; // Weight when used as filter bool m_combine_with_trend; // Only trade with trend double m_tolerance; // Price tolerance for levels // Pattern weights (0-100) int m_pattern_0; // Model 0 "price at strong Fib level (0.382/0.618)" int m_pattern_1; // Model 1 "price at medium Fib level (0.500)" int m_pattern_2; // Model 2 "price at weak Fib level (0.236/0.786)" int m_pattern_3; // Model 3 "Fib level with price action confirmation" // Internal state variables double m_high_price; double m_low_price; datetime m_high_time; datetime m_low_time; bool m_uptrend; double m_current_strength; ENUM_TIMEFRAMES m_actual_period; // Store the actual timeframe to use
スマート構成:複雑さを伴わずにユーザーにコントロールを提供する
ここでは、フィボナッチシグナルの「コントロールパネル」を定義します。これらのシンプルなセッターメソッドは、それぞれMQL5ウィザードのインターフェース上で設定可能なパラメータとなります。ユーザーがこのシグナルを選択すると、Depth、MinRetracement、そして最も重要なパターンの重みなどを調整できるスライダーや入力フィールドが表示されます。
パターンの重み付けシステム(0〜100)は、このシグナルを知的にする重要な要素です。これは、「価格が強い0.618のフィボナッチレベルにあるときは80%の確信度を持たせたいが、より弱い0.236のレベルでは60%程度にしたい」とシステムに指示するようなものです。このような細かいコントロールこそが、アマチュアのインジケーターとプロフェッショナルな取引システムを分けるポイントです。ユーザーは、異なる重みの組み合わせをバックテストすることで、自分の取引スタイルや市場環境に最も適した設定を見つけることができます。
public: // Parameter methods for Wizard void Depth(int value) { m_depth = value; } void MinRetracement(double value) { m_min_retracement = value; } void MaxRetracement(double value) { m_max_retracement = value; } void WeightFactor(double value) { m_weight_factor = value; } // Pattern weight methods void Pattern_0(int value) { m_pattern_0 = value; } void Pattern_1(int value) { m_pattern_1 = value; }
脳:重要な市場のスイングポイントを見つける
ここからが本格的な分析の始まりです。FindSwingPoints()は、市場構造の重要なポイント、つまりトレンドを形作る高値(ピーク)と安値(ボトム)を特定するためのメソッドです。iHighest()とiLowest()を使用して、指定したバー数(m_depthパラメータ)まで遡り、直近の重要な高値と安値を見つけます。
ここでプロのコツです。m_depthパラメータは非常に重要です。なぜなら、市場は時間足ごとに異なる「性格」を持っているからです。5分足では50本のバーを遡ると数時間分のデータですが、日足では数ヶ月分に相当することもあります。このパラメータによって、ユーザーはコードを変更することなく、自分の取引スタイルに合わせてシグナルを調整できます。
また、高値と安値のタイムスタンプを比較してトレンド方向を判断している点にも注目してください。これはシンプルでありながら効果的に市場の文脈を把握する方法です。このトレンド認識は、後にフィボナッチのサポート(上昇トレンド時)とレジスタンス(下降トレンド時)を区別する際に役立ちます。
bool CSignalFibonacci::FindSwingPoints(void) { if(m_depth <= 0) return false; int highest_bar = iHighest(m_symbol.Name(), calc_period, MODE_HIGH, m_depth, 1); int lowest_bar = iLowest(m_symbol.Name(), calc_period, MODE_LOW, m_depth, 1); if(highest_bar == -1 || lowest_bar == -1) return false; m_high_price = iHigh(m_symbol.Name(), calc_period, highest_bar); m_low_price = iLow(m_symbol.Name(), calc_period, lowest_bar); // ... trend detection
フィボナッチ数学:正確なリトレースメントレベルの計算
この関数の美しさは、その洗練されたシンプルさにあります。スイングポイントが取得できれば、フィボナッチレベルの計算は非常にシンプルな数学になります。ここでの重要なポイントは、フィボナッチリトレースメントがトレンドとは逆方向に働くため、上昇トレンドと下降トレンドで異なる処理をおこなうという点です。
上昇トレンドでは、高値から安値に向かって下方向へのリトレースメントを測定します。一方、下降トレンドでは、安値から高値に向かって上方向へのリトレースメントを測定します。一見すると当たり前に思えるかもしれませんが、多くの取引システムがこの点を誤っているのを見てきました。この処理によって、市場がサポートやレジスタンスとして反応すると予想される、正確な価格レベルを導き出すことができます。
また、ここではクラシックなフィボナッチ比率(0.236、0.382、0.500、0.618、0.786)を使用しています。これらは、世界中のトレーダーが注目する心理的かつ数学的に重要な水準です。この共通認識が自己実現的に働くことで、これらのレベルの信頼性を高めています。
double CSignalFibonacci::CalculateRetracementLevel(double level) { double range = m_high_price - m_low_price; if(m_uptrend) { // Uptrend: calculate retracement from high to low return m_high_price - (range * level); } else { // Downtrend: calculate retracement from low to high return m_low_price + (range * level); } }
インテリジェントなパターン認識:フィボナッチ数列の分類
ここで、シグナルに知性を加えます。すべてのフィボナッチレベルを同じように扱うのではなく、その強さによって分類し、異なるパターンタイプを割り当てます。0.382と0.618のレベルは「黄金比」に基づく重要なリトレースメントとして最も強力とされ(パターン0)、一方で0.500は心理的には重要であるものの数学的な裏付けはやや弱いため、別のカテゴリ(パターン1)として扱います。
ここで重要になるのが「許容範囲」の考え方です。実際の市場では価格がフィボナッチレベルにぴったり一致することはほとんどないため、一定のバッファゾーン(ポイント単位で定義)を設け、その範囲内であれば「到達した」とみなします。これにより、わずかな価格のズレによって有望なエントリーチャンスを逃すのを防ぎます。
この関数は、true/falseの結果だけでなく、参照パラメータを通じてパターンタイプも返します。この洗練された設計により、呼び出し元の関数はフィボナッチレベルに到達したかどうかだけでなく、どの種類のレベルで、どれほど重要かまで把握することができます。
bool CSignalFibonacci::IsAtFibonacciLevel(double price, int &pattern) { // Define Fibonacci levels and their pattern types struct FibLevel { double level; int pattern; }; FibLevel levels[5] = { {0.236, 2}, // Weak level -> pattern 2 {0.382, 0}, // Strong level -> pattern 0 {0.500, 1}, // Medium level -> pattern 1 {0.618, 0}, // Strong level -> pattern 0 {0.786, 2} // Weak level -> pattern 2 };
プライスアクションによる確認:強気反転を見抜く
フィボナッチレベルを見つけるだけでは十分ではありません。価格が実際にそれらのレベルを尊重しているかどうかを確認する必要があります。この関数では、ロングポジションへのエントリーに自信を与えてくれる、代表的な強気の反転パターンを探します。
包み足の検出はシンプルです。小さな陰線(赤いローソク足)の後に、それを完全に包み込む大きな陽線(緑のローソク足)が現れるパターンを確認します。これは、売り圧力から買い圧力への劇的な転換を示しています。
ハンマーパターンについては、実用的な計算ロジックを用いて、小さな実体と長い下ヒゲを持つローソク足を特定します。重要なのは、ヒゲの長さと実体の長さを比較する点です。本物のハンマーは、下ヒゲが実体の少なくとも2倍以上あります。これは安値圏での拒否(反発)を示し、強気の反転シグナルとなります。
これらの確認パターンを組み合わせることで、フィボナッチシグナルは単なる価格レベルの検出ツールから、「そのレベルが本当に重要であることを価格自身が証明するのを待つ」高度な取引システムへと進化します。
bool CSignalFibonacci::IsBullishReversal(void) { double open1 = iOpen(m_symbol.Name(), calc_period, 1); double close1 = iClose(m_symbol.Name(), calc_period, 1); // ... get more price data // Bullish engulfing pattern if(close1 > open1 && open2 > close2 && close1 > open2 && open1 < close2) { return true; } // Hammer pattern detection double range1 = high1 - low1; double body1 = MathAbs(close1 - open1); double lower_wick = (open1 > close1) ? (close1 - low1) : (open1 - low1); if(lower_wick >= (2 * body1)) { return true; } return false; }
意思決定エンジン:買いエントリーシグナルの生成
ここで、すべてがひとつにまとまります。LongCondition()メソッドは、最終的な取引判断を下す「頭脳」です。注目すべきは、このメソッドが0から100までの整数を返し、シグナルの信頼度を示す点です。これは、MQL5ウィザードがすべてのシグナルに求める標準化されたインターフェースです。
IS_PATTERN_USAGEマクロは、ユーザーがウィザードのインターフェース上で特定のパターンを有効化または無効化できる巧妙なシステムです。たとえば、強力な0.618レベルだけをトレードしたいが、弱いレベルは無視したい場合、このシステムによってコードを変更せずに柔軟に対応できます。
本当の知性は、フィボナッチレベルとプライスアクションの確認をどのように組み合わせるかにあります。フィボナッチレベルと強気の反転パターンの両方が揃った場合は、パターン3(フィボナッチ+プライスアクション)の高い重みを採用します。これにより、シグナルの質に階層を設け、取引判断をより洗練されたものにしています。
int CSignalFibonacci::LongCondition(void) { int result = 0; int pattern = -1; double current_price = m_symbol.Bid(); if(IsAtFibonacciLevel(current_price, pattern)) { if(pattern >= 0) { if(IS_PATTERN_USAGE(pattern)) { result = (int)GetPatternWeight(pattern); } if(IS_PATTERN_USAGE(3) && IsBullishReversal()) { int pa_weight = (int)GetPatternWeight(3); if(pa_weight > result) result = pa_weight; }
私たちは、市場構造を理解し、重要なフィボナッチの数学的レベルを特定し、価格の確認を待って信頼度付きシグナルを生成する、完全な取引インテリジェンスモジュールを構築しました。本当の力は、これをMQL5ウィザード内の他のシグナルと組み合わせたときに発揮されます。まず、目標を達成するために他のシグナルと組み合わせる前に、このアイデアが正しく機能するか確認するため、別のテスト用EAを作成しました。以下は、ストラテジーテスターの結果です。通常通り、MQL5ウィザードを起動するには、MetaEditorで[新規ドキュメント]を選択するか、Ctrl+Nのショートカットを使い、エキスパートアドバイザー(EA)の生成を選びます。

MetaEditorのMQL5ウィザードでフィボナッチシグナルを選択する
テスト1
下の画像は、カスタムフィボナッチシグナルをUSDJPYのM5チャートでテストするために生成したEAのパフォーマンスを示しています。

MQL5ウィザードで生成したEAをUSDJPY、M5で検証する
フィボナッチシグナルのテストが成功したので、次は本当に強力な仕組みを構築する準備が整いました。単純なロボットではなく、まるで専門取引アナリストチームのように協調して動く、マルチシグナル対応のEAを設計します。これは、自分だけの取引「ドリームチーム」を作るようなもので、それぞれのシグナルが独自の専門性を持ち寄ります。
MQL5ウィザードの利点は、複雑なインフラ部分を処理してくれるため、私たちは本当に重要な部分、つまり「インテリジェントな取引ロジックの作成」に集中できることです。以下の手順で、単一シグナルのテストを高度なトレーディングシステムに変換します。
前回と同様にMetaEditorでCtrl+Nを押してMQL5ウィザードを開き、[エキスパートアドバイザ(生成)]を選択します。シグナルセクションで、以下のモジュールを追加します:
- フィボナッチシグナル(精密エントリーの専門家)
- アクセラレーターオシレーター(市場エネルギーの解析者)
- Moving Average(トレンド専門家)
- RSI(モメンタムアナリスト)
以下は、MQL5ウィザードによって生成されたEAです。
//+------------------------------------------------------------------+ //| Multi-Signal Expert.mq5 | //| Copyright 2025, Clemence Benjamin. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, Clemence Benjamin." #property link "https://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ //| Include | //+------------------------------------------------------------------+ #include <Expert\Expert.mqh> //--- available signals #include <Expert\Signal\SignalFibonacci.mqh> #include <Expert\Signal\SignalAC.mqh> #include <Expert\Signal\SignalMA.mqh> #include <Expert\Signal\SignalRSI.mqh> //--- available trailing #include <Expert\Trailing\TrailingParabolicSAR.mqh> //--- available money management #include <Expert\Money\MoneySizeOptimized.mqh> //+------------------------------------------------------------------+ //| Inputs | //+------------------------------------------------------------------+ //--- inputs for expert input string Expert_Title ="Multi-Signal Expert"; // Document name ulong Expert_MagicNumber =-108721665; // bool Expert_EveryTick =false; // //--- inputs for main signal input int Signal_ThresholdOpen =10; // Signal threshold value to open [0...100] input int Signal_ThresholdClose =10; // Signal threshold value to close [0...100] input double Signal_PriceLevel =0.0; // Price level to execute a deal input double Signal_StopLevel =50.0; // Stop Loss level (in points) input double Signal_TakeLevel =50.0; // Take Profit level (in points) input int Signal_Expiration =4; // Expiration of pending orders (in bars) input double Signal_Fib_Weight =1.0; // Fibonacci Retracement Weight [0...1.0] input double Signal_AC_Weight =1.0; // Accelerator Oscillator Weight [0...1.0] input int Signal_MA_PeriodMA =12; // Moving Average(12,0,...) Period of averaging input int Signal_MA_Shift =0; // Moving Average(12,0,...) Time shift input ENUM_MA_METHOD Signal_MA_Method =MODE_SMA; // Moving Average(12,0,...) Method of averaging input ENUM_APPLIED_PRICE Signal_MA_Applied =PRICE_CLOSE; // Moving Average(12,0,...) Prices series input double Signal_MA_Weight =1.0; // Moving Average(12,0,...) Weight [0...1.0] input int Signal_RSI_PeriodRSI =8; // Relative Strength Index(8,...) Period of calculation input ENUM_APPLIED_PRICE Signal_RSI_Applied =PRICE_CLOSE; // Relative Strength Index(8,...) Prices series input double Signal_RSI_Weight =1.0; // Relative Strength Index(8,...) Weight [0...1.0] //--- inputs for trailing input double Trailing_ParabolicSAR_Step =0.02; // Speed increment input double Trailing_ParabolicSAR_Maximum =0.2; // Maximum rate //--- inputs for money input double Money_SizeOptimized_DecreaseFactor=3.0; // Decrease factor input double Money_SizeOptimized_Percent =10.0; // Percent //+------------------------------------------------------------------+ //| Global expert object | //+------------------------------------------------------------------+ CExpert ExtExpert; //+------------------------------------------------------------------+ //| Initialization function of the expert | //+------------------------------------------------------------------+ int OnInit() { //--- Initializing expert if(!ExtExpert.Init(Symbol(),Period(),Expert_EveryTick,Expert_MagicNumber)) { //--- failed printf(__FUNCTION__+": error initializing expert"); ExtExpert.Deinit(); return(INIT_FAILED); } //--- Creating signal CExpertSignal *signal=new CExpertSignal; if(signal==NULL) { //--- failed printf(__FUNCTION__+": error creating signal"); ExtExpert.Deinit(); return(INIT_FAILED); } //--- ExtExpert.InitSignal(signal); signal.ThresholdOpen(Signal_ThresholdOpen); signal.ThresholdClose(Signal_ThresholdClose); signal.PriceLevel(Signal_PriceLevel); signal.StopLevel(Signal_StopLevel); signal.TakeLevel(Signal_TakeLevel); signal.Expiration(Signal_Expiration); //--- Creating filter CSignalFibonacci CSignalFibonacci *filter0=new CSignalFibonacci; if(filter0==NULL) { //--- failed printf(__FUNCTION__+": error creating filter0"); ExtExpert.Deinit(); return(INIT_FAILED); } signal.AddFilter(filter0); //--- Set filter parameters filter0.Weight(Signal_Fib_Weight); //--- Creating filter CSignalAC CSignalAC *filter1=new CSignalAC; if(filter1==NULL) { //--- failed printf(__FUNCTION__+": error creating filter1"); ExtExpert.Deinit(); return(INIT_FAILED); } signal.AddFilter(filter1); //--- Set filter parameters filter1.Weight(Signal_AC_Weight); //--- Creating filter CSignalMA CSignalMA *filter2=new CSignalMA; if(filter2==NULL) { //--- failed printf(__FUNCTION__+": error creating filter2"); ExtExpert.Deinit(); return(INIT_FAILED); } signal.AddFilter(filter2); //--- Set filter parameters filter2.PeriodMA(Signal_MA_PeriodMA); filter2.Shift(Signal_MA_Shift); filter2.Method(Signal_MA_Method); filter2.Applied(Signal_MA_Applied); filter2.Weight(Signal_MA_Weight); //--- Creating filter CSignalRSI CSignalRSI *filter3=new CSignalRSI; if(filter3==NULL) { //--- failed printf(__FUNCTION__+": error creating filter3"); ExtExpert.Deinit(); return(INIT_FAILED); } signal.AddFilter(filter3); //--- Set filter parameters filter3.PeriodRSI(Signal_RSI_PeriodRSI); filter3.Applied(Signal_RSI_Applied); filter3.Weight(Signal_RSI_Weight); //--- Creation of trailing object CTrailingPSAR *trailing=new CTrailingPSAR; if(trailing==NULL) { //--- failed printf(__FUNCTION__+": error creating trailing"); ExtExpert.Deinit(); return(INIT_FAILED); } //--- Add trailing to expert (will be deleted automatically)) if(!ExtExpert.InitTrailing(trailing)) { //--- failed printf(__FUNCTION__+": error initializing trailing"); ExtExpert.Deinit(); return(INIT_FAILED); } //--- Set trailing parameters trailing.Step(Trailing_ParabolicSAR_Step); trailing.Maximum(Trailing_ParabolicSAR_Maximum); //--- Creation of money object CMoneySizeOptimized *money=new CMoneySizeOptimized; if(money==NULL) { //--- failed printf(__FUNCTION__+": error creating money"); ExtExpert.Deinit(); return(INIT_FAILED); } //--- Add money to expert (will be deleted automatically)) if(!ExtExpert.InitMoney(money)) { //--- failed printf(__FUNCTION__+": error initializing money"); ExtExpert.Deinit(); return(INIT_FAILED); } //--- Set money parameters money.DecreaseFactor(Money_SizeOptimized_DecreaseFactor); money.Percent(Money_SizeOptimized_Percent); //--- Check all trading objects parameters if(!ExtExpert.ValidationSettings()) { //--- failed ExtExpert.Deinit(); return(INIT_FAILED); } //--- Tuning of all necessary indicators if(!ExtExpert.InitIndicators()) { //--- failed printf(__FUNCTION__+": error initializing indicators"); ExtExpert.Deinit(); return(INIT_FAILED); } //--- ok return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Deinitialization function of the expert | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { ExtExpert.Deinit(); } //+------------------------------------------------------------------+ //| "Tick" event handler function | //+------------------------------------------------------------------+ void OnTick() { ExtExpert.OnTick(); } //+------------------------------------------------------------------+ //| "Trade" event handler function | //+------------------------------------------------------------------+ void OnTrade() { ExtExpert.OnTrade(); } //+------------------------------------------------------------------+ //| "Timer" event handler function | //+------------------------------------------------------------------+ void OnTimer() { ExtExpert.OnTimer(); } //+------------------------------------------------------------------+
テスト2
EAを生成した後、ストラテジーテスターでテストを実行し、そのパフォーマンスを確認しました。以下のGIFスクリーンキャストは、EURUSD、M5での動作を示しています。この段階では、まだエクイティカーブのチャートやその他の詳細なテスト指標は追加していません。現在はあくまで、ビジュアル上のパフォーマンスに注目しているためです。画像の下では、生成したEAのパフォーマンスについての私の考察と批評を共有しています。これは、EAをさらに改善し、目標により近づけるための準備として行っています。

生成されたマルチシグナルEAのテスト
重要な分析—ウィザード生成EAが私たちのビジョンから逸脱している点
MQL5ウィザードによって生成されたコードを確認すると、生成された内容と、私たちが最初に描いていた「マルチシグナルかつコンフルエンス重視のフレームワーク」との間に明確なギャップがあることがわかります。MQL5ウィザードは便利な出発点を提供してくれますが、デフォルトの状態では単純なシグナル集約器に過ぎず、意図的で階層を意識した意思決定エンジンにはなっていません。このセクションでは、主な欠点を整理し、EAを設計目標に近づけるための調整方法を概説します。
1. 意味のあるシグナル階層の復元
デフォルトでは、生成されたEAはすべてのシグナルに対して重み1.0を割り当てています。テスト用としては便利ですが、私たちのシグナルが同じ重要度を持つわけではないという事実を完全に無視しています。私たちのコンセプトでは、フィボナッチシグナルが主要な意思決定者であり、移動平均、RSI、アクセラレーターオシレーターは補助的な役割を果たします。
現在自動生成された入力:
// Uniform weights (problematic) input double Signal_Fib_Weight = 1.0; // Should be 0.8 (80%) input double Signal_AC_Weight = 1.0; // Should be 0.4 (40%) input double Signal_MA_Weight = 1.0; // Should be 0.6 (60%) input double Signal_RSI_Weight = 1.0; // Should be 0.5 (50%)
すべてのシグナルに同じ重みを与えると、階層構造が平坦化され、フィボナッチの影響力が希薄化してしまいます。また、取引経験をモデルに直接反映させる貴重な機会を失ってしまいます。より戦略的な重みの配分が必要です。
// Strategic weight distribution input double Signal_Fib_Weight = 0.8; // Core signal – mathematical precision input double Signal_MA_Weight = 0.6; // Trend context and alignment input double Signal_RSI_Weight = 0.5; // Momentum validation input double Signal_AC_Weight = 0.4; // Early energy/acceleration hint
この簡単な変更だけでも、シグナルの「平等な民主制」から脱却し、構造化され意図的に設計されたシステムへと近づけることができます。
2.エントリーの閾値:過剰取引から選択的エントリーへ
ウィザードは、エントリーの閾値を非常に低く初期化しています。これにより、すべてのシグナルの重みが1.0に設定されている場合、弱いシグナルの組み合わせでもEAが取引を実行してしまう可能性が高くなります。
// Extremely permissive configuration input int Signal_ThresholdOpen = 10; // Too low for serious use
このような閾値では、EAは過剰取引に偏ります。小さなシグナルの変動でもエントリーの理由になってしまい、取引コストが増え、複合条件(コンフルエンス)の必要性がなくなり、取引全体の質が低下してしまいます。
複数のシグナルを用いた確認型のシステムでは、エントリーにはより高いハードルを設け、クローズの条件は柔軟に設定する必要があります。
// Thresholds aligned with our confluence idea input int Signal_ThresholdOpen = 120; // Strong confirmation required to open input int Signal_ThresholdClose = 80; // More relaxed exit behaviour
この構造では、強力なフィボナッチシグナル(80)に加えて、少なくとも1つの有効な補助シグナル(例:40)があればエントリーを正当化できます。一方で、単独の小さなシグナルでは、もはやエントリーが発生しなくなります。
3. 複合条件検出の欠如:価格と時間のクラスタリング
生成されたEAには、真の複合条件(コンフルエンス)エンジンが搭載されていません。私たちの設計では、複数のシグナルが価格と時間の両方で一致している場合に、高確率のゾーンを認識できるようにすることを目指しています。
概念的には、これらのシグナルが同じ価格帯に集中しているか、同じ時間帯に出現しているかといった質問に答えられるコンポーネントが必要です。最小限のインターフェースは次のようになります。
// Price–time confluence skeleton class CConfluenceEngine { public: bool HasPriceTimeConfluence(); int CalculateConfluenceBonus(); bool CheckSignalClustering(); };
これにより、複数のシグナルが狭い範囲で重なり合う場合に、追加の「ボーナス」の重みを加えることが可能になり、市場が私たちが重視する稀な一致条件を示した際に、確信度を高めることができます。
4. 固定ロットサイズ vs.信頼度に基づくポジションサイジング
ウィザードによって生成された資金管理は、基本的に固定的です。シグナルが弱い場合でも、非常に強い場合でも、同じリスク割合が適用されます。
// Static risk usage input double Money_SizeOptimized_Percent = 10.0; // Same for all setups
コンフルエンス(複数の要因の一致)に基づくフレームワークにおいて、これは機会損失と言えます。複数の整合したシグナルによって裏付けられた強力なセットアップは、境界的な条件よりも大きなリスク配分を正当化できるはずです。より良いアプローチは、シグナル全体の信頼度からポジションサイズを導き出すことです。
// Example of dynamic, confidence-based position sizing double CalculateDynamicPositionSize(int total_confidence) { if(total_confidence >= 200) return BaseSize * 2.0; // Exceptional confluence if(total_confidence >= 150) return BaseSize * 1.5; // Strong setup if(total_confidence >= 120) return BaseSize * 1.0; // Standard setup if(total_confidence >= 100) return BaseSize * 0.7; // Marginal but tradable return 0.0; // No trade }
これにより、シグナルエンジンはリスクエンジンとしての役割も果たすようになります。より良い情報は、より適切な資本配分につながります。
5. マーケットレジーム認識の欠如
生成されたEAは、すべての市場環境を同一であるかのように扱っています。生成されたEAは、すべての市場環境を同一であるかのように扱っています。静かな相場とボラティリティの高い相場、あるいは強いトレンドと方向感のないレンジ相場を区別していません。実際には、これらの異なるレジームにおいてシグナルの挙動は大きく変わるため、戦略もそれに応じて適応すべきです。
最初のシンプルなステップとして、ATRやADXといった一般的な指標を用いた基本的なレジーム判定を導入することが考えられます。
// Simple regime detection examples bool IsHighVolatilityPeriod() { return (iATR(Symbol(), Period(), 14, 0) > high_vol_threshold); } bool IsStrongTrendingMarket() { return (iADX(Symbol(), Period(), 14, PRICE_CLOSE, MODE_MAIN, 0) > 25); } void AdjustStrategyForMarketConditions() { if(IsHighVolatilityPeriod()) { // Example: tighten filters when volatility is elevated Signal_ThresholdOpen = 150; } }
このような単純なチェックであっても、すべての環境において同じルールを盲目的に適用してしまうことを防ぐことができます。
6. 単純な重み合計から、意味のあるシグナル相互作用へ
基本的な形では、ウィザードはシグナル同士の相互作用を考慮せず、単に重みを合計するだけです。これは数学的にはシンプルですが、戦略的には浅いアプローチと言えます。
// Naive aggregation
Total_Weight = Fib_Weight + MA_Weight + RSI_Weight + AC_Weight;
私たちの目標は、より構造化されたアプローチです。フィボナッチを軸(アンカー)とし、他のモジュールはそれを確認するか、中立にとどまるべきです。より表現力のある相互作用は、次のように考えられます。
ここではロジックの構造自体が明確なストーリーを示しています。フィボナッチが主導し、他の要素がそれを確認し、コンフルエンス(複数の一致)が評価される仕組みになっています。
// Interaction-aware weighting logic double CalculateStrategicWeight() { double total = 0.0; // Base: Fibonacci direction total += Fib_Weight; // Trend confirmation if(MA_Confirms_Fib_Direction) total += MA_Weight; // Momentum validation if(RSI_Confirms_Fib_Setup) total += RSI_Weight; // Acceleration / early energy if(AC_Shows_Momentum_Acceleration) total += AC_Weight; // Extra boost when multiple modules agree if(Active_Signals >= 3) total += Confluence_Bonus; return total; }
7. 学習ループの欠如:重みが適応しない
現在の実装は時間的にも静的であり、重み、シグナル、ロジックはいずれもパフォーマンスに基づいて進化しません。長期間稼働するシステムにおいては、少なくとも各シグナルの挙動を追跡し、将来的な適応ロジックの余地を残しておくことが有用です。
まずは小さなトラッキング構造を導入するだけでも十分な第一歩となります。
// Basic performance tracking per signal struct SignalPerformance { string name; int successful_trades; int total_trades; double success_rate; }; void UpdateSignalWeightsBasedOnPerformance() { // Placeholder: adjust weights according to success_rate // e.g. increase for strong performers, decrease for weak ones }
たとえ最初のバージョンではシンプルなレポートから始めるとしても、この構成により、EAを一から作り直すことなく、将来的に適応的な振る舞いを導入しやすくなります。
8. 市場環境と信頼度に連動したリスク管理
最後に、ウィザードのデフォルトのリスク管理では、固定されたストップロスおよびテイクプロフィットの距離が使用されています。
// Fixed levels for all conditions input double Signal_StopLevel = 50.0; // pips, independent of volatility input double Signal_TakeLevel = 50.0;
このような固定値は簡単なデモには適していますが、ボラティリティやシグナルの質がリスクに与える影響を適切に反映しているとは言えません。より堅牢なアプローチでは、ストップレベルをATRに連動させ、さらに全体の信頼度に応じて調整するようにします。
// Example of dynamic, ATR-based risk management double CalculateDynamicStopLoss(int signal_confidence,double volatility) { double base_stop = volatility * 2.0; // ATR-driven base distance if(signal_confidence >= 200) return base_stop * 0.7; // Tighter stops on very strong setups if(signal_confidence <= 100) return base_stop * 1.5; // Wider stops for weaker conditions return base_stop; }
このようにして、EAは現在の市場の状態とシグナルの強さの両方を適切に反映するようになります。
これらの観察を総合すると、ウィザードは便利な骨組みを提供してくれるものの、私たちが必要とする完成されたアーキテクチャではないことが分かります。今後のステップとしては、上記で説明した重み付け階層、コンフルエンスロジック、動的なポジションサイジング、そして適応的なリスク管理へと、汎用的なコンポーネントを段階的に置き換えていくことになります。これにより、生成されたEAが当初の設計思想をより正確に反映するものとなります。
結論
今回は、マルチシグナル型EAを開発するための基礎を築きました。最も広く利用されているテクニカルフレームワークの一つであるフィボナッチに焦点を当て、その理論を実際の売買シグナルへと変換する方法を示しました。MQL5ウィザードを用いた初期テストでは、カスタムのフィボナッチシグナルに基づいて取引をおこなうEAを作成することができました。ただし、これは収益性を保証するものではありません。結果は、さらなるリサーチ、慎重なテスト、そして入念な最適化にどれだけ取り組むかに大きく左右されます。提供された基礎的なソースファイルをもとに、自分の取引目標に合ったパラメータの組み合わせを探っていくことが可能です。
このアイデアをマルチシグナルEAへと拡張すると、ウィザードはあくまで出発点に過ぎないことが明確になります。デフォルトで生成されるコードには、個々のシグナルをどのように連携させるかというロジックは含まれていません。フィボナッチ、移動平均、RSI、アクセラレーターオシレーターの関係性(どのように相互に確認し、上書きし、あるいは強化し合うのか)は定義されていないのです。このため、コード生成後にMetaEditor上で追加開発をおこなうことが不可欠です。複数のシグナルを持つEAを生成すること自体は容易ですが、それらを知的に連携させるためには、ソースコードを開いてロジックを手動で洗練させる必要があります。
以下に、本記事で使用したファイルのソースコードを示します。ぜひ内容をご確認のうえ、修正を加え、コメント欄でご意見を共有してください。次回の公開では、ウィザードで生成されたEAをさらに改善し、当初のマルチシグナル設計および取引の目標により適合させる方法に焦点を当てます。
| ソースファイル | 説明: |
|---|---|
| SignalFibonacci.mqh | フィボナッチに基づく取引ロジックをカプセル化し、MQL5ウィザードから再利用可能なシグナルコンポーネントとして利用できるカスタムシグナルモジュール |
| TestSignalFibonacci.mq5 | フィボナッチシグナルが正しくコンパイルされ、読み込まれ、単体で取引を実行できるかを検証するために、MQL5ウィザードで生成されたスタンドアロンのテスト用EA |
| Multi-Signal Expert.mq5 | フィボナッチ、移動平均、RSI、アクセラレーターオシレーターの各シグナルを組み合わせた、ウィザード生成のマルチシグナルEA(高度なマルチシグナルフレームワークの基盤) |
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/20289
警告: これらの資料についてのすべての権利はMetaQuotes Ltd.が保有しています。これらの資料の全部または一部の複製や再プリントは禁じられています。
この記事はサイトのユーザーによって執筆されたものであり、著者の個人的な見解を反映しています。MetaQuotes Ltdは、提示された情報の正確性や、記載されているソリューション、戦略、または推奨事項の使用によって生じたいかなる結果についても責任を負いません。
MQL5における純粋なRSA暗号化の実装
MQL5での取引戦略の自動化(第44回):スイングハイ/ローのブレイクによる性格の変化(CHoCH)検出
エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法
プライスアクション分析ツールキットの開発(第53回):サポート・レジスタンスゾーン発見のためのPattern Density Heatmap
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索