MT4で未来時間に垂直線・ラベルを表示するMQL4実装手順

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

こんにちは。trade-engineer.com 運営者のHです。MT4で「現在足の右側(未来時間)に垂直線やラベルを表示したい」という要望は、エントリーシグナルの発生位置や判定時刻を視覚化したいときに必ず出てきます。固定座標で描くのではなく、時間と価格に応じて動的に位置が変わるオブジェクトを置けると、相場の進行に合わせて参照点が自動で追随してくれるため、検証中も実運用中も格段にチャートが読みやすくなります。今回はMT4 垂直線とラベルを未来時間に表示するインジケーターを、MQL4のコピペで動く完成コード付きで実装していきます。

記事のポイント
  • Time[0]とChartPeriod()で未来時間を計算する具体的な仕組み
  • OBJ_VLINEとOBJ_LABELを動的に再描画するMQL4の完成コード
  • パラメータ化して表示位置や色を自由にカスタマイズする方法
  • オブジェクトが消えない・複数表示される典型エラーの対処法
目次

MT4 垂直線とラベルを未来時間に表示するMQL4の仕組み

MT4で未来時間(現在足の右側)にオブジェクトを描画するには、X座標を直接ピクセル指定するのではなく、時間軸の未来側に時刻データを与えるアプローチを取ります。チャートのシフト機能を有効にしているユーザーであれば、現在足から数本先の空白エリアにオブジェクトを置きたい場面が頻繁にあるはずです。ここではその基礎となる時間計算、オブジェクト種別の選択、OnCalculateの再描画設計までを整理していきます。

未来時間オブジェクトを表示する用途と効果

現在足の右側(未来時間)に垂直線やラベルを表示したい場面は意外と多いです。例えば判定時刻ベースでロジックを組んでいる場合、エントリー時刻から5本先・10本先の判定足を視覚的に示しておくと、ロジック検証中もリアルタイムトレード中も「今どの足を待っているか」が一目で分かります。エントリー価格を未来時間側にラベルとして残しておけば、現在価格との乖離も瞬時に把握できます。さらに、経済指標発表の予定時刻を未来時間の垂直線として描いておけば、相場急変前にポジション整理する判断材料になります。

固定座標(OBJ_LABELのX_DISTANCE指定)でも代替できますが、チャートをスクロールしたりズーム倍率を変えたりすると相対位置がズレるため、時間と価格に紐づく座標系(OBJ_VLINEとOBJ_LABEL_TIME_PRICEモード)を使うのがエンジニアリング的に正解です。本記事の手法は再描画コストも低く、Tick単位で位置を更新しても重さを感じないレベルに抑えられます。ロジック検証用の補助インジケーターとして気軽に追加できる軽量さも利点です。MT4上にアローオブジェクトを表示する基礎と組み合わせれば、エントリーポイントと判定ポイントの両方を可視化する仕組みが完成します。

動作環境とMT4・MQL4のバージョン確認

本記事のコードはMetaTrader 4(MT4)+ MQL4を前提としています。MT5/MQL5ではObjectCreate関数のシグネチャや時間関連関数の挙動が異なるため、コピペでは動作しません。ビルド番号は1340以降を想定していますが、それ以前のレガシービルドでもMqlDateTime構造体に依存しない範囲では問題なく動作します。新規にMT4環境を準備する場合はMT4のダウンロードとインストール手順・初期設定まとめを参照してビルド番号を確認してください。

MetaEditorのバージョンも確認しておきます。ヘルプメニュー→「MetaQuotes Language Editorについて」でビルド番号が確認できます。古いビルドだとObjectSetIntegerが使えずObjectSet(旧API)で代用する必要があり、動的な色変更などのコードが書きにくくなります。MQL4のリファレンスでも新APIの利用が推奨されていますので、特別な事情がない限り最新ビルドで進めるのが無難です。なお、本記事のコードはストラテジーテスター内ではなくリアルタイムチャートでの動作を前提にしています。バックテスト中はObjectCreateの動作が制限されることがあるため、検証目的の場合は別途デバッグ用のPrint文を仕込んでください。検証フローについてはカスタムインジケーターの作成から導入まで基本的な部分を理解するで全体像を押さえておくと、後段のコード解説が頭に入りやすくなります。

Time[0]とChartPeriod()で未来時間を求める計算式

未来時間を表現する基本式は次のとおりです。

int n = 5;
datetime label_time = Time[0] + ChartPeriod() * 60 * n;

Time[0]は「現在足の開始時刻」をdatetime型(UNIX時間秒)で返します。ChartPeriod()はチャートの時間足を分単位で返す関数で、M1なら1、M5なら5、H1なら60を返します。これを秒に変換するために60を掛け、さらにn本分先にずらしたい本数を掛け合わせると、現在足からn本先の足の開始時刻が秒精度で求まります。datetime型に対する加減算は内部的にlong(秒)として扱われるため、計算誤差が出ません。

