【MQL5】CalendarValueById関数について

MQL5リファレンス
スポンサーリンク
スポンサーリンク

CalendarValueById関数の働き・役割

CalendarValueById関数は、特定の経済イベントの値をIDによって取得するために使用されます。

この関数は、イベントIDを指定し、そのイベントに関連するデータを受け取るためのMqlCalendarValue構造体に値を格納します。

経済指標カレンダーから取得したイベントデータを分析するために、CalendarValueById関数を利用することができます。

CalendarValueById関数の引数について

CalendarValueById関数には2つの引数があります。

書式

bool CalendarValueById(
  ulong                value_id,    // イベント値ID
  MqlCalendarValue&    value       // イベント値を受け取るための変数
);

第1引数
value_idはイベント値IDを指定します。ここで指定されたIDに基づいて、該当する経済イベントの情報を取得します。IDは符号なしの整数型で、特定のイベントを一意(1つしか存在しない)に識別するための番号です。

第2引数
valueはMqlCalendarValue構造体型の変数で、イベント値を受け取るために使用します。この引数には、取得したイベントの情報が格納されます。MqlCalendarValue構造体には、実際の値、予測値、以前の値など、経済指標の詳細情報が含まれています。この引数参照渡しによって指定され、関数の呼び出し後に、イベント情報が格納された状態で戻されます。

CalendarValueById関数の戻り値について

CalendarValueById関数は、処理の成功または失敗を示す真偽値を返します。

  • 戻り値がtrueの場合、指定したIDに基づいてイベントのデータが正常に取得され、MqlCalendarValue構造体に格納されています。
  • 戻り値がfalseの場合、データの取得に失敗しています。この場合、GetLastError関数を使用することで、失敗の原因を詳細に確認することが可能です。

可能なエラーコード

  • 4001 – ERR_INTERNAL_ERROR
    一般的なランタイムエラーです。関数が正常に実行されなかったことを示します。
  • 5402 – ERR_CALENDAR_NO_DATA
    指定した国コードやイベントが存在しない、またはデータが無効な場合に発生します。
  • 5401 – ERR_CALENDAR_TIMEOUT
    サーバーからの応答が一定の時間内に得られなかったため、タイムアウトが発生したことを示します。

CalendarValueById関数の実行結果を適切に確認し、必要に応じてGetLastError関数を利用することで、エラー発生時のトラブルシューティングが可能になります。

CalendarValueById関数を使う際の注意点

CalendarValueById関数では、取得したデータの時刻はユーザーの現地時間ではなく、取引サーバー時間で設定されます。
日本時間で実行した場合でも、サーバー時間を基準にしているため、データの時刻は異なる可能性がある点に注意してください。

取得した経済データには、実際の値が設定されていない場合、「-9223372036854775808」という数値が格納されます。
この数値が入っている場合、データが存在しないことを意味します。データを利用する前に、この値が入っていないかを必ず確認する必要があります。

CalendarValueById関数で取得したデータの数値は、実際の値より100万倍されて格納されています。たとえば、実際の値が「2.5」の場合、この関数で取得する値は「2500000」となります。そのため、取得した数値をそのまま利用する際には注意が必要です。実際の値として使用するには、取得した数値を「100万で除算」する必要があります。

CalendarValueById関数を使ったサンプルコード

