sequential-countdown/mql5/Indicators/SequentialCountdown/SignalAlerts.mqh
83 lines
3.1 KiB
MQL5
//+------------------------------------------------------------------+
//| SignalAlerts.mqh |
//| Copyright 2026, Allan Niñal |
//| https://www.allanninal.dev/mql5 |
//+------------------------------------------------------------------+
//| Same alert semantics as Allan's signal indicators (UT Bot, |
//| SuperTrend): one alert per closed-bar signal (pop-up, sound, |
//| push, e-mail), never during the history load, never twice for |
//| the same bar, silent in the tester. A scanner watches many |
//| symbols, so the cells that signal in the same second are sent |
//| as ONE message (push and e-mail are rate limited). |
//+------------------------------------------------------------------+
// SPDX-License-Identifier: LicenseRef-PolyForm-Noncommercial-1.0.0 (see LICENSE)
#property strict
#include <ChartKit/CkDebug.mqh>
input group "Alerts"
input bool InpAlertPopup = true; // Pop-up alert
input bool InpAlertSound = false; // Play a sound
input string InpSoundFile = "alert.wav"; // Sound file (terminal Sounds folder)
input bool InpAlertPush = true; // Push notification (set up MetaQuotes ID in Options)
input bool InpAlertEmail = false; // E-mail (set up in Options)
//--- send one message to every channel that is switched on
void SignalAlertMessage(const string product,const string msg)
{
if(msg=="")
return;
if(MQLInfoInteger(MQL_TESTER))
{
CkDbg("alert not sent in the Strategy Tester: "+msg);
return;
}
string text=product+": "+msg;
CkDbg("alert: "+msg);
if(InpAlertPopup)
Alert(text);
if(InpAlertSound && InpSoundFile!="")
PlaySound(InpSoundFile);
if(InpAlertPush)
{
if(!TerminalInfoInteger(TERMINAL_NOTIFICATIONS_ENABLED))
CkDbg("push not sent: notifications are off in Options");
else
if(!SendNotification(StringSubstr(text,0,255)))
CkDbg("push failed, error "+IntegerToString(GetLastError()));
}
if(InpAlertEmail)
{
if(!TerminalInfoInteger(TERMINAL_EMAIL_ENABLED))
CkDbg("e-mail not sent: e-mail is off in Options");
else
if(!SendMail(product,text))
CkDbg("e-mail failed, error "+IntegerToString(GetLastError()));
}
}
//--- Object budget: an indicator that draws labels or lines keeps at most OBJ_CAP of them. Past that, the oldest
//--- are deleted as new ones are made, so a 20000-bar history cannot make the chart crawl. Buffers are not affected.
#define OBJ_CAP 2500
string g_objq[];
int g_objn=0,g_objh=0;
void ObjBudgetReset(void)
{
g_objn=0;
g_objh=0;
}
void ObjBudget(const string name)
{
if(ArraySize(g_objq)!=OBJ_CAP)
ArrayResize(g_objq,OBJ_CAP);
if(g_objn<OBJ_CAP)
{
g_objq[(g_objh+g_objn)%OBJ_CAP]=name;
g_objn++;
return;
}
ObjectDelete(0,g_objq[g_objh]);
g_objq[g_objh]=name;
g_objh=(g_objh+1)%OBJ_CAP;
}
//+------------------------------------------------------------------+