EAで祝日を判定しようと思ったが予想通りそんな機能はない。祝日を計算するプログラムを見つけたが複雑で使いづらい。しかも祝日のルールはころころ変わるので完全な自動化はできない。いっそのことカレンダー情報を手入力した方が早いと思いテストプログラムを実装した。この程度であれば半日で30年分くらい対応できそう。
本記事はFXの自動売買に使用されるプログラムについて解説していますが内容を保証するものではありません。金銭にかかわる内容であるためご注意ください。参考にする場合は自己責任でお願いします。
本記事ではMT4を使用する。
FXDD – MetaTrader
・Version: 4.00 build 1322
・8Feb 2021
MetaEditor
・Version 5.00 build 2375
・7 Jan 2021
サンプルコードの概要
土日以外の祝日情報を配列にリテラルで記入し判定。難しいことはせずに登録した日付と一致するかだけで判定している。ただしMT4時間と日本時間にズレがあるので正確に求めるには日本時間に補正する必要がある。日本時間の補正についてはこちら。
【EA開発ガイド】Part 4 MQL4開発応用 – Chapter 3 サマータイムを考慮して日本時間を取得する
コード解説
各年ごとに構造体を作り土日以外の祝日を管理している。
(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年くらいならなんとかなる
- ロジックより信頼性が高い(ハズ?)
時には力技が有効な場合もあります。