//+------------------------------------------------------------------+
//| スクリプトプログラム開始関数                                     |
//+------------------------------------------------------------------+
void OnStart()
 {
  //--- 日本の国コード(ISO 3166-1 Alpha-2)を指定
  string japan_code = "JP";
  
  //--- イベントを取得する期間の境界を設定する
  // 2018年のすべてのイベントを取得するために、開始日を2018年1月1日に設定
  datetime date_from = D'01.01.2018';
  // 終了日を0に設定すると、すべての既知のイベント(今後のイベントも含む)を取得
  datetime date_to = 0;
  
  //--- 日本のイベント値の配列を作成し、取得する
  MqlCalendarValue values[];
  int values_count = CalendarValueHistory(values, date_from, date_to, japan_code);
  
  //--- 取得したイベントがあるかどうかを確認
  if (values_count > 0)
    {
    // 取得した日本のイベントの数を出力
    PrintFormat("Number of values for Japan events: %d", values_count);
    
    //--- 値が存在しないイベントを配列から削除する
    // 具体的には、actual_valueが-9223372036854775808のものを削除
    for(int i = values_count - 1; i >= 0; i--)
       {
        if(values[i].actual_value == -9223372036854775808)
          ArrayRemove(values, i, 1);  // 配列の該当する要素を削除
       }
    //--- 空の値を削除した後のイベント数を出力
    PrintFormat("Number of values after deleting empty ones: %d", ArraySize(values));
    }
  else
    {
    // イベントの取得に失敗した場合、エラーコードとともにメッセージを出力
    PrintFormat("Failed to receive events for the country code %s, error %d",
                 japan_code, GetLastError());
    // スクリプトの終了
    return;
    }
  
  //--- values配列の要素数が10より多い場合、10個に減らす
  if (ArraySize(values) > 10)
    {
    PrintFormat("Reduce the list of values to 10 and display them");
    // 最初の要素から、指定した数を削除して配列を10個の要素に絞る
    ArrayRemove(values, 0, ArraySize(values) - 10);
    }
  //--- 配列の内容を出力
  ArrayPrint(values);
  
  //--- 各イベントのIDに基づいて詳細なイベント値を取得する
  for (int i = 0; i < ArraySize(values); i++)
    {
    // 各イベントの詳細を格納するための変数を作成
    MqlCalendarValue value;
    
    // CalendarValueById関数でイベントIDに基づいて詳細な値を取得
    CalendarValueById(values[i].id, value);
    
    // 各イベントのID、実際の値、影響度の情報を出力
    PrintFormat("%d: value_id=%d value=%d impact=%s",
                 i, values[i].id, value.actual_value, EnumToString(ENUM_CALENDAR_EVENT_IMPACT(value.impact_type)));
    }
 }
//--- 実行結果の例:
// Number of values for Japan events: 1734
// Number of values after deleting empty ones: 1017
// Reduce the list of values to 10 and display them
// [id] [event_id]              [time]            [period] [revision] [actual_value] [prev_value] [revised_prev_value] [forecast_value] [impact_type] [reserved]
// [0] 56500  392030004 2019.03.28 23:30:00 2019.03.01 00:00:00          0         900000       600000 -9223372036854775808           500000             1          0
// [1] 56501  392030005 2019.03.28 23:30:00 2019.03.01 00:00:00          0         700000       700000 -9223372036854775808           700000             0          0
// [2] 56502  392030006 2019.03.28 23:30:00 2019.03.01 00:00:00          0        1100000      1100000 -9223372036854775808           900000             1          0
// [3] 56544  392030007 2019.03.28 23:30:00 2019.02.01 00:00:00          0        2300000      2500000 -9223372036854775808          2200000             2          0
// [4] 56556  392050002 2019.03.28 23:30:00 2019.02.01 00:00:00          0        1630000      1630000              1610000          1620000             1          0
// [5] 55887  392020003 2019.03.28 23:50:00 2019.02.01 00:00:00          0         400000       600000 -9223372036854775808          1300000             2          0
// [6] 55888  392020004 2019.03.28 23:50:00 2019.02.01 00:00:00          0       -1800000     -3300000 -9223372036854775808         -2000000             1          0
// [7] 55889  392020002 2019.03.28 23:50:00 2019.02.01 00:00:00          0         200000     -2300000             -1800000           300000             2          0
// [8] 55948  392020006 2019.03.28 23:50:00 2019.02.01 00:00:00          1        1400000     -3400000 -9223372036854775808          -300000             1          0
// [9] 55949  392020007 2019.03.28 23:50:00 2019.02.01 00:00:00          1       -1000000       300000 -9223372036854775808          -100000             2          0
// Display brief data on event values based on value_id
// 0: value_id=56500 value=900000 impact=CALENDAR_IMPACT_POSITIVE
// 1: value_id=56501 value=700000 impact=CALENDAR_IMPACT_NA
// 2: value_id=56502 value=1100000 impact=CALENDAR_IMPACT_POSITIVE
// 3: value_id=56544 value=2300000 impact=CALENDAR_IMPACT_NEGATIVE
// 4: value_id=56556 value=1630000 impact=CALENDAR_IMPACT_POSITIVE
// 5: value_id=55887 value=400000 impact=CALENDAR_IMPACT_NEGATIVE
// 6: value_id=55888 value=-1800000 impact=CALENDAR_IMPACT_POSITIVE
// 7: value_id=55889 value=200000 impact=CALENDAR_IMPACT_NEGATIVE
// 8: value_id=55948 value=1400000 impact=CALENDAR_IMPACT_POSITIVE
// 9: value_id=55949 value=-1000000 impact=CALENDAR_IMPACT_NEGATIVE

