English Deutsch
preview
Candlestick Trend Constraintモデルの構築(第4回):トレンドの波ごとに表示スタイルをカスタマイズ

Candlestick Trend Constraintモデルの構築(第4回):トレンドの波ごとに表示スタイルをカスタマイズ

MetaTrader 5トレーディングシステム | 31 7月 2024, 09:48
105 0
Clemence Benjamin
Clemence Benjamin

内容


はじめに

カスタム描画スタイルは、チャートの視覚的な魅力を高め、より魅力的で読みやすくすることができます。優れたデザインのチャートは、ユーザーの使い勝手を向上させ、長時間の取引における目の疲れを軽減します。 特定のニーズに合わせて描画スタイルを調整することで、トレーダーはより効率的で効果的な取引設定をおこなうことができます。例えば、出来高データをヒストグラムで表現したり、移動平均線を線で表現したりすると、これらの指標を一目で解釈しやすくなります。矢印や銘柄のような描画スタイルは、チャート上の特定のイベントやシグナル(売買ポイントなど)をマークするために使用でき、取引機会を見つけやすくします。

MQL5は、MetaTrader 5上の指標のための様々な描画スタイルを誇っています。これらの視覚的要素は、MetaTrader 5チャート上に表示されたときにトレーダーに分析上の優位性を提供し、市場センチメントへの迅速な適応を助けます。このような多様な描画スタイルを取り入れることで、チャートの美的魅力を高めるだけでなく、トレーダーが市場力学の包括的な分析に基づいて情報に基づいた意思決定をおこなえるようになります。トレーダーは値動きを効果的に解釈し、トレンドを見極め、反転の可能性をより正確に予測することができます。MQL5には18種類のグラフィカルなプロットが豊富に用意されています。この記事では、これらの表示スタイルのひとつをモデルに実装する方法を、さらに掘り下げて探りたいとおもいます。

