MQL5超入門(11)/iRSIをスムージングしたインジケータ

今日は、昨日より一歩進んで、iRSIを使用したインジケータにスムージングを掛けてみます。
サンプルコードからの抜粋なので、動くことは間違いないと思うのですが、100%動作保証はできない点はご了承くださいませ。


MQL4 と、これまでのMQL5 の知識があれば、だいたい理解できると思うので、いきなりコード紹介です。(手抜き...

#property indicator_separate_window
#property indicator_buffers 2        // 使用するバッファは2本
#property indicator_plots   2        // 表示に使用するバッファも2本

//--- 外部入力パラメータ             // MQL4 の extern は input に変更
input int      RSIperiod=14;         // RSIの期間
input int      Smooth=8;             // RSIのスムージング期間
input ENUM_MA_METHOD meth=MODE_SMMA; // スムージング方法(移動平均の種類)

//---- plot RSI
#property indicator_label1  "RSI"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//---- plot RSI_Smoothed
#property indicator_label2  "RSI_Smoothed"
#property indicator_type2   DRAW_LINE
#property indicator_color2  Navy
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1

//--- indicator buffers
double         RSIBuffer;          // RSI値を格納する配列
double         RSI_SmoothedBuffer; // RSIの移動平均を格納する配列
int            RSIhandle;            // RSIのハンドル(配列管理番号)


void OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,RSIBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,RSI_SmoothedBuffer,INDICATOR_DATA);
   IndicatorSetString(INDICATOR_SHORTNAME,"iRSI");     // 文字を設定する時は、IndicatorSetString
   IndicatorSetInteger(INDICATOR_DIGITS,2);            // 整数を設定する時は、IndicatorSetInteger
//--- 
   RSIhandle=iRSI(NULL,0,RSIperiod,PRICE_CLOSE);       // MT5 にRSIを依頼...。
//---
  }

// OnCalculate は実は 2 種類あり、どちらを使ってもよい。
int OnCalculate(const int rates_total,
                const int prev_calculated,    // 
                const int begin,              // beginは、有効なデータが始まる位置を示す
                const double &price         // priceは、インジケータのプロパティで指定した価格になる
                )
  {

   ResetLastError(); // GetLastError()を使う前に必ず実行すること。

//---RSIのラインを引くために、RSIBuffer  にコピー
   int copied=CopyBuffer(RSIhandle,0,rates_total,0,RSIBuffer);

   if(copied<=0)
     {
      Print("Unable to copy the values of the indicator RSI. Error =",
            GetLastError(),",  copied =",copied);
      return(0);
     }
//--- RSI の移動平均を作成する。

// iMA の引数の最後に、配列のハンドルを渡すと、その配列の移動平均配列のハンドルが得られる。 
   int RSI_MA_handle=iMA(NULL,0,Smooth,0,meth,RSIhandle); 
// 移動平均配列のハンドルから、ライン描画の配列にデータをコピーする。
    copied=CopyBuffer(RSI_MA_handle,0,rates_total,0,RSI_SmoothedBuffer);
   if(copied<=0)
     {
      Print("Unable to copy the smoothed indicator of RSI. Error ",
            GetLastError(),",  copied =",copied);
      return(0);
     }

   return(rates_total); // 定型句です..。

  }

今日覚えておくべきポイントは…

関数名の違い

MQL4 MQL5
IndicatorDigits ( 2 ) IndicatorSetInteger ( INDICATOR_DIGITS , 2 )
IndicatorShortName ( "iRSI" ) IndicatorSetString ( INDICATOR_SHORTNAME , "iRSI" )

このような関数名の変更は、かなりあります。
MQL4 時代は、関数の総数が少なかったので、関数名に機能を含めた命名方法になっていましたが、MQL5 では、引数に何を指定するかという方式にかわっています。この辺りは地道にヘルプファイルを調べて移植するしかありません。

OnCalculate について

MQL5 では、引数の異なる同じ関数を定義できる(オーバーロードできる)という説明をしましたが、OnCalculate 自体もオーバーロードされていて、2種類用意されています。
MQL5超入門(10)の OnCalculate は、フルバージョンで、今回の OnCalculate は簡易バージョンといった感じです。
インジケータを作る際は、どちらを採用しても良いのですが、両方同時に使うことは出来ません..。
引数から渡される配列データを使うかどうかで使い分ければ良いと思います。

ResetLastError();

MQL4 では、エラーコード取得の GetLastError() は、エラー時に 1 度しか呼び出すことが出来ませんでした。
エラー発生後の一度目のGetLastError() では、正しいエラーコードが得られるのですが、1 度呼ぶと、内部のエラーコードがリセットされる為に、2 回続けて、GetLastError() を呼び出してしまうと、正しいエラーコードが得られなかったのです。
この仕様を知らない人も多いようで、フリーで出回っているEA にも正しくない使い方をしているものがみられます。


そこで、MQL5 では、2 回呼び出しても正しいエラーコードが得られる代わりに、自分でエラーコードのリセットをする仕様になりました。
それが、冒頭の ResetLastError(); で、エラーの起きる可能性のある関数を使うときは、直前に ResetLastError(); を呼ぶ必要があります。


iMAOnArray としての iMA

MQL4 では、任意のバッファ配列に対して移動平均を計算する為に、iMAOnArray を使用しました。
MQL5 では、 iXXXXOnArray という関数を無くして、大半のテクニカル指標関数 ( iXXXX ) に類似した機能を持たせました。
それが、コード中の iMA で、iMA の引数の最後に配列のハンドルを指定すると、その配列の移動平均を計算してくれます。


・・・とここまで説明して、ふと疑問に思ったのは、配列のハンドルが分からない配列 ( 例えば、自分で用意した動的配列や、バッファ配列RSI_SmoothedBuffer自体 )に対しては、iMA を適用できないのではないか?ということ..。
これはこれで不便な気がするのですが、詳細は、リリース後に調べたいと思っています。