注意点として、Time[0]は「現在足の開始時刻」であって「現在時刻」ではありません。Tick受信ごとに時刻が更新されるわけではなく、新しい足が確定したタイミングで更新されます。リアルタイムの未来時間が必要な場合はTimeCurrent()を使う選択肢もありますが、足単位でロジックを組むなら必ずTime[0]ベースで揃えるのが筋です。これによって「現在足の確定時刻と判定足の開始時刻」のような時間関係が常に整数本数分の足としてズレなく表現できます。判定時刻ベースでロジックを設計する場合の時間取り扱いについては、過去のMQL学習実践編|ラベルオブジェクトを表示して勝敗結果を確認するで詳しく扱っていますので、合わせて参照してください。MQL4公式リファレンス(OnCalculate)も時間配列の挙動を確認するときに役立ちます。

OBJ_VLINEとOBJ_LABELの役割分担

未来時間に「縦線」を引きたい場合はOBJ_VLINE(垂直線オブジェクト)を使います。OBJ_VLINEは時間軸のみを引数に取り、価格軸を持ちません。一方、特定の時間・価格点に文字を表示したい場合はOBJ_LABELではなくOBJ_TEXTを使うのがMQL4では正解です。OBJ_LABELは「ピクセル座標固定」のテキストオブジェクトで、チャートをスクロールしてもラベルがウィンドウの相対位置に残り続けます。これは「常に画面左上に勝敗カウンタを表示しておきたい」ような用途には向きますが、未来時間にラベルを置きたい本記事のケースには合いません。

本記事ではOBJ_VLINE(垂直線)とOBJ_TEXT(時間・価格に紐づくテキスト)の組み合わせで実装します。OBJ_TEXTはObjectCreateの引数に時間と価格を渡せるため、未来時間の指定座標に文字列を配置できます。色やフォントサイズはObjectSetInteger / ObjectSetStringで後から変更可能で、Tickごとに表示内容を更新することもできます。なお、OBJ_TEXTは描画コストが低く、数十個程度なら同時表示してもチャートが重くなりません。表示文字列に現在価格やスプレッドを動的に埋め込むことで、ラベルというよりリアルタイムインフォメーションパネルとして活用できる柔軟性があります。ObjectCreate公式仕様を一度眺めてからコードを読むと、各引数の意味がより明確になります。

OnCalculateで動的に再描画する設計

カスタムインジケーターのOnCalculate関数はTickを受信するたびに呼ばれます(チャート上にTickが来た時、または新規ヒストリカルバーがロードされた時)。未来時間オブジェクトをTickごとに更新するか、新規足確定時のみ更新するかは設計判断になります。Tickごとに更新する場合は表示価格を最新値で書き換えられる反面、計算コストが増えます。新規足確定時のみ更新する場合はオブジェクト位置が固定化されるため軽量ですが、価格表示がリアルタイムに追随しません。

本記事のサンプルコードでは「OnInitでオブジェクト生成、OnCalculateで位置・テキスト更新、OnDeinitで削除」という三段構成を採用します。OnInitでObjectCreateを呼んで一度だけオブジェクトを作成し、以降はObjectSetIntegerやObjectSetDoubleで位置と内容を書き換えるだけにすることで、不要なObjectCreate/ObjectDelete往復を避けます。OnDeinitでObjectDeleteを呼んでおかないと、インジケーターを取り外してもオブジェクトがチャートに残り続けるため、必ず実装してください。チャート切替時やテンプレート切替時の挙動も含めて、OnDeinitの実装は地味だが重要な仕事です。

point

OnInitで作成・OnCalculateで更新・OnDeinitで削除の三段構成にすると、Tick処理が軽くなり、インジケーター取り外し時のゴミオブジェクトも残らない。

MQL4インジケーター実装と動作検証・応用方法

ここからは実際のコードを示し、ブロックごとに何をしているかを解説します。コピペでそのまま動く完成版を提示するので、お手元のMetaEditorで新規インジケーター(Custom Indicator)として保存し、コンパイルしてチャートに適用してください。MT4 垂直線とラベルが、現在足から指定本数分先の未来時間に表示されるはずです。

完成版MQL4コード(コピペで動くフル実装)

下記がインジケーター本体の完成コードです。新規にMetaEditorで「FutureLabel.mq4」のような名前で保存してください。

//+------------------------------------------------------------------+
//|                                                  FutureLabel.mq4 |
//|                          Copyright 2025, trade-engineer.com      |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 0
#property strict

input int    Shift_Bars   = 5;            // 未来側にずらす本数
input color  Line_Color   = clrDodgerBlue;// 垂直線の色
input int    Line_Width   = 1;            // 垂直線の太さ
input color  Text_Color   = clrWhite;     // テキスト色
input int    Text_Size    = 10;           // テキストサイズ

