MT4の時間を日本時間に変換する方法と時間ずれの解消手順

※当サイトはアフィリエイト広告(Amazonアソシエイツ等)を利用しています。

こんにちは。trade-engineer.com 運営者のHです。

EAの時間フィルターを実装しているときに、TimeCurrent()の返り値をそのまま「日本時間」として扱ってロンドン時間の判定に失敗したことがある。MT4のTimeCurrent()が返すのはブローカーのサーバー時間であり、多くのブローカーはGMT+2(冬時間)またはGMT+3(夏時間)に設定している。日本時間(JST=GMT+9)との差は夏時間期間中で6時間、冬時間期間中で7時間になる。この記事では、MT4の時間ずれの仕組みをGMTベースで整理し、MQL4でJSTに変換する実装コードまで解説する。

記事のポイント
  • MT4サーバー時間がGMT+2/3になっている理由と日本時間との時差計算
  • XMなど主要ブローカーのGMTオフセット一覧と夏冬時間の切り替えタイミング
  • ServerToJST()のMQL4実装コード(TimeGMT()ベースとTimeCurrent()ベースの2通り)
  • EAの時間フィルターをJSTで実装する方法と日またぎ条件の処理
目次

MT4の時間ずれの仕組みとGMTタイムゾーン

MT4のサーバー時間がなぜ日本時間と異なるのか。時間関数ごとの返り値の違いを整理しておくと、コード実装でのミスが減る。

MT4の時間が日本時間とずれる技術的な理由

MT4開発元のMetaQuotes Softwareはキプロスに本社を置き、MT4の標準サーバー設定はEET(Eastern European Time=冬時間GMT+2、夏時間GMT+3)に基づいている。日本標準時(JST)は通年でGMT+9のため、MT4サーバーとの差分は夏時間中に6時間、冬時間中に7時間となる。

MT4には時間を取得する関数が3種類ある。TimeCurrent()はブローカーのサーバー時間を返す。この値はブローカーがどのGMTオフセットを設定しているかに依存し、ブローカーごとに異なる。TimeLocal()はMT4が起動しているPCまたはVPSのローカル時刻を返す。VPSを使っている場合、VPSのタイムゾーン設定によって値が変わる点に注意が必要だ。TimeGMT()はUTC(協定世界時)を直接返す。この関数はブローカーのGMT設定に依存しないため、JSTへの変換に最も適している。

日本時間への変換式は「TimeGMT() + 9 * 3600」だ。JSTはGMT+9(夏時間なし)なので、この加算で常にJSTが得られる。TimeCurrent()を使う場合は「TimeCurrent() + (9 - server_gmt_offset) * 3600」となり、ブローカーのGMTオフセット(2または3)を知っている必要がある。TimeDaylightSavings()を呼ぶと、ブローカーのサーバーが夏時間中かどうかを示す値(非ゼロ=夏時間、0=冬時間)が返るが、一部のブローカーではこの関数が正確に動作しないケースがあり、後述する対処が必要になる。

point

MT4の時間関数はTimeCurrent()(サーバー時間)、TimeLocal()(PCローカル)、TimeGMT()(UTC)の3種類。JSTへの変換にはTimeGMT()+9×3600が最も確実で、ブローカー依存がない。

主要ブローカーのGMTオフセットと夏冬時間差分一覧

主要なMT4ブローカーのGMTオフセット設定を以下に示す。実際の値はTimeCurrent()とTimeGMT()の差から後述のスクリプトで確認することを推奨する。

ブローカー冬時間(11月〜3月)夏時間(3月〜10月)JSTとの差(冬)JSTとの差(夏)
XM TradingGMT+2GMT+3+7時間+6時間
AxioryGMT+2GMT+3+7時間+6時間
FXTFGMT+2GMT+3+7時間+6時間
TradeviewGMT+2GMT+3+7時間+6時間
OANDAGMT+0GMT+0+9時間+9時間
GMOクリック証券GMT+2GMT+3+7時間+6時間

XM・Axiory・FXTFをはじめ、多くのブローカーはGMT+2(冬)/GMT+3(夏)設定を採用している。例外的にOANDAはGMT+0固定のため、JSTとの差は常に9時間になる。

