ma_cross_alert_once_b
Download scriptThis script is designed for traders who use Moving Averages (MA) to identify trends in the financial markets. Its primary purpose is to detect "crosses"—the specific moments when a fast-moving average line intersects and passes through a slower-moving average line—and provide immediate visual and audio notifications.
Core Functionality
1. Trend Detection (The Logic) The script constantly monitors two different Moving Average lines:
- Fast Moving Average: Reacts quickly to recent price changes.
- Slow Moving Average: Represents the longer-term trend.
When the Fast MA moves from below to above the Slow MA, the script identifies a potential "Buy" signal (an upward crossover). Conversely, when the Fast MA moves from above to below the Slow MA, it identifies a "Sell" signal (a downward crossover).
2. Smart Alerting System Unlike basic indicators that might send an alert on every single price tick while a cross is happening (which can be overwhelming), this script is designed to be efficient:
- Once-per-Cross Logic: It only triggers an alert the very first time a cross occurs. It will remain silent until the lines cross back in the opposite direction.
- Visual Markers: It automatically places arrows on your price chart at the exact point where the crossover occurred, making it easy to review past signals.
3. Customizable Notifications The script is highly versatile in how it communicates with you. Depending on your preferences, you can enable various notification methods:
- Popup Alerts: On-screen messages within the trading platform.
- Audio Alerts: A sound file plays to grab your attention immediately.
- Push Notifications: Sends a message directly to your mobile device (via the MetaTrader app).
- Email Alerts: Sends a detailed summary of the cross (including symbol, price, time, and account info) to your registered email address.
Customization Options
Users can fine-tune the script to match their specific trading style by adjusting the following:
- MA Settings: Choose the speed (period), the shift, and the calculation method (e.g., Simple, Exponential, etc.) for both the fast and slow lines.
- Price Source: Define which price data the averages should calculate from (e.g., Close Price, Median Price, or Weighted Price).
- Alert Toggles: Easily turn specific notification types on or off without changing the core logic.
//+------------------------------------------------------------------+
//| MA_Cross_Alert_Once_b.mq4 |
//| Copyright 2016, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, file45."
#property link "https://www.mql5.com/en/users/file45/publications"
#property version "1.00"
#property strict
#property description "When two Moving Averages cross the indicator will alert once per cross between crosses(not once per candle) and mark the cross point with down or up arrow."
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 Lime
#property indicator_color2 Red
input bool Cross_Alert = true; // Alert
input bool Sound_Only = false; // Sound Only
input bool Cross_PN = false; // Push Notification
input bool Cross_Email = false; // Email
input int Slow_MA_Period = 7; // Slow Period
input int Slow_MA_Shift = 0; // Slow Shift
input ENUM_MA_METHOD Slow_MA_Method = 0; // Slow Method
input ENUM_APPLIED_PRICE Slow_MA_Price = 0; // Slow Price
input int Fast_MA_Period = 1; // Fast Period
input int Fast_MA_Shift = 0; // Fast Shift
input ENUM_MA_METHOD Fast_MA_Method = 0; // Fast Method
input ENUM_APPLIED_PRICE Fast_MA_Price = 0; // Farst Price
input string Key;
input string Price = "Close Price : Open Price : High Price : Low Price";
input string Price_= "Median Price (high+low)/2 : Typical Price (high+low+close)/3";
input string Price__ = "Weighted Price (high+low+close+close)/4";
double CrossUp[];
double CrossDown[];
#define ALERT_BAR 1
string MA, TM;
int SMP, SMS, FMP, FMS;
datetime LastAlertTime;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
LastAlertTime = TimeCurrent();
switch(Slow_MA_Method)
{
case 0: MA = "SMA";break;
case 1: MA = "EMA"; break;
case 2: MA = "SMMA"; break;
case 3: MA = "LWMA";
}
switch(Period())
{
case 1: TM = "M1"; break;
case 2: TM = "M2"; break;
case 3: TM = "M3"; break;
case 4: TM = "M4"; break;
case 5: TM = "M5"; break;
case 6: TM = "M6"; break;
case 7: TM = "M7"; break;
case 8: TM = "M8"; break;
case 9: TM = "M9"; break;
case 10: TM = "M10"; break;
case 11: TM = "M11"; break;
case 12: TM = "M12"; break;
case 13: TM = "M13"; break;
case 14: TM = "M14"; break;
case 15: TM = "M15"; break;
case 20: TM = "M20"; break;
case 25: TM = "M25"; break;
case 30: TM = "M30"; break;
case 40: TM = "M40"; break;
case 45: TM = "M45"; break;
case 50: TM = "M50"; break;
case 60: TM = "H1"; break;
case 120: TM = "H2"; break;
case 180: TM = "H3"; break;
case 240: TM = "H4"; break;
case 300: TM = "H5"; break;
case 360: TM = "H6"; break;
case 420: TM = "H7"; break;
case 480: TM = "H8"; break;
case 540: TM = "H9"; break;
case 600: TM = "H10"; break;
case 660: TM = "H11"; break;
case 720: TM = "H12"; break;
case 1440: TM = "D1"; break;
case 10080: TM = "W1"; break;
case 43200: TM = "MN"; break;
}
SMP = Slow_MA_Period;
SMS = Slow_MA_Shift;
FMP = Fast_MA_Period;
FMS = Fast_MA_Shift;
SetIndexStyle(0, DRAW_ARROW,0,2);
SetIndexArrow(0, 225);
SetIndexBuffer(0, CrossUp);
SetIndexStyle(1, DRAW_ARROW,0,2);
SetIndexArrow(1, 226);
SetIndexBuffer(1, CrossDown);
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, i;
double Fast_MA_Bar_0, Slow_MA_Bar_0, Fast_MA_Bar_1, Slow_MA_Bar_1;
int counted_bars=IndicatorCounted();
//---- check for possible errors
if(counted_bars<0) return(-1);
//---- last counted bar will be recounted
if(counted_bars>0) counted_bars--;
limit=Bars-counted_bars;
for(i = 0; i <= limit; i++)
{
Fast_MA_Bar_0 = iMA(NULL, 0, Fast_MA_Period, Fast_MA_Shift, Fast_MA_Method, Fast_MA_Price, i+1);
Fast_MA_Bar_1 = iMA(NULL, 0, Fast_MA_Period, Fast_MA_Shift, Fast_MA_Method, Fast_MA_Price, i+2);
Slow_MA_Bar_0 = iMA(NULL, 0, Slow_MA_Period, Slow_MA_Shift, Slow_MA_Method, Slow_MA_Price, i+1);
Slow_MA_Bar_1 = iMA(NULL, 0, Slow_MA_Period, Slow_MA_Shift, Slow_MA_Method, Slow_MA_Price, i+2);
static datetime PrevSignal = 0, PrevTime = 0;
if(ALERT_BAR > 0 && Time[0] <= PrevTime)
{
return(0);
}
PrevTime = Time[0];
if(PrevSignal <= 0)
{
if((Fast_MA_Bar_1 < Slow_MA_Bar_1) && (Fast_MA_Bar_0 > Slow_MA_Bar_0)) // For Examples see: https://book.mql4.com/samples/indicators if( M_1 < S_1 && M_0 > S_0 )
{
CrossUp[i=1] = Low[i=1] - iATR(NULL,0,20,i)/2;
PrevSignal = 1;
if(Sound_Only)
{
PlaySound("Alert.wav");
}
if(Cross_Alert && Sound_Only == false)
{
Alert("BUY cross: ",Symbol(), " ", TM , " - ",IntegerToString(SMP)," ",MA," ",IntegerToString(SMS),"\n",DoubleToStr(Ask,Digits),"\n",TimeToStr(TimeCurrent(),TIME_SECONDS)," ",TimeToStr(TimeCurrent(),TIME_DATE),"\n",AccountCompany());
}
if(Cross_Email)
{
SendMail ("Buy cross -" + Symbol() + "-" + TM + "-" + AccountCompany(),
"Buy Cross Alert" + "\n" +
"--------------------" + "\n" +
"Symbol : " + " " + Symbol() + " \n" +
"Period : " + " " + TM + " \n" +
"Slow MA : " + IntegerToString(SMP)+" "+MA+" "+IntegerToString(SMS)+ " \n" +
"Fast MA : " + IntegerToString(FMP)+" "+MA+" "+IntegerToString(FMS)+ " \n" +
"Ask Price : " + DoubleToStr(Ask,Digits)+ " \n" +
"Time and Date : " + TimeToStr(TimeCurrent(), TIME_SECONDS)+ " " + TimeToStr(TimeCurrent(), TIME_DATE) + " \n" +
"Broker : " + " " + AccountCompany() + "\n" +
"Account # : " + " " + IntegerToString(AccountNumber()));
}
if(Cross_PN)
{
SendNotification("BUY: " + Symbol() + " " + TM + " <" + IntegerToString(SMP) + " " + MA + " " + IntegerToString(SMS) + "> " + DoubleToStr(Ask,Digits) + " " + "\n"+
TimeToStr(TimeCurrent(),TIME_SECONDS)+" "+TimeToStr(TimeCurrent(),TIME_DATE)+" " + AccountCompany());
}
}
}
if(PrevSignal >= 0)
{
if((Fast_MA_Bar_1 > Slow_MA_Bar_1) && (Fast_MA_Bar_0 < Slow_MA_Bar_0)) // For Examples see: https://book.mql4.com/samples/indicators ( if( M_1 > S_1 && M_0 < S_0 )
{
CrossDown[i=1] = High[i=1] + iATR(NULL,0,20,i)/2;
PrevSignal = -1;
if(Sound_Only)
{
PlaySound("Alert.wav");
}
if(Cross_Alert && Sound_Only == false)
{
Alert("SELL cross: ",Symbol(), " ", TM , " - ",IntegerToString(SMP)," ",MA," ",IntegerToString(SMS),"\n",DoubleToStr(Bid,Digits) + "\n",TimeToStr(TimeCurrent(),TIME_SECONDS)," ",TimeToStr(TimeCurrent(),TIME_DATE),"\n",AccountCompany());
}
if(Cross_Email)
{
SendMail ("Sell cross -" + Symbol() + "-" + TM + "-"+ "-" + AccountCompany(),
"Sell Cross ALert" + "\n" +
"--------------------" + "\n" +
"Symbol : " + " " + Symbol() + " \n" +
"Period : " + " " + TM + " \n" +
"Slow MA : " + IntegerToString(SMP)+" "+MA+" "+IntegerToString(SMS)+ "-" + "\n" +
"Fast MA : " + IntegerToString(FMP)+" "+MA+" "+IntegerToString(FMS)+ " \n" +
"Bid Price : " + DoubleToStr(Bid,Digits)+ "\n" +
"Time and Date : " + TimeToStr(TimeCurrent(), TIME_SECONDS)+ " " + TimeToStr(TimeCurrent(), TIME_DATE) + " \n" +
"Broker : " + " " + AccountCompany() + "\n" +
"Account # : " + " " + IntegerToString(AccountNumber()));
}
if(Cross_PN)
{
SendNotification("SELL: " + Symbol() + " " + TM + " <" + IntegerToString(SMP) + " " + MA + " " + IntegerToString(SMS) + "> " + DoubleToStr(Bid,Digits) + " " + "\n" +
TimeToStr(TimeCurrent(),TIME_SECONDS)+" "+TimeToStr(TimeCurrent(),TIME_DATE)+" " + AccountCompany());
}
}
}
}
return(rates_total);
}
Comments