برنامه‌نویسی ربات معامله‌گر

اتصال متاتریدر به تلگرام: ارسال اعلان از اکسپرت با WebRequest

تصویر شاخص مقاله اتصال متاتریدر به تلگرام؛ لپ‌تاپ با نمودار شمعی که با یک خط نورانی به گوشی وصل است و روی گوشی پیام و زنگ اعلان دیده می‌شود
اکسپرت با WebRequest اعلان باز و بسته شدن معامله را به تلگرام می‌فرستد؛ فقط برای رویدادهای مهم، نه هر تیک.

پاسخ کوتاه: برای اتصال متاتریدر به تلگرام یک ربات تلگرام با BotFather بسازید، توکن و شناسه چت (chat_id) را بردارید، نشانی https://api.telegram.org را در تنظیمات متاتریدر مجاز کنید و در اکسپرت با تابع WebRequest متد sendMessage را صدا بزنید. WebRequest در اندیکاتور و Strategy Tester کار نمی‌کند و تا رسیدن پاسخ، اکسپرت را نگه می‌دارد؛ پس فقط برای رویدادهای مهم پیام بفرستید.

اعلان تلگرام از اکسپرت به چه کاری می‌آید؟

رباتی که روی VPS یا کامپیوتر خانه کار می‌کند، بیشتر وقت‌ها جلوی چشم شما نیست. اعلان تلگرام همان چیزهایی را که در زبانه‌های Experts و Journal متاتریدر ثبت می‌شود، به گوشی‌تان می‌رساند. کاربردهای رایج:

  • باز و بسته شدن معامله: نماد، حجم، قیمت و نتیجه معامله.
  • هشدار ریسک: وقتی افت سرمایه (Drawdown) از حدی که تعیین کرده‌اید گذشت یا ربات به سقف ضرر روزانه رسید.
  • خطاهای اجرایی: رد شدن سفارش، قطع ارتباط با سرور بروکر یا خاموش شدن Auto Trading.
  • گزارش دوره‌ای: مثلاً هر روز در ساعتی مشخص، موجودی، Equity و تعداد معامله‌های باز.

اعلان، خودِ معامله را بهتر نمی‌کند؛ فقط زودتر خبردارتان می‌کند. اگر ربات بی‌دلیل معامله باز نمی‌کند، اول دلیل‌های باز نشدن معامله در ربات را بررسی کنید و اگر Auto Trading مدام خاموش می‌شود، حل مشکل Auto Trading Off را.

پیش‌نیاز: ربات تلگرام، توکن و chat_id

ساخت ربات با BotFather

  1. در تلگرام حساب @BotFather را باز کنید و دستور /newbot را بفرستید.
  2. یک نام نمایشی و یک نام کاربری که به bot ختم شود انتخاب کنید.
  3. BotFather یک توکن می‌دهد، رشته‌ای شبیه 123456789:AA.... این توکن رمز ربات شماست و جایی منتشرش نکنید.

پیدا کردن chat_id

ربات فقط به چتی پیام می‌دهد که شناسه‌اش را داشته باشد و قبلاً با آن در تماس بوده باشد:

  • چت خصوصی: به ربات خودتان پیام /start بدهید، سپس نشانی https://api.telegram.org/bot<TOKEN>/getUpdates را در مرورگر باز کنید و به جای <TOKEN> توکن خودتان را بگذارید. عددی که بعد از "chat":{"id": آمده، شناسه چت شماست.
  • گروه: ربات را به گروه اضافه کنید و در گروه دستوری مثل /start بفرستید. شناسه گروه در همان getUpdates عددی منفی است.
  • کانال: ربات را مدیر (Admin) کانال کنید. برای کانال عمومی می‌توانید به جای عدد، نام کاربری کانال را با @ بدهید، مثل @channelusername.

مجاز کردن نشانی تلگرام در متاتریدر

