English Deutsch
preview
Candlestick Trend Constraintモデルの構築(第7回):EA開発モデルの改良

Candlestick Trend Constraintモデルの構築(第7回):EA開発モデルの改良

MetaTrader 5トレーディング | 23 9月 2024, 11:26
112 0
Clemence Benjamin
Clemence Benjamin

関心のあるセクション


        はじめに

        利用可能な指標に基づいて、EAを開発することが可能です。この記事では2つの方法を紹介します。

        1. 指標の条件をEAアルゴリズムにコーディングすることは、ストラテジーテスターでも効率的で非常に高速です。この方法では、指標を別途使用することなくEAが動作します。
        2. もう1つのアプローチは指標のバッファに注目したEAのアルゴリズムを準備することです。EAはバッファがTrueかFalseに応じて特定の反応をするようにプログラムされています。この方法でシステムをMetaTrader 5で機能させるには、EAと指標がプラットフォームパス内の特定のディレクトリに配置されている必要があります。しかし、カスタム指標を利用するEAをMQL5コミュニティで公開しようとすると、検証システムが指標を認識できず、公開が難しい場合があります。実際に試してみたところ、エラーが発生したため、公開せずに自身のコンピュータでのみ実行できました。

        EAを正常に動作させるには、まず指標を準備する必要があります。これには、指標バッファを適切に整理し、その動作を理解することが重要です。そうすることで、EAの開発がスムーズに進みます。どちらのアプローチも効果的ですが、それぞれに長所と短所があり、今後の記事で詳しく議論します。指標とEAを組み合わせる主なメリットは、EAアルゴリズムの複雑さを軽減できる点にあります。指標プログラムで条件が既にコーディングされているため、開発者は特定のアルゴリズム部分に集中することが可能です。

        第6回では、Trend Constraint V1.08が最終的に進化を遂げ、TelegramとWhatsAppのシグナル統合を1つのプログラムにまとめました。これにより、シグナルへのアクセスが容易になり、非常に満足しています。しかし、次のような疑問も浮かんでいます。

        • シグナルは受信しているが、それが最良のものなのか
        • 取引はできるが、いつエグジットすべきか

        こうした疑問は、チャートの再検討や指標の過去のパフォーマンス確認、またはソースコードの再コーディングを通じて新しい機能を追加し、システムを強化することでしか解決できません。EAのシステムを改善するにあたり、以下の点を提案します。

        1. 各バッファの目的を徹底的に理解する
        2. 移動平均クロスオーバーをエントリシグナルとして再導入する
        3. リスクとリターンの比率を使い、緑色で利益目標範囲、赤色で損失範囲を示す矩形を描く

        私たちは、エントリおよびエグジットの概念を可視化し、トレーダーが手動でそれに従うことができる指標を設計することを目指しています。この手動ストラテジーは自動化することも可能です。また、リスクリワードレシオ(RRR)は、トレーダーが取引の潜在的な収益性を評価するのに役立ちます。今後、以下のRRRの計算式など新たな機能を指標に組み込み、潜在的なエグジットレベルの概説について議論していきます。

         


        リスク-リワードレシオ、計算式

        ここで

        RRR:リスクと報酬の比率
        Potential Loss:取引や投資が不利に動いた場合に失う可能性のある金額のこと
        Potential Gain:取引や投資が有利に動いた場合に得られると予想される金額

        例を挙げます。

        ある銘柄を50ドルで買おうと考えているとします。損切り価格を48ドル(1株当たり2ドルの潜在的損失を示す)に設定し、目標価格を56ドル(1株当たり6ドルの潜在的利益を示す)に設定します。株式のリスクリワードレシオを計算します。

        • Potential Loss:50ドル(エントリ価格)-48ドル(ストップロス)=2ドル
        • Potential Gain:56ドル(目標価格)-50ドル(エントリ価格)=6ドル

        値を式に代入すると、リスクと報酬の比率=1/3です。

        つまり、1ドルのリスクに対して3ドルの利益が期待できるということです。比率が低い(例えば1:1以下)ほど、潜在的な報酬に対してリスクが高いことを示し、比率が高いほど、リスクと報酬のシナリオがより有利であることを示唆します。

        上記の例に基づいて、矩形を使った図解を示します。赤の矩形はリスクを、緑の矩形は報酬を表しています。

        リスクリワードレシオ図解


        これについては、次のセクションで詳しく説明します。このディスカッションの終わりまでに、私たちが焦点を当てるべきポイントは以下の通りです。

        1. アルゴリズム取引におけるリスク管理の重要性を理解する
        2. リスクリワードレシオの導入とその数学的基礎
        3. 最適な取引管理のためのダイナミックなエグジット戦略の開発
        4. より良い取引意思決定のための視覚的指標の強化
        5. 指標を実世界に適用するためのテストと検証


        現行システムの限界を見極める

        新機能を備えた指標システムを向上させるには、重要な部分を再評価し、現システムが遅れている点を特定することが必要です。そのために、私は次の2つの手法を用いるアプローチを取っています。これらは以下の通りです。

        1. チャートの再検討:指標チャートの履歴ウィンドウを確認し、表示の精度に注目して、異常があれば特定します。 
        2. コードの再検討:第1段階で特定された問題に関連するコードを検証し、必要な修正をおこないます。


        チャートの再検討

        こちらはブーム500指数のチャート画像です。以下に、私が気づいた問題点を表にまとめます。


        ブーム500インデックスM1


        • 図では、(A)がスパイクローソク足を示しています。この場合、矢印は本来ローソク足の上に表示されるべきですが、下に表示されています。これは、矢印がRSIの買われ過ぎゾーンを表しているためであり、ローソク足が閉じた後にのみ発生する問題です。
        • DRAW_LINEの表示機能は正しく機能しており、ラインの色の変化を通じて新たなトレンドを特定できます。相場が方向転換するときは、通常大きな動きが見られるからです。
        • 青色の買いシグナルは、トレンドの継続を示す可能性があり、現在の上昇トレンドがRSIの売られ過ぎゾーンに支配されていることを表しています。ここでのテーマは、シグナルをD1ローソク足と市場センチメントに限定する点を忘れてはいけません。相対力指数(RSI)の極端な水準はエントリに適した指標となることがありますが、反転を保証するわけではなく、相場のゾーンを示すに過ぎません。RSIの水準に関係なく、相場はトレンドの中で引き続き優勢を保つ可能性があります。利益を最大化するために、私は移動平均クロスオーバーを他のエントリに再導入することを提案します。これは通常プライスアクションと一致するからです。
        • また、冒頭で述べたように、指標がエントリシグナルを発する際に、リスクとリターンの比率を矩形で表示する利点にも注目しています。この新バージョンでは、リスクとリターンを正しく表示するために、矩形の輪郭を正確に描画する必要があります。以下のチャート画像で示されたアイデアをご覧ください。最初のチャートはEURUSD、2番目のチャートはBoom500です。

        EURUSD、M1:ユーロ対ドル

        ユーロドル


        ブーム500指数、M1:

        ブーム500インデックスM1

        これらの図から、新しいアプローチが明確に確認できます。手動で示された内容を正確に反映させるために、指標のコードを準備したいと考えています。複数のテクニカルアナリストやトレーダーによれば、ピボットは従来、利食いと損切りのターゲットとして重要視されてきました。したがって、リスクとリターンの比率が1:3という考え方は、図表のようにリスクが潜在的な利益を大きく上回るシナリオには適さない可能性があります。

        上の図を要約すると

        1. ピボットはストップロスやテイクプロフィットといったエグジットポイントを設定するための基準として使われます。
        2. エントリレベルとエグジットレベルの価格は、後のロジックで使用可能です。 

        次のセクションでは、コードの重要な部分を検証し、それらに対応します。


        コードの再検討

        ここに、変更を加えることができるスニペットがあります。
        #property indicator_type1 DRAW_ARROW
        #property indicator_width1 5
        #property indicator_color1 0xFF3C00
        #property indicator_label1 "Buy" // We are going to change it to "Buy Zone"
        
        #property indicator_type2 DRAW_ARROW
        #property indicator_width2 5
        #property indicator_color2 0x0000FF
        #property indicator_label2 "Sell"// We are going to change it to "Sell Zone"


        このセクションでは、ローソク足上の矢印の位置を固定します。これには、バッファ2の反復関数が関係しています。指標はローソク足の高値で表示されなければならないので、Low[i]を High[i]に変更します。

        //Indicator Buffer 2 // We are going to set the indicator to display at candlestick high by changing the highlighted text to High[i]
              if(RSI[i] > Overbought
              && RSI[i+1] < Overbought //Relative Strength Index crosses above fixed value
              && Open[barshift_M1[i]] <= Close[1+barshift_D1[i]] //Candlestick Open <= Candlestick Close
              && MA[i] < MA2[i] //Moving Average < Moving Average
              && MA3[i] < MA4[i] //Moving Average < Moving Average
              )
        
                {
                 Buffer2[i] = Low[i]; //Set indicator value at Candlestick Low // change to High[i]
                 if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Sell Zone"); //Alert on next bar open
                 time_alert = Time[1];
                }
              else
                {
                 Buffer2[i] = EMPTY_VALUE;
                }



        移動平均のクロスオーバーを組み込む

        以下のコードスニペットを使って、プログラムに新しい機能を追加するプロセスを明らかにしましょう。既存のバッファに加え、新たに2つのバッファを追加し、バッファ6とバッファ7とします。

        私たちの賢いプログラムのロジックに従って、まずそのプロパティを定義します。最近、RSI指標に「売りゾーン」と「買いゾーン」を採用したため、 これらは指標の新しい「売り」と「買い」のシグナルとなります。

        #property indicator_type6 DRAW_ARROW
        #property indicator_width6 1
        #property indicator_color6 0x0000FF
        #property indicator_label6 "Sell"
        
        #property indicator_type7 DRAW_ARROW
        #property indicator_width7 1
        #property indicator_color7 0xFFAA00
        #property indicator_label7 "Buy"

        最適なシグナルを得るために、カスタマイズのための入力を設定する必要があります。移動平均線は7期間と21期間を使用します。

        input int Entry_MA_fast = 7 ;
        input int Entry_MA_slow = 21 ;

        新機能のOnCalculate関数を以下に示します。条件が満たされたとき、プログラムがどのように結果を表示するかについて詳しく説明します。

        SetIndexBuffer(5, Buffer6);
           PlotIndexSetDouble(5, PLOT_EMPTY_VALUE, EMPTY_VALUE);
           PlotIndexSetInteger(5, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
           PlotIndexSetInteger(5, PLOT_ARROW, 242);
           SetIndexBuffer(6, Buffer7);
           PlotIndexSetDouble(6, PLOT_EMPTY_VALUE, EMPTY_VALUE);
           PlotIndexSetInteger(6, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
           PlotIndexSetInteger(6, PLOT_ARROW, 241);


        この段階では、移動平均のクロスオーバーの条件を組み込んでいます。このシナリオでは、バッファ7の条件はバッファ6の条件と同じです。基本的にプロセスは同じですが、各バッファで逆になっています。

        //Indicator Buffer 6
              if(MA8[i] < MA9[i]
              && MA8[i+1] > MA9[i+1] //Moving Average crosses below Moving Average
              && Open2[i] <= Close[1+barshift_D1[i]] //Candlestick Open <= Candlestick Close
              )
                {
                 Buffer6[i] = High[i]; //Set indicator value at Candlestick High
                 if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Sell"); //Alert on next bar open
                 time_alert = Time[1];
                }
              else
                {
                 Buffer6[i] = EMPTY_VALUE;
                }
              //Indicator Buffer 7
              if(MA8[i] > MA9[i]
              && MA8[i+1] < MA9[i+1] //Moving Average crosses above Moving Average
              && Open2[i] >= Close[1+barshift_D1[i]] //Candlestick Open >= Candlestick Close
              )
                {
                 Buffer7[i] = Low[i]; //Set indicator value at Candlestick Low
                 if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Buy"); //Alert on next bar open
                 time_alert = Time[1];
                }
              else
                {
                 Buffer7[i] = EMPTY_VALUE;
                }


        矩形を描く

        このコードに取り組むのはとても楽しかったです。最近追加されたバッファを修正し、リスクゾーンとプロフィットゾーンを示す矩形を配置する機能を組み込むことで、既存のプログラムを拡張することを検討しました。また、オブジェクトの配置方法と、どのバッファに関連付けるかについて、特にBuffer6とBuffer7のロジックを紙に書き出すことから始めました。

        これが実際の実装前のペーパーロジックです。

         動きの速い移動平均線が、動きの遅い移動平均線の下をクロスします。 

        Buffer7の条件がtrueの場合、現在のローソク足の安値の下に矩形を配置します。
          • 矩形の幅は5本以上
          • 矩形の高さはX pips下方(Xはpips数)
          • 矩形は緑色
          • Buffer7の条件がtrueのとき、緑の矩形の上に、緑の矩形の1/3の高さの赤い矩形を配置
          • すべてのパラメータはカスタマイズ可能

        高速移動平均が低速移動平均を上回ったとき、Buffer6の条件がtrueであれば、現在のローソク足の高値の上に矩形を置きます。

        スペックは以下の通りです。

          • 矩形の幅は5本以上
          • 矩形の高さはX pips上方(Xはpips数)
          • 矩形は緑色
          • 緑の矩形の下に、バッファ6の条件が真のとき、緑の矩形の1/3の高さの赤の矩形を配置します。
          • すべてのパラメータはカスタマイズ可能

        まず、カスタマイズのためのパラメータを入力する機能が必要です。以下は、組み込みを示すコードスニペットであります。

        //--- new inputs for rectangles
        input int RectWidth = 5;                 // Width of the rectangle in bars
        input int RectHeightPointsBuy = 50;      // Height of the profit rectangle in points for Buy
        input int RectHeightPointsSell = 50;     // Height of the profit rectangle in points for Sell
        input color ProfitRectColor = clrGreen;  // Color of the profit rectangle
        input color RiskRectColor = clrRed;      // Color of the risk rectangle
        
        デフォルトではポイントを50に設定していますが、ニーズや利益目標に合わせて調整できます。また、利益目標に対する比率として、リスク矩形の高さを自動的に調整する機能も盛り込みました。これは、指標が背景色の変化に適応できるようにするために重要です。例えば、チャートの背景を緑色にすると緑色の矩形が溶け込んで見えなくなってしまいますが、黄色だとコントラストが良くなります。ツールを完全にコントロールするためには、カスタマイズが重要です。


        では、OnCalculate関数を調べて、反復がどのように機能しているかを見てみましょう。

        if(RSI[i] > Overbought) {
                if(close[i] > MA[i])
                    Buffer6[i] = close[i] - pips * myPoint;
            }
        
            if(RSI[i] < Oversold) {
                if(close[i] < MA[i])
                    Buffer7[i] = close[i] + pips * myPoint;
            }
        
            if(Buffer6[i] > 0) {
                Buffer1[i] = close[i] - pips * myPoint;
                Buffer3[i] = close[i] - pips * myPoint;
                if (Buffer6[i - 1] < 0) {
                    myAlert("indicator", "Sell Signal Detected!");
                    if (Audible_Alerts)
                        Alert(Symbol(), " ", Period(), ": Sell Signal Detected!");
        
                    // Create profit rectangle for Sell
                    double highProfitRect = close[i];
                    double lowProfitRect = close[i] - RectHeightPointsSell * myPoint;
                    string profitRectName = "SellProfitRect" + IntegerToString(i);
                    if (ObjectFind(0, profitRectName) != 0) {
                        ObjectCreate(0, profitRectName, OBJ_RECTANGLE, 0, time[i], highProfitRect, time[i + RectWidth], lowProfitRect);
                        ObjectSetInteger(0, profitRectName, OBJPROP_COLOR, ProfitRectColor);
                        ObjectSetInteger(0, profitRectName, OBJPROP_STYLE, STYLE_SOLID);
                        ObjectSetInteger(0, profitRectName, OBJPROP_WIDTH, 2);
                    }
        
                    // Create risk rectangle for Sell
                    double highRiskRect = close[i];
                    double lowRiskRect = close[i] + (RectHeightPointsSell / 3) * myPoint;
                    string riskRectName = "SellRiskRect" + IntegerToString(i);
                    if (ObjectFind(0, riskRectName) != 0) {
                        ObjectCreate(0, riskRectName, OBJ_RECTANGLE, 0, time[i], highRiskRect, time[i + RectWidth], lowRiskRect);
                        ObjectSetInteger(0, riskRectName, OBJPROP_COLOR, RiskRectColor);
                        ObjectSetInteger(0, riskRectName, OBJPROP_STYLE, STYLE_SOLID);
                        ObjectSetInteger(0, riskRectName, OBJPROP_WIDTH, 2);
                    }
                }
            }
        
            if(Buffer7[i] > 0) {
                Buffer2[i] = close[i] + pips * myPoint;
                Buffer4[i] = close[i] + pips * myPoint;
                if (Buffer7[i - 1] < 0) {
                    myAlert("indicator", "Buy Signal Detected!");
                    if (Audible_Alerts)
                        Alert(Symbol(), " ", Period(), ": Buy Signal Detected!");
        
                    // Create profit rectangle for Buy
                    double highProfitRect = close[i] + RectHeightPointsBuy * myPoint;
                    double lowProfitRect = close[i];
                    string profitRectName = "BuyProfitRect" + IntegerToString(i);
                    if (ObjectFind(0, profitRectName) != 0) {
                        ObjectCreate(0, profitRectName, OBJ_RECTANGLE, 0, time[i], highProfitRect, time[i + RectWidth], lowProfitRect);
                        ObjectSetInteger(0, profitRectName, OBJPROP_COLOR, ProfitRectColor);
                        ObjectSetInteger(0, profitRectName, OBJPROP_STYLE, STYLE_SOLID);
                        ObjectSetInteger(0, profitRectName, OBJPROP_WIDTH, 2);
                    }
        
                    // Create risk rectangle for Buy
                    double highRiskRect = close[i] - (RectHeightPointsBuy / 3) * myPoint;
                    double lowRiskRect = close[i];
                    string riskRectName = "BuyRiskRect" + IntegerToString(i);
                    if (ObjectFind(0, riskRectName) != 0) {
                        ObjectCreate(0, riskRectName, OBJ_RECTANGLE, 0, time[i], highRiskRect, time[i + RectWidth], lowRiskRect);
                        ObjectSetInteger(0, riskRectName, OBJPROP_COLOR, RiskRectColor);
                        ObjectSetInteger(0, riskRectName, OBJPROP_STYLE, STYLE_SOLID);
                        ObjectSetInteger(0, riskRectName, OBJPROP_WIDTH, 2);
                    }
                }
            
        

        ここでは矩形が作成されています。

        プロフィット矩形

        • 売りシグナルの場合、緑色の矩形が終値から下方向に伸びる
        • 買いシグナルの場合、緑色の矩形が終値から上方に伸びる


        リスクの矩形

          • 売りシグナルの場合、赤い矩形が終値から上方に伸び、その高さは利益の矩形の1/3
          • 買いシグナルの場合、赤い矩形が終値から下方に伸び、高さは利益矩形の1/3

        では、今回導入された新機能を簡単に説明しましょう。

        • ObjectFind:特定の名前のオブジェクトがすでにチャート上に存在するかどうかをチェックする関数

        int ObjectFind(
           long   chart_id,   // Chart ID (0 means the current chart)
           string name        // Name of the object to search for
        );
        


        • ObjectCreate:チャート上に新しいグラフィカルオブジェクトを作成するために使用される関数。オブジェクトのタイプを指定することができる(例:矩形、トレンドラインなど)

        bool ObjectCreate(
           long    chart_id,   // Chart ID (0 means the current chart)
           string  name,       // Name of the object to create
           ENUM_OBJECT type,   // Type of the object (e.g., OBJ_RECTANGLE, OBJ_TREND, etc.)
           int     sub_window, // Number of the subwindow (0 means the main chart window)
           datetime time1,     // First coordinate time
           double  price1,     // First coordinate price
           ...                 // Additional coordinates depending on the object type
        );
        


        • ObjectSetInteger:色、スタイル、幅などのグラフィカルオブジェクトの整数プロパティを設定するために使用される関数

        bool ObjectSetInteger(
           long   chart_id,     // Chart ID (0 means the current chart)
           string name,         // Name of the object
           int    prop_id,      // ID of the property to set (e.g., OBJPROP_COLOR, OBJPROP_STYLE, etc.)
           long   value         // Value of the property
        );
        

        この関数は以下のブール値を返します。

        • true:プロパティの設定に成功した場合
        • false:プロパティの設定に失敗した場合

        これらの関数の詳細な説明については、MQL5言語に関するすべてが記載されているMQL5ドキュメントをご覧ください。 


        エグジットポイントの導入

        エグジットポイントの導入は、Trend Constraint V1.08の重要な強化点です。効果的なエグジット戦略は、単に利益を確保し損失を抑えるだけではありません。私たちは、主要な支持線と抵抗線に基づく事前設定されたエグジットポイントを統合し、潜在的な反転ゾーンを特定することを提案します。以前のシグナルロジックはペア名のみを提供していましたが、今回の改良では、エントリ、ストップロス、テイクプロフィットといったすべての関連価格を提示します。これらのレベルを活用することで、トレーダーは価格が反転しやすいポイントや重要な抵抗に直面する可能性の高いエグジットポイントを判断でき、エグジット戦略をより最適化することが可能です。


        これがそのやり方です。

        矩形に沿って価格ラインを挿入するプログラムを修正するために、特定の価格レベルに3本のラインを追加します。

        • シグナル価格(シグナルの終値) 
        • 利益目標 
        • リスク目標 

        これらのラインは、シグナルが検出された直後に配置されます。また、これらの特定の価格水準をユーザーに通知するアラートも設定します。

        まず、プロフィットポイントリスクポイントを入力として定義し、カスタマイズできるようにします。

        input double profitPoints = 60; // Points for profit target
        input double riskPoints = 20;   // Points for risk target
        

        ここで、線を配置するためのカスタム関数を紹介しましょう。以下のスニペットは、これらの関数の定義を示しています。MQL5を初めて使用する方は、関数が値を返さないことを示すためにvoidが使用されることに注意してください。 

        void CreatePriceLine(string name, color lineColor, double price, datetime time) {
            if (ObjectFind(0, name) == -1) {
                ObjectCreate(0, name, OBJ_HLINE, 0, time, price);
                ObjectSetInteger(0, name, OBJPROP_COLOR, lineColor);
                ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
            } else {
                ObjectMove(0, name, 0, time, price);
            }
        }
        
        void PlaceSignalLines(double signalPrice, double profitTarget, double riskTarget, datetime time) {
            CreatePriceLine("SignalPriceLine", clrBlue, signalPrice, time);
            CreatePriceLine("ProfitTargetLine", clrGreen, profitTarget, time);
            CreatePriceLine("RiskTargetLine", clrRed, riskTarget, time);
        }
        


        最後は、シグナル検出のロジックです。ご覧のように、重要な価格レベルを示すアラートがあり、プログラムを手動で実行する際にトレーダーを支援します。 

        void CheckSignalAndPlaceLines() {
            for (int i = rates_total - 2; i >= 0; i--) {
                if (Buffer6[i] != 0.0) { // Buy Signal Detected
                    double signalPrice = Close[i];
                    double profitTarget = signalPrice + profitPoints * Point;
                    double riskTarget = signalPrice - riskPoints * Point;
                    PlaceSignalLines(signalPrice, profitTarget, riskTarget, Time[i]);
                    Alert("Buy Signal: Signal Price = ", signalPrice, " Profit Target = ", profitTarget, " Risk Target = ", riskTarget);
                }
                if (Buffer7[i] != 0.0) { // Sell Signal Detected
                    double signalPrice = Close[i];
                    double profitTarget = signalPrice - profitPoints * Point;
                    double riskTarget = signalPrice + riskPoints * Point;
                    PlaceSignalLines(signalPrice, profitTarget, riskTarget, Time[i]);
                    Alert("Sell Signal: Signal Price = ", signalPrice, " Profit Target = ", profitTarget, " Risk Target = ", riskTarget);
                }
            }
        }
        


        要約すると、以下のように、プログラムに3つの大きな変更を加えました。

        1. Trend ConstraintV1.08を改良し、エントリシグナルに移動平均クロスオーバーを採用しました。
        2. リスクゾーンとプロフィットゾーンを表す矩形を取り入れることについて議論しました。
        3. さらに、プログラムにおけるエグジットポイントの重要性についても話し合いました。

        プログラムを改良し続ける中で、3つのバージョンができました。Trend Constraint V1.09、V1.10、V1.11です。次に、テストのパフォーマンスと結果について説明します。


        テストと検証

        バージョンV1.09のテストとコンパイルは成功しました。いくつかの問題が発生しましたが、完全に解決されました。以下は、起動に成功したパネルと、CPU上の機能パフォーマンスの詳細を示すプロファイラのサマリーを示す画像です。


        Trend Constraint V1.09開始


        テスターのプロファイリング結果

        メタエディタープロファイラー


        上記の成功を収める前にエラーに遭遇しましたが、その後修正されました。このプロセスがどのように展開したかをお伝えできることを嬉しく思います。下の画像をご覧ください。


        エラーログ


        エラーログを確認した後、プログラムを見直し、欠けている部分を特定するのが容易になりました。移動平均のクロスオーバーを追加する際には、既存のバッファに加え、新しいバッファのMA8、MA9、MA_handle8、MA_handle9も宣言する必要がありました。以下のコードはその宣言を示しています。ハイライトされた行は、エラーの原因となった行です。

        int RSI_handle;
        double RSI[];
        double Open[];
        double Close[];
        int MA_handle;
        double MA[];
        int MA_handle2;
        double MA2[];
        int MA_handle3;
        double MA3[];
        int MA_handle4;
        double MA4[];
        double Low[];
        double High[];
        int MA_handle5;
        double MA5[];
        int MA_handle6;
        double MA6[];
        int MA_handle7;
        double MA7[];
        int MA_handle8;
        double MA8[];
        int MA_handle9;
        double MA9[];
        double Open2[];

        ハイライトした宣言を追加すると、プログラムは正常にコンパイルされました。

        V1.10に移ると、矩形を組み込んだ後、プログラムのコンパイルは成功しましたが、チャートには何も表示されません。どこを見落としたのか判断するのは難しいので、問題が解決するまで一行ずつデバッグを続け、次回の記事でその結果を共有したいとおもいます。

        V1.11ではコンパイルエラーが発生しましたが、その解決プロセスについては次の記事で紹介します。

        どのバッファが必要な条件を実行するかを理解するために、プログラム内のバッファの要約はEA開発にとって重要です。下の表を参照してください。

        バッファ 詳細
        Buffer1 RSIが一定値(買われすぎ)を上回った場合、現在の建値が特定のバーの終値以上である場合、2本の移動平均線(MAとMA3)がともにそれぞれの比較移動平均線(MA2とMA4)より大きい場合、チャート上に「買いゾーン」をマークする場合に使用
        Buffer2
        RSIが一定値(買われすぎ)を上回った場合、現在の建値が特定のバーの終値以下である場合、2本の移動平均線(MAとMA3)がそれぞれの比較移動平均線(MA2とMA4)よりも小さい場合、チャート上に「売りゾーン」をマークする場合に使用
        Buffer3
        MA5がMA6を上回ったかどうかを識別し、チャート上に「買いスイング」をマークするために使用
        Buffer4
        MA5がMA6を下回ったら、チャート上に「売りスイング」をマークするために使用
        Buffer5
        MA3がMA7より大きいかどうかを追跡
        Buffer6
        MA8がMA9を下回ったら、チャート上に「売り」をマークするために使用
        Buffer7
        MA8がMA9を上回ったかどうかを識別し、チャート上に「買い」をマークするために使用
        Buffer8  MA3がMA7より小さいかどうかを追跡


        結論

        結論として、Trend Constraintの開発と改良は、アルゴリズム取引における重要な進歩をもたらしました。現行システムの限界に対処し、戦略的なエグジットを導入することで、より堅牢で効果的な指標の構築を目指しています。損切りと利食いのレベルが組み込まれ、視覚的表現が強化された結果、使いやすく、変化する市況に適応しやすい指標となっています。これらの機能により、潜在的な取引結果が明確に視覚化され、より良い意思決定が可能となりました。

        厳格なテストと検証を通じて、この指標の信頼性と有効性が実証されました。エラーに直面しましたが、粘り強く徹底的な調査を行い解決しました。ドキュメントを活用し、開発者コミュニティと協力しながら残された問題にも対応していきます。

        全体として、強化されたTrend Constraintは、複雑な金融市場を自信と精度でナビゲートしようとするトレーダーに包括的なソリューションを提供します。その高度な機能とリスク管理および利益の最適化に対する戦略的アプローチにより、あらゆるトレーダーのツールキットに加わる価値ある存在となっています。

        以下に、あなたのプロジェクトでさらに発展させるためのファイルを添付します。開発をお楽しみください。

        ファイル名 詳細
        Trend ConstraintV1.09 MAクロスオーバーシグナルによる洗練されたプログラム
        Trend ConstraintV1.10 オブジェクト描画機能を備えた高度なプログラムまだデバッグの段階です。


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

        添付されたファイル |
        データサイエンスと機械学習(第27回):MetaTrader 5取引ボットにおける畳み込みニューラルネットワーク(CNN)に価値はあるか? データサイエンスと機械学習(第27回):MetaTrader 5取引ボットにおける畳み込みニューラルネットワーク(CNN)に価値はあるか?
        畳み込みニューラルネットワーク(CNN)は、画像や映像のパターンを検出する能力に優れていることで有名で、さまざまな分野に応用されています。この記事では、金融市場の価値あるパターンを識別し、MetaTrader 5取引ボットのための効果的な取引シグナルを生成するCNNの可能性を探ります。このディープマシンラーニングの手法を、よりスマートな取引判断のためにどのように活用できるかを見てみましょう。
        MQL5とPythonで自己最適化EAを構築する MQL5とPythonで自己最適化EAを構築する
        この記事では、市況に基づいて取引戦略を自律的に選択変更できるエキスパートアドバイザー(EA)を構築する方法について解説します。マルコフ連鎖の基本を学び、それがアルゴリズムトレードにどのように役立つかを探っていきます。
        MQL5取引ツールキット(第2回):ポジション管理EX5ライブラリの拡張と実装 MQL5取引ツールキット(第2回):ポジション管理EX5ライブラリの拡張と実装
        MQL5コードやプロジェクトでEX5ライブラリをインポートして使用する方法をご紹介します。今回は、既存のライブラリにポジション管理関数を追加し、2つのエキスパートアドバイザー(EA)を作成することで、EX5ライブラリを拡張します。最初の例では、可変指数ダイナミック平均(VIDyA: Variable Index Dynamic Average)テクニカル指標を使用して、トレーリングストップ取引戦略EAを開発し、2番目の例では、取引パネルを使用して、ポジションの監視、オープン、クローズ、および修正をおこないます。この2つの例では、アップグレードされたEX5ポジション管理ライブラリの使用方法と実装方法を紹介します。
        時系列の非定常性の指標としての2標本コルモゴロフ–スミルノフ検定 時系列の非定常性の指標としての2標本コルモゴロフ–スミルノフ検定
        この記事では、最も有名なノンパラメトリック同質性検定の1つである2標本のコルモゴロフ–スミルノフ検定について考察します。モデルデータと実際の相場の両方が分析されています。また、この記事では非定常性指標(iスミルノフ距離)の構築例も紹介しています。