アラート専用の価格ラインを1本引くために、「あと3pips上に線を引きたい」

と思うたびに、コードの数値を書き換えてコンパイルし直していませんか。

ObjectGetDouble・ObjectSetDoubleという関数と、

CHARTEVENT_OBJECT_DRAGというイベントを組み合わせれば、

チャート上でラインをマウスでドラッグするだけで、

アラート価格をその場で変更できるツールが作れます。

この記事では、非推奨になった旧関数ObjectGet/ObjectSetとの違いから、

ドラッグされた価格を取得してアラートを出す設計まで、実際に動くコード付きで解説します。

この記事で分かること
・ObjectGetDouble/ObjectSetDoubleの基本構文
・非推奨になった旧ObjectGet/ObjectSetとの違い
・マウスでドラッグできる価格ラインの作り方
・CHARTEVENT_OBJECT_DRAGでドラッグ後の新しい価格を取得する方法
・価格到達時に一度だけアラートを鳴らし、ライン移動で再武装する設計
  1. ObjectGetDouble/ObjectSetDoubleとは何か(非推奨ObjectGet/ObjectSetとの違い)
    1. 旧関数ObjectGet/ObjectSetがなぜ非推奨になったか
    2. ObjectGetDoubleの構文(2つのバリアント)
    3. ObjectSetDoubleの構文(2つのバリアント)
  2. マウスでドラッグできる価格ラインの作成
    1. ObjectCreateで水平線を1本作る
    2. ドラッグ可能にするためのOBJPROP_SELECTABLE設定
    3. ObjectGetDoubleで現在の価格を取得する
  3. CHARTEVENT_OBJECT_DRAGでドラッグ後の価格を取得する
    1. OnChartEventの基本構文
    2. sparamでドラッグされたオブジェクト名を判定する
    3. ドラッグ後の新しい価格をObjectGetDoubleで取得する
  4. 価格到達でアラートを出す処理を組み込む
    1. 前回のBidと比較してクロスを判定する
    2. 一度だけアラートを鳴らすためのフラグ管理
    3. ラインを動かしたらアラート済みフラグをリセットする
  5. 実際に動くコード全体
  6. MetaEditorでのコンパイル・実行手順
  7. よくあるエラーと注意点
    1. ObjectGetDoubleが0を返す原因
    2. ドラッグしてもCHARTEVENT_OBJECT_DRAGが発火しない原因
    3. MQL4とMQL5の違い
  8. よくある質問
    1. 複数の価格ラインを同時にドラッグ対応にできますか?
    2. EAの中でこの仕組みを使ってエントリー価格を指定できますか?
    3. ObjectSetDoubleでラインの価格をプログラム側から動かせますか?
  9. 【MQL4】ObjectGetDouble・ObjectSetDoubleでドラッグ可能な価格アラートラインを作る方法について解説してみた:まとめ
    1. 関連記事

ObjectGetDouble/ObjectSetDoubleとは何か(非推奨ObjectGet/ObjectSetとの違い)

まず、この2つの関数がどんな役割を持つのかを確認します。

旧関数ObjectGet/ObjectSetがなぜ非推奨になったか

本サイトのオブジェクト系記事でもたびたび触れてきたとおり、

旧来のObjectGet()/ObjectSet()は、

座標・価格(double)も、色・幅(int)も、

同じ関数で一律にdouble型としてやり取りしていました。

用語補足
・ObjectGet/ObjectSetは公式リファレンスで「非推奨」と明記されている
・型ごとに専用の関数(Integer/Double/String版)が用意されている

ObjectGetDoubleの構文(2つのバリアント)

double ObjectGetDouble(
   long   chart_id,
   string object_name,
   int    prop_id,
   int    prop_modifier=0
);

bool ObjectGetDouble(
   long    chart_id,
   string  object_name,
   int     prop_id,
   int     prop_modifier,
   double &double_var
);

chart_idは0で現在のチャート、

prop_idはOBJPROP_PRICE等のプロパティ識別子です。

prop_modifierはフィボナッチツールのように、

複数の価格点を持つオブジェクト用の番号です。

水平線のように価格点が1つだけのオブジェクトでは0を指定します。

ObjectSetDoubleの構文(2つのバリアント)

bool ObjectSetDouble(
   long   chart_id,
   string object_name,
   int    prop_id,
   double prop_value
);

bool ObjectSetDouble(
   long   chart_id,
   string object_name,
   int    prop_id,
   int    prop_modifier,
   double prop_value
);

引数の並びはObjectGetDoubleとほぼ対になっており、

