自分でカスタムインジケーターやEAを作る際、複数の時間足のデータを1つの時間足のチャート上に表示したいことがよくあります。これをMTF(マルチタイムフレーム)と呼びます。

MTFを作るのは難しいと感じたりしますが、実は簡単に作れます。ただし、ネットでよく紹介されるテンプレートコードには、変数名が途中で入れ替わっていてそのままではコンパイルが通らないものが少なくありません。この記事では、MTFの基本テンプレートと、実際にコンパイルして表示確認できる完成形のコードの両方を紹介します。

MTF(マルチタイムフレーム)のテンプレート

自分でカスタムインジケーターやEAそして制作する際に

MTF(マルチタイムフレーム)で作成する場合が多いと思います。

MTF(マルチタイムフレーム)を作るのは難しいと感じたりしますが、実は簡単に作れます。

今回は、MTF(マルチタイムフレーム)のテンプレートを紹介します。

パラメーター

まず、inputでenumを活用したタイムフレームを作りましょう。

enumについては以下の記事を参照してください。

【MQL言語入門】定数をひとつにまとめることができる「Enum(列挙型)」についてわかりやすく説明してみた

ENUM_TIMEFRAMESは以下の表に従い取得したい時間軸を指定します。

ID 詳細
PERIOD_CURRENT 0 現在チャートの時間軸
PERIOD_M1 1 1分
PERIOD_M5 5 5分
PERIOD_M15 15 15分
PERIOD_M30 30 30分
PERIOD_H1 60 1時間
PERIOD_H4 240 4時間
PERIOD_D1 1440 1日
PERIOD_W1 10080 1週間
PERIOD_MN1 43200 1ヶ月

変数の型はENUM_TIMEFRAMESという事前定義済みのENUM列挙型を使用しています。

初期値はPERIOD_CURRENT(現在のチャートの時間軸)を設定します。

ちなみにこのENUM列挙型というのは、整数(int)型の定数リストです。

この定数リストの値は全て重複していないユニーク値になります。

input ENUM_TIMEFRAMES timeFrame = PERIOD_CURRENT;//MTF

MTFで表示する移動平均線の期間も、input変数として用意しておきます。これを次のOnCalculate()の中で使います。

input int maPeriod = 20;//MTFの移動平均線の期間

OnCalculate()

iBarShiftは指定したオープン時間のバーシフト数を返します。

iBarShift(通貨ペア名, 時間足, 時間, 戻り値モード)
  • 通貨ペア:通貨ペアを文字列で指定
  • 時間足:時間足を整数または定数で指定
  • 時間:datetime型の時間を指定
  • 戻り値モード:false or true

具体的には以下のように記述しましょう。

int shift = iBarShift(NULL, timeFrame, time[i]);//シフト数iの指定時間足のシフト数

そして必要なテクニカル指標関数のshiftに入れるだけです。

double mtfMa = iMA(NULL, timeFrame, maPeriod, 0, MODE_SMA, PRICE_CLOSE, shift);//MTFのMA

とても簡単にできます。具体的には以下のような形で記述していきます。

int limit = rates_total-maPeriod-1;
for(int i=limit; i>=1; i--)
{
  int shift = iBarShift(NULL, timeFrame, time[i]);//シフト数iの指定時間足のシフト数
  double mtfMa = iMA(NULL, timeFrame, maPeriod, 0, MODE_SMA, PRICE_CLOSE, shift);//MTFのMA
}

変数名を統一する

上のサンプルでは移動平均線の期間を表す変数名を、limitの計算部分では「maPeriod」、iMA関数を呼び出す部分でも同じ「maPeriod」に統一しています。

元のテンプレートでは、この2箇所で「maPeriod」と「ma_period」という2つの異なる名前が混在しているケースがよく見られます。MQLでは、宣言されていない名前の変数を使うと「’ma_period’ – undeclared identifier」というエラーでコンパイルが止まってしまいます。

コピペしてそのまま使う場合は、まず記事の最初で宣言したinput変数名(この記事では`maPeriod`)と、後続のコードで使っている変数名が一字一句一致しているかを必ず確認してください。

実際に動くインジケーターとして完成させる

ここまでのOnCalculate()の中身は、あくまでMTFの考え方を示す抜粋です。実際にMetaEditorでコンパイルしてチャートに表示するには、インジケーター全体の型(#property・バッファ宣言・OnInit)が必要です。

MTFで取得した移動平均線をチャート上にラインとして表示する、最小限の完成版を以下に示します。

//+------------------------------------------------------------------+
//|                                                  MTF_Template.mq4 |
//|                     Copyright 2021, FX-EA System Project Creator |
//|                        https://creator.fx-ea-system-project.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, FX-EA System Project Creator"
#property link      "https://creator.fx-ea-system-project.com/"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 clrRed
#property indicator_width1 2

input ENUM_TIMEFRAMES timeFrame = PERIOD_CURRENT;//MTF
input int maPeriod = 20;//MTFの移動平均線の期間

double MtfMaBuffer[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0, MtfMaBuffer);
   SetIndexStyle(0, DRAW_LINE);
   SetIndexLabel(0, "MTF MA(" + IntegerToString(maPeriod) + ")");
   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 limit = rates_total - maPeriod - 1;
   if(prev_calculated > 0)
      limit = rates_total - prev_calculated;

   for(int i = limit; i >= 0; i--)
     {
      int shift = iBarShift(NULL, timeFrame, time[i]);//シフト数iの指定時間足のシフト数
      MtfMaBuffer[i] = iMA(NULL, timeFrame, maPeriod, 0, MODE_SMA, PRICE_CLOSE, shift);//MTFのMA
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+
Copy

このコードでは、`prev_calculated`(前回計算済みのバー数)を利用して、初回はチャート全体、2回目以降は新しく増えた分のバーだけを再計算するようにしています。この最適化を省いて毎回全バーを計算しても動作しますが、長期チャートでは表示が重くなります。

保存後は「コンパイル」(Ctrl+F7)で「0 error(s), 0 warning(s)」になることを確認し、チャートにドラッグ&ドロップして、`timeFrame`に上位足(例:PERIOD_H4)を指定した状態で赤いラインが表示されるか確認してください。

まとめ

今回はMTF(マルチタイムフレーム)のテンプレートをご紹介しました。

こうしたテクニックをいくつか引き出しと持っておくだけで、開発の幅が広がります。

ぜひマスターしておくようにしましょう。

関連記事