English Русский 中文 Español Deutsch Português
領域法

領域法

MetaTrader 5トレーディングシステム | 23 8月 2016, 13:28
1 123 0
Vladimir Karputov
Vladimir Karputov

目次


概論

記事の最後にある添付ファイルからインディケータとエキスパートアドバイザを正しくインストールするには、 "Indicators.zip"と"Experts.zip"アーカイブを<data catalog>\MQL5\で解凍する必要があります。

面積法についての一番初めの記事は2004年[1]に公開されました。この方法はRSIインディケータのデータへの特殊な外観が面白いです。ここでは最後の交差時から50より上(下)のラインを描くオシレーターの領域を評価するものです。2004年から市場は激しく変化し、MQL5言語が開発されました。つまり、MQL5言語や今日の市場で戦略をテストする時が到来したのです。


1. RSIインディケータの指数の一般的な評価方法

RSIインディケータのシグナルに基づく取引の一般的なメソッドは、商品の買われすぎ/売られすぎの指標を評価し、インディケータと価格の指標のあいだの分岐の検索、インディケータによる買われすぎ/売られすぎの領域の発生後の反転です。このように、RSIオシレーターのテクニカル分析には、最低でも4つのシグナルが使用されるため、これが意思決定システムを複雑にしています。

また私達は、RSIインディケータは非常に長い時間買われすぎ(70のラインより上)/売られすぎ(30のラインより下)の領域に留まることはなく、必ず戻ってきて、50の中心線と交差することを知っています。

RSI

図1. RSIオシレーターは常に買われすぎ/売られすぎの領域から戻ってくる

図1で分かるように、オシレーターが買われすぎ/売られすぎ領域にあった総合時間は、他の時間と比べるととても短いことが分かります。また、買われすぎ/売られすぎ領域に入った後、RSIは50の中心線と交差します。RSIオシレーターが必ず戻ってきて、50のラインと交差するという認識と、RSIオシレーターの指標のテクニカル分析を簡素化する必然性が、領域法開発のベースとなりました。


2. 領域法

領域法は、RSIオシレーターの指標を1つの指標(50のラインより上/下のオシレーターによって形成された領域)で評価します。この数値こそが買われすぎ/売られすぎの度合いを定義します。

area_figure

図2. 面積法 - 領域が50のラインより上か下かを評価する方法

ポジションを保有するシグナルは、この場合には、RSIインディケータの最後に交差した時からの50ラインより上/下の領域の値です。   

  • 50のラインよりに長い間RSIがある場合、特定の領域値を超えた後に(領域値が300になる)、売りポジションが保有されます。 

SELL signal 

図3. 売りポジションの保有シグナルは、領域が300となってから

  • また、50のラインよりにRSIが長い間ある場合、特定の領域値を超えた後、買いポジションが保有されます。

ポジション決済のシグナルは、RSIオシレーターが、ローカル最大/最小値の形成を伴う50のラインとの交差と、そこからの4%の後退です。

  • 例えば、50ラインよりも上に長い間あって、売りポジションを保有しているとします。そして、インディケータ値が減少していき、40のラインまで到達し、その後、インディケータの値は増加し始めます(つまり、ローカル最大値が形成されます)。インディケータ値が44のラインまで到達した場合、これがポジション決済のシグナルとなります。 

Close SELL signal 

図4. 売りポジションの決済シグナル ー ローカル最小値とそれに続く4%の後退の形成後

  • 同様のロジックがインディケータが長い間50ラインより下にある場合に発生し、ただこの場合には私達はローカル最大値の形成を待ちます。

50ラインより上/下の領域を可視化するのに、RSIAreaIndicatorが役に立ちます。  


3. インディケータ RSIAreaIndicator_v1

RSIAreaIndicatorは、RSIをベースに作られています。主な違いは、RSIAreaIndicatorは2つのバッファを持っていることです。1つ目のバッファはDRAW_HISTOGRAMの構築スタイルを持ち、2つ目のバッファはDRAW_LINEの構築スタイルを持っています。バッファ値は式によって得られます。

formula RSIAreaIndicaor

RSIAreaIndicator version 1.00の外観

RSIAreaIndicator 

図5. RSIAreaIndicator _v1

 

3.1. インディケータのドラフトを作成する 

貴方が作成したカスタムインディケータを別のフォルダに配置することをお勧めします。私の場合、こういったフォルダには"MyInd"という名前をつけています。インディケータの作成を始めるには、まずそのドラフトをMQL5 Wizardのヘルプを使ったMetaEditorで作成する必要があります。インディケータのドラフト作成の最初のステップこのビデオに集約しました。


