インジケーター作成10

自分を参照するマルチタイムフレームインジケーターをつくろう!

ここでは、単純移動平均線を描画するインジケーター【Sample_Indcator_03.mq4】をカスタマイズして、他の時間足での自分自身を参照して描画するマルチタイムフレームインジケーターにする方法を解説します。

インジケーター【Sample_Indcator_03.mq4】は、記事[インジケーター作成3【単純移動平均線】]で完成したインジケーターファイルです。

カスタマイズ前のコード

Dr.EADr.EA

インジケーター作成3【単純移動平均線】で完成したファイルのコードがこちら

#property strict
#property indicator_chart_window
#property indicator_buffers 1          // インジケーターバッファ 1つ
#property indicator_color1 clrRed      // 1つ目の色 赤色
#property indicator_width1 2           // 1つ目の太さ 2

extern int  SMA_Period  = 10;          // SMAの期間

double buf[];                          // ライン用の配列を宣言

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   SetIndexBuffer(0, buf);             // 配列 buf[]をインジケーター用に割り当てる
   SetIndexStyle(0, DRAW_LINE);        // 描画タイプをラインと定義
   
   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 i, j;
   int limit;
   if (prev_calculated == 0)              // 最初
      limit = rates_total - 1;               // 左端のローソク足から全部
   else                                   // それ以外
      limit = rates_total - prev_calculated; // ローソク足増加時「1」、通常「0」
   
   for (i=limit; i>=0; i--)               // limit本前から現在のローソク足を処理
   {
      if (i + SMA_Period - 1 <= Bars - 1)
      {
         buf[i] = 0; // buf[i]を0に初期化して
         for (j=0; j<SMA_Period; j++) buf[i] += Close[i+j]; // SMA_Period分の終値を足していき
         buf[i] /= SMA_Period; // SMA_Periodで割る
      }
   }
   
   return(rates_total);
}

【Sample_Indicator_03.mq4】をダウンロード

カスタマイズ方針

時間足指定のパラメーターを追加します。表示チャートの時間足を指定した場合は、通常の計算処理をします。
他の時間足を指定した場合は、iCustom()関数その指定時間足で自分自身が通常計算した値を取得するようにします。

自分自身のインジケーター名は、WindowExpertName()関数で取得します。

カスタマイズ内容

他の時間足を指定した場合は、前回の記事[インジケーター作成9【MTF(マルチタイムフレーム)機能】]と同じような記述になります。

パラメーターを追加する

マルチタイムフレーム機能付きにするために、次のように時間足を選択するパラメーターを追加します。

extern ENUM_TIMEFRAMES  Timeframe   = PERIOD_D1;

パラメーター設定を補正

パラメーターTimeframe表示チャートより短い周期を設定した場合は、OnInit()関数内でパラメーター変数Timeframeを表示チャートの時間足に補正します。

   if (Timeframe != PERIOD_CURRENT && Timeframe < Period()) Timeframe = PERIOD_CURRENT;

指定時間足によって分岐

パラメーターTimeframeで表示チャートの時間足を指定した場合に、OnCalculate()関数のfor文内でもともとの自分自身の計算処理をするようにします。

      if (Timeframe == 0 || Timeframe == Period()) // 表示チャートの時間足周期を指定した場合
      {
         if (i + SMA_Period - 1 <= Bars - 1)
         {
            // 中略
         }
      }

それ以外の場合には、前回記事でiClose()関数で値を取得したように、iCustom()関数で次のように値を取得します。


      else                                         // 表示チャートより大きい時間足を指定した場合
      {
         int bar_shift = iBarShift(NULL, Timeframe, Time[i]);  // シフト数iの指定時間足のシフト数
         
         // 指定時間足のシフト数の自分自身の値をbuf[i]に代入
         buf[i] = iCustom(NULL, Timeframe, WindowExpertName(), 0, SMA_Period, 0, bar_shift);
         
         if (i > 1) continue; // 表示開始時は以降スキップ
         
         // 経過途中をbuf[i]に揃える
         for (j=1; i+j<rates_total ;j++)
         {
            if (iBarShift(NULL, Timeframe, Time[i+j]) != bar_shift) break;
            buf[i+j] = buf[i];
         }
      }

iCustom()関数の時間足指定部分にパラメーターTimeframeを指定して、インジケーター名をWindowExpertName()とすることで、その時間足での自分自身の値を取得します。

Dr.EADr.EA

今回完成ファイルのコードがこちら

#property strict
#property indicator_chart_window
#property indicator_buffers 1          // インジケーターバッファ 1つ
#property indicator_color1 clrRed      // 1つ目の色 赤色
#property indicator_width1 2           // 1つ目の太さ 2

extern ENUM_TIMEFRAMES  Timeframe   = PERIOD_D1;
extern int  SMA_Period              = 10;          // SMAの期間

double buf[];                          // ライン用の配列を宣言

//+------------------------------------------------------------------+
int OnInit()
{
   // Timeframe 設定補正
   if (Timeframe != PERIOD_CURRENT && Timeframe < Period()) Timeframe = PERIOD_CURRENT;
   
   SetIndexBuffer(0, buf);             // 配列 buf[]をインジケーター用に割り当てる
   SetIndexStyle(0, DRAW_LINE);        // 描画タイプをラインと定義
   
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
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 i, j;
   int limit;
   if (prev_calculated == 0)              // 最初
      limit = rates_total - 1;               // 左端のローソク足から全部
   else                                   // それ以外
      limit = rates_total - prev_calculated; // ローソク足増加時「1」、通常「0」
   
   for (i=limit; i>=0; i--)               // limit本前から現在のローソク足を処理
   {
      if (Timeframe == 0 || Timeframe == Period()) // 表示チャートの時間足周期を指定した場合
      {
         if (i + SMA_Period - 1 <= Bars - 1)
         {
            buf[i] = 0; // buf[i]を0に初期化して
            for (j=0; j<SMA_Period; j++) buf[i] += Close[i+j]; // SMA_Period分の終値を足していき
            buf[i] /= SMA_Period; // SMA_Periodで割る
         }
      }
      else                                         // 表示チャートより大きい時間足を指定した場合
      {
         int bar_shift = iBarShift(NULL, Timeframe, Time[i]);  // シフト数iの指定時間足のシフト数
         
         // 指定時間足のシフト数の自分自身の値をbuf[i]に代入
         buf[i] = iCustom(NULL, Timeframe, WindowExpertName(), 0, SMA_Period, 0, bar_shift);
         
         if (i > 1) continue; // 表示開始時は以降スキップ
         
         // 経過途中をbuf[i]に揃える
         for (j=1; i+j<rates_total ;j++)
         {
            if (iBarShift(NULL, Timeframe, Time[i+j]) != bar_shift) break;
            buf[i+j] = buf[i];
         }
      }
   }
   return(rates_total);
}

今回完成ファイル【Sample_Indicator_10.mq4】をダウンロード

あとがき

この方法ならカスタムインジケーターのMTF化(マルチタイムフレーム化)も意外と簡単にできますね^^