MQL5 ウィザードの NRTR に基づく NRTR インジケーターとトレーディングモジュール

Dmitrii Troshin | 19 1月, 2018


イントロダクション

この記事では、動的な価格チャネルを構築するインジケーターを検討します。 トレーディングEAは、このチャネルに基づいて作成します。 このようなシステムは、トレンドで実行できますが、レンジな動きでは多くのダマシシグナルが発生します。 したがって、追加のトレンドインジケーターが必要です。 適切なインジケーターの選択は簡単なタスクではなく、特定の相場条件によって選択されることがよくあります。 したがって、良い解決策はすぐに準備ができてトレードシステムに任意の選択したインジケーターを接続する可能性を提供することです。

よって、次のアプローチにします。 MQL5 ウィザード用の特別なトレードシグナルモジュールを作成します。 後でトレンドの有無を示す Yes/No シグナルを作り出すために選択されたトレンドのインジケーターに基づいて同じようなモジュールを作成します。 トレーディングシステムの作成時に複数のモジュールを組み合わせて使用できるため、さまざまなインジケーターを組み合わせることができます。

NRTR インジケーター

NRTR (Nick Rypock Trailing Reverse) インジケーターの考え方は、Konstantin Kopyrkinによって提案されたものです。 豆知識: 名前Nick Rypock は、後に書かれた Kopyrkin から派生しています。 

さて、インジケーターに戻りましょう。 これは、動的な価格チャネルです。 この著者は、次の図で、その主なアイデアを示しています:

NRTR

NRTR インジケーターに基づくトレードシステムは、ブレイクアウト戦略に属します。 買いシグナルは、価格が一定期間の高値を超えた場合に生成されます。価格が低くなると、売りシグナルが生成されます。 このようなシステムでは、トレンドの変化に伴い、過去の高値と安値を使用することがあります。 これを回避するために、計算期間はシステム内で動的に設定されます。 

この著者は、動的価格チャネルブレイクアウトのトレンドインジケーターとして NRTR を定義しています。

インジケータの動作原理は次のとおりです。上昇トレンドでは、インジケーターライン (チャネル) は、指定した時間間隔で検出された高い価格を下回る一定のレベルに配置されます。 ダウントレンドラインは、一定の時間間隔の安値から一定の距離で、価格の上に位置しています。

インジケーターの計算に使用される価格チャネルの期間は、トレンドの起点から動的に増加します。 したがって、前の計算期間の価格は、インジケーターには影響しません。

この図は、インジケータが最初に一定の距離でトレンドに従っていることを示しています。 その後、このインジケータは、ローカルの高値 H1 と H2 から一定の距離に位置しています。 ローカルの H3 は、以前の高値よりも低く、これは計算に使用されません。

この価格はポイント L3 のチャネルを壊す。 これは売りシグナルです。 点 L3 の値は、新しい 安値 として設定されます。 新しい期間は、この時点で開始, すなわち、すべての以前の価格がリセットされ、以上の計算で使用されません. トレンドが成長するにつれて、安値は L3-L4-L5 に更新されます。 ダイナミック価格チャネルの期間は、トレンドが変更されるか、期間の長さが許容最大値に達するまで延長されます。

チャネルの幅は、極端な値のパーセンテージとして計算されるか、価格のボラティリティによって異なります。 この記事では、どちらのメソッドも実装されています。

価格がチャンネルラインを通過すると、買いシグナル/売りシグナルが生成されます。 サポートラインとはいえ、価格が壊れると買いシグナルが形成されます。 レジスタンスが壊れている場合は、売りシグナルが形成されます。

ここで、インディケータ操作原則の説明を MQL5 にする必要があります。 さて、始めましょう。

インジケーターの記述: シンプルなものから複合体へ