出来上がったドラフトは記事の最後で見ることができます。インディケータは"RSIAreaIndicatorStep1.mq5"という名前で保存されています。 

3.2. インディケータの『ヘッダー』を作成する

次のステップはインディケータの説明書きを加えることです。こうすることで、いつでも『共通』タブのインディケータのプロパティで見ることができるようになります。見やすくする為、記事に追加したコードは色で強調表示されています

#property version   "1.00"
#property description   "The indicator displays area RSI over/under line 50"
#property indicator_separate_window

先ほども述べたように、RSIAreaIndicatorには2つのインディケータバッファがあります。その他に、もう1つの補助が必要になります。したがって、インディケータには全部で3つのバッファが使用されることになります。インディケータの『ヘッダー』のコードの編集を始めましょう。

#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots   2
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_type2   DRAW_LINE
#property indicator_color1  clrGray
#property indicator_color2  clrGray
//--- input parameters
input int      ExtRSIPeriod=13;

ここで、インディケータと補助バッファの値が格納される3つの配列を宣言する必要があります。

//--- input parameters
input int      ExtRSIPeriod=13;
//---- buffers
double ExtMapBuffer1[];
double ExtMapBuffer2[];
double ExtMapBuffer3[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |

次に、私達のRSIAreaIndicatorはRSI標準インディケータをベースに計算されるため、インディケータ値を取得する必要があり、Relative Strength Indexハンドラが格納される変数が必要になります。

double ExtMapBuffer3[];
//--- variable for storing the handle of the iRSI indicator 
int    handle;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |

そして最後に、3つの変数の『ヘッダー』で宣言します。name 変数には、インディケータが起動するシンボルの名前が、short_name変数にはインディケータの略名が、そしてbars_calculated変数には、RSIインディケータで計算されたバーの数が格納されます。

int    handle;
//--- variable for storing 
string name=Symbol();
//--- name of the indicator on a chart 
string short_name;
//--- we will keep the number of values in the Relative Strength Index indicator 
int    bars_calculated=0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |

インディケータの『ヘッダー』は記入したので、これでOnInit()関数の編集へと移ることができます。

3.3. インディケータのOnInit()関数の編集 

インディケータを作成するということは、私達のインディケータバッファを前に宣言したdouble型の動的配列と繋げる必要があるということです。

int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,ExtMapBuffer1,INDICATOR_DATA);
   SetIndexBuffer(1,ExtMapBuffer2,INDICATOR_DATA);
   SetIndexBuffer(2,ExtMapBuffer3,INDICATOR_CALCULATIONS);
//---
   return(INIT_SUCCEEDED);

それから、バッファと配列を繋げた後すぐに、時系列での配列要素の目録作成を設定します(ArraySetAsSeriesを参考にすることをお勧めします)。配列の右端の要素はインデックス『0』となります。

   SetIndexBuffer(1,ExtMapBuffer2,INDICATOR_DATA);
   SetIndexBuffer(2,ExtMapBuffer3,INDICATOR_CALCULATIONS);
   ArraySetAsSeries(ExtMapBuffer1,true);
   ArraySetAsSeries(ExtMapBuffer2,true);
   ArraySetAsSeries(ExtMapBuffer3,true);
//---
   return(INIT_SUCCEEDED);

ここで、表示精度を設定します。インディケータは小数点以下2桁を表示します。

   ArraySetAsSeries(ExtMapBuffer3,true);
//--- set accuracy 
   IndicatorSetInteger(INDICATOR_DIGITS,2);
//---
   return(INIT_SUCCEEDED);

 あとはOnInit()関数でRSIndexのハンドルを取得し、short_name変数を埋め、私達のインディケータに略名をつけます。

   ArraySetAsSeries(ExtMapBuffer2,true);
   ArraySetAsSeries(ExtMapBuffer3,true);
//--- set accuracy 
   IndicatorSetInteger(INDICATOR_DIGITS,2);
   handle=iRSI(name,0,ExtRSIPeriod,PRICE_CLOSE);
//--- if the handle is not created 
   if(handle==INVALID_HANDLE)
     {
      //---  notify about failure and output error code
      PrintFormat("Failed to create handle of the iRSI indicator for the symbol %s/%s, error code %d",
                  name,
                  EnumToString(PERIOD_CURRENT),
                  GetLastError());
      //--- the indicator is stopped early 
      return(INIT_FAILED);
     }