このコードは、指定した期間内の日本の経済イベントを取得し、そのイベントデータを処理・表示するものです。

まず、2018年以降のすべての日本のイベントを取得し、空のデータを削除します。次に、最大10件までのイベント情報に絞り込んで一覧を表示します。その後、各イベントのIDに基づいて詳細な値(たとえば、実際の値や影響度)を取得し、結果をエキスパートログに出力します。このようにして、指定されたイベントに関する詳細情報を簡潔に確認できるようになっています。

サンプルコード解説1

//+------------------------------------------------------------------+
//| スクリプトプログラム開始関数                                     |
//+------------------------------------------------------------------+
void OnStart()
 {
  //--- 日本の国コード(ISO 3166-1 Alpha-2)を指定
  string japan_code = "JP";
  
  //--- イベントを取得する期間の境界を設定する
  // 2018年のすべてのイベントを取得するために、開始日を2018年1月1日に設定
  datetime date_from = D'01.01.2018';
  // 終了日を0に設定すると、すべての既知のイベント(今後のイベントも含む)を取得
  datetime date_to = 0;

このコードの冒頭では、日本の経済イベントを取得するための初期設定が行われています。まず、日本の国コード「JP」を指定し、ISO3166-1 Alpha-2形式で記述します。これは、経済イベントが日本のものであることを特定するために用いられます。

次に、取得するイベントの期間を定義しています。date_fromには開始日として「2018年1月1日」を指定しており、これ以降のイベントを対象としています。一方、date_toには0を指定しています。この0の指定は、すべての既知のイベント、つまり過去のデータに加え、将来発表される予定のイベントも含めて取得することを意味します。

サンプルコード解説2

  //--- 日本のイベント値の配列を作成し、取得する
  MqlCalendarValue values[];
  int values_count = CalendarValueHistory(values, date_from, date_to, japan_code);

この部分のコードでは、日本の経済イベントデータを取得するために、MqlCalendarValue構造体型の配列valuesを作成しています。この配列は、指定された期間内のイベントデータを格納するためのものです。

CalendarValueHistory関数を用いて、指定した期間内の日本の経済イベント情報をvalues配列に取得しています。
CalendarValueHistory関数には、values配列、開始日と終了日、国コードの4つの引数が渡されています。取得したイベントデータの数は、関数戻り値として返され、values_countに格納されます。

サンプルコード解説3

//--- 取得したイベントがあるかどうかを確認
  if (values_count > 0)
    {
    // 取得した日本のイベントの数を出力
    PrintFormat("Number of values for Japan events: %d", values_count);
    
    //--- 値が存在しないイベントを配列から削除する
    // 具体的には、actual_valueが-9223372036854775808のものを削除
    for(int i = values_count - 1; i >= 0; i--)
       {
        if(values[i].actual_value == -9223372036854775808)
          ArrayRemove(values, i, 1);  // 配列の該当する要素を削除
       }
    //--- 空の値を削除した後のイベント数を出力
    PrintFormat("Number of values after deleting empty ones: %d", ArraySize(values));
    }

このコードの部分では、日本の経済イベントのデータを取得し、特定の条件に合ったデータのみを残して整理する処理が行われています。

取得したイベントがあるかどうかの確認

まず、取得したイベントの数を示す変数values_countが0より大きいかどうかをif文で確認しています。if文は、指定した条件が正しい場合のみ処理を行う構文で、ここでは「取得したイベントが1件以上あるかどうか」を確認しています。

ここでは、values_countが0以上なら、取得したイベントがあると判断して次の処理を行います。もしもvalues_countが0であれば、取得したイベントがないことを意味します。

イベントの数をエキスパートログに出力

PrintFormat関数を使って、取得したイベントの数をエキスパートログに出力しています。エキスパートログとは、出力内容を確認できる画面です。

PrintFormat関数は、文字列変数の値を組み合わせて表示するための関数です。”%d”はフォーマット指定子で、「整数」を挿入する場所を示しています。ここではvalues_countがその整数値として表示されます。

空のイベント値を削除するためのforループ

次に、イベントの配列valuesから、値が入っていないデータを削除します。ここでは、forループを使用して配列の各要素を確認します。

forループは、指定した回数だけ繰り返し処理を行う構文です。iはインデックス(通し番号)として使われており、values_count – 1から0まで1ずつ減少させながら繰り返します。これにより、配列の末尾から先頭に向かって処理を行います。

actual_valueが空であるデータの削除

イベントデータの中で、actual_valueというフィールド(個々のメンバ変数)が特定の値になっているかを確認し、該当するものを削除します。actual_valueは経済イベントの「実際の値」を示すフィールドです。

MqlCalendarValue構造体では、データが存在しない場合、actual_valueには特殊な値「-9223372036854775808」が格納されます。これを確認するため、if文を使ってactual_valueがその値に等しいかどうかを確認しています。

もしもactual_valueがこの値であれば、データが存在しないと判断し、ArrayRemove関数を使って配列valuesから削除します。

ArrayRemove関数は、指定したインデックス位置にある要素を削除するための関数です。ここでは、i番目の要素を1つ削除し、配列内のデータを整理しています。

削除後のイベント数をエキスパートログに出力

空のデータをすべて削除した後、再度PrintFormat関数を使って、削除後のイベント数をエキスパートログに表示します。

ここでは、ArraySize関数を使って配列要素数を取得し、削除後のイベント数を表示しています。このようにして、不要なデータを削除し、必要なイベントデータのみが配列に残るように整理しています。

サンプルコード解説4

else
    {
    // イベントの取得に失敗した場合、エラーコードとともにメッセージを出力
    PrintFormat("Failed to receive events for the country code %s, error %d",
                 japan_code, GetLastError());
    // スクリプトの終了
    return;
    }

この部分のコードでは、イベントの取得が成功しなかった場合に、エラー情報を表示する処理が行われています。else文を使って、前の条件(イベント取得成功)が成り立たなかった場合にのみ、この処理が実行されます。

まず、PrintFormat関数を用いて、エラーコードと共にエラーメッセージをエキスパートログに出力します。ここで使用されるフォーマット指定子%sは文字列(国コード)を、%dは整数(エラーコード)を表示するためのものです。具体的には、japan_codeには国コード「JP」が含まれており、GetLastError関数は直近に発生したエラーコードを取得します。

次に、return文によってスクリプトの実行を中断しています。returnは、関数の処理を終了させ、呼び出し元に制御を戻すための記述です。この場合、エラーが発生した場合に、処理を続けるのではなく、ここでスクリプトを終了する意図で使われています。

サンプルコード解説5

 //--- values配列の要素数が10より多い場合、10個に減らす
  if (ArraySize(values) > 10)
    {
    PrintFormat("Reduce the list of values to 10 and display them");
    // 最初の要素から、指定した数を削除して配列を10個の要素に絞る
    ArrayRemove(values, 0, ArraySize(values) - 10);
    }
  //--- 配列の内容を出力
  ArrayPrint(values);

この部分のコードでは、取得した日本の経済イベントの数が多すぎる場合に、配列要素数を10個に制限する処理が行われています。

まず、ArraySize関数を使って、配列valuesに含まれる要素の数が10より大きいかどうかを確認しています。この関数は、配列内の現在の要素数を返します。

もし要素数が10を超える場合、PrintFormat関数を使って、配列要素数を10個に減らす旨をエキスパートログに表示します。

次に、ArrayRemove関数を使って、配列の最初から指定した数の要素を削除することで、配列要素数を10個に絞ります。この場合、ArraySize関数で取得した現在の要素数から10を引いた数だけ削除することで、配列に10個の要素だけが残るようにしています。

最後に、ArrayPrint関数を使用して、配列valuesに残った10件のイベント情報をエキスパートログに出力します。ArrayPrint関数は、配列の内容を一度に表示するために使われる関数です。

サンプルコード解説6

  //--- 各イベントのIDに基づいて詳細なイベント値を取得する
  for (int i = 0; i < ArraySize(values); i++)
    {
    // 各イベントの詳細を格納するための変数を作成
    MqlCalendarValue value;
    
    // CalendarValueById関数でイベントIDに基づいて詳細な値を取得
    CalendarValueById(values[i].id, value);
    
    // 各イベントのID、実際の値、影響度の情報を出力
    PrintFormat("%d: value_id=%d value=%d impact=%s",
                 i, values[i].id, value.actual_value, 
                 EnumToString(ENUM_CALENDAR_EVENT_IMPACT(value.impact_type)));
    }
 }