夏時間の切り替えタイミングはブローカーの所在地によって異なる。欧州夏時間(CEST)は3月最終日曜から10月最終日曜まで、米国夏時間(EDT)は3月第2日曜から11月第1日曜まで。この2種類の切り替え時期には2〜3週間のずれがある。日本のFXトレーダーが最も混乱しやすいのは10月〜11月の約2週間で、欧州はすでに冬時間に移行しているがMT4表示は従来通りGMT+2になり、JSTとの差が一時的に7時間固定になる点だ。この時期に時間フィルターのパラメータを変更し忘れると、意図しないタイミングでEAが稼働することになる。

caution

上記のGMTオフセットはブローカーの標準設定であり、変更される場合がある。本番EAを運用する前に、TimeCurrent()とTimeGMT()の差を確認して実際のオフセット値を検証すること。

日本時間変換の早見表と計算式

GMT+2(冬時間)/GMT+3(夏時間)のブローカーを使っている場合の変換早見表を示す。チャート確認時のクイックリファレンスとして活用してほしい。

MT4表示時間JST(冬: +7時間)JST(夏: +6時間)備考
00:0007:0006:00
03:0010:0009:00東京オープン前後
09:0016:0015:00欧州オープン
14:00〜15:0021:00〜22:0020:00〜21:00NYオープン
22:0005:00翌04:00翌NYクローズ・日足確定

変換式で頭の中だけで計算するより、スクリプトで実測値を取得しておくほうが確実だ。以下のスクリプトをMetaEditor(MQL4/Scripts/)に保存してF5実行すると、各時間関数の値とGMTオフセットがエキスパートログに出力される。

// CheckMT4Time.mq4 — 時間関数確認スクリプト
#property script_show_inputs
void OnStart() {
    datetime srv = TimeCurrent();
    datetime utc = TimeGMT();
    datetime loc = TimeLocal();
    datetime jst = utc + (9 * 3600);
    Print("TimeCurrent() サーバー時間: ", TimeToString(srv, TIME_DATE|TIME_MINUTES|TIME_SECONDS));
    Print("TimeGMT()     UTC:          ", TimeToString(utc, TIME_DATE|TIME_MINUTES|TIME_SECONDS));
    Print("TimeLocal()   PC時間:       ", TimeToString(loc, TIME_DATE|TIME_MINUTES|TIME_SECONDS));
    Print("JST (計算値): UTC+9:        ", TimeToString(jst, TIME_DATE|TIME_MINUTES|TIME_SECONDS));
    int  dst      = (int)TimeDaylightSavings();
    long gmt_diff = (long)utc - (long)srv;
    Print("TimeDaylightSavings(): ", dst, " (1=夏時間)");
    Print("実際のGMTオフセット:   GMT+", (int)(-gmt_diff / 3600));
}

gmt_diffがマイナス値になる(utc < srv)場合はブローカーがGMTより進んだタイムゾーンを使っている。この値から正確なオフセットを算出してServerToJST()の計算に使用する。

TimeCurrent()とTimeGMT()の動作確認と注意点

TimeCurrent()TimeGMT()の差分を実際に計算するとブローカーのGMTオフセットが逆算できる。例えばTimeCurrent()が「10:00:00」を返し、TimeGMT()が「08:00:00」を返す場合、ブローカーはGMT+2を使っていることになる(10 – 8 = 2)。

ここで注意が必要なのは、TimeGMT()がMT4のビルドによっては正常動作しないケースだ。Build 500以下の古いMT4環境ではTimeGMT()が未実装で0を返すか、TimeCurrent()と同じ値を返すことがある。MT4の「ヘルプ→このプラットフォームについて」でビルド番号を確認し、Build 600以下なら最新版へのアップデートを推奨する。

TimeDaylightSavings()は前述のとおり、ブローカーのサーバー実装に依存する。この関数の返り値を信頼するかどうかは、実際にサーバー時間を確認して判断する必要がある。確認方法は冬時間期間中にTimeDaylightSavings()が0を返すことと、TimeGMT()とTimeCurrent()の差が7200秒(2時間)になることを照合すればよい。片方だけでは判断できないため、必ず両方を確認する習慣をつけておきたい。