最後の引数に「設定したい値」を渡す点だけが違います。

マウスでドラッグできる価格ラインの作成

実際に、ドラッグ操作を受け付ける水平線を作ります。

ObjectCreateで水平線を1本作る

ObjectCreate(0, "DraggableAlertLine", OBJ_HLINE, 0, 0, Bid);
ObjectSetInteger(0, "DraggableAlertLine", OBJPROP_COLOR, clrOrange);
ObjectSetInteger(0, "DraggableAlertLine", OBJPROP_WIDTH, 2);

OBJ_HLINEは水平線オブジェクトで、価格(第6引数)だけを指定すれば描画できます。

ドラッグ可能にするためのOBJPROP_SELECTABLE設定

ObjectSetInteger(0, "DraggableAlertLine", OBJPROP_SELECTABLE, true);

OBJPROP_SELECTABLEがfalseになっていると、

そもそもマウスでクリックして選択することができず、ドラッグ自体が発生しません。

水平線は既定でtrueですが、明示的に指定しておくと事故が起きにくくなります。

ObjectGetDoubleで現在の価格を取得する

double linePrice = ObjectGetDouble(0, "DraggableAlertLine", OBJPROP_PRICE, 0);

OBJPROP_PRICEは水平線の価格プロパティで、これが「今ラインが引かれている価格」

を返します。

CHARTEVENT_OBJECT_DRAGでドラッグ後の価格を取得する

ドラッグされたことをどうやって検知するかを確認します。

OnChartEventの基本構文

void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   // ここでイベントの種類(id)ごとに処理を分岐する
  }

OnChartEventは、チャート上でクリック・ドラッグ・キー入力等の

イベントが発生するたびに、MT4から自動的に呼び出される関数です。

sparamでドラッグされたオブジェクト名を判定する

if(id == CHARTEVENT_OBJECT_DRAG && sparam == "DraggableAlertLine")
  {
   // このオブジェクトがドラッグされた
  }

CHARTEVENT_OBJECT_DRAGが発生したとき、

sparamには「ドラッグされたオブジェクトの名前」が入ります。

自分が作ったラインの名前と一致するかを確認することで、

他のオブジェクト(水平線を複数引いていた場合など)と区別できます。

ドラッグ後の新しい価格をObjectGetDoubleで取得する

double newPrice = ObjectGetDouble(0, "DraggableAlertLine", OBJPROP_PRICE, 0);

ドラッグが終わった時点で改めてObjectGetDoubleを呼べば、

ユーザーが動かした後の新しい価格が取得できます。

価格到達でアラートを出す処理を組み込む

ラインの価格に実勢価格が到達したときの通知処理を作ります。

前回のBidと比較してクロスを判定する

bool crossedUp   = (prevBid < linePrice && Bid >= linePrice);
bool crossedDown = (prevBid > linePrice && Bid <= linePrice);

「Bidがラインの価格と完全に一致したか」ではなく、

前回のBidと今回のBidの間にラインの価格を挟んだかどうかで判定すると、

値が1pipsも動かない静かな相場でも取りこぼしません。

一度だけアラートを鳴らすためのフラグ管理

注意
・Alert()に直結すると、価格が上下するたびに何度も鳴ってしまう
・alertedという変数で「鳴らし終えたか」を管理し、以降は鳴らさない

ラインを動かしたらアラート済みフラグをリセットする

if(id == CHARTEVENT_OBJECT_DRAG && sparam == "DraggableAlertLine")
  {
   alerted = false;
  }

CHARTEVENT_OBJECT_DRAGの中でalertedをfalseに戻すことで、

ユーザーがラインを動かした時点で「もう一度見張る」状態に、

自動的に再武装される設計になります。

実際に動くコード全体

ここまでの要素をまとめた、実際に動くインジケーターです。

//+------------------------------------------------------------------+
//|                                       DraggableAlertLine.mq4      |
//|                     Copyright 2026, FX-EA System Project Creator |
//|                        https://creator.fx-ea-system-project.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, FX-EA System Project Creator"
#property link      "https://creator.fx-ea-system-project.com/"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 0

#define LINE_NAME "DraggableAlertLine"

bool   alerted = false;
double prevBid = 0;