//--- show the symbol/timeframe the RSI Area Indicator is calculated for 
   short_name=StringFormat("RSIArea(%d)",ExtRSIPeriod);
   IndicatorSetString(INDICATOR_SHORTNAME,short_name);
//--- normal initialization of the indicator 
   return(INIT_SUCCEEDED);

これでインディケータの『ヘッダー』とOnInit()関数を埋めました。編集したコードは、記事の最後で参照することができます。インディケータは"RSIAreaIndicatorStep2.mq5"という名前で保存されています。  

3.4. インディケータの補助関数の作成 

RSIAreaIndicatorの動作には、OnCalculate()関数への各エントリでRSIインディケータのデータを取得する必要があります。コード読み取りの容易性を確保することとプログラムの機能を分けることは同じように重要です。その為、RSI値を取得する補助コードと、RSIAreaIndicatorバッファのうちの1つへのこれらの数値のコピーは、個別のFillArrayFromBuffer()関数に入れました。これをOnCalculate()の後に配置します。数値はCopyBuffer関数を使ってコピーされます。

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+ 
//| Filling indicator buffers from the iRSI indicator                | 
//+------------------------------------------------------------------+ 
bool FillArrayFromBuffer(double &rsi_buffer[],  // indicator buffer of Relative Strength Index values 
                         int ind_handle,        // handle of the iRSI indicator 
                         int amount             // number of copied values 
                         )
  {
//--- reset error code 
   ResetLastError();
//--- fill a part of the iRSIBuffer array with values from the indicator buffer that has 0 index 
   if(CopyBuffer(ind_handle,0,0,amount,rsi_buffer)<0)
     {
      //--- output error code if copying fails 
      PrintFormat("Failed to copy data from the iRSI indicator, error code %d",GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated 
      return(false);
     }
//--- all in order
   return(true);
  }
//+------------------------------------------------------------------+

3.5. インディケータの主要動作コードの作成 

RSIAreaIndicatorの主要な動作コード(またはロジック)はOnCalculate()関数に配置しました。ここでは主要変数values_to_copyを宣言します。続いて、values_to_copy変数が、RSIインディケータからコピーする必要がある数値の数を保存します。

                const int &spread[])
  {
//--- number of values copied from the iRSI indicator 
   int values_to_copy;
//--- determine the number of values calculated in the indicator 
   int calculated=BarsCalculated(handle);
   if(calculated<=0)
     {
      PrintFormat("BarsCalculated() returned %d, error code %d",calculated,GetLastError());
      return(0);
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }

values_to_copy値の計算:

      PrintFormat("BarsCalculated() returned %d, error code %d",calculated,GetLastError());
      return(0);
     }
//--- if it is the first calculation of the indicator or if the number of values in the iRSI indicator changed 
//---calculate 
   if(prev_calculated==0 || calculated!=bars_calculated || rates_total>prev_calculated+1)
     {
      //--- if the iRSIBuffer array is greater than the number of values in the iRSI indicator for symbol/period, then we don't copy everything  
      //--- otherwise, we copy less than the size of indicator buffers 
      if(calculated>rates_total) values_to_copy=rates_total;
      else                       values_to_copy=calculated;
     }
   else
     {
      //--- it means that the indicator is calculated not for the first time, but since the last call of OnCalculate()  
      //--- not more than one bar is added for calculation 
      values_to_copy=(rates_total-prev_calculated)+1;
     }
//--- return value of prev_calculated for next call
   return(rates_total);

何故values_to_copy変数はこのように計算されるのでしょうか?MQL5のインディケータでは、OnCalculate()関数に引き渡される配列要素(time[]、open[]、high[]、low[]、close[]、tick_volume[]、volume[]、spread[])は、配列の始めから最後まで索引付けされています。チャート上ではこのようになります。

Array Not Series

図6. 配列が時系列でない場合の要素の索引付け 

つまり、時系列ではない配列では、一番右の要素は最大インデックスを持つことになります。これは数学的な計算の際に考慮する必要があります。

values_to_copy変数の値が計算されたら、FillArrayFromBuffer()補助関数を呼び出し、ExtMapBuffer1[]ExtMapBuffer2[]のインディケータバッファを数値で埋めます。

      //--- for calculation not more than one bar is added 
      values_to_copy=(rates_total-prev_calculated)+1;
     }
//--- fill the array with values of the iRSI indicator 
//--- not ready 
   if(!FillArrayFromBuffer(ExtMapBuffer3,handle,values_to_copy)) return(0);