OANDAのようにGMT+0固定のブローカーを使っている場合、TimeCurrent()TimeGMT()の差はゼロになる。JSTへの変換は単純に「TimeCurrent() + 9 * 3600」でよい。この場合はTimeDaylightSavings()の影響も受けない。

TimeDaylightSavings()が正確でないブローカーへの対処

TimeDaylightSavings()の返り値と実際のサーバー時間が食い違うケースが一部ブローカーで確認されている。例えばTimeDaylightSavings()が1(夏時間)を返しているのに、TimeGMT()とTimeCurrent()の差が7200秒(GMT+2=冬時間相当)のまま変化しない場合だ。これはブローカー側がサーバータイムゾーンの変更とTimeDaylightSavings()フラグの更新を連動させていない実装になっていることを意味する。

この問題を完全に回避するには、TimeGMT()ベースの変換に統一することだ。TimeGMT()は常にUTCを返すため、ブローカーのGMT設定や夏時間フラグの状態に左右されない。JSTへの変換はどのブローカーを使っていても「TimeGMT() + 9 * 3600」の一式で完結する。

どうしてもTimeCurrent()ベースの実装が必要な場合(例:バックテストでTimeGMT()が動作しないケース)は、ブローカーのGMTオフセットを定数として外部パラメーターで設定できるようにしておく方法が次善策だ。input int BrokerGMTOffset = 2;のように定義して、バックテスト期間に合わせて手動で設定する形にすると管理しやすい。

MQL4で日本時間を扱う実装と設定手順

JSTを扱うための実際のMQL4コードと、MT4への設定手順を示す。コードはそのままコピーして使用できる形で提供する。

ServerToJST()関数の実装コード全文

JSTへの変換関数を2通り実装する。TimeGMT()ベースとTimeCurrent()ベースだ。本番EAでの使用にはTimeGMT()ベースを推奨するが、一部のバックテスト環境ではTimeGMT()が正常動作しないため、TimeCurrent()ベースも把握しておく価値がある。

// ===== MT4 日本時間変換関数 =====
// trade-engineer.com

// 方法1: TimeGMT()ベース(推奨)
// ブローカーのGMTオフセット・夏冬時間に依存しない
datetime JSTFromGMT() {
    return TimeGMT() + (datetime)(9 * 3600);
}

// 方法2: TimeCurrent()ベース
// ブローカーがGMT+2(冬)/GMT+3(夏)の場合に使用
// TimeDaylightSavings()の動作が正確なブローカーが前提
datetime ServerToJST(datetime server_time = 0) {
    if (server_time == 0) server_time = TimeCurrent();
    int gmt_offset = (TimeDaylightSavings() != 0) ? 3 : 2;
    return server_time + (datetime)((9 - gmt_offset) * 3600);
}

// OANDA(GMT+0固定)の場合
datetime ServerToJST_OANDA(datetime server_time = 0) {
    if (server_time == 0) server_time = TimeCurrent();
    return server_time + (datetime)(9 * 3600);
}

// 使用例(OnTick内)
// datetime jst = JSTFromGMT();
// int jst_hour   = TimeHour(jst);
// int jst_minute = TimeMinute(jst);
// Print("現在のJST: ", TimeToString(jst, TIME_DATE|TIME_MINUTES));

JSTFromGMT()はTimeGMT()がUTCを直接返すことを利用している。MT4 Build 509以降では基本的に正常動作する。ビルドが古い場合はMT4の最新版にアップデートするか、ServerToJST()の方法に切り替える。ServerToJST()にserver_time = 0のデフォルト引数を設定しているのは、引数なしで呼んだ場合に自動的にTimeCurrent()を使う利便性のためだ。特定のバー時刻(例:過去足の時間)を変換したい場合はserver_time引数に値を渡す。

日本時間をチャートに常時表示するインジケーター

チャート上に日本時間を常時表示するインジケーターを作成する。MetaEditorで新規ファイルを作成し、MQL4/Indicators/フォルダに保存してコンパイルする。

