Candlestick Trend Constraintモデルの構築(第5回):通知システム(パート1)
内容
- はじめに
- 端末通知
- プッシュ通知
- Eメール通知
- Trend Constraint V1.04のデバッグ
- ソーシャルネットワークチャンネル(TelegramやWhatsAppなど)との統合
- Telegramとの統合
- WhatsAppとの統合
- 通知システムにおける仮想プライベートサービス(VPS)の威力
- 結論
はじめに
MetaTrader 5は、端末、Eメール、プッシュ通知など、取引イベントをユーザーに通知するためのさまざまな通知オプションを提供しています。TelegramやWhatsAppのようなソーシャルプラットフォームと統合してシグナルを共有することは、非常に有益です。MetaTrader 5で通知を設定すると、場所に関係なく取引活動について常に情報を得ることができます。前述の通知アクセス方法を利用することで、要件に最も適したオプションを選択することができます。このガイドでは、Telegramや他のソーシャルメディアプラットフォームとの統合を含む、MetaTrader 5通知の設定とカスタマイズについて説明します。本連載では、構成の詳細と統合のための初期ステップに焦点を当て、本連載の第II回でより深く掘り下げるための道を開きます。
端末通知
端末通知は、MetaTrader 5プラットフォームの内部アラートです。これらは、MetaTrader 5内でトリガーされるすべてのアラートイベントをカバーしています。MetaTrader 5では、特定の条件が満たされたときに作動するアラートを手動で設定できます。アラート設定は通常、デフォルトのMetaTrader 5ウィンドウの下部にある[ツール]タブにあります。
- 銘柄:アラートを設定したい取引商品を選択します。
- 条件:アラートをトリガーする条件を選択します(例:Bid >、 Ask <、 Time =など)。
- 値:条件が比較される値を指定します(特定の価格レベルなど)。
- ソース:アラートの種類(サウンド、ファイル、Eメールなど)を選択します。端末の通知には、サウンドを選択できます。
- アクション:アラートがトリガーされたときに実行するアクションを選択します(サウンドの再生、通知の送信など)。
- サウンド:アラートがトリガーされたときに再生されるサウンドファイルを選択します。
- タイムアウト:アラートが再度チェックされるまでの時間間隔を設定します。
- 最大反復:アラートをトリガーする回数を指定します。
以下は、ステップインデックス合成を使用したアラートの設定例です。表に示した値は、ニーズに応じて調整できます。設定を構成した後、[OK]をクリックしてアラートを作成すると、アクティベーションの準備が整います。表の下にあるアニメーションデモ画像で簡単な概要をご覧ください。開始するには、ツールウィンドウの[アラート]タブを右クリックし、表示されるメニューから[作成]を選択します。表に概説されている設定のダイアログボックスが開きます。
設定 | 値 |
---|---|
銘柄 | Step Index |
条件 | Bid> |
値 | 9666 |
ソース | サウンド |
アクション | サウンドファイルを選択( alert2.wav) |
タイムアウト | 60秒に設定 |
最大反復回数 | 5に設定 |
プッシュ通知
これはMetaTrader 5の機能で、内部で生成されたものであれ、指標やエキスパートアドバイザーによって生成されたものであれ、プラットフォーム上で生成された通知を、モバイルデバイスのMetaQuotes IDを介して携帯電話のMetaTrader 5プラットフォームに送信することができます。プッシュ通知を受信するためには、Androidの場合はplayストア、iOSの場合はApple StoreからMetaTrader 5をインストールする必要があります。携帯電話でアラートを受信するには、デスクトップでMetaTrader 5のプッシュ通知を有効にする必要があります。モバイルMetaTrader 5のインストール後すぐに、携帯電話に固有のMetaQuotes IDが作成されます。
左側に、MetaQuotes IDの見つけ方を説明する画像があります。右側には、デスクトップのMetaTrader 5プラットフォームでプッシュ通知を有効にする方法を示す画像と、MetaQuotes IDを入力する欄があります。ボックスにチェックを入れ、モバイルプラットフォームからIDを入力すると、MetaTrader 5モバイルプラットフォームのメッセージセクションで即座に通知を受信できるようになります。様々なモバイルデバイスから多くのMetaQuotes IDを分離して追加することができます。
Eメール通知
Eメールは、その利便性、効率性、幅広い機能性により、依然として強力で汎用性の高いコミュニケーションツールです。個人的な使用であれ、ビジネス上のやりとりであれ、仕事上のネットワーク作りであれ、Eメールは信頼できる効果的な連絡手段であり、情報交換の手段です。MetaTrader 5でEメール通知を設定すると、価格の動き、注文の約定、カスタムイベントなど、さまざまな取引活動に関するアラートをEメールで受け取ることができます。
Eメールの利点は、ほぼ瞬時に配信されることで、迅速な情報交換や大人数への効率的な情報発信が可能になります。Eメールサービスは、多くの場合、コンテンツを保護するために暗号化を提供し、機密情報を保護します。受信者の受信トレイに直接配信されるため、他の通信形態に比べて傍受リスクを最小限に抑えることができます。
ここでは、Eメール通知を設定するためのステップごとのガイドを示します。
- コンピュータでMetaTrader 5プラットフォームを起動します。
- [ツール] > [オプション] > [Eメール]に移動します。
- [メール設定を有効にする]にチェックを入れます。
- SMTPサーバーの詳細を入力します。
設定 詳細を記入 SMTPサーバー EメールプロバイダーのSMTPサーバーアドレス(例:Gmailの場合はsmtp.gmail.com) SMTPログイン Eメールアドレス(例:your-email@gmail.com) SMTPパスワード Gmailの場合は、Eメールのパスワードまたはアプリ固有のパスワード 差出人 Eメールアドレス(例:your-email@gmail.com) 宛先 通知を受信するEメールアドレス(Fromアドレスと同じでも異なっていてもかまいません)
SMTPサーバーとは?
私の調査によると、SMTP (Simple Mail Transfer Protocol)サーバーとは、SMTPプロトコルを利用してEメールの送受信と中継をおこなうEメールサーバーのことです。Eメール転送エージェント(Mail Transfer Agent: MTA)と並んで機能し、送信者のEメールクライアントから受信者のEメールサーバーにEメールを転送します。SMTPサーバーを持つEメールプロバイダーのリストです。
- gmail
- yahoo mail
- hotmail
- zohomail
- icloud mail
Trend Constraint V1.04のデバッグ
Draw_Lineスタイルをシステムのトレンドに組み込むことに成功しました。しかし、この新機能のせいで、各バーの後に多数のアラートがトリガーされていることを発見しました。例えば、チャートが分単位の時間枠に設定されている場合、アラートはローソク足の終値が1分経過するごとに生成されていました。
私たちの目的は、厳選された数少ないものだけに焦点を当て、最適なシグナルを得ることです。この問題に取り組むため、5番目と6番目のバッファからmyalert()を削除することで問題を解決しようと考えました。本記事で説明するように、TelegramとWhatsAppのシームレスな統合のためには、このコードを修正することが不可欠です。以下は改訂版のコードです。
バッファー5を変更します。
// --- Buffer5 (Buy Trend) if(MA5[i] > MA6[i]) { Buffer5[i] = Low[i] - 15 * myPoint; // Disabled myAlert from Buffer 5 // myAlert("indicator", "BUY TREND | MA Fast: " + DoubleToString(MA5[i], 2) + " | MA Slow: " + DoubleToString(MA6[i], 2)); }
バッファー6を変更します。
// --- Buffer6 (Sell Trend) if(MA5[i] < MA6[i]) { Buffer6[i] = High[i] + 15 * myPoint; // Disabled myAlert from Buffer 6 // myAlert("indicator", "SELL TREND | MA Fast: " + DoubleToString(MA5[i], 2) + " | MA Slow: " + DoubleToString(MA6[i], 2)); }
Trend Constraint V1.044を修正します。
///Indicator Name: Trend Constraint #property copyright "Clemence Benjamin" #property link "https://mql5.com" #property version "1.04" #property description "A model that seek to produce sell signal when D1 candle is Bearish only and buy signal when it is Bullish" //--- indicator settings #property indicator_chart_window #property indicator_buffers 6 #property indicator_plots 6 #property indicator_type1 DRAW_ARROW #property indicator_width1 5 #property indicator_color1 0xFF3C00 #property indicator_label1 "Buy" #property indicator_type2 DRAW_ARROW #property indicator_width2 5 #property indicator_color2 0x0000FF #property indicator_label2 "Sell" #property indicator_type3 DRAW_ARROW #property indicator_width3 2 #property indicator_color3 0xE8351A #property indicator_label3 "Buy Reversal" #property indicator_type4 DRAW_ARROW #property indicator_width4 2 #property indicator_color4 0x1A1AE8 #property indicator_label4 "Sell Reversal" #property indicator_type5 DRAW_LINE #property indicator_style5 STYLE_SOLID #property indicator_width5 2 #property indicator_color5 0xFFAA00 #property indicator_label5 "Buy Trend" #property indicator_type6 DRAW_LINE #property indicator_style6 STYLE_SOLID #property indicator_width6 2 #property indicator_color6 0x0000FF #property indicator_label6 "Sell Trend" #define PLOT_MAXIMUM_BARS_BACK 5000 #define OMIT_OLDEST_BARS 50 //--- indicator buffers double Buffer1[]; double Buffer2[]; double Buffer3[]; double Buffer4[]; double Buffer5[]; double Buffer6[]; input double Oversold = 30; input double Overbought = 70; input int Slow_MA_period = 200; input int Fast_MA_period = 100; datetime time_alert; //used when sending alert input bool Audible_Alerts = true; input bool Push_Notifications = true; double myPoint; //initialized in OnInit int RSI_handle; double RSI[]; double Open[]; double Close[]; int MA_handle; double MA[]; int MA_handle2; double MA2[]; int MA_handle3; double MA3[]; int MA_handle4; double MA4[]; double Low[]; double High[]; int MA_handle5; double MA5[]; int MA_handle6; double MA6[]; void myAlert(string type, string message) { if(type == "print") Print(message); else if(type == "error") { Print(type+" | Trend Constraint V1.04 @ "+Symbol()+","+IntegerToString(Period())+" | "+message); } else if(type == "order") { } else if(type == "modify") { } else if(type == "indicator") { if(Audible_Alerts) Alert(type+" | Trend Constraint V1.04 @ "+Symbol()+","+IntegerToString(Period())+" | "+message); if(Push_Notifications) SendNotification(type+" | Trend Constraint V1.04 @ "+Symbol()+","+IntegerToString(Period())+" | "+message); } } //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { SetIndexBuffer(0, Buffer1); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); PlotIndexSetInteger(0, PLOT_ARROW, 241); SetIndexBuffer(1, Buffer2); PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); PlotIndexSetInteger(1, PLOT_ARROW, 242); SetIndexBuffer(2, Buffer3); PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); PlotIndexSetInteger(2, PLOT_ARROW, 236); SetIndexBuffer(3, Buffer4); PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(3, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); PlotIndexSetInteger(3, PLOT_ARROW, 238); SetIndexBuffer(4, Buffer5); PlotIndexSetDouble(4, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(4, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); SetIndexBuffer(5, Buffer6); PlotIndexSetDouble(5, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(5, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); //initialize myPoint myPoint = Point(); if(Digits() == 5 || Digits() == 3) { myPoint *= 10; } RSI_handle = iRSI(NULL, PERIOD_CURRENT, 14, PRICE_CLOSE); if(RSI_handle < 0) { Print("The creation of iRSI has failed: RSI_handle=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle = iMA(NULL, PERIOD_CURRENT, 7, 0, MODE_SMMA, PRICE_CLOSE); if(MA_handle < 0) { Print("The creation of iMA has failed: MA_handle=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle2 = iMA(NULL, PERIOD_CURRENT, 400, 0, MODE_SMA, PRICE_CLOSE); if(MA_handle2 < 0) { Print("The creation of iMA has failed: MA_handle2=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle3 = iMA(NULL, PERIOD_CURRENT, 100, 0, MODE_EMA, PRICE_CLOSE); if(MA_handle3 < 0) { Print("The creation of iMA has failed: MA_handle3=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle4 = iMA(NULL, PERIOD_CURRENT, 200, 0, MODE_SMA, PRICE_CLOSE); if(MA_handle4 < 0) { Print("The creation of iMA has failed: MA_handle4=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle5 = iMA(NULL, PERIOD_CURRENT, Fast_MA_period, 0, MODE_SMA, PRICE_CLOSE); if(MA_handle5 < 0) { Print("The creation of iMA has failed: MA_handle5=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle6 = iMA(NULL, PERIOD_CURRENT, Slow_MA_period, 0, MODE_SMA, PRICE_CLOSE); if(MA_handle6 < 0) { Print("The creation of iMA has failed: MA_handle6=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ 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[]) { int limit = rates_total - prev_calculated; //--- counting from 0 to rates_total ArraySetAsSeries(Buffer1, true); ArraySetAsSeries(Buffer2, true); ArraySetAsSeries(Buffer3, true); ArraySetAsSeries(Buffer4, true); ArraySetAsSeries(Buffer5, true); ArraySetAsSeries(Buffer6, true); //--- initial zero if(prev_calculated < 1) { ArrayInitialize(Buffer1, EMPTY_VALUE); ArrayInitialize(Buffer2, EMPTY_VALUE); ArrayInitialize(Buffer3, EMPTY_VALUE); ArrayInitialize(Buffer4, EMPTY_VALUE); ArrayInitialize(Buffer5, EMPTY_VALUE); ArrayInitialize(Buffer6, EMPTY_VALUE); } else limit++; datetime Time[]; int RSIBuffer; int MABuffer; int RSIPeriod = 14; ArrayResize(RSI, rates_total); ArrayResize(Open, rates_total); ArrayResize(Close, rates_total); CopyOpen(NULL, 0, 0, rates_total, Open); CopyClose(NULL, 0, 0, rates_total, Close); if(CopyBuffer(RSI_handle, 0, 0, rates_total, RSI) < 0) { Print("Getting RSI values failed, not enough bars!"); } ArrayResize(MA, rates_total); if(CopyBuffer(MA_handle, 0, 0, rates_total, MA) < 0) { Print("Getting MA values failed, not enough bars!"); } ArrayResize(MA2, rates_total); if(CopyBuffer(MA_handle2, 0, 0, rates_total, MA2) < 0) { Print("Getting MA values failed, not enough bars!"); } ArrayResize(MA3, rates_total); if(CopyBuffer(MA_handle3, 0, 0, rates_total, MA3) < 0) { Print("Getting MA values failed, not enough bars!"); } ArrayResize(MA4, rates_total); if(CopyBuffer(MA_handle4, 0, 0, rates_total, MA4) < 0) { Print("Getting MA values failed, not enough bars!"); } ArrayResize(Low, rates_total); if(CopyLow(NULL, 0, 0, rates_total, Low) < 0) { Print("Getting LOW values failed, not enough bars!"); } ArrayResize(High, rates_total); if(CopyHigh(NULL, 0, 0, rates_total, High) < 0) { Print("Getting HIGH values failed, not enough bars!"); } ArrayResize(MA5, rates_total); if(CopyBuffer(MA_handle5, 0, 0, rates_total, MA5) < 0) { Print("Getting MA values failed, not enough bars!"); } ArrayResize(MA6, rates_total); if(CopyBuffer(MA_handle6, 0, 0, rates_total, MA6) < 0) { Print("Getting MA values failed, not enough bars!"); } for(int i=limit-1; i>=0; i--) { if(i < rates_total-1 && time[i] != time[i+1]+PeriodSeconds()) { continue; } Buffer1[i] = EMPTY_VALUE; Buffer2[i] = EMPTY_VALUE; Buffer3[i] = EMPTY_VALUE; Buffer4[i] = EMPTY_VALUE; Buffer5[i] = EMPTY_VALUE; Buffer6[i] = EMPTY_VALUE; // --- Indicator calculations // --- Buffer1 (Buy) if((Close[i] > MA[i] && MA[i] > MA2[i] && RSI[i] < Oversold) || (RSI[i] < Oversold && Close[i] > MA3[i])) { Buffer1[i] = Low[i] - 5 * myPoint; myAlert("indicator", "BUY OPPORTUNITY | RSI: " + DoubleToString(RSI[i], 2) + " | MA: " + DoubleToString(MA[i], 2)); } // --- Buffer2 (Sell) if((Close[i] < MA[i] && MA[i] < MA2[i] && RSI[i] > Overbought) || (RSI[i] > Overbought && Close[i] < MA3[i])) { Buffer2[i] = High[i] + 5 * myPoint; myAlert("indicator", "SELL OPPORTUNITY | RSI: " + DoubleToString(RSI[i], 2) + " | MA: " + DoubleToString(MA[i], 2)); } // --- Buffer3 (Buy Reversal) if(RSI[i] < Oversold && Close[i] > MA[i]) { Buffer3[i] = Low[i] - 10 * myPoint; myAlert("indicator", "BUY REVERSAL | RSI: " + DoubleToString(RSI[i], 2) + " | MA: " + DoubleToString(MA[i], 2)); } // --- Buffer4 (Sell Reversal) if(RSI[i] > Overbought && Close[i] < MA[i]) { Buffer4[i] = High[i] + 10 * myPoint; myAlert("indicator", "SELL REVERSAL | RSI: " + DoubleToString(RSI[i], 2) + " | MA: " + DoubleToString(MA[i], 2)); } // --- Buffer5 (Buy Trend) if(MA5[i] > MA6[i]) { Buffer5[i] = Low[i] - 15 * myPoint; //Disabled myAlert from Buffer 5 // myAlert("indicator", "BUY TREND | MA Fast: " + DoubleToString(MA5[i], 2) + " | MA Slow: " + DoubleToString(MA6[i], 2)); } // --- Buffer6 (Sell Trend) if(MA5[i] < MA6[i]) { Buffer6[i] = High[i] + 15 * myPoint; // Disabled myAlert from Buffer 6 // myAlert("indicator", "SELL TREND | MA Fast: " + DoubleToString(MA5[i], 2) + " | MA Slow: " + DoubleToString(MA6[i], 2)); } } return(rates_total); }
ソーシャルネットワークの統合(TelegramやWhatsAppなど)
この記事では、MetaTrader 5のTelegramとWhatsAppの統合、特にTrend Constraint指標について説明します。このプロセスは、リアルタイムで安全かつ便利な通知を提供することにより、MetaTrader 5の機能を大幅に向上させます。これらの統合は、取引活動の効率性、応答性、有効性を高め、今日のトレーダーにとって貴重なツールとなっています。これらのプラットフォームには膨大な数のユーザーがいるため、これらのコミュニティとシグナルを共有することは有益です。指標が生成したシグナルを、どのようにソーシャルメディアプラットフォームに発信できるかを掘り下げてみましょう。その機能を確認するために調査し、テストしました。
必要条件
- 最新のMetaTrader 5プラットフォームデスクトップ
- 認証済みのWhatsappとTelegramアカウント(Androidはplayストアから、iOSはApp Storeからダウンロード)
- Webブラウザ(例:Google Chrome)
- ミドルウェアのスクリプトをホストするサーバー
Telegramとの統合
手順1:Telegramボットの作成
ボットを作成する:
- Telegramを開き、「BotFather」ボットを検索します。
- BotFatherでチャットを開始し、/newbotコマンドで新しいボットを作成します。
- プロンプトに従って、ボットの名前とユーザー名を設定します。
- BotFatherはトークンを提供します。このトークンを使ってTelegram APIとやり取りします。
チャットIDを取得する:
- ボットをTelegramグループに追加したり、チャットを開始したりできます
- ブラウザでhttps://api.telegram.org/bot<YourBotToken>/getUpdatesを使用して更新を取得し、チャットIDを検索します
- チャットでメッセージを送信し、もう一度URLをチェックしてチャットIDを見つけます
チャットIDの取得に関するより包括的なガイドについては、githubをご覧ください。
手順2:ミドルウェアスクリプトの作成
TelegramのAPI経由でメッセージを送信するにはスクリプトが必要です。
ミドルウェアのスクリプトを作成するために、私がおこなった調査に従ってPython言語を使用します。 このPythonスクリプトは、requestsライブラリを使って、ボット経由でTelegramチャットにメッセージを送信します。以下、スクリプトの各行について説明します。
import requests
PythonでHTTPリクエストをおこなうためのrequestsライブラリをインポートします。このスクリプトでは、Telegram Bot APIにPOSTリクエストを送信するために使用します。
def send_telegram_message(chat_id, message, bot_token):
send_telegram_messageという名前の関数を定義します。この関数は3つのパラメータを取ります。
- chat_id:ターゲットチャットの一意の識別子またはターゲットチャネルのユーザー名
- message:送信するテキストメッセージ
- bot_token:ボット作成時に@BotFatherから提供されるTelegramボットのトークン
url = f"https://api.telegram.org/bot{bot_token}/sendMessage"
この行は、提供されたbot_tokenを使用してTelegram Bot API メソッドsendMessageのURLを構築します。
payload = { 'chat_id': chat_id, 'text': message }
POSTリクエストのペイロードを作成します。この辞書には、sendMessageメソッドに必要なパラメータが含まれています。
- chat_id:メッセージを送信するチャットのID
- text:メッセージの内容
response = requests.post(url, data=payload)
この行は、requests.postメソッドを使用して、構築されたURLにペイロードデータとともにHTTP POSTリクエストを送信します。APIからのレスポンスはレスポンス変数に格納されます。
return response.json()
この行はレスポンスをJSON形式に変換して返します。このJSONレスポンスには通常、メッセージID、送信者、チャットの詳細など、送信されたメッセージに関する情報が含まれています。
すべてのコードを組み合わせるとこうなります。
import requests def send_telegram_message(chat_id, message, bot_token): url = f"https://api.telegram.org/bot{bot_token}/sendMessage" payload = { 'chat_id': chat_id, 'text': message } response = requests.post(url, data=payload) return response.json()
手順3:ミドルウェアを使用するようにMetaTrader 5を設定する
ミドルウェアのスクリプトにHTTPリクエストでアラートを送信するMQL5スクリプトを作成する
コードの内訳を見て、各行を理解しましょう。
void SendTelegramMessage(string chat_id, string message, string bot_token)
SendTelegramMessageという名前の関数を定義します。
関数内のパラメータ:
- chat_id:メッセージが送信されるTelegramチャットIDを表す文字列
- message:送信するメッセージを含む文字列
- bot_token:Telegram APIでの認証に必要なボットトークンを表す文字列
{ string url = "http://your-server-url/send_telegram_message";
サーバのエンドポイントURLを変数urlに代入します。このURLは、メッセージをTelegramに転送するサーバーのアドレスです。
char postData[]; StringToCharArray("chat_id=" + chat_id + "&message=" + message + "&bot_token=" + bot_token, postData);
postData配列:
- 宣言:POSTリクエストデータを格納するchar型の配列postDataを宣言します。
- 文字列から文字配列への変換:chat_id、message、bot_tokenパラメータを連結した文字列を文字配列に変換し、postDataに格納します。連結された文字列は、サーバーが要求する形式でPOSTリクエストの本文を形成します。
char result[];
Webリクエストからのレスポンスを保持するchar型の配列resultを宣言します。
int res = WebRequest("POST", url, "", NULL, 0, postData, 0, result, NULL);
Webリクエスト:
- HTTPメソッド:POSTはリクエストタイプを示す
- URL:リクエストを送信するエンドポイント
- ヘッダー:空の文字列""は、追加ヘッダーがないことを意味します
- Cookies:NULLはcookiesがないことを示します
- タイムアウト:0はタイムアウトなしを指定します。
- postData:POSTリクエストで送信されるデータ
- 結果:応答が格納される場所
- この関数は、レスポンスのHTTPステータスコードresを整数で返します。
if (res != 200)
レスポンスコードを確認します。レスポンスコードresと200 (HTTP OK)を比較します。200でない場合はエラーを示します。
エラーハンドラ:
{ Print("Error sending message: ", GetLastError()); }
エラーメッセージを出力します。レスポンスコードが200でない場合、このブロックはGetLastError()を使用してエラーメッセージと最後のエラーコードを表示します。
サクセスハンドラ:
else { Print("Message sent successfully."); }
成功メッセージを出力します。レスポンスコードが200の場合、このブロックはメッセージが正常に送信されたことを示す成功メッセージを表示します。
この行でSendTelegramMessage関数は終了します。
Telegramメッセージを送信するMQL5コード:
void SendTelegramMessage(string chat_id, string message, string bot_token) { string url = "http://your-server-url/send_telegram_message"; char postData[]; StringToCharArray("chat_id=" + chat_id + "&message=" + message + "&bot_token=" + bot_token, postData); char result[]; int res = WebRequest("POST", url, "", NULL, 0, postData, 0, result, NULL); if (res != 200) { Print("Error sending message: ", GetLastError()); } else { Print("Message sent successfully."); } }
上記のMQL5スクリプトは、サーバーのエンドポイントにWebリクエストをおこなうことで、Telegramチャットにメッセージを送信するように設計されています。使用例では、スクリプトが開始されたときに実行されるOnStartイベント内でSendTelegramMessage関数を使用する方法を示しています。WhatsAppとの統合については次のセクションで説明し、telegramとの統合は異なるソーシャルプラットフォームであっても意味があることを説明しました。これらのコードが機能するためには、必ずコードの一部にご自分の実際の認証情報を代入することを忘れないでください。
WhatsAppとの統合
手順1:メッセージングAPIプロバイダでの登録
- プロバイダーを選択:WhatsAppとの統合にはTwilioが人気です。
- アカウントを作成:Twilioに新規登録し、必要な認証を完了します。
- API認証情報を取得:TwilioからAPI認証情報(アカウントSID、認証トークン)を取得します。
手順2:ミドルウェアスクリプトの作成
WhatsApp統合のためのミドルウェアPythonスクリプト:
import requests def send_whatsapp_message(to, message, account_sid, auth_token): url = f"https://api.twilio.com/2010-04-01/Accounts/{account_sid}/Messages.json" payload = { 'From': 'whatsapp:+14155238886', # Twilio sandbox number 'To': f'whatsapp:{to}', 'Body': message } headers = { 'Authorization': f'Basic {account_sid}:{auth_token}' } response = requests.post(url, data=payload, headers=headers) return response.json()
手順3:ミドルウェアを使用するようにMetaTrader 5を設定する
MQL5コードでWhatsApp通知を送信:
void SendWhatsAppMessage(string to, string message, string account_sid, string auth_token) { string url = "http://your-server-url/send_whatsapp_message"; char postData[]; StringToCharArray("to=" + to + "&message=" + message + "&account_sid=" + account_sid + "&auth_token=" + auth_token, postData); char result[]; int res = WebRequest("POST", url, "", NULL, 0, postData, 0, result, NULL); if (res != 200) { Print("Error sending message: ", GetLastError()); } else { Print("Message sent successfully."); } }
通知システムにおける仮想プライベートサービス(VPS)の威力
仮想プライベートサービスはダウンタイムなしで継続的に稼動し、MetaTrader 5プラットフォームと通知システムが常にアクティブであることを保証します。これは、中断することなくリアルタイムの通知を受け取るために非常に重要です。VPSプロバイダーは堅牢で安定したインターネット接続を提供し、自宅やオフィスのネットワークで起こりうる切断のリスクを軽減します。 VPSサーバーは多くの場合、主要な金融取引所への高速接続が可能なデータセンターに設置されているため、遅延が短縮され、取引アラートや通知を受信して対処する速度が向上します。 共有ホスティングとは異なり、VPSは専用のCPU、RAM、ストレージリソースを提供し、MetaTrader 5の実行と通知の処理に安定したパフォーマンスを保証します。 VPSはインターネット接続があればどのデバイスからでもリモートアクセスが可能で、どこからでもMetaTrader 5プラットフォームを管理し、通知を受け取ることができます。
結論
WhatsAppとTelegramを統合するための土台を築き、私たちは指標のための強固な通知システムを構成することに成功しました。これらのシグナルは即座に共有されるため、この強化は大規模なコミュニティを惹きつける上で極めて重要です。開発者は、これらの人気のあるプラットフォームを通じて興味のあるトレーダーにこれらのシグナルをマーケティングすることにより、プラットフォームからソーシャルメディアチャンネルに直接送信する迅速かつ効率的な手段を提供し、資本化することができます。
このアプローチにより、インターネットがあればいつでもどこでもシグナルにアクセスできるようになり、クリックするだけで簡単に共有できるようになります。トレーダーはシグナルへのアクセスにTelegramかWhatsAppを選択できます。さらなる統合の詳細については、パートIIで検討します。以下に参考ファイルを添付します。コメント欄で自由に議論してください。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/14963
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索