MT5で水平線タッチ時にアラート・メール・プッシュ通知を実行するツールを作成する【MQLプログラミングの基礎】
1.ファイルの新規作成
この記事では、手動で引いた水平線へローソク足(現在価格)がタッチしたときに、各種通知(アラート・メール・プッシュ通知)を実行するツールを作成します。
※この記事はMQL5の内容です。MQL4に対応した類似記事は以下を参照してください。
MetaEditorの「新規作成」アイコンをクリックしてMQLウィザードを開始します。
「カスタムインディケータ」を選択して「次へ」をクリック。
ファイル名を「LineTouchAlert.mq5」とします。
パラメーターの「追加」ボタンを押して「ALERT」「MAIL」「PUSH」を追加し、各パラメーターのタイプは「bool」、初期値は「true」とした後に「次へ」をクリック。
イベントハンドラは一番上のOnCalculateのみを選択して「次へ」をクリック。
「カスタムインディケータの描画プロパティ」では、特に何も追加せず「完了」をクリックすれば、ファイルのベースが作成されます。
今回のファイルでは、インジケーターバッファを利用しないので、「#property indicator_chart_window」の行の下へ、下記を追加します。
#property indicator_buffers 0
#property indicator_plots 0
2.チャート上にある水平線の検出
OnCalculate関数内に下記のfor文を追加し、チャート上の水平線を検出します。
for (int i = 0; i < ObjectsTotal(0, 0, OBJ_HLINE); i++) {
string name = ObjectName(0, i, 0, OBJ_HLINE);
}
ObjectsTotal関数は、チャート上のオブジェクトの数を出力します。
引数は、ObjectsTotal(チャートID, ウィンドウ番号, オブジェクトの種類)を示しており、上記for文の指定であれば、チャートのメインウィンドウにある水平線の数が返されます。
ObjectName関数にて、全ての水平線の名称を順に取得しています。
3.水平線への価格タッチ判定
for文内(nameを定義した次の行)に下記を追加し、各水平線の価格情報を取得します。
double price = ObjectGetDouble(0, name, OBJPROP_PRICE, 0);
OnCalculateで定義されている価格情報の配列close[]を、最新足を0番目の足として扱うために、下記の行をfor文の前に追加します。
ArraySetAsSeries(close, true);
for文内(priceを定義した次の行)にタッチ判定の式を追加します。
bool touchUp = close[0] >= price && close[1] < price;
bool touchDown = close[0] <= price && close[1] > price;
touchUpが水平線の下から上への価格タッチ、touchDownは水平線の上から下への価格タッチを判定しています。
close[0]は最新価格、close[1]は最新未確定足より1本前の確定足の終値です。
タッチ判定が成立したときのみ処理を実行するよう、下記のif文を追加します。
if (touchUp || touchDown) {
}
4.各種通知の実行
タッチ判定成立のif文内に、通知する文字列を定義します。
string text = _Symbol + " : Line Touch " + (touchUp ? "Up" : "Down");
例えば、米ドル/円チャートで水平線の下から上へタッチした場合、「USDJPY : Line Touch Up」と通知されます。
上から下へのタッチの場合、Upの文字がDownになります。
水平線の価格情報も通知に加えるため、下記の行を追加します。
text += " (" + DoubleToString(price, _Digits) + ")";
アラート通知を実行するために、下記の式を追加します。
if (ALERT) Alert(text);
メール通知を実行するために、下記の式を追加します。
メールの件名は、本ツールのファイル名称(MQLInfoString(MQL_PROGRAM_NAME))としています。
if (MAIL) SendMail(MQLInfoString(MQL_PROGRAM_NAME), text);
プッシュ通知を実行するために、下記の式を追加します。
if (PUSH) SendNotification(text);
5.1本のローソク足での通知を1回のみに制限
OnCalculateで定義されている価格情報の配列time[]を、最新足を0番目の足として扱うために、下記の行をfor文の前に追加します。
ArraySetAsSeries(time, true);
通知を実行したときの最新足の時間を、文字情報として水平線に入力するため、下記の式をif文内に追加します(オブジェクトのプロパティ「共有」タブの「説明」欄に時間情報の文字列が記憶されます)。
ObjectSetString(0, name, OBJPROP_TEXT, TimeToString(time[0], TIME_DATE | TIME_MINUTES));
水平線から通知時間情報を取得し、現在のローソク足の時間以下の場合は、通知判定を実行しないよう、下記の式をfor文内のnameを定義した行の次へ追加します。
string textTime = ObjectGetString(0, name, OBJPROP_TEXT);
if (time[0] <= StringToTime(textTime)) continue;
上記までの作業にて、水平線への価格タッチで通知するツールの完成です。
6.ソースコード
今回、作成したソースコードは下記の通りです。
//+------------------------------------------------------------------+
//| LineTouchAlert.mq5 |
//| Copyright 2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots 0
//--- input parameters
input bool ALERT=true;
input bool MAIL=true;
input bool PUSH=true;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int32_t rates_total,
const int32_t 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 int32_t &spread[])
{
ArraySetAsSeries(close, true);
ArraySetAsSeries(time, true);
//---
for (int i = 0; i < ObjectsTotal(0, 0, OBJ_HLINE); i++) {
string name = ObjectName(0, i, 0, OBJ_HLINE);
string textTime = ObjectGetString(0, name, OBJPROP_TEXT);
if (time[0] <= StringToTime(textTime)) continue;
double price = ObjectGetDouble(0, name, OBJPROP_PRICE, 0);
bool touchUp = close[0] >= price && close[1] < price;
bool touchDown = close[0] <= price && close[1] > price;
if (touchUp || touchDown) {
string text = _Symbol + " : Line Touch " + (touchUp ? "Up" : "Down");
text += " (" + DoubleToString(price, _Digits) + ")";
if (ALERT) Alert(text);
if (MAIL) SendMail(MQLInfoString(MQL_PROGRAM_NAME), text);
if (PUSH) SendNotification(text);
ObjectSetString(0, name, OBJPROP_TEXT, TimeToString(time[0], TIME_DATE | TIME_MINUTES));
}
}
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
本記事の監修者・HT FX
2013年にFXを開始し、その後専業トレーダーへ。2014年からMT4/MT5のカスタムインジケーターの開発に取り組む。ブログでは100本を超えるインジケーターを無料公開。投資スタイルは自作の秒足インジケーターを利用したスキャルピング。
EA(自動売買)を学びたい方へオススメコンテンツ

OANDAではEA(自動売買)を稼働するプラットフォームMT4/MT5の基本的な使い方について、画像や動画付きで詳しく解説しています。MT4/MT5のインストールからEAの設定方法までを詳しく解説しているので、初心者の方でもスムーズにEA運用を始めることが可能です。またOANDAの口座をお持ちであれば、独自開発したオリジナルインジケーターを無料で利用することもできます。EA運用をお考えであれば、ぜひ口座開設をご検討ください。
本ホームページに掲載されている事項は、投資判断の参考となる情報の提供を目的としたものであり、投資の勧誘を目的としたものではありません。投資方針、投資タイミング等は、ご自身の責任において判断してください。本サービスの情報に基づいて行った取引のいかなる損失についても、当社は一切の責を負いかねますのでご了承ください。また、当社は、当該情報の正確性および完全性を保証または約束するものでなく、今後、予告なしに内容を変更または廃止する場合があります。なお、当該情報の欠落・誤謬等につきましてもその責を負いかねますのでご了承ください。