MQL5 CopyTimeの使い方|バー時刻・新バー判定・確定足確認
MQL5でEAの新バー判定、確定足判定、同一バー制御を作る時は、バーの開始時刻を正しく取得する必要があります。
CopyTimeは、指定した銘柄・時間足のバー開始時刻を取得するための関数です。現在足、1本前の確定足、過去バーの時刻を取得し、EA内部で「新しい足になったか」「同じバーで重複処理していないか」を確認する時に使えます。
EAが同じ足で何度もエントリーする、確定足ではなく現在足で判定してしまう、バックテストとリアル環境で新バー判定がずれる、別時間足のバー更新を確認したい、といった場合は、CopyTime、iTime、CopyRatesの使い分けを整理すると原因を追いやすくなります。
このページでは、MQL5のCopyTimeの使い方を、バー時刻、新バー判定、確定足確認、同一バー制御、iTimeやCopyRatesとの違いから整理します。
なお、このページはMQL5開発における技術確認を目的とした内容です。売買判断、推奨エントリー、推奨ロット、利益保証、損失回避保証を行うものではありません。
CopyTimeとは何か
CopyTimeは、指定した銘柄と時間足のバー開始時刻をdatetime配列へコピーする関数です。
EAでは、現在足の開始時刻、1本前の確定足の開始時刻、過去バーの時刻を取得し、新バー判定や重複処理防止に使います。
void PrintCurrentBarTime()
{
datetime times[];
ArraySetAsSeries(times, true);
ResetLastError();
int copied = CopyTime(_Symbol, PERIOD_CURRENT, 0, 1, times);
if(copied != 1)
{
PrintFormat("[COPYTIME_NG] symbol=%s timeframe=%d copied=%d last_error=%d",
_Symbol,
PERIOD_CURRENT,
copied,
GetLastError());
return;
}
PrintFormat("[COPYTIME_OK] bar_time=%s",
TimeToString(times[0], TIME_DATE|TIME_SECONDS));
}CopyTimeの戻り値は、コピーできたデータ数です。必要本数を取得できていない場合は、その値を判定に使わないようにしてください。
CopyTimeで取得できるもの
CopyTimeで取得するのは、バーの開始時刻です。
価格そのものではなく、バーがいつ始まったかを確認するための情報です。
| 取得対象 | 内容 | EAでの使い方 |
|---|---|---|
| 現在足の時刻 | shift 0 のバー開始時刻 | 新バー判定、同一バー制御に使う |
| 確定足の時刻 | shift 1 のバー開始時刻 | 確定足ベースのサイン判定に使う |
| 過去足の時刻 | shift 2 以降のバー開始時刻 | 過去比較、履歴確認、検証ログに使う |
| 別時間足の時刻 | PERIOD_M15、PERIOD_H1などのバー時刻 | 上位足フィルターやマルチタイムフレーム判定に使う |
バー開始時刻は、同じ時間足では新しいバーになるまで変わりません。そのため、最後に処理したバー時刻を保存しておくと、新バー判定に使えます。
start_pos 0 と shift 1 の違い
CopyTimeでstart_posに0を指定すると、現在の未確定バーの時刻を取得します。
1を指定すると、1本前の確定足のバー時刻を取得できます。
| 指定 | 意味 | EAでの注意点 |
|---|---|---|
| start_pos = 0 | 現在足 | 形成中のバーです。値やサインが変わる場合があります。 |
| start_pos = 1 | 1本前の確定足 | 確定済みバーとして判定しやすくなります。 |
| start_pos = 2以上 | さらに過去の足 | 過去比較やクロス判定に使います。 |
EAで確定足ベースの判定を行う場合は、価格やインジケーター値だけでなく、バー時刻もshift 1を基準に確認してください。
新バー判定の基本
新バー判定では、現在足のバー開始時刻を取得し、前回保存したバー時刻と比較します。
バー時刻が変わった時だけ処理を行うことで、同じバーで何度も判定やエントリーを行う状態を防ぎやすくなります。
datetime g_last_bar_time = 0;
bool IsNewBar()
{
datetime times[];
ArraySetAsSeries(times, true);
ResetLastError();
int copied = CopyTime(_Symbol, PERIOD_CURRENT, 0, 1, times);
if(copied != 1)
{
PrintFormat("[NEWBAR_COPYTIME_NG] symbol=%s timeframe=%d copied=%d last_error=%d",
_Symbol,
PERIOD_CURRENT,
copied,
GetLastError());
return false;
}
datetime current_bar_time = times[0];
if(g_last_bar_time == 0)
{
g_last_bar_time = current_bar_time;
PrintFormat("[NEWBAR_INIT] bar_time=%s",
TimeToString(current_bar_time, TIME_DATE|TIME_SECONDS));
return false;
}
if(current_bar_time != g_last_bar_time)
{
PrintFormat("[NEWBAR_DETECTED] prev=%s current=%s",
TimeToString(g_last_bar_time, TIME_DATE|TIME_SECONDS),
TimeToString(current_bar_time, TIME_DATE|TIME_SECONDS));
g_last_bar_time = current_bar_time;
return true;
}
return false;
}初回起動時は、前回バー時刻がないため、すぐにエントリー判定へ進めるか、次の新バーまで待つかを仕様として決めてください。
同一バー制御で使う
CopyTimeは、同じバーで何度もエントリーや通知を行わないための制御にも使えます。
同一バー制御では、最後にエントリーしたバー時刻、最後に通知したバー時刻、最後に決済判定したバー時刻などを分けて持つと確認しやすくなります。
datetime g_last_entry_bar_time = 0;
bool CanEnterThisBar()
{
datetime times[];
ArraySetAsSeries(times, true);
if(CopyTime(_Symbol, PERIOD_CURRENT, 0, 1, times) != 1)
return false;
datetime current_bar_time = times[0];
if(g_last_entry_bar_time == current_bar_time)
{
PrintFormat("[ENTRY_SKIP] reason=same_bar bar_time=%s",
TimeToString(current_bar_time, TIME_DATE|TIME_SECONDS));
return false;
}
return true;
}
void MarkEntryBar()
{
datetime times[];
ArraySetAsSeries(times, true);
if(CopyTime(_Symbol, PERIOD_CURRENT, 0, 1, times) == 1)
{
g_last_entry_bar_time = times[0];
PrintFormat("[ENTRY_BAR_MARK] bar_time=%s",
TimeToString(g_last_entry_bar_time, TIME_DATE|TIME_SECONDS));
}
}同一バー制御では、signal判定、entry実行、通知、決済などを同じ変数で管理しすぎないようにしてください。処理の目的ごとにバー時刻を分けると、ログ確認がしやすくなります。
確定足判定で使う
EAを確定足ベースで動かす場合は、1本前のバーを基準にして判定します。
CopyTimeで確定足の時刻を取得し、その時刻に対応する価格やインジケーター値をCopyClose、CopyBuffer、CopyRatesなどで確認します。
bool GetConfirmedBarTime(datetime &confirmed_bar_time)
{
datetime times[];
ArraySetAsSeries(times, true);
ResetLastError();
int copied = CopyTime(_Symbol, PERIOD_CURRENT, 1, 1, times);
if(copied != 1)
{
PrintFormat("[CONFIRMED_BAR_TIME_NG] symbol=%s timeframe=%d copied=%d last_error=%d",
_Symbol,
PERIOD_CURRENT,
copied,
GetLastError());
return false;
}
confirmed_bar_time = times[0];
PrintFormat("[CONFIRMED_BAR_TIME_OK] time=%s",
TimeToString(confirmed_bar_time, TIME_DATE|TIME_SECONDS));
return true;
}確定足判定では、時刻だけでなく、取得する価格やインジケーター値も同じshiftで揃える必要があります。時刻はshift 1、値はshift 0のように混在させると、判定がずれる場合があります。
iTimeとの違い
iTimeも、指定した銘柄・時間足・shiftのバー開始時刻を取得する関数です。
1本だけ時刻を確認したい場合はiTimeでも書けます。一方で、複数本まとめて取得する場合や、CopyClose、CopyRatesなどと同じ形式で扱いたい場合はCopyTimeが便利です。
| 関数 | 特徴 | 使いやすい場面 |
|---|---|---|
| CopyTime | バー時刻を配列へコピーする | 複数本取得、新バー判定、他のCopy系関数と揃える |
| iTime | 指定shiftのバー時刻を直接返す | 1本だけ簡単に確認したい場合 |
| CopyRates | 時刻、始値、高値、安値、終値、出来高などをまとめて取得する | バー情報をまとめて確認したい場合 |
datetime current_bar_time = iTime(_Symbol, PERIOD_CURRENT, 0);
PrintFormat("[ITIME] bar_time=%s",
TimeToString(current_bar_time, TIME_DATE|TIME_SECONDS));iTimeが0を返す場合は、データ取得エラーや履歴未準備の可能性があります。GetLastErrorやBars、SeriesInfoIntegerなども合わせて確認してください。
CopyRatesとの使い分け
バー時刻だけが必要な場合はCopyTimeで十分です。
一方で、同じバーの始値、高値、安値、終値、出来高も同時に確認したい場合は、CopyRatesを使うとまとめて取得できます。
| 目的 | 使う関数 | 理由 |
|---|---|---|
| 新バー判定だけしたい | CopyTime | バー開始時刻だけで判定できるため |
| 確定足の終値も確認したい | CopyClose または CopyRates | 価格情報が必要なため |
| 高値・安値・終値をまとめて使いたい | CopyRates | MqlRatesでバー情報をまとめて取得できるため |
| 複数時間足のバー時刻を確認したい | CopyTime | 時間足ごとにバー開始時刻を比較しやすいため |
EAの処理を軽くしたい場合は、必要な情報だけ取得してください。新バー判定だけならCopyTime、価格も必要ならCopyRates、というように目的で分けると整理しやすくなります。
別時間足の新バー判定
マルチタイムフレームEAでは、現在チャートの時間足とは別に、上位足の新バーを確認したい場合があります。
CopyTimeでは、symbolとtimeframeを指定できるため、M15チャート上でH1の新バー判定を行うこともできます。
datetime g_last_h1_bar_time = 0;
bool IsNewBarOnTimeframe(const ENUM_TIMEFRAMES timeframe)
{
datetime times[];
ArraySetAsSeries(times, true);
int copied = CopyTime(_Symbol, timeframe, 0, 1, times);
if(copied != 1)
{
PrintFormat("[MTF_NEWBAR_NG] symbol=%s timeframe=%d copied=%d last_error=%d",
_Symbol,
timeframe,
copied,
GetLastError());
return false;
}
if(g_last_h1_bar_time == 0)
{
g_last_h1_bar_time = times[0];
return false;
}
if(times[0] != g_last_h1_bar_time)
{
PrintFormat("[MTF_NEWBAR_DETECTED] timeframe=%d prev=%s current=%s",
timeframe,
TimeToString(g_last_h1_bar_time, TIME_DATE|TIME_SECONDS),
TimeToString(times[0], TIME_DATE|TIME_SECONDS));
g_last_h1_bar_time = times[0];
return true;
}
return false;
}実際には、時間足ごとに前回バー時刻を分けて管理してください。複数時間足を同じ変数で管理すると、新バー判定が混ざります。
履歴データ不足を確認する
CopyTimeで必要本数を取得できない場合、対象銘柄・時間足の履歴データが不足している可能性があります。
EAをチャートへセットした直後、ストラテジーテスター開始直後、別銘柄・別時間足を初めて参照した時などは、必要な履歴がまだ準備できていない場合があります。
| 確認項目 | 内容 | ログ例 |
|---|---|---|
| CopyTime戻り値 | 必要本数を取得できたか | COPYTIME_NG |
| GetLastError | 取得失敗時のエラー確認 | last_error |
| Bars | 対象銘柄・時間足のバー数 | BARS_CHECK |
| SeriesInfoInteger | 時系列データの同期状態確認 | SERIES_SYNC_CHECK |
| 再試行 | 次tickやOnTimerで再確認するか | HISTORY_WAIT |
履歴が不足している時は、無理に値を使わず、次のtickまたはOnTimerで再確認する設計にしてください。
ログで確認したい項目
CopyTimeを使う処理では、バー時刻、timeframe、shift、取得本数、前回バー時刻、判定結果をログに出すと確認しやすくなります。
| ログ名 | 確認内容 | 用途 |
|---|---|---|
| COPYTIME_OK | bar_time、copied、timeframe | バー時刻取得成功の確認 |
| COPYTIME_NG | copied、last_error | 履歴不足や取得失敗の確認 |
| NEWBAR_INIT | 初回バー時刻 | 初期化時の状態確認 |
| NEWBAR_DETECTED | 前回バー時刻と現在バー時刻 | 新バー判定の確認 |
| ENTRY_SKIP | same_barなどの見送り理由 | 同一バー制御の確認 |
| CONFIRMED_BAR_TIME_OK | shift 1のバー時刻 | 確定足判定の確認 |
| MTF_NEWBAR_DETECTED | 別時間足の新バー判定 | マルチタイムフレーム確認 |
新バー判定ログは毎tick出すと多くなります。通常時は新バー検出時だけ、異常時は詳細、デバッグ時だけ全ログというように切り替えると確認しやすくなります。
ログ出力例
[COPYTIME_OK] symbol=GOLD timeframe=15 shift=0 copied=1 bar_time=2026.05.26 10:15:00
[NEWBAR_INIT] bar_time=2026.05.26 10:15:00
[NEWBAR_DETECTED] prev=2026.05.26 10:15:00 current=2026.05.26 10:30:00
[ENTRY_SKIP] reason=same_bar bar_time=2026.05.26 10:30:00
[CONFIRMED_BAR_TIME_OK] shift=1 time=2026.05.26 10:15:00
[MTF_NEWBAR_DETECTED] timeframe=60 prev=2026.05.26 09:00:00 current=2026.05.26 10:00:00
[COPYTIME_NG] symbol=GOLD timeframe=240 shift=0 copied=-1 last_error=4401
ログ例の銘柄、時間足、時刻、エラー番号は確認用です。実際の値は、銘柄、時間足、履歴データ、テスター条件によって変わります。
よくある失敗パターン
| 失敗パターン | 問題点 | 確認方法 |
|---|---|---|
| 新バー判定をせず毎tick判定する | 同じバーで何度もentry判定が走る | CopyTimeでbar_timeを比較する |
| 現在足と確定足を混同する | 未確定の値で売買判定してしまう | shift 0 と shift 1 を分ける |
| 初回起動時にすぐ判定する | 起動直後の同一バーで想定外に処理される場合がある | NEWBAR_INIT後は次バーまで待つ設計にする |
| 時間足ごとのlast_bar_timeを分けない | M15とH1の判定が混ざる | timeframe別に前回バー時刻を保持する |
| CopyTime戻り値を確認しない | 取得失敗時の未初期化値を使う可能性がある | copiedが必要本数と一致するか確認する |
| 履歴不足を考慮しない | 別銘柄・別時間足で値が取れない | BarsやSeriesInfoIntegerも確認する |
| ログを毎tick出しすぎる | Expertsログが膨らみ、検証が重くなる | 新バー時・NG時・debug時に限定する |
CopyTimeとあわせて確認したい価格取得
CopyTimeで新バー判定や確定足判定を作る場合は、終値やOHLCをどのタイミングで読むかも重要です。CopyClose、CopyRates、TimeCurrentをあわせて確認すると、バー単位の判定を整理しやすくなります。
| 確認したい内容 | 関連ページ | 確認ポイント |
|---|---|---|
| 終値・高値・安値の取得 | MQL5 CopyCloseとiCloseの違い | 確定足の終値、高値、安値を取得する方法と、shift 0 / shift 1 の違いを確認します。 |
| サーバー時間と現在時刻 | MQL5 TimeCurrentの使い方 | TimeCurrentで現在時刻を取得する場合の、OnTick / OnTimer / サーバー時間の違いを確認します。 |
| 価格取得関数の整理 | MQL5時系列・価格取得関数辞典 | CopyTime、CopyRates、CopyClose、iClose、TimeCurrentの使い分けを確認します。 |
関連ページ
CopyTimeは、時系列データ、関数辞典、イベント処理、ログ確認、EA稼働時間の確認と合わせて整理すると理解しやすくなります。
| 関連ページ | 確認できること |
|---|---|
| MQL5関数辞典 | CopyTime、TimeCurrent、SymbolInfo系など主要関数の全体確認 |
| MQL5イベント処理完全ガイド | OnTick、OnTimer、OnInitなどイベントごとの処理整理 |
| MQL5デバッグ・ログファースト開発完全ガイド | Expertsログ、再現条件、ログ設計の確認 |
| MT5のログ確認方法 | ExpertsログとJournalログの確認方法 |
| EAの稼働時間とは | EAの稼働時間、停止時間、サーバー時間の基本 |
時系列データとローソク足情報をあわせて確認する場合
CopyTimeは、バー開始時刻を取得し、新バー判定、確定足確認、同一バー制御に使う関数です。価格データやローソク足情報とあわせて確認したい場合は、時系列データ全体やCopyRatesの使い方も確認してください。
| 確認したいこと | 確認するページ | 主な確認内容 |
|---|---|---|
| MQL5の時系列データ取得全体を確認したい | MQL5時系列データ・価格取得完全ガイド | CopyTime、CopyRates、CopyClose、iClose、価格データ、バー時刻の確認 |
| バー時刻とOHLCをまとめて確認したい | MQL5 CopyRatesの使い方 | MqlRates、バー時刻、始値、高値、安値、終値、出来高、スプレッドの確認 |
新バー判定を作る時は、現在足と確定足、CopyTimeで取得したバー時刻、CopyRatesやCopyCloseで取得した価格のshiftをそろえて確認してください。時刻と価格の基準がずれると、同一バー制御や確定足判定が不安定になる場合があります。
開発依頼前に整理したい情報
CopyTime、新バー判定、確定足判定、同一バー制御の実装を相談する場合は、次の情報を整理してください。
| 整理する情報 | 確認内容 |
|---|---|
| 対象EA | 新規EA、既存EA改修、インジケーターEA化、通知ツールのどれか |
| 判定時間足 | 現在チャート時間足か、M15、H1など別時間足か |
| 判定タイミング | 現在足で見るか、確定足で見るか |
| 新バー判定の用途 | entry、exit、通知、ログ、外部連携のどこに使うか |
| 同一バー制御 | 1バー1回だけにしたい処理は何か |
| 複数時間足 | 時間足ごとにlast_bar_timeを分ける必要があるか |
| 関連データ | CopyClose、CopyRates、CopyBufferと組み合わせるか |
| ログ | COPYTIME_OK、NEWBAR_DETECTED、ENTRY_SKIP、CopyTime失敗ログ |
| 検証条件 | バックテスト期間、銘柄、時間足、ログ量、再現手順 |
新バー判定の不具合を相談する場合は、EAが使っているtimeframe、CopyTimeの戻り値、前回バー時刻、現在バー時刻、entry skip理由をログで確認してください。
まとめ
CopyTimeは、MQL5で指定した銘柄・時間足のバー開始時刻を取得するための関数です。
新バー判定、確定足判定、同一バー制御、マルチタイムフレーム判定では、CopyTimeで取得したバー時刻を前回値と比較すると整理しやすくなります。
start_pos 0は現在足、start_pos 1は1本前の確定足です。EAで確定足ベースの判定を行う場合は、時刻、価格、インジケーター値のshiftを揃えて確認してください。
CopyTimeの戻り値、GetLastError、履歴データ不足、時間足別のlast_bar_time、ログ出力範囲を確認しておくと、同じバーでの重複処理やバックテスト時の判定ずれを追跡しやすくなります。