このコードでは、values配列に残っている各イベントについて、そのIDを使って詳細なイベント情報を取得し、エキスパートログに出力しています。

まず、forループを使用して、values配列の全要素に順番にアクセスします。ArraySize関数を用いて、配列要素数だけ繰り返し処理を行う設定にしています。

ループ内で、各イベントの詳細を格納するためのMqlCalendarValue構造体型の変数valueを作成します。この変数は、イベントごとの詳細情報を一時的に保持するためのものです。

次に、CalendarValueById関数を用いて、values配列内のイベントIDを使い、該当するイベントの詳細情報をvalueに格納します。CalendarValueById関数は、指定されたIDに基づいてイベントの詳細を取得する関数です。

最後に、PrintFormat関数を使って、エキスパートログにイベントの詳細情報を出力します。出力内容として、各イベントのインデックス(通し番号)、イベントID、実際の値、影響度の情報が含まれています。
ここで使用されているフォーマット指定子は、整数を示す%dや文字列を示す%sなどです。なお、影響度の情報はENUM_CALENDAR_EVENT_IMPACTという列挙型を使い、EnumToString関数文字列として出力しています。これにより、影響度が数値ではなく、わかりやすい文字列として表示されます。

CalendarValueById関数を使ってEAを作る際のアイディア

