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.
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()returnsfalsewhen the file isn't found. The name is relative to theSoundsfolder of the terminal's installation;alert2.wavis 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_ENABLEDandTERMINAL_MQIDtell 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()returnsfalseandGetLastError()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'sSoundsfolder; 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.