見出し画像

FXトレードMT5運用のモバイル通知(Discord)の設定方法

こんにちは。

こちら ⬇️ のマガジンでご紹介している『高い勝率で利小損大を乗り切る』方針のFXトレード戦略を運用しています。

運用している戦略をモバイルでモニタリングするために、Discordへメッセージ、および、チャート画像の送信する方法をこちら ⬇️でご紹介しました。

この記事では、現在運用中のMT4戦略をMT5に移行するために、Discordへの送信部分もMT5に作り変えましたものを共有いたします。

背景

作成した戦略をMT4でバックテストしたところ、デモ環境での結果との乖離が大きいことが判明しました。
その対策として、MT4で運用している戦略をMT5に移行することを検討しています。
実際に現在運用している利小損大戦略のEAをMT5に移行してみましたが、MT4とMT5では互換性が全くなく、意外と面倒です。

MT4で作成していたDiscordへの送信のスクリプトもMT5ではかなり変更が必要になります。

MT5の場合も、ソースコードレベルでそのまま参考になるブログ、ネット情報があまりなかったため、再度AIに相談しながらやりましたが、今回もチャート画像の連携部分で非常に苦労しました。

MT5 EAからのDiscord通知の事前準備

事前準備すべきことは、MT4と変わりあません。
以下の2点について必要な設定をしていただく必要があります。

  • DiscordのWebhook URL発行

  • MT4の通知許可を設定


Discord通知するEAスクリプト例 

今回ご紹介するのはサンプル用として作成したEA全体を共有いたします。

WEBHOOK_URLの部分だけご自身で準備したものを設定いただければ、そのまま稼働すると思います。

価格情報・チャート画像を送信するEAサンプル


//--- Discord Webhook URL (ここにあなたの Webhook URL を入力)
#define WEBHOOK_URL "https://discord.com/api/webhooks/xxxxxxxxxxxxxxxxxxxxxxxxx"

#define SYMBOL_NAME  Symbol() // 現在のチャートのシンボル
#define _ASK SymbolInfoDouble(_Symbol, SYMBOL_ASK)
#define _BID SymbolInfoDouble(_Symbol, SYMBOL_BID)
#define _SPREAD SymbolInfoInteger(_Symbol, SYMBOL_SPREAD)

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {

   //--- Discord に送信するメッセージを作成
    
   // 基本情報
   string info = "```\\n"; // Discordのコードブロック形式
   info += "Time: " + TimeToString(TimeLocal(), TIME_DATE|TIME_SECONDS) + "   EA:" + MQLInfoString(MQL_PROGRAM_NAME) + "\\n";
    
   // 価格情報    
   info += "\\n";
   info += "Ask: " + DoubleToString(_ASK,Digits()) + ", Bid:" + DoubleToString(_BID,Digits()) + "\\n";
   info += "Spread: " + IntegerToString(_SPREAD) + " pips\\n";

    // 日足情報
   info += "\\n";
   info += "Daily  High: " + DoubleToString(iHigh(Symbol(), PERIOD_D1, 0), Digits()) 
        + " ,Low: " + DoubleToString(iLow(Symbol(), PERIOD_D1, 0), Digits()) + "\\n";
   double daily_range = (iHigh(Symbol(), PERIOD_D1, 0) - iLow(Symbol(), PERIOD_D1, 0)) / Point();
   info += "Range: " + DoubleToString(daily_range, 1) + " pips\\n";

   info += "```\\n"; // Discordのコードブロック形式

   //--- Discord に送信
   SendDiscordMessage(info);
   SendScreenshotToDiscord();
   
   
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Discord にメッセージを送信する関数                                   |
//+------------------------------------------------------------------+
bool SendDiscordMessage(string message)
  {
   string json_data = StringFormat("{\"content\":\"%s\"}", message);
   string headers = "Content-Type: application/json";
   char post[], result[];
   int post_size;

   post_size = StringToCharArray(json_data, post, 0, WHOLE_ARRAY, CP_UTF8);
   ArrayResize(post, post_size - 1);

   string result_headers;

   int res = WebRequest("POST", WEBHOOK_URL, headers, 5000, post, result, result_headers);

   if(res != 200 && res != 204)
     {
      Print("Discord Message sending failed. Error code: ", res);
      Print("Result: ",CharArrayToString(result));
      return false;
     }

   Print("Discord Message sent successfully.");
   return true;
  }

//+------------------------------------------------------------------+
//| チャートのスクリーンショットを撮影してDiscordに送信する           |
//+------------------------------------------------------------------+
bool SendScreenshotToDiscord()
{
    string filename = "chart_" + TimeToString(TimeCurrent(), TIME_DATE | TIME_MINUTES) + ".png";
    StringReplace(filename,":","-");
    StringReplace(filename," ","_");

    if(!ChartScreenShot(0, filename, 460, 320, ALIGN_RIGHT))
    {
        Print("## スクリーンショットの取得エラー");
        return false;
    }


    // Discord Webhookにファイルを送信
    string boundary = "---------------------------" + IntegerToString(TimeLocal());    
    string headers = "Content-Type: multipart/form-data; boundary=" + boundary + "\r\n";
    
    string data = "";
    data += "--" + boundary + "\r\n";
    data += "Content-Disposition: form-data; name=\"file\"; filename=\"" + filename + "\"\r\n";
    data += "Content-Type: image/png\r\n\r\n";

    uchar post_data[];
    StringToCharArray(data, post_data, 0, StringLen(data), CP_UTF8);

    char file_data[];
    int file_handle = FileOpen(filename, FILE_READ|FILE_BIN);
    if(file_handle != INVALID_HANDLE)
    {
        FileReadArray(file_handle, file_data, 0, (int)FileSize(file_handle));
        ArrayResize(file_data, ArraySize(file_data) - 1); 
        FileClose(file_handle);

        ArrayCopy(post_data, file_data, ArraySize(post_data));

        string end_boundary = "\r\n--" + boundary + "--\r\n";
        uchar end_data[];
        StringToCharArray(end_boundary, end_data, 0, StringLen(end_boundary), CP_UTF8);
        ArrayResize(end_data, ArraySize(end_data) - 1); 
        ArrayCopy(post_data, end_data, ArraySize(post_data));

        char result[];
        string result_headers;

        int res = WebRequest("POST", WEBHOOK_URL, headers, 5000, post_data, result, result_headers);

        // ファイルを削除
        FileDelete(filename);

        if(res != 200 && res != 204)
        {
          Print("Discord Chart sending failed. Error code: ", res);
          Print("Result: ",CharArrayToString(result));
          return false;
        }
     }
    
    return true;

}


コードの詳細説明は省きますが、質問などあればコメントいただければ、できるだけ回答いたします。

Discord通知の例

Discord側に送られてくる通知イメージの例は以下のとおりです。

MT5でも、なかなかいい感じに通知が届くようなりました。
これで、MT5に移行してもモバイルでのモニタリングが快適に行えます。

最後に

この記事はお気に入りいただけましたでしょうか?
内容お役にたちましたらうれしく思います。
また、サポートなど応援いただけましたら幸いです。


#FXトレード
#EA
#MT5
#DISCORD
#モバイル
#自動取引
#トレード戦略
#利小損大
#利小損大戦略

いいなと思ったら応援しよう!

なべなべ
記事の内容を有効に活用できた、記事を気に入っていただけたようでしたらチップでサポートいただけますと嬉しいです。 また、こんなことを知りたい、あんなことができないかなど記事にしたいことがございましたら、サポートの有無にかかわらずお知らせくださいませ。