English Deutsch
preview
MQL5標準ライブラリエクスプローラー(第5回):マルチシグナルEA

MQL5標準ライブラリエクスプローラー(第5回):マルチシグナルEA

MetaTrader 5 |
20 3
Clemence Benjamin
Clemence Benjamin

内容



はじめに

前回は、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が「生存」し、かつ成果を上げ続けることを可能にします。

FlowDigram

マルチシグナルEAの概念的な処理フロー

システムの流れ:

  • 市場データは継続的にマルチシグナルEAシステムへ入力されます。
複数のシグナルモジュールが同時にデータを処理します。
  1. プライマリトリガーはエントリー機会を探索します。
  2. フィルターシグナルは判断の検証および精緻化をおこないます。
  3. すべてのモジュールは組み合わせ可能であり、組み込みシグナルと今回のフィボナッチのようなカスタムシグナルを併用できます。
  4. 重み付けシステムは、すべてのアクティブなシグナルから確信度を収集します。
  5. 意思決定エンジンは、合計確信度が取引閾値を超えているかを評価します。
  6. リスク管理はポジションサイズおよびリスク制御を担当します。
  7. すべての条件が一致した場合にのみ、取引が実行されます。

可視化される主な利点

  1. レジリエンス複数のシグナル経路があるため、一つが機能しなくても他がトリガーとなり得ます。
  2. 適応性:市場状況に応じて異なるシグナルが主導的役割を持ちます。
  3. 専門性:各モジュールは自身の得意分野に集中します。
  4. プロフェッショナルな基盤: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)の生成を選びます。

MQL5ウィザードがフィボナッチシグナルを登録する

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のテスト

重要な分析—ウィザード生成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

添付されたファイル |
SignalFibonacci.mqh (17.77 KB)
最後のコメント | ディスカッションに移動 (3)
prasad
prasad | 3 12月 2025 において 13:12
デフォルトのセッティングでプレーしているのですが、莫大な損失が出ています。
Stanislav Korotky
Stanislav Korotky | 13 12月 2025 において 15:58
EAの入力から複雑な論理条件を設定可能で、再コンパイルなしで複数のシグナルを組み合わせた取引戦略を構築するために、ユーザーはコードベースからユニバーサルシグナルモジュールを 試すことができます。
Steven Glanz
Steven Glanz | 16 1月 2026 において 16:28
MQL5市場には、このモデルに基づいたEAはありますか?
MQL5における純粋なRSA暗号化の実装 MQL5における純粋なRSA暗号化の実装
MQL5には組み込みの非対称暗号が存在しないため、HTTPのような安全でないチャネルでのデータ交換は困難です。本記事では、PKCS#1 v1.5パディングを用いた純粋なMQL5実装のRSAを紹介し、外部ライブラリを使用せずにAESのセッションキーや小規模なデータブロックを安全に送信できる方法を解説します。このアプローチにより、標準HTTP上でも、アプリケーションレベルでHTTPSに近い安全性を実現できるだけでなく、MQL5アプリケーションにおける安全な通信の重要なギャップを埋めることができます。
MQL5での取引戦略の自動化(第44回):スイングハイ/ローのブレイクによる性格の変化(CHoCH)検出 MQL5での取引戦略の自動化(第44回):スイングハイ/ローのブレイクによる性格の変化(CHoCH)検出
この記事では、MQL5で性格の変化(CHoCH)検出システムを開発します。本システムは、ユーザーが設定したバーの長さに基づいてスイングハイとスイングローを特定し、高値には「HH/LH」、安値には「LL/HL」とラベル付けをおこない、トレンド方向を判定します。そして、これらのスイングポイントをブレイクした際にエントリーをおこない、潜在的な反転を示すサインとして活用します。構造が変化した際のブレイクもエントリー対象とします。
エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法 エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法
この記事では、MT4において複数のEAの衝突をさける方法を扱います。ターミナルの操作、MQL4の基本的な使い方がわかる人にとって、役に立つでしょう。
プライスアクション分析ツールキットの開発(第53回):サポート・レジスタンスゾーン発見のためのPattern Density Heatmap プライスアクション分析ツールキットの開発(第53回):サポート・レジスタンスゾーン発見のためのPattern Density Heatmap
本記事では、パターン密度ヒートマップ(Pattern Density Heatmap)を紹介します。これは、繰り返し出現するローソク足パターンの検出結果を、統計的に有意なサポート・レジスタンスゾーンに変換するプライスアクションマッピングツールです。単一のシグナルを個別に扱うのではなく、EAは検出結果を固定価格レンジに集約し、密度をスコア化(必要に応じて直近の重み付けも可能)し、高い時間軸のデータと照合してレベルを確認します。その結果として得られるヒートマップは、市場が過去にどの価格レベルで反応したかを可視化し、売買のタイミング、リスク管理、戦略への信頼性向上に活用できます。あらゆる取引スタイルに対応可能です。