今回の概要
今回は、インジケータからLINEに通知するプログラムを紹介します。
MT5(MQL5)からLINEに通知する方法は、下記3通りくらいの方法があると思います。
- MQL5のWebRequest関数を利用する
- WinAPIのインターネット接続系関数(HttpSendRequestW()、等)を利用する
- WinAPIをシェル実行関数(ShellExecuteW)でcurlを実行する
ただ、1.に関しては公式サイトのWebRequestの説明にもある通り、インジケータから呼び出すことはできませんし、2.に関しては結構なボリュームのプログラムを書く必要が出てきてしまいますので、今回は、3.の方法でプログラムを作成していきます。
LINE通知をするための準備作業
LINE通知をするための準備として、LINE Notifyのサービスでアクセストークンを発行する必要があります。発行したアクセストークンは、MQL5のコードに設定します。
LINEのアクセストークンを発行する手順については、色々なサイトで解説しているので、当記事では説明を割愛します。こちらのサイトなどを参考に、アクセストークンを発行してください。
MQL5コード
LINE通知するMQL5コードを紹介します。今回のコードは
- LINE通知用クラス(CNotifyLine.mqh)
- LINE通知確認用インジケータ(IndicatorNotifyLine.mq5)
の2本になります。LINE通知関連のロジックは、インジケータ以外(EAやスクリプト)からも簡単に呼び出せるように、クラスライブラリ化しました。
LINE通知用クラス(CNotifyLine.mqh)
コード
//+------------------------------------------------------------------+
//| CNotifyLine.mqh |
//| Copyright 2023, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#import "shell32.dll"
int ShellExecuteW(int hWnd,string lpVerb,string lpFile,string lpParameters,string lpDirectory,int nCmdShow);
#import
//+------------------------------------------------------------------+
//|
//| [LINE通知用クラス]
//|
//+------------------------------------------------------------------+
class CNotifyLine
{
private:
public:
//|---------------------------------------------------------------+
//| メンバ変数
//|---------------------------------------------------------------+
string m_curl_path;
string m_webhook_url;
string m_token;
//|---------------------------------------------------------------+
//| コンストラクタ、デストラクタ
//|---------------------------------------------------------------+
CNotifyLine();
~CNotifyLine() {};
//|---------------------------------------------------------------+
//| メンバ関数
//|---------------------------------------------------------------+
//| curlの実行コマンドパス
void CurlPath(string sArgValue) { this.m_curl_path = sArgValue; };
//| LINEのWebhookURL
void WebhookURL(string sArgValue) { this.m_webhook_url = sArgValue; };
//| LINE Notifyのアクセストークン
void Token(string sArgValue) { this.m_token = sArgValue; };
//| LINE通知実行
void Notify(string);
};
//+------------------------------------------------------------------+
//| [コンストラクタ]
//+------------------------------------------------------------------+
CNotifyLine::CNotifyLine()
{
this.m_curl_path="c:\\Windows\\System32\\curl.exe";
this.m_webhook_url="https://notify-api.line.me/api/notify";
this.m_token="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
}
//+------------------------------------------------------------------+
//| [メンバ関数]
//| LINE通知実行
//+------------------------------------------------------------------+
void CNotifyLine::Notify(string sArgMessage)
{
string sCommand;
StringConcatenate(
sCommand,
"/c ",
this.m_curl_path,
" -X POST -H \"Authorization: Bearer ",
this.m_token,
"\" -F \"",
"message=",
sArgMessage,
"\" ",
this.m_webhook_url);
ShellExecuteW(0,"","cmd.exe",sCommand,"",5);
}
//+------------------------------------------------------------------+
コード解説
10~12行目
Windowsのコマンドプロンプトを叩くために必要なWindowsAPIを定義しています。
41~48行目
メンバ変数設定用の関数です。メンバ変数をpublicで定義しているので、この関数群は定義しなくても大丈夫ですが、気になる方はメンバ変数をprivateにするか、当関数群を削除しても問題ありません。
60~62行目
クラスのコンストラクタでLINE Notifyを利用する際に必要な固定値を設定しています。
60行目のcurlの実行コマンドパスは動作環境に合わせて修正してください。
62行目には、準備作業で発行したアクセストークンを設定してください。
69~86行目
LINEの通知コマンドです。LINEのインターフェース仕様に合わせてパラメータを指定して通知をしています。
LINE通知確認用インジケータ(IndicatorNotifyLine.mq5)
コード
//+------------------------------------------------------------------+
//| IndicatorNotifyLine.mq5 |
//| Copyright 2023, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#property indicator_chart_window
#include "CNotifyLine.mqh"
#property indicator_buffers 1
#property indicator_plots 1
#property indicator_type1 DRAW_LINE
#property indicator_style1 STYLE_SOLID
#property indicator_color1 clrRed
#property indicator_width1 1
double bufHigh[];
CNotifyLine NotifyLine;
//+------------------------------------------------------------------+
//| 【初期化関数】
//| ・チャートの初期表示時、または時間足変更等のチャート初期化が必要な
//| タイミングで呼び出される。
//+------------------------------------------------------------------+
int OnInit()
{
ArraySetAsSeries(bufHigh, true);
ArrayInitialize(bufHigh, 0);
SetIndexBuffer(0, bufHigh, INDICATOR_DATA);
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);
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[])
{
//+------------------------------------------------------------------+
//| 1. 新規チャートのインジケータ値がまだ計算されていない場合
//| → 過去チャートのインジケータ値を計算する。
//+------------------------------------------------------------------+
if(prev_calculated == 0)
{
for(int i=rates_total-1; i>=0; i--)
{
setBufferValue(i,false);
}
}
//+------------------------------------------------------------------+
//| 2. 過去チャートのインジケータ値は計算済で、
//| 前回計算済Bar数 < チャートの最大Bar数 の場合 (Liveで新規Barが発生した)
//| → 新規Barのインジケータ値を計算する。
//+------------------------------------------------------------------+
else
{
if(prev_calculated < rates_total)
{
setBufferValue(0,true);
}
}
//+------------------------------------------------------------------+
//| 3. 同Bar内でのティック変更によって呼び出された場合
//| → インジケータ値は計算しない
//+------------------------------------------------------------------+
// NOP
//+------------------------------------------------------------------+
//| 今回の処理でインジケータ値を計算したBar数を返却する。
//| → このreturn値は、次回OnCalculate関数が呼び出された際、
//| 引数のprev_calculatedに設定される。
//+------------------------------------------------------------------+
return(rates_total);
}
//+------------------------------------------------------------------+
//| 【インデックスバッファ設定関数】
//| ・指定されたBar位置のインジケータ値を計算する。
//+------------------------------------------------------------------+
void setBufferValue(int iCurrentBar, bool bIsLiveNewBar)
{
// 現在Bar位置に、1つ前のBarの高値をプロットする。
bufHigh[iCurrentBar] = iHigh(Symbol(),PERIOD_CURRENT,iCurrentBar+1);
// Liveで新規Barが発生した場合のみ、LINEでインジケータ値を通知する。
// 過去チャートのインジケータ値を計算している時は通知しない。
if(bIsLiveNewBar)
{
NotifyLine.Notify(DoubleToString(bufHigh[iCurrentBar],5));
}
}
//+------------------------------------------------------------------+
コード解説
11行目
LINE通知用クラスのクラスファイルを取り込んでいます。インジケータファイルと同階層に配置する前提のため””で括っていますが、クラスファイルをIncludeフォルダに配置した場合は、<>で括ってください。詳しくは、MQL5の公式サイトのこちらを参照してください。
22行目
LINE通知用クラスのインスタンスを定義しています。クラスの実体を作成しているため、コンストラクタがこのタイミングで動き、LINEとの接続情報がクラスのインスタンスに設定されます。
55~93行目
新規ローソク足発生時のみ計算する処理になっています。解説はこちらの記事を参照してください。
107~113行目
Liveで新規Barが発生した場合のみ、インジケータの値をLINEで通知しています。過去データのインジケータ値算出の際もLINE通知処理を呼び出してしまうと、大量にLINE通知が届いて大変な事になるので注意してください。
実行結果
「LINE通知確認用インジケータ」をチャートに設定する際、下記ダイアログが表示されるので、「DLLの使用を許可する」にチェックをしてください。
「LINE通知確認用インジケータ」を1分足チャートに設定した実行結果です。過去データのインジケータ値算出の際にはLINE通知されず、Liveで新規Barが発生した場合のみ、LINE通知されている事が分かります。
まとめ
今回は、インジケータからLINEに通知する方法を紹介しました。
メッセージングアプリの中でLINEは、世界で見るとそれほど普及率が高くないですが、日本では異様に高い普及率になっています。日本でMT5を利用している人にとっては、当記事の内容は有益だと思いますので、ぜひ活用してみてください。
コメント
MT5のソースコードの公開、ありがとうございます。
勉強させていただきます。
MT4よりMT5は情報量が少ないので助かりました。
感謝いたします。
コメントありがとうございます。
MT5の情報、本当に少ないですよね。
記事を書きながら、実はほとんどニーズが無いのでは?
と思っていたので、ニーズがあったようでホッとしました。