//---
   for(int i=0;i<values_to_copy;i++)
     {
      ExtMapBuffer1[i]=ExtMapBuffer2[i]=ExtMapBuffer3[i]-50.0;
     }
//--- memorize the number of values in the Relative Strength Index indicator 
   bars_calculated=calculated;
//--- return value of prev_calculated for next call
   return(rates_total);

RSIAreaIndicator version 1.00の出来上がりです。これは記事の最後でダウンロードすることができます(RSIAreaIndicatorv1.mq5)。これで領域法に基づいて取引を行うRSIAreaEA version 1.00エキスパートアドバイザの作成に取り掛かることができます。


4. エキスパートアドバイザ RSIAreaExpert version 1.00

インディケータの時と同じように、作成したエキスパートアドバイザは別個のフォルダに配置することをお勧めします。私の場合、エキスパートアドバイザ用のフォルダ名は"MyExp"としています。インディケータの時と同様に、RSIAreaExpert_v1のドラフトを作成します。重要:ステップでは全てのチェックを外す必要があります。


 

 図7. エキスパートアドバイザの作成時の設定

出来上がったエキスパートアドバイザのドラフトは記事の最後で参照することができます(RSIAreaExpert_v1_Step1.mq5)。 

4.1. エキスパートアドバイザの『ヘッダー』の編集

エキスパートアドバイザの説明書きを追加します。これはエキスパートアドバイザの『共通』タブで見ることができるようになります。

#property version   "1.00"
#property description "EA trades on \"Method areas\""
//+------------------------------------------------------------------+
//| Expert initialization function                                   |

説明書きはすぐには書きたくないものですが、最終的にはこれが貴方に大いに役立つものになるでしょう。 

エキスパートアドバイザは標準ライブラリを使用し、取引操作実行の為のCTradeクラスを使用します。この為にはCTradeクラスを接続し、my_trade変数を宣言する必要があります。

#property description "EA trades on \"Method areas\""
#include <Trade\Trade.mqh>
//--- global variables
CTrade      my_trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |

また、3つの変数を追加します(Relative Strength Indexインディケータのハンドルを保存するもの、算出された現在の領域を保存するもの、そして補助変数)。

//--- global variables
CTrade      my_trade;
int         handle;     // variable for storing the handle of the iRSI indicator 
double      RSIArea;    // the calculated area
double      RSIOpen;    // the auxiliary variable
//+------------------------------------------------------------------+
//| Expert initialization function                                   |

そして、エキスパートアドバイザの『ヘッダー』の編集の最後のステップは、入力パラメータの追加です。

double      RSIOpen;    // the auxiliary variable
//--- input parametres
input int   ExtRSIPeriod=13;    // period of RSI
input int   AreaCondition=300;  // area
input ENUM_TIMEFRAMES period=PERIOD_M15;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |

period変数はストラテジーテスターでのテストを快適にする為に導入されていて、こうすることでテスト期間の様々な範囲を設定することができるようになります。


図8. period変数で幅広い期間でエキスパートアドバイザをテストできるようになる 

エキスパートアドバイザの『ヘッダー』は埋めたので、次はOnInit()関数です。OnInit()では、現在のシンボル(Symbol())と設定した期間(period)でのインディケータのハンドルの取得という1つの操作のみ行います。

int OnInit()
  {
//---
   handle=iRSI(Symbol(),period,ExtRSIPeriod,PRICE_CLOSE);
//--- if the handle is not created 
   if(handle==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code 
      PrintFormat("Failed to create handle of the iRSI indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(period),
                  GetLastError());
      //--- the indicator is stopped early 
      return(INIT_FAILED);
     }
//---
   return(INIT_SUCCEEDED);
  }

エキスパートアドバイザの編集プロセスでのこれらの全ての変更はRSIAreaExpert_v1_Step2.mq5ファイルで見ることができます。

4.2. RSIAreaFunc補助関数 

領域を特定するRSIAreaFunc()関数は、いくつかの機能ユニットから構成されています。機能を順を追って追加していきましょう。第一ブロック(説明はコードの後):

void OnTick()
  {
//---

  }
//+------------------------------------------------------------------+
//| Area calculation                                                 |
//+------------------------------------------------------------------+
double RSIAreaFunc(int &RSIAreaShift,int BeginShift)
  {
   int    shift,limit;
   double rsivalue,result;
//--- get current RSI 
   limit=Bars(Symbol(),period)-ExtRSIPeriod;
   if(limit>100)
      limit=100;
   double   arr_rsi[];
   ArrayResize(arr_rsi,limit);
   ArraySetAsSeries(arr_rsi,true);
   if(CopyBuffer(handle,0,0,limit,arr_rsi)==-1)
     {
      Print("CopyBuffer from iRSI failed, no data");
      return(0);
     }
   return(result);
  }