int OnInit()
  {
   if(ObjectFind(0, LINE_NAME) < 0)
     {
      ObjectCreate(0, LINE_NAME, OBJ_HLINE, 0, 0, Bid);
      ObjectSetInteger(0, LINE_NAME, OBJPROP_COLOR, clrOrange);
      ObjectSetInteger(0, LINE_NAME, OBJPROP_WIDTH, 2);
      ObjectSetInteger(0, LINE_NAME, OBJPROP_SELECTABLE, true);
     }
   prevBid = Bid;
   return(INIT_SUCCEEDED);
  }

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

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[])
  {
   double linePrice = ObjectGetDouble(0, LINE_NAME, OBJPROP_PRICE, 0);

   if(!alerted)
     {
      bool crossedUp   = (prevBid < linePrice && Bid >= linePrice);
      bool crossedDown = (prevBid > linePrice && Bid <= linePrice);

      if(crossedUp || crossedDown)
        {
         Alert(_Symbol, "の価格が ", DoubleToString(linePrice, _Digits), " へ到達しました");
         alerted = true;
        }
     }

   prevBid = Bid;
   return(rates_total);
  }

void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   if(id == CHARTEVENT_OBJECT_DRAG && sparam == LINE_NAME)
     {
      alerted = false;
      Print("ラインが移動されました。新しい価格: ",
            DoubleToString(ObjectGetDouble(0, LINE_NAME, OBJPROP_PRICE, 0), _Digits));
     }
  }

MetaEditorでのコンパイル・実行手順

実際にMT4で動かすまでの手順を確認します。

  1. MetaEditorで新規カスタムインジケーター「DraggableAlertLine」を作成し、上のコードを貼り付けてコンパイルする
  2. MT4のナビゲーターからチャートへドラッグ&ドロップで適用する
  3. チャート上にオレンジ色の水平線が表示されることを確認する
  4. 水平線をクリックして選択し、上下にドラッグして動かしてみる
  5. 「エキスパート」タブに移動先の価格を示すPrintの出力が表示されることを確認する
  6. 価格がラインに到達したら、Alertのポップアップが表示されることを確認する

よくあるエラーと注意点

実装でつまずきやすいポイントをまとめます。

ObjectGetDoubleが0を返す原因

原因 対処
オブジェクト名のスペルミス ObjectCreateで作った名前とObjectGetDoubleに渡す名前を定数(#define)で統一する
prop_idの指定間違い(OBJPROP_PRICEではなくOBJPROP_PRICE1等) OBJ_HLINEにはOBJPROP_PRICEのみ存在することを公式リファレンスで確認する
OnInitより前にObjectGetDoubleを呼んでいる オブジェクト作成後に呼び出す順序を守る

ドラッグしてもCHARTEVENT_OBJECT_DRAGが発火しない原因

OBJPROP_SELECTABLEがfalseに設定されている場合、

そもそもマウスでの選択自体ができず、ドラッグイベントも発生しません。

ObjectSetIntegerでOBJPROP_SELECTABLEを、

trueにしているか確認してください。

MQL4とMQL5の違い

ObjectGetDouble/ObjectSetDouble、

CHARTEVENT_OBJECT_DRAGの関数シグネチャ・定数名は、

MQL4とMQL5で完全に共通です。

現行のMQL4は内部的にMQL5と同じコンパイラ基盤を使っているため、

オブジェクト操作まわりの新しいAPIに関しては、

両者の違いを気にする必要がほとんどない領域の1つです。

よくある質問

ドラッグ可能な価格ラインについて、よく検索される疑問に回答します。

複数の価格ラインを同時にドラッグ対応にできますか?

できます。

ライン名を配列やループで管理し、

OnChartEventのsparamをどのライン名と一致するか、

判定する処理をライン本数ぶん繰り返せば対応できます。

EAの中でこの仕組みを使ってエントリー価格を指定できますか?

可能です。

本記事はアラート専用として紹介しましたが、

ObjectGetDoubleで取得した価格を、

OrderSendの価格として使えば、

「チャート上でドラッグして決めた価格に指値を置く」EAも作れます。

ObjectSetDoubleでラインの価格をプログラム側から動かせますか?

動かせます。

ObjectSetDouble(0, "DraggableAlertLine", OBJPROP_PRICE, 新しい価格);

のように呼び出せば、ユーザーのドラッグを待たずに、

プログラム側からラインの位置を更新できます。

(例: 現在値から常に一定pips上に追従させる等)

【MQL4】ObjectGetDouble・ObjectSetDoubleでドラッグ可能な価格アラートラインを作る方法について解説してみた:まとめ

ObjectGetDouble/ObjectSetDoubleは、

非推奨になった旧ObjectGet/ObjectSetの後継として、

プロパティの型ごとに分かれた現行のAPIです。

CHARTEVENT_OBJECT_DRAGと組み合わせれば、

コードを書き直すことなく、チャート上の操作だけでアラート価格を変更できるツールが作れます。

関連記事