const string OBJ_VLINE_NAME = "FL_VLINE";
const string OBJ_TEXT_NAME  = "FL_TEXT";

int OnInit()
{
   ObjectCreate(0, OBJ_VLINE_NAME, OBJ_VLINE, 0, Time[0], 0);
   ObjectSetInteger(0, OBJ_VLINE_NAME, OBJPROP_COLOR, Line_Color);
   ObjectSetInteger(0, OBJ_VLINE_NAME, OBJPROP_WIDTH, Line_Width);
   ObjectSetInteger(0, OBJ_VLINE_NAME, OBJPROP_BACK,  true);

   ObjectCreate(0, OBJ_TEXT_NAME, OBJ_TEXT, 0, Time[0], Close[0]);
   ObjectSetInteger(0, OBJ_TEXT_NAME, OBJPROP_COLOR,    Text_Color);
   ObjectSetInteger(0, OBJ_TEXT_NAME, OBJPROP_FONTSIZE, Text_Size);
   ObjectSetString (0, OBJ_TEXT_NAME, OBJPROP_FONT,     "Arial");
   return(INIT_SUCCEEDED);
}

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[])
{
   datetime future_time = Time[0] + ChartPeriod() * 60 * Shift_Bars;
   double   price       = Close[0];

   ObjectSetInteger (0, OBJ_VLINE_NAME, OBJPROP_TIME,  future_time);

   ObjectSetInteger (0, OBJ_TEXT_NAME,  OBJPROP_TIME,  future_time);
   ObjectSetDouble  (0, OBJ_TEXT_NAME,  OBJPROP_PRICE, price);
   ObjectSetString  (0, OBJ_TEXT_NAME,  OBJPROP_TEXT,  DoubleToString(price, _Digits));

   return(rates_total);
}

void OnDeinit(const int reason)
{
   ObjectDelete(0, OBJ_VLINE_NAME);
   ObjectDelete(0, OBJ_TEXT_NAME);
}

このコードはOnInitで垂直線とテキストを生成し、OnCalculateでTickごとに位置と表示価格を更新、OnDeinitで取り外し時に削除します。インプットパラメータでシフト本数・色・太さ・フォントサイズを変更できるため、複数チャートに適用しても見分けが付きます。

各処理ブロックの解説

#propertyディレクティブはコンパイラに対するメタ情報の宣言です。indicator_chart_windowはメインチャートウィンドウに描画することを示し、indicator_buffers 0はラインバッファを使わないことを意味します(オブジェクト描画のみなのでバッファ不要)。strictは型チェックを厳格にするおまじないで、新規コードでは必ず付けます。inputで宣言した変数はインジケーターのパラメータ画面に表示され、ユーザーが値を変更できます。const stringで宣言したオブジェクト名はマジックナンバーと同じ役割を果たし、別のインジケーターと名前衝突しないように一意にしておきます。

OnInit内のObjectCreateは引数を6つ取ります。第1引数はチャートID(0はカレントチャート)、第2引数はオブジェクト名、第3引数はオブジェクト種別、第4引数はサブウィンドウ番号、第5引数は時間、第6引数は価格です。OBJ_VLINEは価格不要なので0を渡しますが、引数省略はできません。ObjectSetIntegerで色・太さ・前面/背面フラグを設定します。OBJPROP_BACKをtrueにするとローソク足の背面に描画され、視認性が上がります。OBJ_TEXTの場合はObjectSetString(OBJPROP_FONT)でフォント、ObjectSetInteger(OBJPROP_FONTSIZE)でサイズを指定します。OnCalculateではObjectSetIntegerでOBJPROP_TIMEを書き換えることでオブジェクトの時間軸位置を更新できます。OBJ_TEXTの表示文字列はDoubleToStringで価格を_Digits桁で整形してから渡しています。

コンパイルからチャート適用までの手順

MetaEditorで保存したらF7キーまたはツールバーの「コンパイル」ボタンを押します。エラー0、警告0であれば成功です。エラーが出る場合は行番号と内容をエラーペインで確認してください。よくあるエラーは「セミコロン忘れ」「中括弧の対応漏れ」「inputキーワードのスペルミス」など、純粋なシンタックスエラーです。コンパイルに成功するとMT4のターミナル「ナビゲーター」→「カスタム指標」配下にFutureLabelが追加されます。

