インジケーターを作る上で避けて通れないのがサマータイム。
取引でも、夏と冬で開始時間が1時間ずれるので生活リズムにも少し影響があったりしてちょっと面倒ですよね。
これまでは、「mql4 夏時間 冬時間」で検索すると結構出てくる以下のようなサイト
【MQL】サマータイムに対応した日本時間を出力する【EA】
https://note.com/ronta_trader/n/n49f55f0ea469
からコードをいただき、年が明けた時などに遠い未来の3月第2日曜日と11月第1日曜日をカレンダーで調べて追加したりしてました。2040年くらいまで。(この記事を書くまで2038年問題を知らず(笑))
上記ページの通り、これだけのためにしてはコードが長すぎるし、ここだけ力業っていうのもしっくりこない。なんとか計算式で自動化できないかなぁ・・・と探していたところ、ドンピシャな先人
10.3 ○月のN回目のW曜日は何日? – C/C++ 関数・マクロ集 ((ほぼ?) 処理系・OS 非依存)
http://www5d.biglobe.ne.jp/~noocyte/Programming/CMacros.html#NthDayOfWeekToDay
を見つけたので試してみたところ、使えそうなのが書けました。夏時間の開始日と終了日を割り出してサーバ時間を元に計算しているのでやっていることは同じです。
ど素人ですから冗長ですよ。変数の命名とかめちゃくちゃですし。でもこのくらいの長さになって、もう過去や未来を気にしなくて済むならありですよね。
2038年以降も動くといいですが、きっとその頃には MetaTrader は使われてないですね。
計算式(MQL4 / MQL5 両用)
//+------------------------------------------------------------------+ //| 日本時間へ変換(夏時間・冬時間) //| convertToJapanTime() //| とすれば現在のサーバ時間を日本時間で返す //| convertToJapanTime(Time[n]) //| などパラメータに指定時間を渡せば指定時間を日本時間に変換して返す //+------------------------------------------------------------------+ datetime convertToJapanTime(datetime day = 0) { MqlDateTime cjtm; // 時間構造体 day = day == 0 ? TimeCurrent() : day; // 対象サーバ時間 datetime time_summer = 21600; // 6時間 datetime time_winter = 25200; // 7時間 int target_dow = 0; // 日曜日 int start_st_n = 2; // 夏時間開始3月第2週 int end_st_n = 1; // 夏時間終了11月第1週 TimeToStruct(day, cjtm); // 構造体の変数に変換 string year = (string)cjtm.year; // 対象年 // 対象年の3月1日と11月1日の曜日 TimeToStruct(StringToTime(year + ".03.01"), cjtm); int fdo_mar = cjtm.day_of_week; TimeToStruct(StringToTime(year + ".11.01"), cjtm); int fdo_nov = cjtm.day_of_week; // 3月第2日曜日 int start_st_day = (target_dow < fdo_mar ? target_dow + 7 : target_dow) - fdo_mar + 7 * start_st_n - 6; // 11月第1日曜日 int end_st_day = (target_dow < fdo_nov ? target_dow + 7 : target_dow) - fdo_nov + 7 * end_st_n - 6; // 対象年の夏時間開始日と終了日を確定 datetime start_st = StringToTime(year + ".03." + (string)start_st_day); datetime end_st = StringToTime(year + ".11." + (string)end_st_day); // 日本時間を返す return day += start_st <= day && day <= end_st ? time_summer : time_winter; }
旧バージョン(MQL4 のみ)
//+------------------------------------------------------------------+ //| 日本時間へ変換(夏時間・冬時間) //| convertToJapanTime() //| とすれば現在のサーバ時間を日本時間で返す //| convertToJapanTime(Time[n]) //| などパラメータに指定時間を渡せば指定時間を日本時間に変換して返す //+------------------------------------------------------------------+ datetime convertToJapanTime(datetime day = 0) { day = day == 0 ? TimeCurrent() : day; // 対象サーバ時間 datetime time_summer = 21600; // 夏時間差6時間 datetime time_winter = 25200; // 冬時間差7時間 int start_st_n = 2; // 夏時間開始3月第2週 int end_st_n = 1; // 夏時間終了11月第1週 int target_dow = 0; // 日曜日 string year = (string)TimeYear(day); // 対象年 // 対象年の3月1日と11月1日の曜日 int fdo_mar = TimeDayOfWeek(StringToTime(year + ".03.01")); int fdo_nov = TimeDayOfWeek(StringToTime(year + ".11.01")); // 3月第2日曜日 int start_st_day = (target_dow < fdo_mar ? target_dow + 7 : target_dow) - fdo_mar + 7 * start_st_n - 6; // 11月第1日曜日 int end_st_day = (target_dow < fdo_nov ? target_dow + 7 : target_dow) - fdo_nov + 7 * end_st_n - 6; // 対象年の夏時間開始日と終了日を確定 datetime start_st = StringToTime(year + ".03." + (string)start_st_day); datetime end_st = StringToTime(year + ".11." + (string)end_st_day); // 日本時間を返す return day += start_st <= day && day <= end_st ? time_summer : time_winter; }