【MT5/MQL5】インジケータからSlackに簡単通知(ソースあり)

この記事は約15分で読めます。

今回の概要

今回は、インジケータからSlackに通知するプログラムを紹介します。
前回紹介した「インジケータからLINEに簡単通知」の記事と同様、「WinAPIをシェル実行関数(ShellExecuteW)でcurlを実行する」という方法を使ってプログラムを作成してきたいと思います。

Slack通知をするための準備作業

Slackに通知するための方法はいくつかありますが、今回は一番簡単なIncoming Webhooksを利用します。Incoming Webhooksを利用するためには、専用のWebhook URLを作成し、MQLコードに設定する必要があります。

Webhook URLの作成手順については色々なサイトで解説があるので、当記事では説明を割愛します。Slack公式サイトの手順や、日本語で説明しているこちらのサイトなどを参考にして、Webhook URLを準備してください。

MQL5コード

Slack通知するMQL5コードを紹介します。今回のコードは

  • Slack通知用クラス(CNotifySlack.mqh)
  • Slack通知確認用インジケータ(IndicatorNotifySlack.mq5)

の2本になります。Slack通知関連のロジックは、インジケータ以外(EAやスクリプト)からも簡単に呼び出せるように、クラスライブラリ化しました。

Slack通知用クラス(CNotifySlack.mqh)

コード

//+------------------------------------------------------------------+
//|                                                 CNotifySlack.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

//+------------------------------------------------------------------+
//|
//| [Slack通知用クラス]
//|
//+------------------------------------------------------------------+
class CNotifySlack
  {
private:

public:
   //|---------------------------------------------------------------+
   //| メンバ変数
   //|---------------------------------------------------------------+
   string            m_curl_path;
   string            m_webhook_url;

   //|---------------------------------------------------------------+
   //| コンストラクタ、デストラクタ
   //|---------------------------------------------------------------+
                     CNotifySlack();
                    ~CNotifySlack() {};

   //|---------------------------------------------------------------+
   //| メンバ関数
   //|---------------------------------------------------------------+

   //| curlの実行コマンドパス
   void              CurlPath(string sArgValue) { this.m_curl_path = sArgValue; };

   //| SlackのWebhookURL
   void              WebhookURL(string sArgValue) { this.m_webhook_url = sArgValue; };

   //| Slack通知実行
   void              Notify(string, bool);

  };

//+------------------------------------------------------------------+
//| [コンストラクタ]
//+------------------------------------------------------------------+
CNotifySlack::CNotifySlack()
  {
   this.m_curl_path="c:\\Windows\\System32\\curl.exe";
   this.m_webhook_url="https://hooks.slack.com/services/XXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
  }

//+------------------------------------------------------------------+
//| [メンバ関数]
//|   Slack通知実行
//+------------------------------------------------------------------+
void CNotifySlack::Notify(
   string   sArgMessage,        // 通知メッセージ
   bool     bAddMention         // メッセージをメンションするかどうか
)
  {
   string sCommand = "";
   string sMention = "";

   if(bAddMention == true)
     {
      sMention="^<!channel^>";
     }

   StringConcatenate(
      sCommand,
      "/c ",
      this.m_curl_path,
      " -X POST --data-urlencode \"payload={",
      "\\\"text\\\": \\\"",sMention, sArgMessage,"\\\"}\" ",
      this.m_webhook_url);

   ShellExecuteW(0,"","cmd.exe",sCommand,"",5);
  }
Expand

コード解説

10~12行目

Windowsのコマンドプロンプトを叩くために必要なWindowsAPIを定義しています。

40~44行目

メンバ変数設定用の関数です。メンバ変数をpublicで定義しているので、この関数群は定義しなくても大丈夫ですが、気になる方はメンバ変数をprivateにするか、当関数群を削除しても問題ありません。

56~57行目

クラスのコンストラクタでSlack Notifyを利用する際に必要な固定値を設定しています。
56行目のcurlの実行コマンドパスは動作環境に合わせて修正してください。
57行目には、準備作業で発行したWebhook URLを設定してください。

69~85行目

Slackの通知コマンドです。Slack Incoming Webhookのインターフェース仕様に合わせてパラメータを指定して通知をしています。

Slack通知確認用インジケータ(IndicatorNotifySlack.mq5)

コード

//+------------------------------------------------------------------+
//|                                         IndicatorNotifySlack.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 "CNotifySlack.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[];

CNotifySlack NotifySlack;

//+------------------------------------------------------------------+
//| 【初期化関数】
//|  ・チャートの初期表示時、または時間足変更等のチャート初期化が必要な
//|    タイミングで呼び出される。
//+------------------------------------------------------------------+
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が発生した場合のみ、Slackでインジケータ値を通知する。
// 過去チャートのインジケータ値を計算している時は通知しない。
   if(bIsLiveNewBar)
     {
      NotifySlack.Notify(DoubleToString(bufHigh[iCurrentBar],5),true);
     }
  }

//+------------------------------------------------------------------+
Expand

コード解説

11行目

Slack通知用クラスのクラスファイルを取り込んでいます。インジケータファイルと同階層に配置する前提のため””で括っていますが、クラスファイルをIncludeフォルダに配置した場合は、<>で括ってください。詳しくは、MQL5の公式サイトのこちらを参照してください。

22行目

Slack通知用クラスのインスタンスを定義しています。クラスの実体を作成しているため、コンストラクタがこのタイミングで動き、Slackとの接続情報がクラスのインスタンスに設定されます。

55~93行目

新規ローソク足発生時のみ計算する処理になっています。解説はこちらの記事を参照してください。

107~113行目

Liveで新規Barが発生した場合のみ、インジケータの値をSlackでメンション付きで通知しています。過去データのインジケータ値算出の際もSlack通知処理を呼び出してしまうと、大量にSlack通知が届いて大変な事になるので注意してください。

実行結果

「Slack通知確認用インジケータ」をチャートに設定する際、下記ダイアログが表示されるので、「DLLの使用を許可する」にチェックをしてください。

「Slack通知確認用インジケータ」を1分足チャートに設定した実行結果です。過去データのインジケータ値算出の際にはSlack通知されず、Liveで新規Barが発生した場合のみ、Slack通知されている事が分かります。

まとめ

今回は、インジケータからSlackに通知する方法を紹介しました。

Slackはビジネスチャットツールなので、単にメッセージを通知するだけではなくて色々なサービス連携機能があります。MT5のシグナルをトリガにして他サービスを起動したり、逆にSlackからコマンドを叩く事によりMT5を操作したり、というような事も出来ますので、面白いネタがあれば記事にしてきたいと思います。

コメント

タイトルとURLをコピーしました