متاتریدر به هیچ اکسپرتی اجازه نمی‌دهد به هر نشانی اینترنتی درخواست بفرستد. از منوی Tools ← Options، در زبانه Expert Advisors گزینه Allow WebRequest for listed URL را تیک بزنید و https://api.telegram.org را به فهرست اضافه کنید. اگر این کار انجام نشود، WebRequest مقدار -1 برمی‌گرداند و پیامی نمی‌رسد. این تنظیم برای هر نصب متاتریدر جداست و روی VPS هم باید دوباره انجام شود.

کد ارسال پیام در MQL5

تابع زیر پیام را به شکل JSON و با رمزگذاری UTF-8 می‌فرستد، پس متن فارسی هم درست می‌رسد:

input string InpBotToken = "";   // token from @BotFather
input string InpChatId   = "";   // numeric chat id or @channelusername

string JsonEscape(string s)
{
   StringReplace(s, "\\", "\\\\");
   StringReplace(s, "\"", "\\\"");
   StringReplace(s, "\r", "\\r");
   StringReplace(s, "\n", "\\n");
   StringReplace(s, "\t", "\\t");
   return s;
}

bool SendTelegram(const string text)
{
   if(InpBotToken == "" || InpChatId == "")
      return false;
   if(MQLInfoInteger(MQL_TESTER))          // WebRequest does not run in the Strategy Tester
      return true;

   string url  = "https://api.telegram.org/bot" + InpBotToken + "/sendMessage";
   string body = "{\"chat_id\":\"" + JsonEscape(InpChatId) + "\",\"text\":\"" + JsonEscape(text) + "\"}";
   char   data[], result[];
   int    len = StringToCharArray(body, data, 0, WHOLE_ARRAY, CP_UTF8);
   ArrayResize(data, len - 1);             // drop the terminating zero
   string result_headers;

   ResetLastError();
   int code = WebRequest("POST", url, "Content-Type: application/json\r\n", 5000, data, result, result_headers);
   if(code != 200)
   {
      PrintFormat("Telegram failed: HTTP %d, error %d, %s", code, GetLastError(),
                  CharArrayToString(result, 0, WHOLE_ARRAY, CP_UTF8));
      return false;
   }
   return true;
}

چند نکته درباره همین کد:

  • CP_UTF8 باعث می‌شود حروف فارسی درست تبدیل شوند. بدون آن، متن فارسی خراب به تلگرام می‌رسد.
  • StringToCharArray صفر انتهای رشته را هم در آرایه می‌گذارد. ArrayResize(data, len - 1) آن را حذف می‌کند تا بدنه درخواست فقط همان JSON باشد.
  • عدد 5000 مهلت انتظار به میلی‌ثانیه است. WebRequest همزمان (synchronous) است: تا پاسخ نرسد یا مهلت تمام نشود، اکسپرت کار دیگری نمی‌کند.
  • اگر ارسال شکست بخورد، کد HTTP، کد خطا و پاسخ تلگرام در زبانه Experts ثبت می‌شود. خواندن این کدها را در آموزش Error Handling در MT5 توضیح داده‌ایم.

کِی پیام بفرستیم؟ اعلان باز و بسته شدن معامله

بهترین جا برای اعلان معامله در MQL5 رویداد OnTradeTransaction است. این رویداد فقط وقتی اجرا می‌شود که در حساب اتفاقی بیفتد، پس برخلاف OnTick با هر تیک قیمت صدا زده نمی‌شود:

input long InpMagic = 20251025;         // only this EA's trades

void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
{
   if(trans.type != TRADE_TRANSACTION_DEAL_ADD || !HistoryDealSelect(trans.deal))
      return;
   if(HistoryDealGetInteger(trans.deal, DEAL_MAGIC) != InpMagic)
      return;

   string symbol = HistoryDealGetString(trans.deal, DEAL_SYMBOL);
   int    digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
   double volume = HistoryDealGetDouble(trans.deal, DEAL_VOLUME);
   double price  = HistoryDealGetDouble(trans.deal, DEAL_PRICE);
   long   entry  = HistoryDealGetInteger(trans.deal, DEAL_ENTRY);

   if(entry == DEAL_ENTRY_IN)
      SendTelegram(StringFormat("Opened %s %.2f lot at %s", symbol, volume, DoubleToString(price, digits)));
   else if(entry == DEAL_ENTRY_OUT)
      SendTelegram(StringFormat("Closed %s %.2f lot, profit %.2f", symbol, volume,
                                HistoryDealGetDouble(trans.deal, DEAL_PROFIT)));
}