limit変数は、いくつのiRSIインディケータの数値をarr_rsi[]配列にCopyBufferを使ってコピーするかを担っています。limit変数を『100』で制限します。つまり、常にiRSIインディケータの最後の100の数値をコピーするということです。エキスパートアドバイザの編集のこれらの変更はRSIAreaExpert_v1_Step3.mq5ファイルで見ることができます。

4.3CopyBuffer関数の動作コードの検証 

もしCopyBuffer関数の動作やどんな数値がインデックス『0』に含まれるのか、あまり良くわからない場合は、検証済の簡単なコードを書くこともできます。OnTick()関数にRSIAreaFunc()補助関数の呼び出しを記述します。

void OnTick()
  {
//---
   static int RSIAreaShift=0;
   RSIAreaFunc(RSIAreaShift,0);
  }
//+------------------------------------------------------------------+
//| Area calculation                                                 |
//+------------------------------------------------------------------+
double RSIAreaFunc(int &RSIAreaShift,int BeginShift)

RSIAreaFunc()関数の最初のブロックの最後に、arr_rsi[]配列要素の最初と最後の数値というコメントを書き加えます。

   if(CopyBuffer(handle,0,0,limit,arr_rsi)==-1)
     {
      Print("CopyBuffer from iRSI failed, no data");
      return(0);
     }
//---
   Comment("arr_rsi[",limit-1,"]=",DoubleToString(arr_rsi[limit-1],2),
           "; arr_rsi[0]=",DoubleToString(arr_rsi[0],2));
   return(result);
  }

これは検証済コードで RSIAreaExpert_v1_Step3_check.mq ファイルにのみ入れられており、これは主要エキスパートアドバイザにはありません。チェックの為に次のことを行います。

  • (以前に行っていない場合)RSIAreaExpert_v1_Step3_check.mq5エキスパートアドバイザのファイルをコンパイルする。
  • 任意の商品の新規チャートを開き、時間軸をM15に変更する(デフォルトでは入力パラメータのperiod変数はPERIOD_M15となっている為)。
  • RSIインディケータをチャートに入れる(メニュー『挿入』→『インディケータ』→『オシレーター』→『期間』13およびCloseを『適用する』という設定をした『Relative Strength Index』)。
  • チャートにRSIAreaExpert_v1_Step3_check.mq5エキスパートアドバイザをつける。

チャート上ではarr_rsi配列のインデックス『0』の要素値が、一番初めのバーでRSIインディケータの値と一致していることがすぐにわかります。

  check function CopyBuffer 

図9. CopyBuffer関数の動作チェック 

4.4. 補助関数の編集の続き

RSIAreaFunc()関数の次のブロック:

   if(CopyBuffer(handle,0,0,limit,arr_rsi)==-1)
     {
      Print("CopyBuffer from iRSI failed, no data");
      return(0);
     }

   result=arr_rsi[0]-50.0; // values from the bar that has 0 index

   for(shift=BeginShift+1;shift<limit;shift++)
     {
      rsivalue=arr_rsi[shift]-50;
      if((result>0 && rsivalue<-3) || (result<0 && rsivalue>3))
        {
         RSIAreaShift=shift;
         break;
        }
      result+=rsivalue;
     }
   return(result);
  }

まずresult変数に一番右のバーのマイナス50のRSIインディケータの値が割り当てられます。それからarr_rsi配列でループが続きます(インデックス『1』の要素から、インデックスlimit-1の要素まで)。このサイクルでは『ゼロラインとの交差はあったか』という条件がチェックされます。交差があった場合、バーのインデックス(右から左へ計算)はRSIAreaShift変数に格納されます。

4.5. エキスパートアドバイザのOnTick()関数

RSIAreaFunc()補助関数の編集が終了しました。次はOnTick()主要取引関数の番です。OnTick()に次のコードを追加します。 

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   static int RSIAreaShift=0;
   int      shift;
   double   RSICurrent,RSILocalMin,RSILocalMax,value;
   double   arr_rsi[1],rsi;
   MqlTick  last_tick;
//---
   if(CopyBuffer(handle,0,0,1,arr_rsi)==-1)
     {
      Print("CopyBuffer from iRSI failed, no data");
      return;
     }
   rsi=arr_rsi[0];