// JSTDisplay.mq4 — 日本時間チャート表示インジケーター
// 配置: MQL4/Indicators/JSTDisplay.mq4
// trade-engineer.com
#property copyright "trade-engineer.com"
#property version   "1.01"
#property indicator_chart_window
#property indicator_buffers 0

input color  TextColor = clrWhite;
input int    FontSize  = 11;
const string OBJ = "JSTDisplay_Clock";

int OnInit() {
    EventSetTimer(1);
    return INIT_SUCCEEDED;
}

void OnTimer() { UpdateDisplay(); }

int OnCalculate(const int rates_total, const int 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 int &spread[]) {
    UpdateDisplay();
    return rates_total;
}

void UpdateDisplay() {
    datetime jst = TimeGMT() + (datetime)(9 * 3600);
    string   txt = "JST: " + TimeToString(jst, TIME_DATE|TIME_MINUTES|TIME_SECONDS);
    if (ObjectFind(0, OBJ) < 0) {
        ObjectCreate(0, OBJ, OBJ_LABEL, 0, 0, 0);
        ObjectSetInteger(0, OBJ, OBJPROP_CORNER,    CORNER_LEFT_UPPER);
        ObjectSetInteger(0, OBJ, OBJPROP_XDISTANCE, 6);
        ObjectSetInteger(0, OBJ, OBJPROP_YDISTANCE, 20);
    }
    ObjectSetString (0, OBJ, OBJPROP_TEXT,     txt);
    ObjectSetInteger(0, OBJ, OBJPROP_COLOR,    TextColor);
    ObjectSetInteger(0, OBJ, OBJPROP_FONTSIZE, FontSize);
    ChartRedraw(0);
}

void OnDeinit(const int reason) {
    EventKillTimer();
    ObjectDelete(0, OBJ);
    Comment("");
}

チャートへの適用はナビゲーターパネルの「インジケーター→JSTDisplay」をダブルクリックするか、チャートにドラッグする。EventSetTimer(1)で1秒ごとに時刻を更新しているためリアルタイムで動作する。Comment()関数ではなくOBJ_LABELオブジェクトで表示する実装にしているのは、他のインジケーターのComment()表示と重なる問題を避けるためだ。MQL4でのラベルオブジェクト操作についてはこちらを参照してほしい。

EAの時間フィルターをJSTで実装する方法

EAに時間帯制限を組み込む場合、JSTベースで指定する関数を用意しておくと管理しやすい。以下は時間帯フィルター関数の完全実装だ。

// JSTベースの取引時間フィルター — trade-engineer.com

// 時間単位のフィルター(start_hour以上 end_hour未満のJST時間帯でtrueを返す)
// 日またぎに対応:start_hour > end_hour の場合は「またぎ」として処理
bool IsJSTTradingHour(int start_hour, int end_hour) {
    datetime jst  = TimeGMT() + (datetime)(9 * 3600);
    int      hour = TimeHour(jst);
    if (start_hour <= end_hour)
        return (hour >= start_hour && hour < end_hour);
    return (hour >= start_hour || hour < end_hour);
}

// 分単位のフィルター
bool IsJSTTradingTime(int sh, int sm, int eh, int em) {
    datetime jst   = TimeGMT() + (datetime)(9 * 3600);
    int      total = TimeHour(jst) * 60 + TimeMinute(jst);
    int      s     = sh * 60 + sm;
    int      e     = eh * 60 + em;
    if (s <= e) return (total >= s && total < e);
    return (total >= s || total < e);
}

// --- 使用例 ---
// void OnTick() {
//     if (!IsJSTTradingHour(9, 17)) return;  // 東京時間(9〜16時)のみ
//     if (!IsJSTTradingHour(21, 3)) return;  // ロンドン〜NY重複帯(21時〜翌2時)
//     if (!IsJSTTradingTime(9, 50, 10, 5)) return; // ゴトー日仲値前後15分
//     // ... エントリーロジック
// }

日またぎ処理の実装がポイントだ。start_hour(21) > end_hour(3)のように日またぎになる場合、単純な範囲チェック(hour >= 21 && hour < 3)はhour < 3が常に偽になるため機能しない。hour >= 21 || hour < 3と論理ORで判定することで、21時以降か3時未満かを正しく判断できる。期間区切りインジケーターを使った時間帯管理の実例も参考にしてほしい。