CalendarValueById関数は、特定の経済イベントの詳細データを取得できるため、経済指標発表のデータを利用したEAエキスパートアドバイザー)を作成する際に活用できます。以下に、EAのアイディアをいくつか紹介します。

経済指標によるトレンドフォロー型EA

経済指標発表直後に価格が大きく動く傾向を利用し、発表の「実際の値」と「予測値」を比較してトレードを行うEAです。たとえば、実際の値が予測値を上回った場合には買いポジション、下回った場合には売りポジションを立てるように設定します。これにより、重要な経済指標の影響を利用したトレンドフォローが可能です。

通貨ペアの影響度に応じたポジションサイズ調整EA

影響度(impact_type)を活用して、発表の影響が高い場合にはポジションサイズを大きく、影響が低い場合にはポジションサイズを小さくするEAです。
たとえば、影響度が高いとされる経済イベントに対してはリスクを上げ、影響が少ない場合は控えめな取引を行うようにしてリスクを調整することができます。

イベントタイミングに合わせた自動取引停止機能

取引のタイミングで重要な経済イベントが予定されている場合に、取引を一時停止させるEAです。経済イベント発表前後の相場は予測が難しいため、特定の影響度を持つイベントが迫っている場合には、事前にすべてのポジションをクローズし、新しい取引を停止することでリスク回避が可能です。

イベント発表後のボラティリティ追従型EA

発表後のボラティリティ(価格の変動幅)を利用し、短期的な価格変動を狙ったEAを作成します。たとえば、発表直後に値が急変動した場合にエントリーを行い、短時間で利益を確保する「スキャルピング戦略」を採用します。この際、一定の変動幅を超えた場合のみ取引を開始し、イベントによる影響が収束したと判断したらポジションを即座にクローズすることでリスクを抑えます。

経済イベントの予測データに基づいたポートフォリオ調整EA

発表される予測値(forecast_value)に基づき、経済イベントの影響が大きいと予想される通貨ペアを強化したり、逆に影響が小さいと判断される通貨ペアを縮小するポートフォリオ調整EAです。
特定の通貨ペアに対する予測データが良好であれば買いポジションを増やし、予測が悪ければ売りポジションを増やすなど、リスクヘッジの観点でポートフォリオを最適化できます。

これらのアイディアを基に、CalendarValueById関数を活用したEAを構築することで、経済イベントの影響を取り入れた取引戦略を実現できます。

タイトルとURLをコピーしました