//--- 
   if(!SymbolInfoTick(Symbol(),last_tick))
      Print("SymbolInfoTick() failed, error = ",GetLastError());
//---
  }

既にお馴染みのCopyBuffer関数を使って、一番右のバーのRSIインディケータの1つの値を取得し、この数値をrsi-変数値に代入します。次に、コード内ではこの変数を数回参照します。それから現在のシンボルの現在価格を取得し、last_tick変数でこれらの価格を格納します。

コードの次のブロックは現在の商品に保有ポジションがある場合に処理されます。

   if(!SymbolInfoTick(Symbol(),last_tick))
      Print("SymbolInfoTick() failed, error = ",GetLastError());
//--- check the conditions for opening a position
   if(!PositionSelect(Symbol()))
     {
      RSIArea=RSIAreaFunc(RSIAreaShift,0);
      //--- check for a chance to take a long position
      if(RSIArea<-AreaCondition)
        {
         my_trade.Buy(1.0,NULL,last_tick.ask,0.0,0.0,NULL);
         RSIOpen=rsi;
         return;
        }
      //---check for a chance to take a short position
      if(RSIArea>AreaCondition)
        {
         my_trade.Sell(1.0,NULL,last_tick.bid,0.0,0.0,NULL);
         RSIOpen=rsi;
         return;
        }
      RSIAreaShift=0;
     }
//---
  }
//+------------------------------------------------------------------+
//| Area calculation                                                 |

コード内ではポジション保有の条件がチェックされます(現在算出された領域(RSIArea変数) が、入力パラメータ (AreaCondition)より少ない/多い場合、買い/売りポジションが保有されます。

次にRSICurrent変数にrsi変数値が割り当てられ(ここには一番右のバーのRSIインディケータ値が保存されます)、OnTick()関数からの条件の発生がチェックされます。

  • 50のラインより上(RSIOpen>50)でポジションを保有する場合、現在私達は50のラインより上(RSICurrent>50)にいるということです。
  • 50のラインより下(RSIOpen<50)でポジションを保有する場合、現在私達は50のラインより下(RSICurrent<50)にいるということです。
      RSIAreaShift=0;
     }
   RSICurrent=rsi;
   if(RSIOpen>50 && RSICurrent>50) return;
   if(RSIOpen<50 && RSICurrent<50) return;

   RSILocalMin = RSICurrent;
   RSILocalMax = RSICurrent;

//---
  }
//+------------------------------------------------------------------+
//| Area calculation                                                 |

コードの次のブロックは、ローカル最大/最小値を検出し、RSILocalMinRSILocalMax変数にこれらの数値を代入します。

   RSILocalMin = RSICurrent;
   RSILocalMax = RSICurrent;
   
//--- search local minimum/maximum
   if(RSIAreaShift>1)
     {
      double   arr_rsi_1[];
      ArrayResize(arr_rsi_1,RSIAreaShift);
      ArraySetAsSeries(arr_rsi_1,true);
      if(CopyBuffer(handle,0,0,RSIAreaShift,arr_rsi_1)==-1)
        {
         Print("CopyBuffer from iRSI failed, no data");
         return;
        }
      for(shift=1; shift<RSIAreaShift; shift++)
        {
         value=arr_rsi_1[shift];
         if(value<RSILocalMin && RSIArea>0) RSILocalMin=value;
         if(value>RSILocalMax && RSIArea<0) RSILocalMax=value;
        }
     }
//---
  }
//+------------------------------------------------------------------+
//| Area calculation                                                 |

そして、最後にコードの最後のブロックです。

         if(value>RSILocalMax && RSIArea<0) RSILocalMax=value;
        }
     }

//--- check for rollback
   if(PositionSelect(Symbol()))
     {
      if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
        {
         //--- сheck if it is time for closing
         if(RSILocalMax>=RSICurrent+4 && RSILocalMax>50)
            my_trade.PositionClose(Symbol(),20);
        }
      if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
        {
         //--- check, can it is time already be closing?
         if(RSILocalMin<=RSICurrent-4 && RSILocalMin<50)
            my_trade.PositionClose(Symbol(),20);
        }
     }
//---
   return;
  }
//+------------------------------------------------------------------+
//| Area calculation                                                 |

ここでは(保有ポジションがある場合)ルールに沿ったポジション決済の条件をチェックします。