スマホ版MT4での日本時間確認手順

MT4スマホアプリ(iOS/Android)のチャート画面に表示される時間は、PC版と同じブローカーのサーバー時間(GMT+2/3)になる。外出先でのポジション管理にJSTを素早く把握する方法をまとめておく。

最も実用的な方法は、スマホの世界時計アプリにGMT+2とGMT+3の時計を追加しておくことだ。iOS標準の「時計」アプリや、Androidの「時計」アプリで「ロンドン」や「キプロス」を追加すると、MT4の時間と照合できる状態になる。XMやFXTFを使っている場合は夏時間期間中はロンドン(BST=GMT+1)ではなく、実際にはGMT+3なので「フランクフルト」や「アテネ」のタイムゾーンを追加するほうが正確だ。

MT4スマホアプリにはインジケーターをインストールできないため、先に作成したJSTDisplayインジケーターはPC版専用になる。スマホでは手動計算またはスマホアプリのタイムゾーン表示で対応するのが現実的だ。スマホからの注文執行時に特に注意が必要なのは、スワップポイントの切り替えタイミング(MT4時間00:00)と、日足の確定時刻(MT4時間22:00 = JST翌4〜5時)の2点だ。ゴトー日の仲値狙いや、指標発表のタイミングでのスマホ操作では、JSTとサーバー時間の変換を確実に行うことが損失回避につながる。

時間表示されない・ずれが想定外に大きい場合の診断

MT4の時間表示やJST変換に問題が起きるケースとその対処をまとめる。

「インジケーターの時間表示が出ない」場合は、他のインジケーターがComment()で上書きしている可能性が高い。MT4ではChart単位でComment()の表示は1つだけ有効で、最後に呼ばれたComment()が上書きする仕様になっている。解決策はJSTDisplayインジケーターのようにOBJ_LABELオブジェクトを使う実装に切り替えることだ。

「JSTの計算値が実際の時刻と大きくずれる」場合は、使用ブローカーがGMT+2/3以外のオフセットを採用している可能性がある。先に示した確認スクリプトでgmt_diffを実測し、実際のGMTオフセットを把握する。例えばgmt_diffが-18000(-5時間)であればGMT+5のブローカーになり、JSTとの差は4時間(JST-4)になる。この値をServerToJST()の定数として設定し直す。

「バックテストでJSTFromGMT()が正常動作しない」場合は、MT4のストラテジーテスターではTimeGMT()が常に0を返すバージョンが存在する。この場合はServerToJST()(TimeCurrent()ベース)を使い、バックテスト用のGMTオフセットをinputパラメーターとして別途設定する方法で対応する。

memo

MT4のバージョン(ビルド番号)は「ヘルプ→このプラットフォームについて」で確認できる。Build 500以下の古いビルドはTimeGMT()が未実装のケースがある。最新ビルドへのアップデートを推奨する。

まとめ:MT4時間管理の実装チェックリスト

MT4の時間ずれとJST変換について、実装上の要点をまとめる。

EAやインジケーターでJSTを扱う基本実装はTimeGMT() + 9 * 3600一択だ。ブローカー依存がなく、夏冬時間の切り替えにも自動対応する。TimeCurrent()ベースの実装はTimeDaylightSavings()の返り値の信頼性に左右されるため、特別な理由がない限り採用しない方がよい。

時間フィルターを日またぎで設定する場合(例:21時〜翌3時のロンドン・NY帯)は、start_hour > end_hourの条件を論理ORで処理することを忘れずに。この実装漏れが原因で「時間フィルターが機能せず朝方にもエントリーが走る」という問題が実際に起きやすい。

本番環境のEAは月に一度程度、確認スクリプトでGMTオフセットを実測することを推奨する。ブローカーのサーバー移行でタイムゾーンが変更されることがあり、アナウンスなしに実施されるケースも存在する。特に夏冬時間の切り替えシーズン(3月・10月)前後は確認しておくとよい。MT4インジケーター作成ツールの活用法と組み合わせることで、時間管理機能を持つカスタムインジケーターの開発効率が向上する。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次