適用したいチャートを開き、ナビゲーターからFutureLabelをドラッグ&ドロップします。パラメータダイアログでShift_Barsを5、Line_Colorを好きな色に設定してOKを押すと、現在足から5本先の未来時間に垂直線とテキスト(現在終値)が表示されます。新しいTickが来るたびにテキストの価格部分が最新値に更新され、垂直線の位置はチャート時間が進むにつれて自動で右方向にシフトしていきます。チャートの右側余白が足りない場合は、チャート上で右クリック→「プロパティ」→「コモン」タブで「チャートの右端をシフト」にチェックを入れて、右側余白を広げてください。動作確認の流れはカスタムインジケーターの作成から導入まで基本的な部分を理解すると同じです。

パラメータ化と表示位置のカスタマイズ

本コードはinputで主要パラメータを公開しているため、コードを書き換えずに表示挙動を変更できます。Shift_Barsを増減すれば未来時間の距離を変えられますし、Line_Colorを変えればチャート背景色に合わせた配色にできます。複数の判定時刻を示したい場合は、オブジェクト名と関連入力をペア化して配列管理にすると拡張しやすくなります。例えばShift_Bars_1, Shift_Bars_2, Shift_Bars_3を用意して、それぞれに対応するOBJ_VLINE_NAME_1, _2, _3を生成・更新する構成です。

テキスト内容のカスタマイズも自由です。DoubleToString(price, _Digits)の部分を、現在のスプレッド表示にしたければStringFormat(“Spread:%d”, spread[0])に変更、判定時刻までの残り秒数を表示したければStringFormat(“T-%d”, (int)(future_time – TimeCurrent()))のように書き換えるだけです。アンカーポイント(OBJPROP_ANCHOR)を変えればテキストの基準点を左上・中央・右下などに切り替えられるので、垂直線とテキストの位置関係も自由に調整できます。ロジックとの連携を考えるなら、エントリーシグナル発生時のみテキストを赤に変える、判定時刻接近時に点滅させるといった応用も簡単に追加できます。

memo

外部からObjectFindでオブジェクト存在チェックを入れておくと、別ツールが同名オブジェクトを削除した場合も自動復旧できる。OnCalculate冒頭でObjectFind() < 0 ならObjectCreateを再実行する分岐を追加するだけ。

よくあるエラーと対処法

つまずきやすい代表例を3つ挙げます。1つ目は「オブジェクトが表示されない」。多くの場合、ObjectCreateの戻り値(bool)を確認せずに進めているケースです。ObjectCreateがfalseを返した場合はGetLastError()でエラーコードを取得します。コード4200(ERR_OBJECT_ALREADY_EXISTS)が返るなら同名オブジェクトが既存です。OnInit先頭でObjectDelete(0, OBJ_VLINE_NAME)を実行してから生成するか、ObjectFindで存在チェックしてからCreateする防御的なコードに変えてください。

2つ目は「インジケーターを外してもオブジェクトが残る」。OnDeinit内のObjectDeleteを忘れている、または別の名前で呼んでいることが原因です。const stringで定義した名前変数をそのまま使うようにすればタイポは防げます。3つ目は「複数チャートに適用すると上書きされる」。これはオブジェクト名がチャート間で共通になっているために発生します。OBJ_VLINE_NAMEを”FL_VLINE_” + IntegerToString(ChartID())のようにチャートIDでサフィックス化すると衝突しなくなります。チャート1枚に対して1回ずつ適用するなら問題になりませんが、複数チャート常時表示の運用では必須の対応です。MT4本体の挙動全般を確認したいときはMT4インストール手順とポータブルモード設定|FX開発者向けでビルド番号を見直すと原因の切り分けが進みます。

まとめ:MT4 垂直線とラベルを未来時間に表示する実装のポイント

本記事ではMT4 垂直線とラベルを現在足の右側(未来時間)に動的表示するMQL4インジケーターを実装しました。Time[0]とChartPeriod()×60×Nで未来時間秒を計算し、OBJ_VLINEとOBJ_TEXTをObjectCreateで生成、OnCalculateで位置と表示内容を更新、OnDeinitで削除する三段構成にすることで、Tick処理を軽く保ちながらゴミオブジェクトも残さない設計が完成しました。

このパターンは判定時刻表示・経済指標カウントダウン・エントリー価格マーカーなど、応用範囲が広いテンプレートです。input変数を増やせばオブジェクト数を可変にできますし、テキスト内容を動的に組み立てればリアルタイムの相場情報パネルとしても機能します。検証段階のロジック開発で「いま何本目の足にいるのか」「次の判定までどれくらいか」を視覚化したいときは、今回のコードを土台にして必要な情報を足していくのが手早い実装ルートです。MQL4のオブジェクト操作に慣れてきたら、ラベルではなくOBJ_TRENDなど時間範囲を持つオブジェクトも同じパターンで動的更新できます。MT4 垂直線とラベルの実装をきっかけに、自分専用のチャート補助ツールを増やしていきましょう。

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

コメント

コメントする


reCaptcha の認証期間が終了しました。ページを再読み込みしてください。

目次