RSIオシレーターの、ローカル最大/最小値の形成を伴う50のラインとの交差と、そこからの4%の後退です。
例えば、50ラインよりも上に長い間あって、売りポジションを保有しているとします。そして、インディケータ値が減少していき、40のラインまで到達し、その後、インディケータの値は増加し始めます(つまり、ローカル最大値が形成されます)。ポジション決済のシグナルは、インディケータ値が44のラインに到達した時です。

これでRSIAreaExpert_v1 エキスパートアドバイザの作成は終了です。RSIAreaExpert_v1.mq5ファイルはこの記事の最後でダウンロードすることができます。


5. 様々な期間と銘柄でのエキスパートアドバイザRSIAreaExpertバージョン1.00のテスト

RSIAreaExpertエキスパートアドバイザのテストは、初めにH1[1]のチャート期間で行われましたが、2004年からは市場は激しく変化しより不安定になった為、領域法のパフォーマンス性のチェックに、M10からH6までの幅広い期間でテストが行われることになりました。またテストの為の領域の範囲が100から800まで大幅に広げられました。テスト期間は、2015年1月5日から2016年1月5日です。

AUDCADのRSIAreaExpert version 1のテスト結果は以下のようになりました。

  RSIAreaExpert version 1 AreaCondition to Profit AUDCAD

図10. RSIAreaExpert version 1のテスト結果。AUDCAD。領域間隔100-800。期間M10-H6。 

H2の期間で、結果の良い密度が分かります。更にH3を計算に入れることができます。ここで、下の図を見て、RSIAreaExpert version 1エキスパートアドバイザのテスト時に1年間においてAUDCADでいくつの取引が行われたかを評価しましょう。

RSIAreaExpert version 1 Trades to Profit AUDCAD

図11.  RSIAreaExpert version 1のテスト結果。AUDCAD。領域間隔100-800。期間M10-H6。 

H2とH3での一年間の取引数は50の範囲内で変動しています。これは少しで、誤差は多いです。その為、AUDCADでは領域法のメソッドの戦略は上手く機能しないと結論づけることができます。

AUDUSDのシンボルでのRSIAreaExpert version 1のテスト結果: 

RSIAreaExpert version 1 AreaCondition to Profit AUDUSD 

 図12.  RSIAreaExpert version 1のテスト結果。AUDUSD。領域間隔100-800。期間M10-H6。 

AUDUSDでの戦略の利益性を考えるなら、H2とH3での取引を検証することができます。これらの期間ではAreaConditionパラメータは、250から400の範囲内で変動しています。H2とH3の期間での取引の論拠を確認する為に、これらの期間での1年間の取引量を検証する必要があります。

RSIAreaExpert version 1 Trades to Profit AUDUSD 

 図13.  RSIAreaExpert version 1のテスト結果。AUDUSD。領域間隔100-800。期間M10-H6。 

お分かりのように、あまりにも少ないです。つまり、AUDUSDでは領域法のメソッドはお勧めできないということです。

EURUSDでのRSIAreaExpert version 1のテスト結果

RSIAreaExpert version 1 AreaCondition to Profit EURUSD

 図14. RSIAreaExpertのテスト結果。領域間隔100-800。期間M10-H6。  

図4で分かるように、M10に対しては400から550まで、M12に対しては300から400まで、M15に対しては300から400までの領域の、利益の結果の良い密度を確認できます。一年間における取引量は少ない為、もっと大きい期間は検証しません(図5参照)。

図5ではEURUSDの為の利益と取引数の依存関係のチャートが表示されています。

RSIAreaExpert version 1 Trades to Profit EURUSD

図15. RSIAreaExpertのテスト結果。領域間隔100-800。期間M10-H6。 

(H1からH6までの)大きな期間での取引数はごくわずかで、これらの期間で領域法を使う正当性に疑問がわきます。M10、M12、M15の期間では、取引数は領域法の利益性を確かめるのに十分なものです。確かにEURUSDは領域法での取引に合っています。

GBPUSDでのRSIAreaExpert version 1のテスト結果

RSIAreaExpert version 1 AreaCondition to Profit GBPUSD 

 図16.  RSIAreaExpert version 1のテスト結果。GBPUSD。領域間隔100-800。期間M10-H6。 

GBPUSDではM20の期間で肯定的な利益の良い密度となります。AreaConditionパラメータは300から500まで変化します。

RSIAreaExpert version 1 Trades to Profit GBPUSD 

図17.  RSIAreaExpert version 1のテスト結果。GBPUSD。領域間隔100-800。期間M10-H6。  

