- 1 1. mql5 itimeとは何か
- 2 ■ つまずきやすいポイント(重要)
- 3 ■ 注意点(実務)
- 4 2. itimeの使い方(コード付き)
- 5 ■ つまずきやすいポイント
- 6 ■ よくある失敗
- 7 ■ 注意点(実務)
- 8 3. 新しいバーの検出方法(EA必須ロジック)
- 9 ■ つまずきやすいポイント(重要)
- 10 ■ よくある失敗
- 11 ■ 注意点(実務)
- 12 ■ 実務的な結論
- 13 4. マルチタイムフレーム・複数通貨での応用
- 14 ■ つまずきやすいポイント(MTF)
- 15 ■ よくある失敗(MTF)
- 16 4.4 複数通貨ペア(マルチシンボル)
- 17 ■ つまずきやすいポイント(マルチシンボル)
- 18 ■ よくある失敗(マルチシンボル)
- 19 ■ 注意点(実務)
- 20 ■ 実務的な結論
- 21 5. itimeを使うときの注意点・環境依存・バグ回避
- 22 つまずきやすいポイント
- 23 よくある失敗
- 24 実務での回避策
- 25 6. itimeと関連関数の使い分け(CopyTime・TimeCurrentなど)
- 26 6.2 itimeとTimeCurrentの違い
- 27 6.3 iTimeとの違い(重要)
- 28 6.4 関数選択の最適戦略
- 29 ■ つまずきやすいポイント
- 30 ■ よくある失敗
- 31 ■ 実務でのベストプラクティス
- 32 ■ 結論(設計視点)
- 33 7. FAQ(よくある質問と解決方針)
- 34 ■ 実務まとめ(最短理解)
1. mql5 itimeとは何か
MQL5のitimeは、指定した通貨ペア・時間足・バー位置から「そのバーの開始時刻」を取得する関数です。
戻り値はdatetime型(日時データ)で、EA(自動売買)やインジケーターにおいて、時間ベースの制御を行うための基礎関数となります。
特に重要なのは、itimeは「価格」ではなく「時間」を扱う点です。
このため、以下のような用途で頻繁に使用されます。
- 新しいバー(ローソク足)の検出
- 一定時間ごとの処理制御
- ログやデバッグ時の時間確認
1.1 itimeの基本機能
itimeは、以下の3つの情報を指定して時間を取得します。
- シンボル(例:EURUSD)
- 時間足(例:1分足、1時間足)
- バーの位置(インデックス)
例えば、以下のように使用します。
datetime t = itime(_Symbol, PERIOD_M5, 0);
このコードは、
- 現在のチャートの通貨ペア(_Symbol)
- 5分足(PERIOD_M5)
- 最新バー(index=0)
の「開始時刻」を取得します。
ここで重要なのは、indexの意味です。
0:現在進行中のバー(未確定)1:直前の確定バー2以降:過去のバー
つまり、itimeは「時間軸上のデータ参照」を行う関数であり、
配列のように過去へ遡って参照できる構造になっています。
1.2 どんなときに使うのか
実務では、itimeはほぼ必ず以下の用途で使われます。
新しいバーの検出
- EAで最も重要な処理
- 同じバー内で複数回エントリーするのを防ぐ
処理の最適化
- 毎ティック(価格更新ごと)ではなく
- 「新バー確定時だけ処理」することで負荷を削減
デバッグ・ログ用途
Print("現在のバー時間: ", itime(_Symbol, PERIOD_M1, 0));
1.3 CopyTimeとの違い(重要)
初心者が混乱しやすいポイントとして、CopyTimeとの違いがあります。
| 関数 | 特徴 |
|---|---|
| itime | 単一のバー時間を取得 |
| CopyTime | 複数のバー時間を配列で取得 |
使い分けの目安
- 1つだけ欲しい → itime
- 複数まとめて処理 → CopyTime
例えば、ループ処理や過去データ分析ではCopyTimeが適していますが、
新バー検出など単発取得はitimeが最適です。
■ つまずきやすいポイント(重要)
初心者が特に間違いやすい点を整理します。
indexの誤解
0は「確定バー」ではない- → 未確定なのでロジックに使うとバグの原因
データ未ロード問題
- シンボルや時間足の履歴がない場合
- → 正しい値が取得できないことがある
CopyTimeとの混同
- 配列処理なのに
itimeを使う - → 非効率またはロジック崩壊
■ 注意点(実務)
- 時刻はサーバー時間基準
- ブローカーによってタイムゾーンが異なる場合あり(環境依存)
- マルチタイムフレームでは時間の整合性に注意
2. itimeの使い方(コード付き)
itimeはシンプルな関数ですが、引数の意味とindexの扱いを正しく理解しないと誤動作の原因になります。
このセクションでは、最短で実務に使えるレベルまで整理します。
2.1 基本構文
datetime itime(
string symbol,
ENUM_TIMEFRAMES timeframe,
int index
);
戻り値
datetime(日時)- 取得できない場合は
0が返ることがある(注意)
2.2 引数の意味
symbol(通貨ペア)
- 例:
"EURUSD"、_Symbol - 通常は
_Symbolを使う(現在のチャート)
timeframe(時間足)
- 例:
PERIOD_M1,PERIOD_M5,PERIOD_H1 - ENUM_TIMEFRAMES(時間足の定数)
index(バー位置)
- 0:現在のバー(未確定)
- 1:直前の確定バー
- 2以上:過去
2.3 最短サンプル(基本)
最新バーの時間取得
datetime current_bar_time = itime(_Symbol, PERIOD_M5, 0);
直前の確定バー
datetime last_closed_bar = itime(_Symbol, PERIOD_M5, 1);
2.4 実務で使う基本パターン
① 時間をログに出す
Print("現在バーの時間: ", TimeToString(itime(_Symbol, PERIOD_M1, 0)));
※ TimeToString:datetimeを文字列に変換
② 安全に値を取得する(重要)
datetime t = itime(_Symbol, PERIOD_M5, 0);
if(t == 0)
{
Print("データ未取得の可能性あり");
return;
}
2.5 実務テクニック(再現性を上げる)
データロードを意識する
if(Bars(_Symbol, PERIOD_M5) < 10)
{
Print("バー数不足");
return;
}
※ Bars:取得済みバー数
明示的にシンボルを指定
datetime t = itime("EURUSD", PERIOD_H1, 1);
※ 複数通貨ペアEAで重要
■ つまずきやすいポイント
indexの誤用
index=0を確定足として使う
→ 未確定なので値が変化する
timeframeミス
- 想定と違う時間足を指定
→ ロジックがズレる
symbolミス
- 異なる通貨ペアを参照してしまう
■ よくある失敗
① 毎ティックで同じ処理を繰り返す
→ itimeを使って制御しないと無限実行
② 取得失敗(0)を無視
→ 条件が常に成立しない
③ CopyTimeと混同
→ ループ処理が非効率
■ 注意点(実務)
- itimeは「軽量」だが、多用しすぎると無駄
- ループ内で連続使用は避ける
- 必要なら一度取得して使い回す
3. 新しいバーの検出方法(EA必須ロジック)
itimeの最も重要な用途は、新しいバー(ローソク足)が生成されたかどうかの検出です。
このロジックは、EAの品質(無駄なエントリー防止・処理負荷削減)に直結します。
3.1 なぜ新バー検出が必要なのか
MQL5のEAは、OnTick()(ティック=価格更新)ごとに実行されます。
しかし、1本のローソク足の中でも何十回・何百回と呼ばれるため、そのままでは以下の問題が発生します。
- 同じ条件で何度もエントリーしてしまう
- 無駄な計算が増えてパフォーマンス低下
- ロジックの再現性が崩れる(バックテストと乖離)
これを防ぐために、「新しいバーが確定したタイミングだけ処理する」必要があります。
3.2 基本ロジック(最重要)
datetime last_bar_time = 0;
void OnTick()
{
datetime current_time = itime(_Symbol, PERIOD_M5, 0);
if(current_time != last_bar_time)
{
last_bar_time = current_time;
// 新バー時のみ実行
Print("新しいバーが生成されました");
}
}
3.3 ロジックの仕組み
状態管理の考え方
| 変数 | 意味 |
|---|---|
| current_time | 現在のバーの時間 |
| last_bar_time | 前回処理したバー時間 |
判定ロジック
- 同じ → 同一バー(何もしない)
- 異なる → 新バー(処理実行)
この「時間比較」が最もシンプルで再現性が高い方法です。
3.4 実務での強化版(推奨)
datetime last_bar_time = 0;
void OnTick()
{
datetime current_time = itime(_Symbol, PERIOD_M5, 0);
// データ取得チェック
if(current_time == 0)
return;
// 初回実行時の初期化
if(last_bar_time == 0)
{
last_bar_time = current_time;
return;
}
// 新バー検出
if(current_time != last_bar_time)
{
last_bar_time = current_time;
// ▼ここに売買ロジックを書く
Print("新バー確定:処理開始");
}
}
3.5 よくある実装パターン
① エントリー制御
if(current_time != last_bar_time)
{
last_bar_time = current_time;
// 条件チェック
if(/* 売買条件 */)
{
// エントリー処理
}
}
② インジケーター計算の最適化
if(current_time != last_bar_time)
{
last_bar_time = current_time;
// 重い計算はここだけで実行
}
■ つまずきやすいポイント(重要)
index=0を使う意味を誤解
- 未確定バーだが「時間」は固定
→ 新バー検出には問題ない
last_bar_timeの初期化忘れ
- 初回で誤判定が起きる
グローバル変数にしない
- ローカルだと毎回リセットされる
■ よくある失敗
① 毎ティックでエントリー
→ 新バー制御なし
② index=1で比較してしまう
→ 1本遅れる(遅延エントリー)
③ timeframe不一致
→ 想定と違うタイミングで動く
■ 注意点(実務)
- マルチタイムフレームでは、時間足ごとに管理が必要
- VPS環境や低流動時間帯ではティックが来ないことがある
→ 厳密には「新バー確定=ティック到達時」
■ 実務的な結論
itime × 比較が最もシンプルで強力- EAの品質はこのロジックでほぼ決まる
- 再現性(バックテスト一致)を重視するなら必須
4. マルチタイムフレーム・複数通貨での応用
itimeは単一チャートだけでなく、複数時間足(MTF)や複数通貨ペア(マルチシンボル)での制御において真価を発揮します。
ただし、この領域はバグ・誤判定・再現性崩壊が起きやすいポイントでもあるため、構造的に理解することが重要です。
4.1 マルチタイムフレーム(MTF)の基本
例えば、以下のようなロジックを想定します。
- エントリー:5分足(M5)
- フィルター:1時間足(H1)
この場合、異なる時間足のバー生成タイミングを個別に管理する必要があります。
4.2 基本実装(MTF)
datetime last_m5_time = 0;
datetime last_h1_time = 0;
void OnTick()
{
datetime m5_time = itime(_Symbol, PERIOD_M5, 0);
datetime h1_time = itime(_Symbol, PERIOD_H1, 0);
if(m5_time == 0 || h1_time == 0)
return;
// M5新バー
if(m5_time != last_m5_time)
{
last_m5_time = m5_time;
// M5ベース処理
Print("M5新バー");
}
// H1新バー
if(h1_time != last_h1_time)
{
last_h1_time = h1_time;
// H1ベース処理
Print("H1新バー");
}
}
4.3 MTFでの設計ポイント(重要)
時間足ごとに状態を分離
last_bar_timeを共有してはいけない- → 各時間足ごとに管理
上位足は更新頻度が低い
- H1は1時間に1回しか更新されない
- → 条件評価タイミングに注意
同期ズレの理解
- M5とH1は同時に更新されない
- → ロジック設計を明確に分離する
■ つまずきやすいポイント(MTF)
変数の共用
→ 全時間足で同じ変数を使う(バグ)
タイミング依存
→ H1条件をM5で毎回チェック(非効率)
■ よくある失敗(MTF)
① 上位足を毎ティックで評価
→ 無駄&バグの温床
② 同期を前提にする
→ 実際はズレる
4.4 複数通貨ペア(マルチシンボル)
複数通貨ペアを扱う場合、symbol引数を明示的に指定します。
基本実装(マルチシンボル)
string symbols[] = {"EURUSD", "USDJPY"};
datetime last_times[2];
void OnTick()
{
for(int i = 0; i < ArraySize(symbols); i++)
{
datetime t = itime(symbols[i], PERIOD_M5, 0);
if(t == 0)
continue;
if(t != last_times[i])
{
last_times[i] = t;
Print(symbols[i], " 新バー");
}
}
}
4.5 マルチシンボルの設計ポイント
配列で管理する
- symbolごとに状態を持つ
データ未取得を考慮
- 初回は履歴がない場合あり
SymbolSelectの必要性(環境依存)
SymbolSelect("EURUSD", true);
■ つまずきやすいポイント(マルチシンボル)
データがない
→ itimeが0を返す
配列インデックスミス
→ 異なる通貨のデータを参照
■ よくある失敗(マルチシンボル)
① last_timeを1つしか用意しない
→ 全通貨が誤動作
② SymbolSelectを忘れる
→ データ取得できない
■ 注意点(実務)
- ブローカーによっては一部シンボルが無効
- ティック配信が来ないと更新されない
- VPS環境では通信遅延の影響あり
■ 実務的な結論
| 項目 | 重要度 |
|---|---|
| MTF | 中〜高 |
| マルチシンボル | 高(実装難易度あり) |
- itimeはスケーラブルな設計に向いている
- ただし、状態管理が全て
5. itimeを使うときの注意点・環境依存・バグ回避
itimeは構文自体は単純ですが、実務では**「関数の使い方」よりも「前提条件の扱い」**で失敗しやすいです。
特に初心者が詰まりやすいのは、バーの確定・履歴不足・時間の基準・ティック到達条件の4点です。
このセクションでは、itimeを安定運用するための注意点を整理します。
5.1 index=0とindex=1の違いを誤解しない
最も多い失敗は、index=0を「確定バー」だと思い込むことです。
index=0:現在形成中のバーindex=1:直前の確定バー
つまり、売買条件の判定に終値ベースの確定情報を使いたいなら、基本はindex=1を使うべきです。
一方で、新バー検出そのものはindex=0の時間比較で問題ありません。
理由は、現在バーの「価格」は変動しても、「バーの開始時刻」は固定だからです。
典型的な誤り
double close_price = iClose(_Symbol, PERIOD_M5, 0);
このように0番バーの価格を条件判定に使うと、未確定バーの途中変化に依存します。
その結果、バックテストと実運用で挙動がずれやすくなります。
より安全な考え方
- 新バー検出 →
itime(..., 0) - 確定足ベースの判定 →
iClose(..., 1)やCopyRates(..., 1, ...)
5.2 データ未取得・履歴不足を前提にする
itimeは、対象シンボルや時間足のデータが十分に読み込まれていない場合、期待通りに取得できないことがあります。
このとき、0が返る、または関連処理が成立しない形で不具合が見えることがあります。
最低限の防御コード
datetime bar_time = itime(_Symbol, PERIOD_H1, 0);
if(bar_time == 0)
{
Print("バー時間を取得できません。履歴未取得の可能性があります。");
return;
}
バー数も確認する
if(Bars(_Symbol, PERIOD_H1) < 2)
{
Print("バー数不足のため処理を中断します。");
return;
}
特にマルチタイムフレームやマルチシンボルでは、
現在のチャートには表示していない時間足・通貨ペアの履歴がまだ揃っていないことが普通にあります。
5.3 時刻はローカル時間ではなく、基本的に相場データ基準で考える
itimeが返すのはバーの時刻です。
実務上は、チャートやサーバー側の時系列データに基づく時刻として扱うのが安全です。
ここで混同しやすいのが、PCのローカル時間やTimeCurrent()との違いです。
混同しやすい時間の種類
itime:バーの開始時刻TimeCurrent():現在のサーバー時刻相当の現在時刻- PCの時計:ユーザー端末のローカル時間
この3つは完全一致するとは限りません。
そのため、「今が何時か」と「このバーが何時に始まったか」は別物として扱う必要があります。
注意点
- ブローカーによってサーバー時刻の基準が異なることがある
- 夏時間の影響が見える環境もある
- 複数口座・複数ブローカー比較では特にズレやすい
したがって、EA設計では
時刻比較をする対象を統一することが重要です。
5.4 新バーは「時刻が来た瞬間」ではなく「ティックが到達した瞬間」に検出される
これは見落としやすい重要ポイントです。
MQL5のEAはOnTick()で動くため、新しいバーがチャート上で理論上始まった瞬間ではなく、次のティックが届いたタイミングで初めて検出されます。
例えば、M5の新バー開始が12:00:00でも、流動性が低い時間帯で最初のティックが12:00:08に来たなら、EAが新バーを認識するのは12:00:08です。
これにより起きること
- 深夜・早朝・マイナー通貨で反応が遅く見える
- バックテストと実運用の印象差が出る
- 「ぴったり00秒で動かない」という誤解が起きる
実務上の判断
- 通常の裁量補助・EA運用では問題ないことが多い
- 秒単位の厳密制御が必要なら、設計自体を見直すべき
つまずきやすいポイント
itimeが壊れていると思い込む
実際には、履歴不足・シンボル未選択・バー数不足であることが多いです。
新バー検出と確定足判定を混同する
時間検出は0番、確定条件は1番という役割分担を意識すると整理しやすくなります。
環境差を無視する
ブローカーや時間設定の違いを考慮しないと、別環境で再現しないロジックになります。
よくある失敗
1. itime(..., 0)の価格情報も確定だと思う
時間は固定でも、価格は未確定です。
2. 取得失敗時の0チェックをしない
そのまま比較すると、初回起動時に誤判定の原因になります。
3. ティックが来ない状況を考慮しない
時間だけで厳密に即時反応すると誤解してしまうケースがあります。
実務での回避策
itimeの戻り値が0なら処理しない- バー数不足なら早期
return - 新バー検出と売買判定を分離する
- 時刻の基準はバー時間で統一する
- 低流動時間帯では検出遅延を前提にする
6. itimeと関連関数の使い分け(CopyTime・TimeCurrentなど)
itimeは単体でも強力ですが、実務では他の時間系関数と組み合わせて使うことで精度と効率が大きく向上します。
このセクションでは、特に混同されやすい以下の関数を整理します。
itimeCopyTimeTimeCurrentiTime(表記揺れに注意)
6.1 itimeとCopyTimeの違い
最も混乱が多いのがCopyTimeとの違いです。
| 項目 | itime | CopyTime |
|---|---|---|
| 取得対象 | 単一バー | 複数バー |
| 戻り値 | datetime | 配列 |
| パフォーマンス | 軽量 | やや重い |
| 用途 | 新バー検出・単発取得 | バックテスト・分析 |
itime(単発取得)
datetime t = itime(_Symbol, PERIOD_M5, 0);
- 1つの値だけ欲しいとき
- 新バー検出に最適
CopyTime(複数取得)
datetime times[];
CopyTime(_Symbol, PERIOD_M5, 0, 10, times);
- 直近10本のバー時間をまとめて取得
- 配列処理・分析に向く
■ 実務判断(重要)
- リアルタイム制御 →
itime - 履歴分析・ループ処理 →
CopyTime
6.2 itimeとTimeCurrentの違い
この2つは完全に用途が異なります。
| 項目 | itime | TimeCurrent |
|---|---|---|
| 意味 | バーの開始時刻 | 現在時刻 |
| 基準 | チャートデータ | サーバー時間 |
| 用途 | ローソク足制御 | 時刻判定 |
TimeCurrentの例
datetime now = TimeCurrent();
■ よくある誤用
誤り例
if(TimeCurrent() != last_time)
{
// 新バーと勘違い
}
これは新バー検出には使えません。
理由は、TimeCurrent()は単に現在時刻が進むだけだからです。
■ 正しい役割分担
- 新バー検出 →
itime - 時刻条件(例:ロンドン時間だけ動かす) →
TimeCurrent
6.3 iTimeとの違い(重要)
MQL4経験者が混乱しやすいポイントです。
- MQL4 →
iTime - MQL5 →
itime
違い
| 項目 | iTime | itime |
|---|---|---|
| 環境 | MQL4 | MQL5 |
| 構文 | ほぼ同じ | 同様 |
| 注意点 | MQL5では非推奨 | 標準 |
■ 実務判断
- MQL5では**
itimeを使うのが正解** - 古いコード移植時のみ
iTimeが出てくる
6.4 関数選択の最適戦略
実務で迷った場合は、以下で判断するとブレません。
パターン別
新バー検出
→ itime
過去データ分析
→ CopyTime
時刻ベース制御(例:9時だけ動かす)
→ TimeCurrent
■ つまずきやすいポイント
itimeとCopyTimeを混同
→ 単発なのに配列を使う(非効率)
TimeCurrentでバー検出しようとする
→ 根本的に用途が違う
MQL4の知識をそのまま使う
→ iTimeを使い続ける
■ よくある失敗
① CopyTimeを毎ティックで呼ぶ
→ 無駄に重い
② itimeをループ内で多用
→ パフォーマンス悪化
③ 時刻の基準を混ぜる
→ ロジックが破綻
■ 実務でのベストプラクティス
- リアルタイム処理はitime中心
- 分析はCopyTimeでまとめて取得
- 時間条件はTimeCurrentで補助
- 関数の役割を分離する
■ 結論(設計視点)
itimeは「トリガー」CopyTimeは「データ取得」TimeCurrentは「現在時刻」
この役割分担を守るだけで、
EAの安定性と再現性が大きく向上します。
7. FAQ(よくある質問と解決方針)
Q1. itimeが0を返すのはなぜですか?
回答方針:
主な原因は「データ未取得」です。
- 該当シンボルや時間足の履歴がロードされていない
SymbolSelectしていない(マルチシンボル時)- バー数不足
対策:
Bars()でバー数を確認itime(...) == 0なら処理を中断- 必要ならチャート表示・履歴ロードを促す
Q2. index=0とindex=1はどちらを使うべきですか?
回答方針:
用途で使い分けます。
- 新バー検出 →
index=0 - 売買ロジック(確定足) →
index=1
注意:index=0の価格は未確定のため、エントリー判断には使わないのが基本です。
Q3. 新しいバーが来たのに検出されません
回答方針:OnTick()はティック到達時にしか実行されないため、
新バー開始=即検出ではない点が原因です。
対策:
- ティックが来るまで待つ仕様と理解する
- 低流動時間帯では遅延を前提に設計する
Q4. itimeとCopyTimeはどちらを使えばいいですか?
回答方針:
目的で判断します。
- 単発取得(新バー検出) →
itime - 複数データ処理 →
CopyTime
注意:
リアルタイムEAでCopyTimeを多用するとパフォーマンス低下の原因になります。
Q5. マルチタイムフレームで正しく動きません
回答方針:
時間足ごとに状態管理していない可能性が高いです。
対策:
last_bar_timeを時間足ごとに分ける- 同一変数の使い回しを避ける
- 上位足は更新頻度が低いことを前提にする
Q6. マルチシンボルでitimeが取得できません
回答方針:
対象シンボルのデータがロードされていない可能性があります。
対策:
SymbolSelect(symbol, true)を実行itime == 0チェックを入れる- 配列管理でシンボルごとの状態を分離
Q7. TimeCurrent()で新バー検出できますか?
回答方針:
できません(用途が異なるため)。
TimeCurrent()→ 現在時刻itime→ バー開始時刻
結論:
新バー検出は必ずitimeを使用します。
Q8. バックテストと実運用で挙動が違います
回答方針:
以下の要因が多いです。
- 未確定バー(index=0)をロジックに使用している
- ティック到達タイミングの違い
- ブローカー時間の違い
対策:
- 確定足ベース(index=1)でロジックを組む
- 新バー検出で処理を限定
- 時刻基準を統一する
■ 実務まとめ(最短理解)
- 新バー検出 →
itime(..., 0)で時間比較 - 売買判定 → 確定足(index=1)
- エラー対策 →
0チェック+バー数確認 - 拡張 → MTF・マルチシンボルは状態分離必須
この4点を守れば、itime関連のバグはほぼ防げます。