【初心者向けEA入門】MQL4で日本の祝日を判定~カレンダー情報手入力の力技で何とかする~

EAで祝日を判定しようと思ったが予想通りそんな機能はない。祝日を計算するプログラムを見つけたが複雑で使いづらい。しかも祝日のルールはころころ変わるので完全な自動化はできない。いっそのことカレンダー情報を手入力した方が早いと思いテストプログラムを実装した。この程度であれば半日で30年分くらい対応できそう。

注意事項

本記事はFXの自動売買に使用されるプログラムについて解説していますが内容を保証するものではありません。金銭にかかわる内容であるためご注意ください。参考にする場合は自己責任でお願いします。

留意事項

本記事ではMT4を使用する。

実行環境

FXDD – MetaTrader
・Version: 4.00 build 1322
・8Feb 2021

MetaEditor
・Version 5.00 build 2375
・7 Jan 2021

サンプルコードの概要

土日以外の祝日情報を配列にリテラルで記入し判定。難しいことはせずに登録した日付と一致するかだけで判定している。ただしMT4時間と日本時間にズレがあるので正確に求めるには日本時間に補正する必要がある。日本時間の補正についてはこちら。

【初心者向けEA入門】日本時間を取得する関数~サマータイムを考慮して日本時間でのエントリを可能にする~

コード解説

各年ごとに構造体を作り土日以外の祝日を管理している。

(1) 土日以外の祝日を判定

入力データの時点で土日に重なった祝日は無視している。2019~2021年までの祝日データを登録してある。何となく雰囲気で増やせると思う。

example-holiday.mqh

//+------------------------------------------------------------------+
//|                                       example-public-holiday.mqh |
//|                                   Copyright 2021, zerokara-blog. |
//|                                       https://zerokara-blog.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, zerokara-blog."
#property link      "https://zerokara-blog.com/"
#property strict

// 祝日構造体
struct holiday
{
    int year;     // 年
    int month;    // 月
    int day;      // 日
};

holiday year2021[15] =
{
    {2021,  1,  1},
    {2021,  1, 11},
    {2021,  2, 11},
    {2021,  2, 23},
    {2021,  4, 29},
    {2021,  5,  3},
    {2021,  5,  4},
    {2021,  5,  5},
    {2021,  7, 22},
    {2021,  7, 23},
    {2021,  8,  9},
    {2021,  9, 20},
    {2021,  9, 23},
    {2021, 11,  3},
    {2021, 11, 23}
};

holiday year2020[16] =
{
    {2020,  1,  1},
    {2020,  1, 13},
    {2020,  2, 11},
    {2020,  2, 24},
    {2020,  3, 20},
    {2020,  4, 29},
    {2020,  5,  4},
    {2020,  5,  5},
    {2020,  5,  6},
    {2020,  7, 23},
    {2020,  7, 24},
    {2020,  8, 10},
    {2020,  9, 21},
    {2020,  9, 22},
    {2020, 11,  3},
    {2020, 11, 23}
};

holiday year2019[17] =
{
    {2019,  1,  1},
    {2019,  1, 14},
    {2019,  2, 11},
    {2019,  3, 21},
    {2019,  4, 29},
    {2019,  4, 30},
    {2019,  5,  1},
    {2019,  5,  2},
    {2019,  5,  3},
    {2019,  5,  6},
    {2019,  7, 15},
    {2019,  8, 12},
    {2019,  9, 16},
    {2019,  9, 23},
    {2019, 10, 14},
    {2019, 10, 22},
    {2019, 11,  4}
};

// 祝日か判定する
bool isPublicHoliday(datetime inputDay)
{
    int year = TimeYear(inputDay);
    
    switch(year)
    {
        case 2021: return isPublicHoliday(inputDay, year2021);
        case 2020: return isPublicHoliday(inputDay, year2020);
        case 2019: return isPublicHoliday(inputDay, year2019);
    }
    return false;
}

// 祝日か判定する
bool isPublicHoliday(datetime inputDay, holiday &inputHoliday[])
{
    int listSize = ArraySize(inputHoliday);

    for(int i = 0; i < listSize; i++ )
    {
        // 祝日に一致するか確認
        if(TimeMonth(inputDay) == inputHoliday[i].month && TimeDay(inputDay) == inputHoliday[i].day)
        {
            return true;
        }
    }
    
    // 祝日に該当しない
    return false;
}

 

(2) 呼び出し処理

先ほどの関数を呼び出しテストデータを入力。

example-holiday.mq4

//+------------------------------------------------------------------+
//|                                              example-holiday.mq4 |
//|                                   Copyright 2021, zerokara-blog. |
//|                                       https://zerokara-blog.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, zerokara-blog."
#property link      "https://zerokara-blog.com/"
#property version   "1.00"
#property strict

#include <example-holiday.mqh>

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
    checkHoliday("2019.01.11 00:00");
    checkHoliday("2019.01.14 00:00");
    checkHoliday("2020.07.23 00:00");
    checkHoliday("2020.07.24 00:00");
    checkHoliday("2020.07.25 00:00");
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   
  }
//+------------------------------------------------------------------+

// 祝日判定のテスト
void checkHoliday(string strTime)
{
    datetime time = StringToTime(strTime);

    string msg;
    if(isPublicHoliday(time))
    {
        msg = "祝日です。";
    }
    else
    {
        msg = "祝日ではありません。";
    }
    Print(strTime,"は、", msg);
}

 

(3) 実行結果の確認

5パターンテスト。7月の23日は「海の日」、24日は「スポーツの日」が祝日。1月14日は「成人の日」。さすがにベタ打ちなので問題なく判定されている。

まとめ

懸案だった祝日判定は2時間ほどで実装と動作確認までできた。あと2時間あれば20年分の情報も入力できそう。そもそも過去データがそんなにないのでそこまでする必要はないか。

ポイント
  • 祝日はコロコロ変わるのでロジック実装が困難
  • 祝日ベタ打ちでも20年くらいならなんとかなる
  • ロジックより信頼性が高い(ハズ?)

時には力技が有効な場合もあります。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です