Edgoro
Expert Advisor · MQL5

MQL5 alerts: Alert, PlaySound and SendNotification

Short answer

Alert(text) opens the terminal's alert window, PlaySound("alert2.wav") plays a file from the terminal's Sounds folder, and SendNotification(text) sends a push to the MetaTrader app whose MetaQuotes ID is set in Tools > Options > Notifications. Send each message once per event, such as once per closed bar: push notifications are rate-limited.

UsesAlertPlaySoundSendNotificationTERMINAL_NOTIFICATIONS_ENABLEDGetTickCount64

The code

An Expert Advisor that trades nothing: it alerts when a bar closes above or below a level, the previous day's high by default. Turn on the channels you want in its inputs.

Save it as MQL5/Experts/alerts-and-push-notifications.mq5 and compile it in MetaEditor (F7): 0 errors, 0 warnings.

MQL5
input double InpLevel     = 0.0;         // Price level to watch (0 = previous day's high)
input bool   InpPopup     = true;        // Pop-up alert in the terminal
input bool   InpSound     = false;       // Play a sound
input string InpSoundFile = "alert2.wav"; // Sound file, in the terminal's Sounds folder
input bool   InpPush      = false;       // Push notification to the MetaTrader app on your phone

// Sends one message through every channel that's switched on
void Notify(const string text)
  {
   string msg = StringFormat("%s %s: %s", _Symbol, StringSubstr(EnumToString(_Period), 7), text);
   if(InpPopup)
      Alert(msg);                         // also plays the terminal's alert sound
   if(InpSound && !PlaySound(InpSoundFile))
      PrintFormat("PlaySound(%s) failed: is the file in the Sounds folder?", InpSoundFile);
   if(InpPush)
     {
      // MetaQuotes allows about 2 pushes a second and 10 a minute: keep at least 6 seconds between them
      static ulong lastPush = 0;
      if(lastPush > 0 && GetTickCount64() - lastPush < 6000)
        {
         Print("Push skipped (too soon after the last one): ", msg);
         return;
        }
      ResetLastError();
      if(!SendNotification(StringSubstr(msg, 0, 255)))   // 255 characters at most
         PrintFormat("SendNotification failed: error %d", GetLastError());
      else
         lastPush = GetTickCount64();
     }
  }

int OnInit()
  {
   if(InpPush && (!TerminalInfoInteger(TERMINAL_NOTIFICATIONS_ENABLED) || TerminalInfoInteger(TERMINAL_MQID) == 0))
      Print("Push notifications are off: add your MetaQuotes ID in Tools > Options > Notifications and tick Enable");
   return INIT_SUCCEEDED;
  }

void OnTick()
  {
   static datetime lastBar = 0;
   datetime bar = iTime(_Symbol, PERIOD_CURRENT, 0);
   if(bar == 0 || bar == lastBar)
      return;                             // check once per bar, so one cross sends one message
   lastBar = bar;

   double level = InpLevel > 0.0 ? InpLevel : iHigh(_Symbol, PERIOD_D1, 1);
   double c1    = iClose(_Symbol, PERIOD_CURRENT, 1);
   double c2    = iClose(_Symbol, PERIOD_CURRENT, 2);
   if(level <= 0.0 || c2 <= 0.0)
      return;
   if(c2 <= level && c1 > level)
      Notify(StringFormat("closed above %s at %s", DoubleToString(level, _Digits), DoubleToString(c1, _Digits)));
   else if(c2 >= level && c1 < level)
      Notify(StringFormat("closed below %s at %s", DoubleToString(level, _Digits), DoubleToString(c1, _Digits)));
  }

How it works

  • Notify(). One function for every channel, so the signal code doesn't care how the message travels. The symbol and timeframe go first, which matters when several charts alert.
  • Alert() shows the message in the terminal's alert window and plays the alert sound set in the terminal's options.
  • PlaySound() returns false when the file isn't found. The name is relative to the Sounds folder of the terminal's installation; alert2.wav is one of the files MetaTrader installs.
  • The push throttle. MetaQuotes limits push notifications to about 2 a second and 10 a minute. Keeping six seconds between pushes stays under both, and a skipped push is printed rather than lost silently.
  • 255 characters. The longest push message accepted; StringSubstr() cuts longer ones.
  • The settings check in OnInit(). TERMINAL_NOTIFICATIONS_ENABLED and TERMINAL_MQID tell whether pushes can work at all, so the problem shows at start instead of at the first signal.

Pitfalls

  • Alerting on every tick. A condition such as "price is above the level" stays true for hundreds of ticks. Alert on the change (the close crossing the level) and check once per bar.
  • Push errors. SendNotification() returns false and GetLastError() says why: 4517 for missing settings (no MetaQuotes ID, or notifications not enabled), 4518 for sending too often, 4516 for an empty message, 4515 when sending failed.
  • Testing alerts in the Strategy Tester. The tester doesn't show pop-ups, play sounds or deliver pushes. Test notifications on a demo chart.
  • Sound files. PlaySound() plays WAV files from the terminal's Sounds folder; an MP3 or a full path elsewhere doesn't play.

Variations

  • Email. SendMail(subject, text) sends through the mail server set in Tools > Options > Email.
  • Telegram, Discord or your server. Post the message to a webhook with WebRequest().
  • An indicator signal. Replace the level with a cross of two indicator values, read once per bar.
  • Mark it too. Draw an arrow where the alert fired with the code in drawing on the chart, so you can review alerts later.
  • On TradingView. Pine Script has its own alert functions: alertcondition() vs alert().

Questions

How do I get MT5 alerts on my phone?

Install the MetaTrader 5 app, find its MetaQuotes ID in the app's settings, enter it in the desktop terminal under Tools > Options > Notifications and tick the box that enables push notifications. SendNotification() then reaches the phone.

Why doesn't SendNotification() work?

Read GetLastError() after the call: 4517 means the MetaQuotes ID or the enable box is missing in the terminal's options, 4518 that you sent too many messages too fast. It also does nothing in the Strategy Tester.

Can I use my own sound for an MT5 alert?

Yes: copy a WAV file into the Sounds folder of the terminal's installation and pass its name to PlaySound(). The sound Alert() plays is set in the terminal's options.

This program is a minimal example written to show one technique, not a trading system, and none of it is a recommendation to trade. Trading involves substantial risk of loss and is not suitable for every investor. Edgoro is a software tool, not a broker or financial adviser: nothing it produces is investment advice, and past or backtested performance does not guarantee future results.

Want it inside a complete EA?

Ask Edgoro's MT5 EA generator for push or sound alerts on your entries and exits and they're added to the EA, once per event. A clean build proves the code compiles, not that a strategy works: test it on a demo account.