アラートに矢印を描くだけでなく、チャート上にもっと高度なビジュアルを作成して、より簡単にしたいです。本連載の目標は、D1ローソク足の形状を忠実に再現し、チャート上に包括的な視覚的シグナルを表示するように、Trend Constraintモデルを改良することであることをお忘れなく。MQL5の描画スタイルでは色、太さ、スタイル(破線や実線など)をカスタマイズできるため、トレーダーは好みに応じてチャートをカスタマイズし、読みやすさを向上させることができます。  さまざまな描画スタイルにより、トレーダーはデータをより明確かつ正確に表現できます。例えば、ライン、ヒストグラム、ローソク足を使えば、値動きや市場トレンドの解釈が容易になります。

    MQL5で利用可能な様々な描画スタイルは、トレーダーに多くの利点を提供します。これらは、データ可視化の明瞭性、正確性、カスタマイズ性を高める役割を果たします。これらの多様なスタイルは、テクニカル分析の能力を拡大し、高度なチャート技術の活用を可能にし、ダイナミックなリアルタイム更新を容易にします。さらに、MQL5の描画スタイルに内在する適応性と創意工夫により、トレーダーは独自の指標や分析手段を作成することができ、それによってトレーダーの取引戦略や市場環境に対する理解力を高めることができます。このトピックを包括的に把握するには、MQL5リファレンスで描画スタイルを詳しく調べてください。


    今までのまとめ

    本連載の前回(第1回第2回第3回)では、すべてのシグナルをD1ローソク足のセンチメントに限定することを目標としました。D1ローソク足が強気であれば、通常、その日の全体的なトレンドは低い時間軸で上昇トレンドになるという概念です。下位の時間枠で高度な分析手法を採用することで、エントリポイントを特定し、現在のトレンドに沿ったシグナルを生成することができます。各フェーズごとにソースコードを改良し、新機能を取り入れ、モデルを強化してきました。連載では、指標の各反復のデザイン要素として矢印を活用し、オプションの表示要素にWingdingsフォントの活用を探りました。

    MQL5チャート上の資産に200本と100本の移動平均線を追加し、戦略を練りました。これらのビルトイン指標の挙動を分析することで、重要な周期的クロスオーバーイベントを特定しました。その後、トレンドが反転する可能性を示す、このような事象を通知するアラートシステムを備えたパーソナライズドクロスオーバー指標が作成されました。MA値をより高いレベルに調整することで、相場変動時のシグナルをフィルタリングすることができます。第3回では、カスタマイズ可能なMA期間の入力を導入することで、様々な期間の値を探り、トレンドの反転に最適な設定を決定するアプローチをさらに改良しました。

    input int Slow_MA_period = 200;
    input int Fast_MA_period = 100;

    このソフトウエアは、視覚的に表示される入力構成を即座に調整する機能を備えています。その属性を変更するには、MetaTrader 5チャートを表示中にCtrl + Iキーを使用するか、マウスを右クリックして指標メニューを表示し、Trend Constraint V1.03を見つけます。

    トレンド反転のためのMAの最適化

     図1:MA期間を最適化し、最良のトレンド反転設定をおこなう

    これらの入力設定を使用してプログラムをコンパイルします。ソースドキュメントはこの記事の結論のすぐ下に添付されています。以下は、Trend Constraint V1.03の最新コードです。

    /// Program after adding Moving Average optimization feature for reversals
    ///Indicator Name: Trend Constraint
    #property copyright "Clemence Benjamin"
    #property link      "https://mql5.com"
    #property version   "1.03"
    #property description "A model that seek to produce sell signal when D1 candle is Bearish only and  buy signal when it is Bullish"
    
    
    //--- indicator settings
    #property indicator_chart_window
    #property indicator_buffers 4
    #property indicator_plots 4
    
    #property indicator_type1 DRAW_ARROW
    #property indicator_width1 5
    #property indicator_color1 0xFF3C00
    #property indicator_label1 "Buy"
    
    #property indicator_type2 DRAW_ARROW
    #property indicator_width2 5
    #property indicator_color2 0x0000FF
    #property indicator_label2 "Sell"
    
    #property indicator_type3 DRAW_ARROW
    #property indicator_width3 1
    #property indicator_color3 0x04CC04
    #property indicator_label3 "Buy Reversal"
    
    #property indicator_type4 DRAW_ARROW
    #property indicator_width4 1
    #property indicator_color4 0xE81AC6
    #property indicator_label4 "Sell Reversal"
    
    #define PLOT_MAXIMUM_BARS_BACK 5000
    #define OMIT_OLDEST_BARS 50
    
    //--- indicator buffers
    double Buffer1[];
    double Buffer2[];
    double Buffer3[];
    double Buffer4[];
    
    input double Oversold = 30;
    input double Overbought = 70;
    input int Slow_MA_period = 200;
    input int Fast_MA_period = 100;
    datetime time_alert; //used when sending alert
    input bool Audible_Alerts = true;
    input bool Push_Notifications = true;
    double myPoint; //initialized in OnInit
    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[];
    
    void myAlert(string type, string message)
      {
       if(type == "print")
          Print(message);
       else if(type == "error")
         {
          Print(type+" | Trend Constraint V1.03 @ "+Symbol()+","+IntegerToString(Period())+" | "+message);
         }
       else if(type == "order")
         {
         }
       else if(type == "modify")
         {
         }
       else if(type == "indicator")
         {
          if(Audible_Alerts) Alert(type+" | Trend Constraint V1.03 @ "+Symbol()+","+IntegerToString(Period())+" | "+message);
          if(Push_Notifications) SendNotification(type+" | Trend Constraint V1.03 @ "+Symbol()+","+IntegerToString(Period())+" | "+message);
         }
      }
    
    //+------------------------------------------------------------------+
    //| Custom indicator initialization function                         |
    //+------------------------------------------------------------------+
    int OnInit()
      {   
       SetIndexBuffer(0, Buffer1);
       PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
       PlotIndexSetInteger(0, PLOT_ARROW, 241);
       SetIndexBuffer(1, Buffer2);
       PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
       PlotIndexSetInteger(1, PLOT_ARROW, 242);
       SetIndexBuffer(2, Buffer3);
       PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
       PlotIndexSetInteger(2, PLOT_ARROW, 236);
       SetIndexBuffer(3, Buffer4);
       PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       PlotIndexSetInteger(3, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
       PlotIndexSetInteger(3, PLOT_ARROW, 238);
       //initialize myPoint
       myPoint = Point();
       if(Digits() == 5 || Digits() == 3)
         {
          myPoint *= 10;
         }
       RSI_handle = iRSI(NULL, PERIOD_CURRENT, 14, PRICE_CLOSE);
       if(RSI_handle < 0)
         {
          Print("The creation of iRSI has failed: RSI_handle=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle = iMA(NULL, PERIOD_CURRENT, 7, 0, MODE_SMMA, PRICE_CLOSE);
       if(MA_handle < 0)
         {
          Print("The creation of iMA has failed: MA_handle=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle2 = iMA(NULL, PERIOD_CURRENT, 400, 0, MODE_SMA, PRICE_CLOSE);
       if(MA_handle2 < 0)
         {
          Print("The creation of iMA has failed: MA_handle2=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle3 = iMA(NULL, PERIOD_CURRENT, Fast_MA_period, 0, MODE_EMA, PRICE_CLOSE);
       if(MA_handle3 < 0)
         {
          Print("The creation of iMA has failed: MA_handle3=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle4 = iMA(NULL, PERIOD_CURRENT, Slow_MA_period, 0, MODE_SMA, PRICE_CLOSE);
       if(MA_handle4 < 0)
         {
          Print("The creation of iMA has failed: MA_handle4=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       return(INIT_SUCCEEDED);
      }
    
    //+------------------------------------------------------------------+
    //| Custom indicator iteration function                              |
    //+------------------------------------------------------------------+
    int OnCalculate(const int rates_total,
                    const int prev_calculated,
                    const datetime& time[],
                    const double& open[],
                    const double& high[],
                    const double& low[],
                    const double& close[],
                    const long& tick_volume[],
                    const long& volume[],
                    const int& spread[])
      {
       int limit = rates_total - prev_calculated;
       //--- counting from 0 to rates_total
       ArraySetAsSeries(Buffer1, true);
       ArraySetAsSeries(Buffer2, true);
       ArraySetAsSeries(Buffer3, true);
       ArraySetAsSeries(Buffer4, true);
       //--- initial zero
       if(prev_calculated < 1)
         {
          ArrayInitialize(Buffer1, EMPTY_VALUE);
          ArrayInitialize(Buffer2, EMPTY_VALUE);
          ArrayInitialize(Buffer3, EMPTY_VALUE);
          ArrayInitialize(Buffer4, EMPTY_VALUE);
         }
       else
          limit++;
       datetime Time[];
       
       datetime TimeShift[];
       if(CopyTime(Symbol(), PERIOD_CURRENT, 0, rates_total, TimeShift) <= 0) return(rates_total);
       ArraySetAsSeries(TimeShift, true);
       int barshift_M1[];
       ArrayResize(barshift_M1, rates_total);
       int barshift_D1[];
       ArrayResize(barshift_D1, rates_total);
       for(int i = 0; i < rates_total; i++)
         {
          barshift_M1[i] = iBarShift(Symbol(), PERIOD_M1, TimeShift[i]);
          barshift_D1[i] = iBarShift(Symbol(), PERIOD_D1, TimeShift[i]);
       }
       if(BarsCalculated(RSI_handle) <= 0) 
          return(0);
       if(CopyBuffer(RSI_handle, 0, 0, rates_total, RSI) <= 0) return(rates_total);
       ArraySetAsSeries(RSI, true);
       if(CopyOpen(Symbol(), PERIOD_M1, 0, rates_total, Open) <= 0) return(rates_total);
       ArraySetAsSeries(Open, true);
       if(CopyClose(Symbol(), PERIOD_D1, 0, rates_total, Close) <= 0) return(rates_total);
       ArraySetAsSeries(Close, true);
       if(BarsCalculated(MA_handle) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle, 0, 0, rates_total, MA) <= 0) return(rates_total);
       ArraySetAsSeries(MA, true);
       if(BarsCalculated(MA_handle2) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle2, 0, 0, rates_total, MA2) <= 0) return(rates_total);
       ArraySetAsSeries(MA2, true);
       if(BarsCalculated(MA_handle3) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle3, 0, 0, rates_total, MA3) <= 0) return(rates_total);
       ArraySetAsSeries(MA3, true);
       if(BarsCalculated(MA_handle4) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle4, 0, 0, rates_total, MA4) <= 0) return(rates_total);
       ArraySetAsSeries(MA4, true);
       if(CopyLow(Symbol(), PERIOD_CURRENT, 0, rates_total, Low) <= 0) return(rates_total);
       ArraySetAsSeries(Low, true);
       if(CopyHigh(Symbol(), PERIOD_CURRENT, 0, rates_total, High) <= 0) return(rates_total);
       ArraySetAsSeries(High, true);
       if(CopyTime(Symbol(), Period(), 0, rates_total, Time) <= 0) return(rates_total);
       ArraySetAsSeries(Time, true);
       //--- main loop
       for(int i = limit-1; i >= 0; i--)
         {
          if (i >= MathMin(PLOT_MAXIMUM_BARS_BACK-1, rates_total-1-OMIT_OLDEST_BARS)) continue; //omit some old rates to prevent "Array out of range" or slow calculation   
          
          if(barshift_M1[i] < 0 || barshift_M1[i] >= rates_total) continue;
          if(barshift_D1[i] < 0 || barshift_D1[i] >= rates_total) continue;
          
          //Indicator Buffer 1
          if(RSI[i] < Oversold
          && RSI[i+1] > Oversold //Relative Strength Index crosses below 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
          )
            {
             Buffer1[i] = Low[1+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
            {
             Buffer1[i] = EMPTY_VALUE;
            }
          //Indicator Buffer 2
          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] = High[1+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
            {
             Buffer2[i] = EMPTY_VALUE;
            }
          //Indicator Buffer 3
          if(MA3[i] > MA4[i]
          && MA3[i+1] < MA4[i+1] //Moving Average crosses above Moving Average
          )
            {
             Buffer3[i] = Low[i]; //Set indicator value at Candlestick Low
             if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Buy Reversal"); //Alert on next bar open
             time_alert = Time[1];
            }
          else
            {
             Buffer3[i] = EMPTY_VALUE;
            }
          //Indicator Buffer 4
          if(MA3[i] < MA4[i]
          && MA3[i+1] > MA4[i+1] //Moving Average crosses below Moving Average
          )
            {
             Buffer4[i] = High[i]; //Set indicator value at Candlestick High
             if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Sell Reversal"); //Alert on next bar open
             time_alert = Time[1];
            }
          else
            {
             Buffer4[i] = EMPTY_VALUE;
            }
         }
       return(rates_total);
      }
    //Thank you, friend. You have reached this stage and you can do more+


    MQL5表示スタイル

    MQL5では、指標の描画スタイルが豊富に用意されています。指標を開発する際の主な目標は、通常、音と視覚的な手がかりの両方を通じてユーザーに通知できるシステムを設計することです。これにより、コンピュータがこの責任を引き受けるため、トレーダーがチャートを常に監視する必要性が減り、取引業務の効率化に役立ちます。DRAW_ARROW、DRAW_LINE、DRAW_HISTOGRAM、DRAW_FILLING、DRAW_NONEなど、MQL5で利用できる描画スタイルの概要を簡単に説明しましょう。概要は以下の表をご参照ください。描画スタイルの詳細については、MQL5リファレンスを参照してください。

    描画スタイル 説明
    DRAW_ARROW 指定した点に矢印を描画する。売買シグナルやその他の重要なイベントを強調するために使用されることが多い
    DRAW_LINE データ点を結ぶ線を引くのに使用。移動平均、トレンドライン、その他のラインベースの指標に最適
    DRAW_HISTOGRAM データをバーまたはヒストグラムで表示する。出来高、MACDヒストグラム、その他のバータイプの指標に便利
    DRAW_FILLING チャート上の2本の線の間の領域を埋めるために使用され、データの範囲、広がり、2つの指標の違いを視覚的に直感的に表現できる
    DRAW_NONE チャート上に視覚的な表現を描画しない指標を定義するために使用


    DRAW_LINEスタイルの実装

    DRAW_LINE関数を使用して、MetaTrader 5チャート上に独自の方法でトレンドを表示してみましょう。過去には、上位期間の移動平均線のクロスオーバーによってトレンドの反転を認識するよう、指標を効果的に設定することができました。私たちの目標は、チャートを多くの要素で過密にすることなく、情報を視覚的に表現する方法を改善することです。この新しい追加により、トレンドを示し、新しい方向性ごとに自動的に色を変える単一のラインを描くことができるようになります。現在4つのバッファがありますが、バージョン1.04ではバッファ5とバッファ6を導入することで、能力の幅を広げたいと考えています。

    • バッファ5 :MA100がMA200の上にあるときに青い線を引くには
    ///properties
    #property indicator_type5 DRAW_LINE
    #property indicator_style5 STYLE_SOLID
    #property indicator_width5 2
    #property indicator_color5 0xFFAA00
    #property indicator_label5 "Buy Trend"

    • バッファ6:MA100がMA200の下にあるときに赤い線を引くには

    #property indicator_type6 DRAW_LINE
    #property indicator_style6 STYLE_SOLID
    #property indicator_width6 2
    #property indicator_color6 0x0000FF
    #property indicator_label6 "Sell Trend"
    注:上記のセクションは、追加情報のためのプレースホルダーとして機能します。詳細は以下のメインコードに記載されています。バッファのレイアウトは厳密ではないので、元の意図が一貫して維持される限り、値のバリエーションは許容されます。

    Trend Constraintv1.04のメインコード

    ///Indicator Name: Trend Constraint
    #property copyright "Clemence Benjamin"
    #property link      "https://mql5.com"
    #property version   "1.04"
    #property description "A model that seek to produce sell signal when D1 candle is Bearish only and  buy signal when it is Bullish"
    //--- indicator settings
    #property indicator_chart_window
    #property indicator_buffers 6
    #property indicator_plots 6
    
    #property indicator_type1 DRAW_ARROW
    #property indicator_width1 5
    #property indicator_color1 0xFF3C00
    #property indicator_label1 "Buy"
    
    #property indicator_type2 DRAW_ARROW
    #property indicator_width2 5
    #property indicator_color2 0x0000FF
    #property indicator_label2 "Sell"
    
    #property indicator_type3 DRAW_ARROW
    #property indicator_width3 2
    #property indicator_color3 0xE8351A
    #property indicator_label3 "Buy Reversal"
    
    #property indicator_type4 DRAW_ARROW
    #property indicator_width4 2
    #property indicator_color4 0x1A1AE8
    #property indicator_label4 "Sell Reversal"
    
    #property indicator_type5 DRAW_LINE
    #property indicator_style5 STYLE_SOLID
    #property indicator_width5 2
    #property indicator_color5 0xFFAA00
    #property indicator_label5 "Buy Trend"
    
    #property indicator_type6 DRAW_LINE
    #property indicator_style6 STYLE_SOLID
    #property indicator_width6 2
    #property indicator_color6 0x0000FF
    #property indicator_label6 "Sell Trend"
    
    #define PLOT_MAXIMUM_BARS_BACK 5000
    #define OMIT_OLDEST_BARS 50
    
    //--- indicator buffers
    double Buffer1[];
    double Buffer2[];
    double Buffer3[];
    double Buffer4[];
    double Buffer5[];
    double Buffer6[];
    
    input double Oversold = 30;
    input double Overbought = 70;
    input int Slow_MA_period = 200;
    input int Fast_MA_period = 100;
    datetime time_alert; //used when sending alert
    input bool Audible_Alerts = true;
    input bool Push_Notifications = true;
    double myPoint; //initialized in OnInit
    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[];
    
    void myAlert(string type, string message)
      {
       if(type == "print")
          Print(message);
       else if(type == "error")
         {
          Print(type+" | Trend Constraint V1.04 @ "+Symbol()+","+IntegerToString(Period())+" | "+message);
         }
       else if(type == "order")
         {
         }
       else if(type == "modify")
         {
         }
       else if(type == "indicator")
         {
          if(Audible_Alerts) Alert(type+" | Trend Constraint V1.04 @ "+Symbol()+","+IntegerToString(Period())+" | "+message);
          if(Push_Notifications) SendNotification(type+" | Trend Constraint V1.04 @ "+Symbol()+","+IntegerToString(Period())+" | "+message);
         }
      }
    
    //+------------------------------------------------------------------+
    //| Custom indicator initialization function                         |
    //+------------------------------------------------------------------+
    int OnInit()
      {   
       SetIndexBuffer(0, Buffer1);
       PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
       PlotIndexSetInteger(0, PLOT_ARROW, 241);
       SetIndexBuffer(1, Buffer2);
       PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
       PlotIndexSetInteger(1, PLOT_ARROW, 242);
       SetIndexBuffer(2, Buffer3);
       PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
       PlotIndexSetInteger(2, PLOT_ARROW, 236);
       SetIndexBuffer(3, Buffer4);
       PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       PlotIndexSetInteger(3, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
       PlotIndexSetInteger(3, PLOT_ARROW, 238);
       SetIndexBuffer(4, Buffer5);
       PlotIndexSetDouble(4, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       PlotIndexSetInteger(4, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
       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));
       //initialize myPoint
       myPoint = Point();
       if(Digits() == 5 || Digits() == 3)
         {
          myPoint *= 10;
         }
       RSI_handle = iRSI(NULL, PERIOD_CURRENT, 14, PRICE_CLOSE);
       if(RSI_handle < 0)
         {
          Print("The creation of iRSI has failed: RSI_handle=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle = iMA(NULL, PERIOD_CURRENT, 7, 0, MODE_SMMA, PRICE_CLOSE);
       if(MA_handle < 0)
         {
          Print("The creation of iMA has failed: MA_handle=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle2 = iMA(NULL, PERIOD_CURRENT, 400, 0, MODE_SMA, PRICE_CLOSE);
       if(MA_handle2 < 0)
         {
          Print("The creation of iMA has failed: MA_handle2=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle3 = iMA(NULL, PERIOD_CURRENT, 100, 0, MODE_EMA, PRICE_CLOSE);
       if(MA_handle3 < 0)
         {
          Print("The creation of iMA has failed: MA_handle3=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle4 = iMA(NULL, PERIOD_CURRENT, 200, 0, MODE_SMA, PRICE_CLOSE);
       if(MA_handle4 < 0)
         {
          Print("The creation of iMA has failed: MA_handle4=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle5 = iMA(NULL, PERIOD_CURRENT, Fast_MA_period, 0, MODE_SMA, PRICE_CLOSE);
       if(MA_handle5 < 0)
         {
          Print("The creation of iMA has failed: MA_handle5=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle6 = iMA(NULL, PERIOD_CURRENT, Slow_MA_period, 0, MODE_SMA, PRICE_CLOSE);
       if(MA_handle6 < 0)
         {
          Print("The creation of iMA has failed: MA_handle6=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       return(INIT_SUCCEEDED);
      }
    
    //+------------------------------------------------------------------+
    //| Custom indicator iteration function                              |
    //+------------------------------------------------------------------+
    int OnCalculate(const int rates_total,
                    const int prev_calculated,
                    const datetime& time[],
                    const double& open[],
                    const double& high[],
                    const double& low[],
                    const double& close[],
                    const long& tick_volume[],
                    const long& volume[],
                    const int& spread[])
      {
       int limit = rates_total - prev_calculated;
       //--- counting from 0 to rates_total
       ArraySetAsSeries(Buffer1, true);
       ArraySetAsSeries(Buffer2, true);
       ArraySetAsSeries(Buffer3, true);
       ArraySetAsSeries(Buffer4, true);
       ArraySetAsSeries(Buffer5, true);
       ArraySetAsSeries(Buffer6, true);
       //--- initial zero
       if(prev_calculated < 1)
         {
          ArrayInitialize(Buffer1, EMPTY_VALUE);
          ArrayInitialize(Buffer2, EMPTY_VALUE);
          ArrayInitialize(Buffer3, EMPTY_VALUE);
          ArrayInitialize(Buffer4, EMPTY_VALUE);
          ArrayInitialize(Buffer5, EMPTY_VALUE);
          ArrayInitialize(Buffer6, EMPTY_VALUE);
         }
       else
          limit++;
       datetime Time[];
       
       datetime TimeShift[];
       if(CopyTime(Symbol(), PERIOD_CURRENT, 0, rates_total, TimeShift) <= 0) return(rates_total);
       ArraySetAsSeries(TimeShift, true);
       int barshift_M1[];
       ArrayResize(barshift_M1, rates_total);
       int barshift_D1[];
       ArrayResize(barshift_D1, rates_total);
       for(int i = 0; i < rates_total; i++)
         {
          barshift_M1[i] = iBarShift(Symbol(), PERIOD_M1, TimeShift[i]);
          barshift_D1[i] = iBarShift(Symbol(), PERIOD_D1, TimeShift[i]);
       }
       if(BarsCalculated(RSI_handle) <= 0) 
          return(0);
       if(CopyBuffer(RSI_handle, 0, 0, rates_total, RSI) <= 0) return(rates_total);
       ArraySetAsSeries(RSI, true);
       if(CopyOpen(Symbol(), PERIOD_M1, 0, rates_total, Open) <= 0) return(rates_total);
       ArraySetAsSeries(Open, true);
       if(CopyClose(Symbol(), PERIOD_D1, 0, rates_total, Close) <= 0) return(rates_total);
       ArraySetAsSeries(Close, true);
       if(BarsCalculated(MA_handle) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle, 0, 0, rates_total, MA) <= 0) return(rates_total);
       ArraySetAsSeries(MA, true);
       if(BarsCalculated(MA_handle2) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle2, 0, 0, rates_total, MA2) <= 0) return(rates_total);
       ArraySetAsSeries(MA2, true);
       if(BarsCalculated(MA_handle3) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle3, 0, 0, rates_total, MA3) <= 0) return(rates_total);
       ArraySetAsSeries(MA3, true);
       if(BarsCalculated(MA_handle4) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle4, 0, 0, rates_total, MA4) <= 0) return(rates_total);
       ArraySetAsSeries(MA4, true);
       if(CopyLow(Symbol(), PERIOD_CURRENT, 0, rates_total, Low) <= 0) return(rates_total);
       ArraySetAsSeries(Low, true);
       if(CopyHigh(Symbol(), PERIOD_CURRENT, 0, rates_total, High) <= 0) return(rates_total);
       ArraySetAsSeries(High, true);
       if(BarsCalculated(MA_handle5) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle5, 0, 0, rates_total, MA5) <= 0) return(rates_total);
       ArraySetAsSeries(MA5, true);
       if(BarsCalculated(MA_handle6) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle6, 0, 0, rates_total, MA6) <= 0) return(rates_total);
       ArraySetAsSeries(MA6, true);
       if(CopyTime(Symbol(), Period(), 0, rates_total, Time) <= 0) return(rates_total);
       ArraySetAsSeries(Time, true);
       //--- main loop
       for(int i = limit-1; i >= 0; i--)
         {
          if (i >= MathMin(PLOT_MAXIMUM_BARS_BACK-1, rates_total-1-OMIT_OLDEST_BARS)) continue; //omit some old rates to prevent "Array out of range" or slow calculation   
          
          if(barshift_M1[i] < 0 || barshift_M1[i] >= rates_total) continue;
          if(barshift_D1[i] < 0 || barshift_D1[i] >= rates_total) continue;
          
          //Indicator Buffer 1
          if(RSI[i] < Oversold
          && RSI[i+1] > Oversold //Relative Strength Index crosses below 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
          )
            {
             Buffer1[i] = Low[1+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
            {
             Buffer1[i] = EMPTY_VALUE;
            }
          //Indicator Buffer 2
          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] = High[1+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
            {
             Buffer2[i] = EMPTY_VALUE;
            }
          //Indicator Buffer 3
          if(MA5[i] > MA6[i]
          && MA5[i+1] < MA6[i+1] //Moving Average crosses above Moving Average
          )
            {
             Buffer3[i] = Low[i]; //Set indicator value at Candlestick Low
             if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Buy Reversal"); //Alert on next bar open
             time_alert = Time[1];
            }
          else
            {
             Buffer3[i] = EMPTY_VALUE;
            }
          //Indicator Buffer 4
          if(MA5[i] < MA6[i]
          && MA5[i+1] > MA6[i+1] //Moving Average crosses below Moving Average
          )
            {
             Buffer4[i] = High[i]; //Set indicator value at Candlestick High
             if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Sell Reversal"); //Alert on next bar open
             time_alert = Time[1];
            }
          else
            {
             Buffer4[i] = EMPTY_VALUE;
            }
          //Indicator Buffer 5
          if(MA5[i] > MA6[i] //Moving Average > Moving Average
          )
            {
             Buffer5[i] = MA6[i]; //Set indicator value at Moving Average
             if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Buy Trend"); //Alert on next bar open
             time_alert = Time[1];
            }
          else
            {
             Buffer5[i] = EMPTY_VALUE;
            }
          //Indicator Buffer 6
          if(MA5[i] < MA6[i] //Moving Average < Moving Average
          )
            {
             Buffer6[i] = MA6[i]; //Set indicator value at Moving Average
             if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Sell Trend"); //Alert on next bar open
             time_alert = Time[1];
            }
          else
            {
             Buffer6[i] = EMPTY_VALUE;
            }
         }
       return(rates_total);
      }
    //You are the best coder


    私たちの革新的なプログラムは、新しいコースが設定されるたびに1本の線の色を調整することで、高度な機能を発揮するようになりました。この機能は、色を取り入れることでチャートを合理化し、視覚的、聴覚的な他の通知と並んで、シグナルシステムを強化します。以下の画像は、この最新機能のインパクトを視覚的に表したものです。

    USDJPYのTrend ConstraintV1.04

    図2:USDJPYのTrend ConstraintV1.04

    Boom 500指数のTrend ConstraintV1.04

    図3:Boom 500指数のTrend ConstraintV1.04

    My D1 candle status

    モデルに新しい機能を追加するために、MetaTrader 5に切り替えてモデルを使い始めたらすぐに、D1ローソク足の状態を素早く確認したいと思います。チャートがD1以外の時間枠であっても、D1のローソク足の状態をチャート上に表示するスクリプトをここに導入することにしました。この改良は、特にM1時間枠で作業しているとき、D1期間セパレーターがズームレベルによっては見えないことがある場合に、ローソク足の状態を素早く識別するのに役立ちます。では、以下に示すMQL5スクリプトのコードを検証してみましょう。

    //My_D1_candlestatus.mql5
    //Author: Clemence Benjamin
    //Link: https://www.mql5.com/ja/users/billionaire2024/seller
    #property copyright "Copyright 2024, Clemence Benjamin"
    #property link      "https://www.mql5.com/ja/users/billionaire2024/seller"
    #property version   "1.00"
    #property script_show_inputs
    #property strict
    
    //+------------------------------------------------------------------+
    //| Script program start function                                    |
    //+------------------------------------------------------------------+
    void OnStart()
      {
       //--- Get the opening and closing prices of the current D1 candle
       double openPrice = iOpen(NULL, PERIOD_D1, 0);
       double closePrice = iClose(NULL, PERIOD_D1, 0);
       
       //--- Determine if the candle is bullish or bearish
       string candleStatus;
       if(closePrice > openPrice)
         {
          candleStatus = " D1 candle is bullish.";
         }
       else if(closePrice < openPrice)
         {
          candleStatus = " D1 candle is bearish.";
         }
       else
         {
          candleStatus = " D1 candle is neutral.";// when open price is equal to close price
         
         }
       
       //--- Print the status on the chart
       Comment(candleStatus);
       
       //--- Also print the status in the Experts tab for logging
       Print(candleStatus);
      }
    //+------------------------------------------------------------------+
    
    


    My_D1_Candlestatus.mq5スクリプト関数と変数について

    関数と変数 説明
    OnStart() スクリプトが実行されたときに実行されるスクリプトのメイン関数です。現在のD1ローソク足の始値と終値を取得し、そのローソク足が強気、弱気、中立のいずれであるかを判断し、Comment()を使用してその情報をチャート上に表示します。
    iOpen()およびiClose() 現在のD1ローソク足の始値と終値を取得します。

    candleStatus 現在のD1ローソク足のステータスメッセージを格納する文字列変数
    Comment() チャート上にステータスメッセージを表示します
    Print() ステータスメッセージを[エキスパート]タブにログ記録します

    コードのコンパイルが完了したら、スクリプトを探し出し、図の指示に従って実行します。スクリプトは、現在の日足の状態を示すコメントを表示します。

    My D1 Candle statusスクリプトの実行

    図4:My_D1_candlestatus.mq5スクリプトの実行


    MQL5描画スタイルの他の選択肢

    MetaTrader 5には、ライン、チャネル、フィギュアなど、実践的な市場評価のための幅広いスケッチ補助機能が搭載されており、これらはすべてMeta Traderプラットフォーム内に便利に配置されています。MQL5オブジェクト指向プログラミング言語とそのPythonやC++とのつながりを深く理解することで、トレーダーは個人向けの補助や拡張を考案する能力を持つようになります。これらのツールを活用することで、テクニカル分析能力を高め、より多くの情報に基づいた取引判断を下すことができます。MetaTrader 5で利用可能な柔軟性とカスタマイズオプションにより、トレーダーは自分の好みや戦略に合わせて取引体験をカスタマイズする機会があります。 


    結論

    ログラムに新機能を統合し、後続の記事で指標からEAへと進化するにつれて、今後のバージョンに影響を与える可能性のある肯定的な結果をもたらしました。MQL5の描画スタイルには、トレーダーにとって特筆すべきメリットがあり、データ可視化の明瞭性、正確性、カスタマイズ性を向上させます。これらのスタイルは、テクニカル分析機能を強化し、高度なチャートテクニックを容易にし、インタラクティブなリアルタイム更新をサポートします。さらに、MQL5の描画スタイルが提供する柔軟性と創造性により、トレーダーは独自の指標や分析ツールを作成することができ、取引アプローチと全体的な市場理解を深めることができます。

    私たちのモデルは洗練された精度で進化しており、ボタンをクリックするだけで瞬時に視覚的な洞察を提供します。スクリプトはD1ローソク足の状態を迅速に伝え、DRAW_LINE機能はより低い時間枠のトレンドをわかりやすく強調します。ここで取り上げたすべての機能のソースファイルを掲載しました。皆さんは、この経過を見守り、見識を深めていると信じています。ご遠慮なくコメントを寄せて、議論に参加してください。


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

    リプレイシステムの開発(第39回):道を切り開く(III) リプレイシステムの開発(第39回):道を切り開く(III)
    開発の第2段階に進む前に、いくつかのアイデアを修正する必要があります。MQL5に必要なことをさせる方法をご存知ですか。ドキュメントに書かれている以上のことをしようとしたことはありますか。そうでないなら、準備をしましょう。ここでは、ほとんどの人が普段やらないことをやるからです。
    Break of Structure (BoS)戦略のステップバイステップガイド Break of Structure (BoS)戦略のステップバイステップガイド
    Break of Structure (BoS)戦略に基づく自動売買アルゴリズム開発のための包括的ガイドです。MQL5でエキスパートアドバイザー(EA)を作成し、MetaTrader 5でテストするためのあらゆる側面に関する詳細情報(価格サポートとレジスタンスの分析からリスク管理まで)が含まれています。
    リプレイシステムの開発(第40回):第2段階の開始(I) リプレイシステムの開発(第40回):第2段階の開始(I)
    今日は、リプレイ/シミュレーターシステムの新しい段階について話しましょう。この段階で、会話は本当に面白くなり、内容もかなり濃くなります。記事を熟読し、そこに掲載されているリンクを利用することを強くお勧めします。そうすることで、内容をより深く理解することができます。
    MetaTrader 5で隠れマルコフモデルを統合する MetaTrader 5で隠れマルコフモデルを統合する
    この記事では、Pythonを使用して学習した隠れマルコフモデルをMetaTrader 5アプリケーションに統合する方法を示します。隠れマルコフモデルは、時系列データをモデル化するために使用される強力な統計的ツールであり、モデル化されるシステムは観測不可能な(隠れた)状態によって特徴付けられます。HMMの基本的な前提は、ある時刻にある状態にある確率は、その前のタイムスロットにおけるプロセスの状態に依存するということです。