まず、インジケーターの動作を定義する必要があります。 このインジケーターは、終値に基づいて行われます。 履歴データに基づくインジケーター値は、明確に解釈されます。 しかし、価格が不完全なロウソク足のサポート/レジスタンスを破る場合はどうなるでしょうか。 このバージョンでは、トレンドが形成されていないため、ローソク足の形成が完了するまで、シグナルは生成されません。 一方で、動きの一部が欠損することがあります。 例えば、チャンネルを壊す巨大なローソク足で始まる場合、ポジションは次のローソク足でのみ開かれます。 一方、これは多数のダマシに対する保護の役割があります。

注意: このインジケーターには多くの種類があります。作者によって提案された元のバージョンをこの記事で使用します。

このインジケーターの実装はコードベースで使用できますが、その期間は部分的にしか動的ではありません。 トレンドが変わると周期はリセットされますが、理論的には際限なく延長されます。 すなわち、サポートラインは、前の値と現在の終値のMathMax() として計算されます。 この場合、サポートラインは上昇するだけで、レジスタンスは常に落下します。 元のバージョンでは、以前の値はすべて古いものと見なされるため、無視されます。 ただし、max/min は ArrayMaximum/Minimum(close,i,dynamic_period).として計算されます。 このアプローチでは、サポートとレジスタンスの両方が上昇し、落下することがあります。 したがって、サポートラインは、動的な期間が短いときに、ゆっくりと横向きの動きに深くドリフトすることができます。 しかし、こうした滑らかな長期トレンドは稀であり、どちらのメソッドも理想的ではありません。 この記事では、インジケーターの作者が提案したオリジナルのアイデアで行います。

時系列と接続されています。 MQL5 の価格シリーズ (終値) には、デフォルト値 ArraySetAsSeries = false があります。 MQL4 の価格シリーズは、時系列フラグを持っており、その終値 [0] 値は右端の足の終値です (左端の足は原則として表示されません)。 この記事では ArraySetAsSeries (close, true) に注意してください。

インジケータの実装に進んでみましょう。 4つのインジケータバッファで動作します: 2つは、サポート/レジスタンスに使用され、他の2つは、売買シグナルに使用されます。

#propertyindicator_chart_window
#propertyindicator_buffers4 
#propertyindicator_plots 4

//インジケーターの線のスタイル
#propertyindicator_type1 DRAW_LINE
#property indicator_color1 Green
#propertyindicator_style1STYLE_DASH

#propertyindicator_type2 DRAW_LINE
#property indicator_color2 Red
#propertyindicator_style2STYLE_DASH

#propertyindicator_type3 DRAW_ARROW
#property indicator_color3 Green

#propertyindicator_type4 DRAW_ARROW
#property indicator_color4 Red

インジケーターのバッファと外部パラメータを宣言してみましょう。

input int    period =12;      //動的期間
input double percent =0.2;    //インデントの割合

double Buff_Up[],Buff_Dn[];  
double Sign_Up[],Sign_Dn[];

