MQL5

マルチタイムフレームRSI for MT5

本記事のテーマ

本記事ではMQL5で書かれたマルチタイムフレームRSIのコードの解説をしていきます。
仕組みを理解することで、RSIだけでなく、ほかのインジケータのマルチタイムフレーム対応版を作れるようになります。

ソースコード

#property copyright   "© shanch, 2020"
#property link        "shanch2@gmail.com"
#property description "MTFRSI"

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1

#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDodgerBlue
#property indicator_width1  1
#property indicator_style1  STYLE_SOLID

input ENUM_TIMEFRAMES  TimeFrame = PERIOD_H1;
input int Period = 14;
input ENUM_APPLIED_PRICE  AppliedPrice = PRICE_CLOSE;

int hRsi;
double BufRsi[];
double BufTemp[];

int OnInit()
{
   SetIndexBuffer(0, BufRsi, INDICATOR_DATA);
   ArraySetAsSeries(BufRsi, true);
   
   ArraySetAsSeries(BufTemp, true);
   
   IndicatorSetInteger(INDICATOR_LEVELS,3);
   IndicatorSetDouble(INDICATOR_LEVELVALUE,0,30);
   IndicatorSetDouble(INDICATOR_LEVELVALUE,1,50);
   IndicatorSetDouble(INDICATOR_LEVELVALUE,2,70);
   IndicatorSetDouble(INDICATOR_MINIMUM,0);
   IndicatorSetDouble(INDICATOR_MAXIMUM,100);
     
   hRsi = iRSI(NULL, TimeFrame, Period, AppliedPrice);

   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
    IndicatorRelease(hRsi);
}

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[])
  {
   ArraySetAsSeries(time,true);
   
   int limit = rates_total - prev_calculated;
   if(limit == 0) limit= 1;
   
   int shift = 0;

   for(int i=0; i<limit; i++)
   {
      shift=iBarShift(_Symbol,TimeFrame,time[i]);
      
      if(CopyBuffer(hRsi, 0, shift, 1, BufTemp) <= 0)
      {
         Print("Getting RSI failed! Error",GetLastError());
         return(0);
      }
      else
      {
          BufRsi[i]=BufTemp[0];
      }
   }

   for(int i=1; i<rates_total; i++)
   {
      if(iBarShift(NULL, TimeFrame, time[i]) > 0)
      {
         break;
      }
      BufRsi[i]=BufRsi[0];
   }

   return(rates_total);
}

初期化(22行目から39行目)

36行目のインジケータ作成時に上位足のTimeFrameを設定するのがポイント

OnCalculate前半(57行目から77行目)

ポイントは66行目で、iBarShiftを使って、現在の時間が上位足では何本目のバーかを取得し、変数shiftに代入する点です。
68行目では、shiftの値を使って、上位足のRSIを取得し、75行目でその値を現在のチャートに表示させています。

わかりにくいので、現在足が5分足で、上位足が1時間足として、具体的な数字でみてみましょう。
例えば、現在が14:15だとしたら次のようになります。

itime[i]shift
014:150
114:100
214:050
314:000
413:551
513:501
以下省略 以下省略 以下省略

OnCalculate後半(79行目から87行目)

OnCalclateの前半部分でほぼ出来上がっているのですが、このままだと1点問題があります。
最新の上位足のRSI値は確定していないので、下図の赤で囲った部分のようにギザギザになってしまいます。

time[i]shift上位足RSI
14:15060
14:10059
14:05061
14:00060
13:55162
13:50162
以下省略 以下省略

そこで、最新の上位足、すなわち、shift=0の時には最新のRSI値(下の表では60)で上書きする必要があります。それを行っているのが85行目になります。
shiftが1以上になったら値を変更する必要がないので、81行目でループを抜けています。

time[i]shift上位足RSI
14:15060
14:10059 60
14:05061 60
14:00060 60
13:55162
13:50162
以下省略 以下省略

完成

こちらが5分足チャートに1時間足MTFRSIを表示した様子です。

今回はRSIを使いましたが、同じ感じで他のインジケータもマルチタイムフレーム対応にできますので、皆さんも独自のマルチタイムフレームインジケータを作ってみてください!