فیلتر Magic Number باعث می‌شود معامله‌های دستی یا اکسپرت‌های دیگرِ همان حساب اعلان نفرستند؛ اگر با این شماره آشنا نیستید، تنظیم Magic Number در ربات معامله‌گر را ببینید. DEAL_PROFIT سود یا زیان ناخالص است و کمیسیون و سواپ جدا ثبت می‌شوند (DEAL_COMMISSION و DEAL_SWAP).

برای گزارش روزانه یا هشدار افت سرمایه، به جای OnTick از OnTimer استفاده کنید تا وضعیت حساب مثلاً هر پنج دقیقه یک بار بررسی شود. فرق این دو رویداد را در تفاوت OnTick و OnTimer در ربات معامله‌گر نوشته‌ایم.

نکته‌هایی که اعلان را قابل اعتماد نگه می‌دارد

  • کم و به‌جا بفرستید. تلگرام توصیه می‌کند در یک چت بیش از یک پیام در ثانیه فرستاده نشود و در گروه سقف ۲۰ پیام در دقیقه است. اکسپرتی که با هر تیک پیام بدهد، هم خودش کند می‌شود و هم به خطای 429 می‌خورد.
  • توکن را داخل کد ننویسید. هر کس توکن را داشته باشد، از طرف ربات شما پیام می‌فرستد. توکن را پارامتر ورودی بگذارید، فایل اکسپرتی را که توکن داخلش است به کسی ندهید و اگر توکن لو رفت، با دستور /revoke در BotFather توکن تازه بگیرید.
  • اندیکاتور نمی‌تواند پیام بدهد. WebRequest در اندیکاتور مجاز نیست و خطای 4014 در MQL5 (و 4060 در MQL4) می‌دهد. اگر هشدار از اندیکاتور می‌آید، ارسال را به اکسپرت یا اسکریپت بسپارید.
  • در بک‌تست پیامی نمی‌آید. WebRequest در Strategy Tester اجرا نمی‌شود. برای آزمودن اعلان‌ها، اکسپرت را روی حساب دمو اجرا کنید؛ کار با تستر را در آموزش استفاده از Strategy Tester در متاتریدر ببینید.
  • دسترسی شبکه را در نظر بگیرید. تلگرام در ایران فیلتر است. اگر متاتریدر روی کامپیوتر یا سروری داخل ایران اجرا شود، درخواست به api.telegram.org معمولاً به جایی نمی‌رسد و فقط خطا ثبت می‌شود. برای همین اعلان تلگرام بیشتر روی سرور مجازی خارج از ایران به کار می‌رود؛ راه‌اندازی ربات روی VPS و مزایا و معایب VPS برای ربات را ببینید.

در MQL4 چه فرقی دارد؟

WebRequest در MQL4 هم با همین دو شکل وجود دارد و همان مجوز نشانی در Tools ← Options لازم است، پس تابع SendTelegram تقریباً بدون تغییر کار می‌کند. فرق اصلی در تشخیص معامله است: MQL4 رویداد OnTradeTransaction ندارد و باید در OnTick یا OnTimer تعداد سفارش‌های باز و تاریخچه را با دفعه قبل مقایسه کنید. تفاوت‌های دیگر دو زبان را در تفاوت MQL4 و MQL5 در ساخت Expert Advisor مرور کرده‌ایم.

جایگزین ساده‌تر: اعلان داخلی متاتریدر

