ホーム » FX自動売買基礎と応用 » MT5版の経済指標情報を表示するツールを作成する【MQLプログラミングの基礎】

MT5版の経済指標情報を表示するツールを作成する【MQLプログラミングの基礎】

1.ファイルの新規作成

この記事では、MT5のサーバーから経済指標情報を取得し、チャート上へ表示するツールを作成します。

※この記事はMQL5の内容です。

取得する情報は、MetaQuotes社が公開している経済指標カレンダーの内容と同じです。

下記URLにて内容を確認できます。
https://www.mql5.com/ja/economic-calendar

MetaEditorの「新規作成」アイコンをクリックしてMQLウィザードを開始します。

MQLウィザード新規作成

「カスタムインディケータ」を選択して「次へ」をクリック。

一般プロパティ

ファイル名を「Economic_Indicator.mq5」とし、「次へ」をクリック。

イベントハンドラ

イベントハンドラは一番上のOnCalculateのみを選択して「次へ」をクリック。

描画プロパティ

「カスタムインディケータの描画プロパティ」では、特に何も追加せず「完了」をクリックすれば、ファイルのベースが作成されます。

今回のファイルでは、インディケーターバッファを利用しないので、「#property indicator_chart_window」の行の下へ、下記を追加します。


#property indicator_buffers 0
#property indicator_plots   0

2.経済指標カレンダーの情報を取得

今回のツールは頻繁に情報更新をする必要のないツールなので、1時間に1回のみ処理を実行するように、下記をOnCalculate関数内に追記します。


   datetime timeH1 = iTime(NULL, PERIOD_H1, 0);
   static datetime timePre;
   if (timeH1 == timePre) return 0;
   timePre = timeH1;

1時間足のローソク足が切り替わるタイミングでのみ処理が実行されるようになります。

取得する経済指標カレンダー情報の開始時間と終了時間を指定するために下記を追記します。


   datetime timeStart = TimeCurrent() - 3600 * 4; // 取得開始時間
   datetime timeEnd = TimeCurrent() + 3600 * 12;  // 取得終了時間

現在時間(TimeCurrent())の4時間前から12時間後までの情報を取得するように、開始時間と終了時間を定義しています。

経済指標カレンダー情報を格納するための構造体を配列として追記します。


   MqlCalendarValue values[];

MqlCalendarValueという構造体には、経済指標の時間やイベントのID等の各種情報が含まれています。

CalendarValueHistory関数を利用して情報を取得するために、下記を追記します。


   if (!CalendarValueHistory(values, timeStart, timeEnd, NULL)) { // 指定期間のイベント取得
       Print("Error! Failed to receive events. Code : ", GetLastError());
   }

上記にて、配列values[]に4時間前から12時間後までの情報が格納されます。

情報の取得に失敗した場合、ツールボックスのエキスパートタブにエラーメッセージが表示されます。

3.表示する情報の文字列を作成

CalendarCountries関数を利用して、国の情報を取得するために下記を追記します。


   MqlCalendarCountry countries[];
   int countCountries = CalendarCountries(countries); // 国情報取得

上記にて、countries[]配列内に国名・国コード・通貨名等の情報が格納されます。

文字情報を格納する配列を定義するため、下記を追記します。


   string text[];

取得した情報values[]から順に文字列を作成するため、下記のfor文を追記します。


   for (int i = 0; i < ArraySize(values); i++) {
      
   }

以降は、上記for文の中に追記していきます。

CalendarEventById関数を利用して経済指標イベント情報を取得するために、下記を追記します。


      MqlCalendarEvent event;
      if(!CalendarEventById(values[i].event_id, event)) continue; // イベント情報取得

上記にて、i番目のvalues[]配列のイベントIDの情報が、構造体eventに入力されます。

休日等の終日イベントを除外するため、下記を追記します。


      if (event.time_mode == CALENDAR_TIMEMODE_DATE) continue; // 終日イベントを除外

日本時間を定義するために、下記を追記します。


      datetime time = values[i].time + 3600 * 6;

values[]配列の時間情報に時差の6時間を足しています(夏時間の場合は7時間となります)。

文字列を格納する配列のサイズを1つ追加するために、下記を追記します。


      int n = ArraySize(text);
      ArrayResize(text, n + 1);

text[]配列に時間情報を入力するため、下記を追記します。


      text[n] += TimeToString(time, TIME_DATE | TIME_MINUTES) + " "; // 時間

指標の重要度情報を入力するため、下記を追記します。


      switch (event.importance) { // 重要度
      case 1 :
         text[n] += "[低] ";
         break;
      case 2 :
         text[n] += "[中] ";
         break;
      case 3 :
         text[n] += "[高] ";
         break;
      }

重要度の高さ(1~3)に合わせて、[低][中][高]の文字列を入力しています。

通貨ペア名と国名を表示するために、下記を追記します。


      for (int j = 0; j < ArraySize(countries); j++) {
         if (countries[j].id == event.country_id) {
            text[n] += countries[j].currency + " " + countries[j].name + " ";
            break;
         }
      }

イベント情報の国IDに合わせて、countries[]に格納されている該当する国の情報を入力しています。

最後に経済指標のイベント名を入力するために、下記を追記します。


      text[n] += event.name;

4.チャート上に情報を表示

ラベルオブジェクトを利用してチャート上へ経済指標情報を並べて表示します。

MetaEditorメニューの「ヘルプ」から「MQL5リファレンス」を開いて、「目次」タブを選択し、「標準的な定数、列挙と構造体」→「オブジェクト定数」→「オブジェクト型」にある「OBJ_LABEL」を選択してください。

ラベルオブジェクト関数

OBJ_LABEL内の「//| ラベルを作成する」以下にあるLabelCreate関数をコピーして、今回のプログラムの最下部へ貼り付けます。

――――― コピーして貼り付けするコード(ここから) ―――――


//+------------------------------------------------------------------+ 
//| ラベルを作成する                                                      | 
//+------------------------------------------------------------------+ 
bool LabelCreate(const long              chart_ID=0,               // チャート識別子 
                const string            name="Label",             // ラベル名 
                const int               sub_window=0,             // サブウィンドウ番号 
                const int               x=0,                     // X 座標 
                const int               y=0,                     // Y 座標 
                const ENUM_BASE_CORNER  corner=CORNER_LEFT_UPPER, // アンカーに使用されるチャートのコーナー 
                const string            text="Label",             // テキスト 
                const string            font="Arial",             // フォント 
                const int               font_size=10,             // フォントサイズ 
                const color             clr=clrRed,               // 色 
                const double            angle=0.0,               // テキストの傾斜 
                const ENUM_ANCHOR_POINT anchor=ANCHOR_LEFT_UPPER, // アンカーの種類 
                const bool              back=false,               // 背景で表示する 
                const bool              selection=false,         // 強調表示して移動 
                const bool              hidden=true,             // オブジェクトリストに隠す 
                const long              z_order=0)               // マウスクリックの優先順位 
 { 
//--- エラー値をリセットする 
  ResetLastError(); 
//--- ラベルを作成する 
  if(!ObjectCreate(chart_ID,name,OBJ_LABEL,sub_window,0,0)) 
    { 
    Print(__FUNCTION__, 
          ": failed to create text label! Error code = ",GetLastError()); 
    return(false); 
    } 
//--- ラベル座標を設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x); 
  ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y); 
//--- ポイント座標が相対的に定義されているチャートのコーナーを設定 
  ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner); 
//--- テキストを設定する 
  ObjectSetString(chart_ID,name,OBJPROP_TEXT,text); 
//--- テキストフォントを設定する 
  ObjectSetString(chart_ID,name,OBJPROP_FONT,font); 
//--- フォントサイズを設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size); 
//--- テキストの傾斜を設定する 
  ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle); 
//--- アンカーの種類を設定 
  ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor); 
//--- 色を設定 
  ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr); 
//--- 前景(false)または背景(true)に表示 
  ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back); 
//--- マウスでラベルを移動させるモードを有効(true)か無効(false)にする 
  ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection); 
  ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection); 
//--- オブジェクトリストのグラフィックオブジェクトを非表示(true)か表示(false)にする 
  ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden); 
//--- チャートのマウスクリックのイベントを受信するための優先順位を設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order); 
//--- 実行成功 
  return(true); 
 } 
//+------------------------------------------------------------------+

――――― コピーして貼り付けするコード(ここまで) ―――――

オブジェクトの名称の頭に共通の文字列を付けて管理するために、接頭辞を定義します。

ファイル上部のプロパティ「#property indicator_plots 0」の下に、下記を追記します。


#define PREFIX "Ec_Indi_"

インジケーターの削除や再読み込み時に、ラベルオブジェクトを一括消去するため、OnDeinit関数を追加します。

下記をOnInit関数の下などへ追加してください(他の関数の中でなければ、どこへ追加しても構いません)。


void OnDeinit(const int reason)
{
   ObjectsDeleteAll(0, PREFIX);
   Comment("");
}

文字列の描画前に、過去の表示を削除するため、文字列情報を取得したfor文の下に下記を追記します。


   ObjectsDeleteAll(0, PREFIX);

LabelCreate関数を利用して文字を表示するため、下記を追記します。


   int y = 20;
   for (int i = 0; i < ArraySize(text); i++) {
      LabelCreate(0, PREFIX + (string)i, 0, 5, y, CORNER_LEFT_UPPER, text[i], "メイリオ ボールド", 9, clrWhite);
      y += 15;
   }
   ChartRedraw();

チャートの左上基準で、X座標5、Y座標20の位置から、下へ15の間隔で、フォント「メイリオ ボールド」、サイズ「9」、色「White」の文字を描画しています。

上記までの状態でコンパイルしてチャートにセットすると、チャート上に経済指標情報が表示されていることを確認できます。

情報表示(初期)

5.表示内容を編集

重要度別に文字の色を変更する回路を追加します。

LabelCreate関数を利用して情報表示しているfor文を下記のように変更します。


   for (int i = 0; i < ArraySize(text); i++) {
      color clr = clrNONE;
      if (StringFind(text[i], "[低]") != -1) {
         clr = clrWhite;
      } else if (StringFind(text[i], "[中]") != -1) {
         clr = clrKhaki;
      } else if (StringFind(text[i], "[高]") != -1) {
         clr = clrOrange;
      }
      LabelCreate(0, PREFIX + (string)i, 0, 5, y, CORNER_LEFT_UPPER, text[i], "メイリオ ボールド", 9, clr);
      y += 15;
   }

情報表示(色分け)

重要度に合わせて、色(White、Khaki、Orange)が変化していることを確認できます。

重要度別に表示/非表示を指定する回路を追加します。

プログラム冒頭の「#define PREFIX "Ec_Indi_"」の下に下記を追記して、パラメーターを追加します。


input bool IMPORTANCE1 = false; // 重要度 [低]
input bool IMPORTANCE2 = true;  // 重要度 [中]
input bool IMPORTANCE3 = true;  // 重要度 [高]

LabelCreate関数を利用して情報表示しているfor文内で、色指定しているif文を下記のように変更します。


      if (StringFind(text[i], "[低]") != -1) {
         if (!IMPORTANCE1) continue;
         clr = clrWhite;
      } else if (StringFind(text[i], "[中]") != -1) {
         if (!IMPORTANCE2) continue;
         clr = clrKhaki;
      } else if (StringFind(text[i], "[高]") != -1) {
         if (!IMPORTANCE3) continue;
         clr = clrOrange;
      }

情報表示(重要度指定)

パラメーターでtrue指定した重要度の経済指標情報のみ表示されるようになります。

今回のツールは上記までで完成となります。

ご自身の表示したい内容に合わせて条件文を追加する等、自由にアレンジしていただければと思います。

6.ソースコード

今回、作成したソースコードは下記の通りです。


//+------------------------------------------------------------------+
//|                                           Economic_Indicator.mq5 |
//|                                  Copyright 2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots   0
#define PREFIX "Ec_Indi_"

input bool IMPORTANCE1 = false; // 重要度 [低]
input bool IMPORTANCE2 = true;  // 重要度 [中]
input bool IMPORTANCE3 = true;  // 重要度 [高]
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   
//---
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
{
   ObjectsDeleteAll(0, PREFIX);
   Comment("");
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int32_t rates_total,
                const int32_t 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 int32_t &spread[])
  {
//---
   datetime timeH1 = iTime(NULL, PERIOD_H1, 0);
   static datetime timePre;
   if (timeH1 == timePre) return 0;
   timePre = timeH1;
   
   datetime timeStart = TimeCurrent() - 3600 * 4; // 取得開始時間
   datetime timeEnd = TimeCurrent() + 3600 * 12;  // 取得終了時間
   
   MqlCalendarValue values[];
   if (!CalendarValueHistory(values, timeStart, timeEnd, NULL)) { // 指定期間のイベント取得
       Print("Error! Failed to receive events. Code : ", GetLastError());
   }
   
   MqlCalendarCountry countries[];
   int countCountries = CalendarCountries(countries); // 国情報取得
   
   string text[];
   for (int i = 0; i < ArraySize(values); i++) {
      MqlCalendarEvent event;
      if(!CalendarEventById(values[i].event_id, event)) continue; // イベント情報取得
      if (event.time_mode == CALENDAR_TIMEMODE_DATE) continue; // 終日イベントを除外
      datetime time = values[i].time + 3600 * 6; // 夏時間の場合の時差は7時間(3600 * 7)
      int n = ArraySize(text);
      ArrayResize(text, n + 1);
      text[n] += TimeToString(time, TIME_DATE | TIME_MINUTES) + " "; // 時間
      switch (event.importance) { // 重要度
      case 1 :
         text[n] += "[低] ";
         break;
      case 2 :
         text[n] += "[中] ";
         break;
      case 3 :
         text[n] += "[高] ";
         break;
      }
      for (int j = 0; j < ArraySize(countries); j++) {
         if (countries[j].id == event.country_id) {
            text[n] += countries[j].currency + " " + countries[j].name + " ";
            break;
         }
      }
      text[n] += event.name;
   }
   ObjectsDeleteAll(0, PREFIX);
   int y = 20;
   for (int i = 0; i < ArraySize(text); i++) {
      color clr = clrNONE;
      if (StringFind(text[i], "[低]") != -1) {
         if (!IMPORTANCE1) continue;
         clr = clrWhite;
      } else if (StringFind(text[i], "[中]") != -1) {
         if (!IMPORTANCE2) continue;
         clr = clrKhaki;
      } else if (StringFind(text[i], "[高]") != -1) {
         if (!IMPORTANCE3) continue;
         clr = clrOrange;
      }
      LabelCreate(0, PREFIX + (string)i, 0, 5, y, CORNER_LEFT_UPPER, text[i], "メイリオ ボールド", 9, clr);
      y += 15;
   }
   ChartRedraw();

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| ラベルを作成する                                                      | 
//+------------------------------------------------------------------+ 
bool LabelCreate(const long              chart_ID=0,               // チャート識別子 
                const string            name="Label",             // ラベル名 
                const int               sub_window=0,             // サブウィンドウ番号 
                const int               x=0,                     // X 座標 
                const int               y=0,                     // Y 座標 
                const ENUM_BASE_CORNER  corner=CORNER_LEFT_UPPER, // アンカーに使用されるチャートのコーナー 
                const string            text="Label",             // テキスト 
                const string            font="Arial",             // フォント 
                const int               font_size=10,             // フォントサイズ  
                const color             clr=clrRed,               // 色 
                const double            angle=0.0,               // テキストの傾斜  
                const ENUM_ANCHOR_POINT anchor=ANCHOR_LEFT_UPPER, // アンカーの種類 
                const bool              back=false,               // 背景で表示する 
                const bool              selection=false,         // 強調表示して移動 
                const bool              hidden=true,             // オブジェクトリストに隠す 
                const long              z_order=0)               // マウスクリックの優先順位 
 { 
//--- エラー値をリセットする 
  ResetLastError(); 
//--- ラベルを作成する 
  if(!ObjectCreate(chart_ID,name,OBJ_LABEL,sub_window,0,0)) 
     { 
     Print(__FUNCTION__, 
           ": failed to create text label! Error code = ",GetLastError()); 
     return(false); 
     } 
//--- ラベル座標を設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x); 
   ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y); 
//--- ポイント座標が相対的に定義されているチャートのコーナーを設定 
  ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner); 
//--- テキストを設定する 
  ObjectSetString(chart_ID,name,OBJPROP_TEXT,text); 
//--- テキストフォントを設定する 
  ObjectSetString(chart_ID,name,OBJPROP_FONT,font); 
//--- フォントサイズを設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size); 
//--- テキストの傾斜を設定する 
  ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle); 
//--- アンカーの種類を設定 
  ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor); 
//--- 色を設定 
  ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr); 
//--- 前景(false)または背景(true)に表示 
  ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back); 
//--- マウスでラベルを移動させるモードを有効(true)か無効(false)にする 
  ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection); 
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection); 
//--- オブジェクトリストのグラフィックオブジェクトを非表示(true)か表示(false)にする 
  ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden); 
//--- チャートのマウスクリックのイベントを受信するための優先順位を設定する 
  ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order); 
//--- 実行成功 
  return(true); 
  } 
//+------------------------------------------------------------------+

本記事の監修者・HT FX

2013年にFXを開始し、その後専業トレーダーへ。2014年からMT4/MT5のカスタムインジケーターの開発に取り組む。ブログでは100本を超えるインジケーターを無料公開。投資スタイルは自作の秒足インジケーターを利用したスキャルピング。

EA(自動売買)を学びたい方へオススメコンテンツ

EA運用の注意点

OANDAではEA(自動売買)を稼働するプラットフォームMT4/MT5の基本的な使い方について、画像や動画付きで詳しく解説しています。MT4/MT5のインストールからEAの設定方法までを詳しく解説しているので、初心者の方でもスムーズにEA運用を始めることが可能です。またOANDAの口座をお持ちであれば、独自開発したオリジナルインジケーターを無料で利用することもできます。EA運用をお考えであれば、ぜひ口座開設をご検討ください。


本ホームページに掲載されている事項は、投資判断の参考となる情報の提供を目的としたものであり、投資の勧誘を目的としたものではありません。投資方針、投資タイミング等は、ご自身の責任において判断してください。本サービスの情報に基づいて行った取引のいかなる損失についても、当社は一切の責を負いかねますのでご了承ください。また、当社は、当該情報の正確性および完全性を保証または約束するものでなく、今後、予告なしに内容を変更または廃止する場合があります。なお、当該情報の欠落・誤謬等につきましてもその責を負いかねますのでご了承ください。

この記事をシェアする