GBPUSDでのM20の期間における1年間の取引量は140から250までです。これは確かに素晴らしい数字ではありませんが、注意に値するものです。言い換えれば、領域法によるGBPUSDでの取引は、全ての人に適しているとは言えないということです。 

USDCADでのRSIAreaExpert version 1のテスト結果:

 

図18.  RSIAreaExpert version 1のテスト結果。USDCAD。領域間隔100-800。期間M10-H6。  

USDCADでは、肯定的な利益性の良い密度が確認されるので、M30だけ検証します。また、AreaConditionパラメータは、280から550の範囲で変化しています。

RSIAreaExpert version 1 Trades to Profit USDCAD 

 図19.  RSIAreaExpert version 1のテスト結果。USDCAD。領域間隔100-800。期間M10-H6。  

M30の時間軸におけるこの通貨ペアでの1年間の取引量は、90から200までの範囲で変化しています。これはそんなに多いものではないので、USDCADの為に領域法を使用することはお勧めできません。

USDJPYでのRSIAreaExpert version 1のテスト結果:

RSIAreaExpert version 1 AreaCondition to Profit USDJPY 

図20.  RSIAreaExpert version 1のテスト結果。USDJPY。領域間隔100-800。期間M10-H6。  

USDJPYでは2つの期間(M10とM30)が割り当てられています。M10の期間ではAreaConditionパラメータは320から650の間にあり、M30の期間では550から600の間にあります。

RSIAreaExpert version 1 Trades to Profit USDJPY 

図21.  RSIAreaExpert version 1のテスト結果。USDJPY。領域間隔100-800。期間M10-H6。  

USDJPYでのM10の期間における領域法による1年間の取引量は150から200の間、またM30も期間における取引量は50から150でした。したがって、ここでは取引の推奨は非常に曖昧であることが分かります。


まとめ

領域法は取引に使用するにはまだ早いことがわかりました。しかし、市場の現在の条件では、システムは[1]以前は主な利益を示したもののH1の期間では損失を示すようになりました。現代の市場では最も利益的で効率的なものは、M10、M12、M15の期間におけるEURUSDでの領域法による取引でした。この通貨ペアとこれらの時間軸でのテストは、1年間の十分な取引量を示しました。

 

リファレンス

  1. I.V.モロゾフ、R.R.ファトフリン、FOREX:単純なものから複雑なものまで。『MetaTrader』クライアントターミナルの新しい機能。2004年、『テレトレード』社、448p。
記事の最後にある添付ファイルからインディケータとエキスパートアドバイザを正しくインストールするには、 "Indicators.zip"と"Experts.zip"アーカイブをdata catalog>\MQL5\で解凍する必要があります。

MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/2249

添付されたファイル |
Indicators.zip (3.91 KB)
Experts.zip (5.37 KB)
トレーダーの為のライフハック:1つのバックテストは良いが、4つは更に良い トレーダーの為のライフハック:1つのバックテストは良いが、4つは更に良い
最初のテストをする時にトレーダーには「4つのモードのうちのどれを使ったらいいのだろうか?」という一つの疑問が浮かんでくると思います。モードにはそれぞれにそれぞれの利点と特徴があるので、それを簡単にして、ワンクリックで一度に全てのモードを起動させましょう!この記事では、Win APIとちょっとしたマジックを使って、4つのテストチャートを一度に表示する方法をご紹介します。
エキスパートアドバイザとインディケータに素早く制御パネルを追加する方法 エキスパートアドバイザとインディケータに素早く制御パネルを追加する方法
自分のエキスパートアドバイザやインディケータに便利な制御パネルを追加したいけど、何をどうしたら良いかわかりませんか?この記事では、貴方のMQL4/MQL5プログラムに入力パラメータを持つダイアログパネルを『取り付ける方法』をステップバイステップでご紹介します。
MQL4による取引におけるファジー論理の適用 MQL4による取引におけるファジー論理の適用
この記事ではMQL4による取引におけるファジー論理の適用例をご紹介します。MQL4の為のFuzzyNetライブラリを使用したエキスパートアドバイザとインディケータの開発を解説していきます。
ビル・ウィリアムズのシステムに基づく取引システムモジュール ビル・ウィリアムズのシステムに基づく取引システムモジュール
この記事では、ビル・ウィリアムズの取引システムや、このシステムパターンをチャート上で発見しマーキングする為に開発されたMQL5モジュールの使用方法、見つけたパターンでの自動売買の原則、また様々な取引銘柄でのテスト結果を公開しています。