インジケータシグナルは、チャート上に矢印として表示されます。 残りのパラメータは、OnInit() 関数で設定されます。 Wingdingsフォント文字のパラメータ236238で DRAW_ARROW を使用しました。 "Up" シグナルのパラメータ:

   SetIndexBuffer(2,Sign_Up,INDICATOR_DATA);
   PlotIndexSetDouble(2,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetInteger(2,PLOT_ARROW,236);
   PlotIndexSetInteger(2,PLOT_LINE_WIDTH,1);
   ArraySetAsSeries(Sign_Up,true);

OnCalculate () の計算の開始時に、必要なデータの可用性と最初のインジケーターの計算開始を確認します。

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
intOnCalculate (const int rates_total、
                constint 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 start =0;                                           //計算ポイント
  
  int trend =0;                                           //トレンド値、1の-1 ダウンの-
  static int trend_prev =0;
  
  double value =0;                                        //インジケーターの値
  static double value_prev =0;
  
  int dyn_period =1;                                     //期間の値
  static int curr_period =1;
  
  
  double maxmin =0;                                       //計算のテクニカル変数
  
  ArraySetAsSeries(close,true);
  
  if(rates_total<period) return(0);
  
     if(prev_calculated==0)                              //インジケーターの計算の最初の開始を確認
  {
      start=rates_total-1;                               //すべての足の計算の開始インデックス
      trend_prev =1;
      value=close[start]*(1-0.01*percent);      
  }
  
  else
     {
      start=rates_total-prev_calculated;                  //新しい足の計算の開始インデックス
     }

trend =trend_prev;
value =value_prev;
dyn_period =curr_period;

主な変数もここで定義されています。 トレンドとチャンネルの値には2つの変数が定義されます。 変数の1つが静的です。 静的変数は、次の計算サイクルまで値を格納します。 この変数は、完全に形成された足でのみ変更されます。 未形成の足のチャネルを通じて価格が壊れる場合は、ローカルの非静的変数のみが変更されます。 価格がチャネルに戻る場合は、以前のトレンドが保持されます。

では、上記の備考を考慮した主な計算ループを作成してみましょう。

trend =trend_prev;
value=value_prev;
dyn_period =curr_period;    
//-------------------------------------------------------------------+
//                        The main calculation loop   
//-------------------------------------------------------------------+  
for(int i=start;i>=0;i--)
{
    Buff_Up[i] =0.0;
    Buff_Dn[i] =0.0;
    Sign_Up[i] =0.0;
    Sign_Dn[i] =0.0;
    
    if(curr_period>period) curr_period=period;
    if(dyn_period>period) dyn_period=period;
    
 //トレンドが昇順の場合   
    if(trend>0)
    {
    maxmin =close[ArrayMaximum(close,i,dyn_period)];
    value =maxmin*(1-percent*0.01);
    
    if(close[i]<value)
      {
      maxmin =close[i];
      value =maxmin*(1+percent*0.01);
      trend =-1;
      dyn_period =1;
      }
    }
  
//下降トレンド
    else
    {
    maxmin =close[ArrayMinimum(close,i,dyn_period)];
    value =maxmin*(1+percent*0.01);
    if(close[i]>value)
      {
      maxmin =close[i];
      value =maxmin*(1-percent*0.01);
      trend =1;
      dyn_period =1;
      }
    }  
 //トレンドの変化 
  
      if(trend>0) Buff_Up[i] =value;
      if(trend<0) Buff_Dn[i] =value;

      if(trend_prev<0  &&  trend>0) 
      {
      Sign_Up[i] =value;
      Buff_Up[i] =0.0;
      }
      if(trend_prev>0 && trend<0)
      {
      Sign_Dn[i] =value;
      Buff_Dn[i] =0.0;
      }

  dyn_period++;
  
  if(i)
  {
  trend_prev =trend;
  value_prev =value;
  if(dyn_period==2)curr_period =2;
  else curr_period++;
  }

}

このループの動的な期間は、指定された値に制限されます。 終値がチャネルをブレイクすると、新しいサポートとレジスタンスが検出され、トレンドが変更されたかどうかがチェックされます。 最後の if() 演算子は、足が完全に形成されているかどうかをチェックします。 足が完全に形成されている場合にのみ、trend_prev と value_prev の値が更新されるため、買い/売りシグナルを生成することができます。 動的な期間は、ここでリセットすることもできます。

完全なインジケーターコードは、添付の NRTR mq5 ファイルで使用できます。

別のパラメータを持つ1つのチャートの2つのNRTRsを起動して、インジケーターの操作を確認してみましょう。最初の NRTR は12の期間と 0.1% の幅があります。第 2 NRTR の期間は120で、幅は 0.2% です。


上記の図は、期間が小さい場合は、サポートラインの両方の上昇と下降することがあります。 これは価値が動的期間を越えて下るという事実になります。 期間が大きい場合、サポートラインは通常 ノンディクリーシング です。

ボラティリティと NRTR

前のアプローチでは、固定価格チャネル偏差パーセントを使用しました。 論理的な解決策は、ボラティリティが上昇するときにチャネルを拡大し、ボラティリティが落ちるときにを狭めることです。 ATR (Average True Range) は、相場のボラティリティを決定するための人気インジケーターです。 ATR 値は、チャンネル幅の設定に使用できます。 ATR の値を自分で計算するか、ターミナルから標準の技術インジケーターを使用することができます。

チャンネルの幅を相場のボラティリティにリンクさせるために、ATR インジケーターの値に偏差の割合を置き換えてみましょう。 係数はスケーリングにも使用されます。 デフォルトで1に設定してみましょう。 ATR インジケータの追加インジケータバッファを宣言する: double Buff_ATR []。 パーセントパラメータは、係数 K = 1 に置き換えられます。 この値を受信するための ATR へのポインタを作成してみましょう:

handle_atr =iATR(_Symbol,PERIOD_CURRENT,period);

ATR 期間は、アクティブな動的期間とは異なる場合があります。 論理的解決策は、パラメータの数が変更されないように、等しくすることです。

ここで新しく追加されたコードです。

#propertyindicator_buffers5 
#propertyindicator_plots 4
.............................
input double K =1;            //スケール係数
double Buff_ATR[];
int handle_atr;
.............................
SetIndexBuffer(4,Buff_ATR,INDICATOR_CALCULATIONS);
ArraySetAsSeries(Buff_ATR,true);
         
handle_atr =iATR(_Symbol,PERIOD_CURRENT,period);
.....................................................
intOnCalculate(){
.....................................................
  if(CopyBuffer(handle_atr,0,0,start+1,Buff_ATR)==-1)
  {
  return(0);
  Print("Copying data to the ATR buffer failed");
  }
.....................................................

//トレンドが昇順の場合  
  if(trend>=0)
  {
  maxmin =close[ArrayMaximum(close,i,dyn_period)];
  value =maxmin-K*Buff_ATR[i];
  
  if(close[i]<value)
   {
   maxmin =close[i];
   value =maxmin+K*Buff_ATR[i];
   trend =-1;
   dyn_period =1;
   }
  }
 
}


チャネルラインの値は、それぞれ式の値 = maxmin(+-)K*Buff_ATR[i]を使用して計算されます。 完全なインジケーターコードは、添付の NRTRvolatile.mq5 ファイルで使用できます。

1つのチャートで同じパラメータを使用して両方のインジケーターを実行し、その動作を比較してみましょう。


この図は、ボラティリティが低く、ATR の値が小さい場合、NRTRvolatile ラインは価格チャートにほぼ "スナップ" されることを示しています。 その後、ボラティリティが高まると、このラインは価格から遠ざかります。

ここでは、このインジケータに基づいてEAを作成してみましょう。 前述したように、トレードシグナルのモジュールを使用します。

MQL5 ウィザードのトレーディングモジュール

場合によって、コピー/貼り付けメソッドを使用して、既存のモジュールに基づいて記述する方が便利です。 しかし、今回のケースでは、代わりに、または変更するすべての場所を記述するのではなく、最初から開始することをお勧めします。

すべてのモジュールの一般的な構造

  • モジュール記述子
  • トレーディングパラメータとパラメータ初期化関数
  • インプットパラメータのチェック
  • 選択したインジケーターをモジュールに接続する
  • トレーディング戦略の説明

まず第一に、独自のシグナルを格納するために、シグナルフォルダ内の別のサブフォルダを作成してみましょう。 たとえば、Include\Expert\MySignals.です。 選択したフォルダを右クリックし、コンテキストメニューの「新規ファイル」を選択します。 MQL5 ウィザードが開きます。 メニューから「新規クラス」を選択します。 NRTRsignal としましょう。 すべてのシグナルは、基本のCExpertSignalクラスから継承されるので、ウィザードで示してみましょう。


CExpertSignal基本クラスのパスを、ウィザードによって生成されたコードに追加し ます。 ".\ExpertSignal.mqh」

//+------------------------------------------------------------------+
//                                                    SignalNRTR mqh |
//                                                        Orangetree |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Orangetree"
#property link      "https://www.mql5.com"
#property version   "1.00"

#include "..\ExpertSignal.mqh"              //CExpertSignal クラス
//+------------------------------------------------------------------+
//                                                                   |
//+------------------------------------------------------------------+
class SignalNRTR : public CExpertSignal
  {
private:

public:
                     SignalNRTR();
                    ~SignalNRTR();
  };
//+------------------------------------------------------------------+
//                                                                   |
//+------------------------------------------------------------------+
SignalNRTR::SignalNRTR()
  {
  }
//+------------------------------------------------------------------+
//                                                                   |
//+------------------------------------------------------------------+
SignalNRTR::~SignalNRTR()
  {
  }
//+------------------------------------------------------------------+

これは序章です。

次に、MQL5 ウィザードがこのコードをシグナルのモジュールとして認識できるように、モジュール記述子を作成する必要があります。

//ウィザードの説明の開始
//+------------------------------------------------------------------+
//クラスの説明                                                         |
//タイトル = インジケーター ' NRTR ' のシグナル                          |
//| Type=SignalAdvanced                                              |
//| Name=NRTR                                                        |
//| ShortName=NRTR                                                   |
//| Class=SignalNRTR                                                 |
//| Page=????                                                        |
//| Parameter=PeriodDyn,int,12,Dynamic channel period                |
//| Parameter=PercentDev,double,0.1,Channel width in percent         |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class SignalNRTR.                                                |
//目的: 下記に基づいたトレードシグナルのジェネレーターのクラス              |
//         ' NRTR ' インジケーター。                                   |
//これは CExpertSignal クラスから派生します。                           |
//+------------------------------------------------------------------+

これ記述子は、"ウィザードの説明の開始"で始まり、" ウィザードの説明の終了"で終了します。 モジュール名と外部パラメータは内部に含まれています。 このモジュールを記述子と共にコンパイルするとすぐに、ウィザードメニューに追加されます: New file/Expert Advisor (generate)/Common parameters/Signal properties of the Expert Advisor/Add

Module

これを初期化するための外部パラメータとメソッドを格納するためのクラス変数を追加してみましょう。

外部パラメータを初期化するメソッドの名前は、記述子に記述されている外部パラメータの名前と一致する必要があります。

class SignalNRTR : public CExpertSignal
  {
protected:
   int m_period_dyn;                                   //チャンネル期間
   double m_percent_dev;           //チャネルの幅を価格のパーセンテージとして
 
public:
                     SignalNRTR();
                    ~SignalNRTR();
   //---調整可能なパラメータの設定メソッド
   void              PeriodDyn(int value)                 { m_period_dyn=value;}
   void              PercentDev(double value)             { m_percent_dev=value;}
   
  };
//+------------------------------------------------------------------+
//                                                                   |
//+------------------------------------------------------------------+
SignalNRTR:: SignalNRTR (): m_period_dyn (12),
                           m_percent_dev(0.1)
  {
  //保護されたデータの---初期化
   m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE;
  }

クラスメンバは、初期化リストを使用して初期化されます。 ウィザードによって生成された "private" メソッドは、"protected" に置き換えることができますが、必要ではありません。

CExpertBaseクラスのvirtual bool ValidationSettings () メソッドを使用すると、インプットの正確性をチェックできます。

クラスにメソッドのプロトタイプを追加し、オーバーライドする必要があります。 たとえば、期間が1より大きく、偏差のパーセント値が正であることを確認する必要があります。

//+------------------------------------------------------------------+
//このメソッドはインプットパラメータをチェックします                       |
//+------------------------------------------------------------------+
boolSignalNRTR:: ValidationSettings ()
  {
   //基本クラスのメソッドを呼び出します。
   if(!CExpertSignal::ValidationSettings())  return(false);
   
   //期間は1より大きくなければなりません
   if(m_period_dyn<2)
   {
   Print(The period must be greater than 1);
   return false;
   }
   //チャネルの幅の値は正でなければなりません
   if(m_percent_dev<=0)
   {
   Print("The channel width value must be positive");
   return false;
   }
   
   return true;
  }

基本クラスのメソッドが最初に呼び出されることに注意してください。

次に、 InitIndicators ()メソッドを使用して、選択したインジケーターをモジュールに接続します。 このクラスでメソッドプロトタイプを作成してみましょう: 仮想 bool InitIndicators (CIndicators * indicators)、およびその説明を追加します。 インジケーターポインタをチェックし、追加のフィルタでインジケーターと時系列を初期化するための標準的なプロセスを使用します。

//+------------------------------------------------------------------+
//| Create indicators.                                               |
//+------------------------------------------------------------------+
bool SignalNRTR::InitIndicators(CIndicators *indicators)
   {
//---チェックポインタ
   if(indicators==NULL)
      return(false);
//---インジケーターの初期化と追加フィルタの時系列
   if(!CExpertSignal::InitIndicators(indicators))
      return(false);  
//NRTR インジケーターの作成と初期化---
if(!InitNRTR(indicators))
      return(false);
//---ok
   return(true);
   }

InitNRTR (インジケーター) 行でインジケーターを作成して初期化してみましょう。 また、InitNRTR (インジケータ) 関数のプロトタイプと説明を追加する必要があり

//+------------------------------------------------------------------+
//| Create NRTR indicators.                                          |
//+------------------------------------------------------------------+  
bool SignalNRTR::InitNRTR(CIndicators *indicators)
   {
//---チェックポインタ
   if(indicators==NULL)
      return(false);
//コレクションにオブジェクトを追加---
   if(!indicators.Add(GetPointer(m_nrtr)))
     {
      printf(__FUNCTION__+": error adding object");
      return(false);
     }
//NRTR パラメータの設定---
   MqlParam parameters[3];
//---
   parameters[0].type=TYPE_STRING;
   parameters[0].string_value="Orangetree\\NRTR.ex5";
   parameters[1].type=TYPE_INT;
   parameters[1].integer_value=m_period_dyn;      //期間
   parameters[2].type=TYPE_DOUBLE;
   parameters[2].double_value=m_percent_dev;      //チャンネル幅
//オブジェクトの初期化---
   if(!m_nrtr.Create(m_symbol.Name(),m_period,IND_CUSTOM,3,parameters))
     {
      printf(__FUNCTION__+": error initializing object");
      return(false);
     }
//---ok
   return(true);   
   }

このインジケーターは、 MqlParam構造体とCreate ()メソッドを使用して作成されます。

必要なコードを用意しました。 ここで、トレードアルゴリズムを記述する必要があります。 LongCondition ()およびShortCondition ()メソッドを使用してみましょう。 インジケーターシグナルを受信するためのメソッドを追加してみましょう。

   //--- データ取得メソッド
   double            UpSignal(int index)                   { return(m_nrtr.GetData(2,index));}
   double            DnSignal(int index)                   { return(m_nrtr.GetData(3,index));}

GetData () 関数は、インデックスと足に基づいてインジケーターバッファの値を受け取ります。 このインジケーターには、トレンド反転シグナルが既に含まれています。 よって、ポジションを開くための条件は簡単です。 インジケーターが "up" シグナルのとき買い、"down" シグナルが生成された場合に売ります。

//+------------------------------------------------------------------+
//| "Voting" that price will grow.                                   |
//+------------------------------------------------------------------+
intSignalNRTR:: LongCondition (void)
   {
   int idx   =StartIndex();
   if(UpSignal(idx))
      return 100;
   else return 0;
   }
//+------------------------------------------------------------------+
//| "Voting" that price will fall.                                   |
//+------------------------------------------------------------------+
intSignalNRTR:: ShortCondition (void)
   {
   int idx   =StartIndex();
   if(DnSignal(idx))
      return 100;
   else return 0;
   }

トレーディングアルゴリズムの定義に加えて、この関数は動作を設定します。 StartIndex ()関数が使用されています。

仮想 int StartIndex () 関数の説明には、現在の足を分析するフラグが true (現在の足からの分析) に設定されている場合に、メソッドは0を返します。 フラグが設定されていない場合は、1を返します (最後に完了した足からの分析)。システムは、完全に形成された足上のシグナルを分析します。 StartIndex () 関数は、戦略に従って、デフォルトで1を返します。 この関数は、 Expert_EveryTick を false に設定するパラメータとして、EAに反映されます。

トレーディングシグナルモジュールの作成手順が終了しました。

ストラテジーテスターを使って EA をテストしましょう。


さらに、トレーディングパラメータを最適化しましょう。 最適化に、 25.09.17-18.10.17 のデータを使用して、H1 の時間枠で EURUSDを使います。 次のインジケーターパラメータのみが最適化されます: チャネルの期間と幅。 損失のストップと利益値の取得は0に設定されます。


この図は、チャンネル幅が 0.25% に設定された48の期間の結果を示しています。

異なるトレンドインジケーターとの NRTR の組み合わせ

たとえば、インジケーターシグナルの確認が必要であるとします。 このインジケーターはトレンドの中でも機能するため、トレンドインジケーターを追加しましょう。 この記事では、MQL5 ウィザードから使用可能なシグナルモジュールを用意しています。 そこで、同じメソッドで進み、シグナルモジュールでもトレンドインジケーターを追加しましょう。

トレンドを特定するのは簡単なタスクではありません。 したがって、トレンドインジケーターのどちらが良いか悪いかを考察することはありません。 今回の目標は、トレードモジュールを使用してインジケータを接続するための技術を動作することですので、ターミナルから任意の標準トレンドインジケーターを選択してみましょう。 この段階でのトレードの結果には重要ではありません

モジュール作成のすべての手順について、前のセクションで説明しました。 したがって、ここでは、"コピー/貼り付け" メソッドを使用して、その利点を評価する方が便利です。 準備完了モジュールを使用して、必要なラインを置き換えてみましょう。

「トレンド」カテゴリから ADX テクニカルインジケーターを選択してみましょう。 特別に予約された CiADX ポインターは、カスタムインジケーター CiCustom へのポインターではなく、インジケーターを参照するために使用できます。 したがって、create メソッドを使用して作成するメソッドは少し異なりますが、パスを指定する必要はありません。

protected:
   CiADX m_adx;                                    //オブジェクト-インジケーター
   int m_period_adx;                               //ADX 期間
....................... その他のコード。。。。。。。。。。。。。。。。。。。。。。。。。。。

//オブジェクトの初期化---
   if(!m_adx.Create(m_symbol.Name(),m_period,m_period_adx))
     {
      printf(__FUNCTION__+": error initializing object");
      return(false);
     }


この区分には、期間のパラメータが1つしかありません。 モジュール記述子とパラメータ設定関数に反映される必要があります。 また、ADX バッファの値を取得するための関数を追加する必要があります。

//パラメータ = PeriodADX、int、14、ADX インジケーターの期間 
.....................................................

//---調整可能なパラメータの設定メソッド
void              PeriodADX(int value)                { m_period_adx=value;}
.....................................................

//--- データ取得メソッド
double            MainADX(int index)                   { return(m_adx.Main(index));}
double            ValueIDPlus(int index)               { return(m_adx.Plus(index));}
double            ValueIDMinus(int index)              { return(m_adx.Minus(index));}

実際には、トレーディングモジュールの作成セクションに記載されているすべての手順を通過します。 必要に応じて NRTR を ADX と交換します。 ADX インジケーターに記載されている標準トレード条件を確認せずに使用しましょう。 古典的なインジケーターは次の条件になります。

  • 買いする場合 +DI >-DI と ADX 成長しています。
  • +DI <-DI と ADX が成長している場合に売りします。
//+------------------------------------------------------------------+
//| "Voting" that trend is "Down".                                   |
//+------------------------------------------------------------------+
intSignalADX:: LongCondition (void)
   {
   int idx   =StartIndex();
   if(ValueIDPlus(idx)>ValueIDMinus(idx)&&MainADX(idx)>MainADX(idx+1))
      return (100);
   else
      return (0);
   }
//+------------------------------------------------------------------+
//| "Voting" that trend is "UP".                                     |
//+------------------------------------------------------------------+
intSignalADX:: ShortCondition (void)
   {
   int idx   =StartIndex();
   if(ValueIDPlus(idx)<ValueIDMinus(idx)&&MainADX(idx)>MainADX(idx+1))
      return (100);
   else
      return (0);
   }

これは基本原則です。 インジケータが上昇トレンドを示していると考えられる場合、買いシグナルになり、トレンドが下落している場合、売りシグナルが生成されます。 シグナルウエイトは便宜上100に設定されています。

MQL5 ウィザードをもう一度開いてみましょう。 EAを作成する場合は、SignalNTRTR および ADXTrendSignal を含む2つのトレーディングシグナルを選択します。 複数のシグナルが使用されている場合、その平均値が計算されます。 したがって、両方のシグナルに等しいウエイト係数を割り当てます。 オープンのしきい値は100に設定されています。 チャンネルを除くその他のパラメータはすべてゼロにリセットされます。 ストラテジーテスターを起動して、エキスパートアドバイザが正しく動作することを確認します。


結論

総括しましょう。 動的価格チャネルブレイクアウト NRTR のトレンドインジケーターについて考察しています。 インジケーターの2つのバージョンが開発されました。価格の極端からの近似曲線の偏差の固定パーセントと相場のボラティリティに応じて偏差の値を持つものです。

インジケータの両方のバージョンは、以下に添付されています。 NRTR に基づいてトレードシグナルのモジュールが作成され、MQL5 ウィザードを使用してエキスパートアドバイザが生成されました。

ADX インジケーターモジュールは、トレンドインジケータと NRTR インジケーターの共同使用の例を視覚化するために作成されています。 NRTR + ADX に基づくテストエキスパートアドバイザが MQL5 ウィザードに作成されました。 トレンドインジケーターの選択はユーザー次第であり、この記事では説明されていないため、NRTR + a トレンドインジケーターの組み合わせは最適化されています。 アプローチは、モジュラーと組み合わせの哲学に基づいています。

添付ファイルを使用する場合は、インストールフォルダに従って、インジケータとトレーディングシグナルへのパスを正しく指定するようにしてください。 例えば、SignalNRTRです。:

   parameters[0].string_value="NRTR.ex5";

インジケータのインストールフォルダに従ってパスを指定します。

Files:

#NameTypeDescription
1NRTR.mq5インジケーター分析されたインジケーターのソースコード
2NRTRvolatile.mq5インジケーター価格変動を考慮したインジケーターのソースコード
3SignalNRTR.mqhトレーディングモジュールトレーディングシグナルのモジュール。 MQL5 ウィザードでエキスパートアドバイザを生成するために使用されます。
 ADXTrendSignal.mqhトレーディングモジュールトレンドインジケーターのテストモジュール

MQL5.zip フォルダ内のファイルは、メタエディタ ディレクトリに従って配置されます。