اگر فقط می‌خواهید روی گوشی خودتان خبردار شوید، تابع SendNotification پیام را به اپ موبایل متاتریدر می‌فرستد. لازم نیست نشانی‌ای را مجاز کنید؛ کافی است MetaQuotes ID اپ موبایل را در زبانه Notifications تنظیمات متاتریدر وارد کنید. در عوض محدودتر است:

ویژگی تلگرام با WebRequest SendNotification
گیرنده چت خصوصی، گروه یا کانال، برای چند نفر اپ موبایل متاتریدر با MetaQuotes ID
طول پیام تا ۴۰۹۶ نویسه تا ۲۵۵ نویسه
سقف ارسال حدود یک پیام در ثانیه در هر چت؛ ۲۰ پیام در دقیقه در گروه ۲ پیام در ثانیه و ۱۰ پیام در دقیقه
تنظیم لازم ساخت ربات، توکن، chat_id و مجوز نشانی وارد کردن MetaQuotes ID
در Strategy Tester کار نمی‌کند کار نمی‌کند

خطاهای رایج و راه رفع

نشانه علت محتمل راه رفع
WebRequest مقدار -1 برمی‌گرداند نشانی در فهرست مجاز نیست، تابع از اندیکاتور صدا زده شده یا اینترنت به تلگرام وصل نمی‌شود https://api.telegram.org را در Options اضافه کنید و کد GetLastError را در زبانه Experts ببینید
خطای 400 با پیام chat not found chat_id اشتباه است یا هنوز به ربات پیام نداده‌اید به ربات /start بدهید و chat_id را دوباره از getUpdates بخوانید
خطای 401 توکن اشتباه است یا باطل شده توکن را دوباره از BotFather کپی کنید
خطای 403 ربات را بلاک کرده‌اید، از گروه حذف شده یا در کانال مدیر نیست ربات را از بلاک درآورید یا دوباره به گروه یا کانال (با دسترسی مدیر) اضافه کنید
خطای 429 تعداد پیام‌ها از سقف تلگرام گذشته ارسال را به رویدادهای مهم محدود کنید و پیام‌های نزدیک به هم را یکی کنید
متن فارسی خراب می‌رسد رشته بدون CP_UTF8 به آرایه تبدیل شده در StringToCharArray و CharArrayToString از CP_UTF8 استفاده کنید

جمع‌بندی

اتصال متاتریدر به تلگرام سه بخش دارد: ربات و chat_id در تلگرام، مجوز نشانی در متاتریدر و چند خط WebRequest در اکسپرت. چیزی که اعلان را مفید نگه می‌دارد، انتخاب درست رویدادهاست: باز و بسته شدن معامله، عبور از سقف افت سرمایه و خطاهای اجرایی، نه هر تیک قیمت. پیش از اجرای واقعی، اکسپرت را روی حساب دمو امتحان کنید تا مطمئن شوید پیام‌ها می‌رسند و ربات کند نمی‌شود.

منبع‌ها: مستند رسمی WebRequest و SendNotification در MQL5، WebRequest در MQL4، Telegram Bot API و پرسش‌های متداول ربات‌های تلگرام.

اگر اکسپرتی با اعلان تلگرام، هشدار افت سرمایه یا گزارش روزانه می‌خواهید، درخواستتان را در صفحه برنامه‌نویسی اکسپرت MQL ثبت کنید. برای ساخت ربات کامل از صفر هم سفارش ربات متاتریدر را ببینید.

هشدار ریسک: این مطلب جنبه آموزشی دارد و توصیه سرمایه‌گذاری نیست. معامله در بازارهای مالی با ریسک از دست دادن سرمایه همراه است و نتایج گذشته یا بک‌تست تضمینی برای آینده نیست.

نویسنده

تیم متااکسپرت در طراحی و برنامه‌نویسی ربات‌های معامله‌گر و اکسپرت‌های متاتریدر با MQL4 و MQL5 تخصص دارد و تجربه‌های عملی خود را در قالب این مقالات منتشر می‌کند.

دیدگاه‌ها

دیدگاه یا سؤال خود را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *