技術辞典

MQL5 CopyTimeの使い方|バー時刻・新バー判定・確定足確認

EAファンクラブ

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 = 11本前の確定足確定済みバーとして判定しやすくなります。
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価格情報が必要なため
高値・安値・終値をまとめて使いたいCopyRatesMqlRatesでバー情報をまとめて取得できるため
複数時間足のバー時刻を確認したい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_OKbar_time、copied、timeframeバー時刻取得成功の確認
COPYTIME_NGcopied、last_error履歴不足や取得失敗の確認
NEWBAR_INIT初回バー時刻初期化時の状態確認
NEWBAR_DETECTED前回バー時刻と現在バー時刻新バー判定の確認
ENTRY_SKIPsame_barなどの見送り理由同一バー制御の確認
CONFIRMED_BAR_TIME_OKshift 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理由をログで確認してください。

MT4/MT5の開発・改修相談はこちら

まとめ

CopyTimeは、MQL5で指定した銘柄・時間足のバー開始時刻を取得するための関数です。

新バー判定、確定足判定、同一バー制御、マルチタイムフレーム判定では、CopyTimeで取得したバー時刻を前回値と比較すると整理しやすくなります。

start_pos 0は現在足、start_pos 1は1本前の確定足です。EAで確定足ベースの判定を行う場合は、時刻、価格、インジケーター値のshiftを揃えて確認してください。

CopyTimeの戻り値、GetLastError、履歴データ不足、時間足別のlast_bar_time、ログ出力範囲を確認しておくと、同じバーでの重複処理やバックテスト時の判定ずれを追跡しやすくなります。

ABOUT ME
記事URLをコピーしました