MA_PriceCrossover_Alert
Download scriptThis tool is designed as a visual and audible signaling system for traders using the MetaTrader platform. It identifies specific moments when price trends shift by monitoring the relationship between two different Moving Averages (MAs).
Core Functionality
The primary logic of the script revolves around detecting "crossovers." Instead of just showing you the lines themselves, the tool looks for instances where the market price moves from being on one side of a moving average to the other.
To provide high precision, the script allows for significant customization:
- Moving Average Types: Users can choose between various calculation methods (such as Simple, Exponential, Smoothed, Linear Weighted, or Least Squares averages).
- Price Source Selection: The logic can be based on different price points, such as just the "Close" price, the "High/Low" extremes, or custom weighted averages of all price points within a candle.
Visual Indicators
When the script detects a significant trend shift, it places visual markers directly on your trading chart:
- Buy Signals: When the price moves above the moving averages, an arrow appears below the current candle.
- Sell Signals: When the price moves below the moving averages, an arrow appears above the current candle.
The placement of these arrows is dynamically calculated based on the recent market volatility (the average range of recent candles), ensuring that the icons remain clearly visible and do not overlap with the price bars.
Alert System
Beyond visual cues, the script acts as a proactive notification system. It is programmed to monitor the market in real-time and trigger alerts based on the following conditions:
- Audio Alerts: The tool can trigger a sound notification on your computer the moment a crossover occurs.
- Email Notifications: If enabled, it can send an automated email containing the specific signal type (Buy or Sell), the current market price (Ask and Bid), and the exact time of the event.
- Smart Filtering: The logic includes a "memory" system (using global variables) to ensure that you are not bombarded with repetitive alerts for the same signal. It attempts to track when the last alert was sent so that it only notifies you of new, distinct crossover events.
Summary of Workflow
- Data Analysis: The script constantly calculates two moving averages based on your preferred settings.
- Comparison: It compares the current price against these averages and checks the previous price position to confirm a "cross" has actually occurred.
- Action: Once a cross is confirmed, it draws an arrow on the chart and simultaneously triggers the chosen notification methods (Sound or Email) to alert the trader immediately.
//+------------------------------------------------------------------+
//| MA-Crossover_Alert.mq4 |
//| Copyright © 2005, Jason Robinson (jnrtrading) |
//| http://www.jnrtading.co.uk |
//| Modified by Robert Hill to add LSMA and alert or send email |
//| Added Global LastAlert to try to have alert only on new cross |
//| but does not seem to work. So indicator does alert every bar |
//+------------------------------------------------------------------+
/*
+------------------------------------------------------------------+
| Allows you to enter two ma periods and it will then show you at |
| Which point they crossed over. It is more usful on the shorter |
| periods that get obscured by the bars / candlesticks and when |
| the zoom level is out. Also allows you then to remove the mas |
| from the chart. (emas are initially set at 5 and 6) |
+------------------------------------------------------------------+
*/
#property copyright "Copyright © 2005, Jason Robinson (jnrtrading)"
#property link "http://www.jnrtrading.co.uk"
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 LawnGreen
#property indicator_color2 Red
extern bool SoundON=true;
extern bool EmailON=false;
extern string m="MA Modes";
extern string m1="0=sma, 1=ema, 2=smma, 3=lwma, 4=lsma";
extern string pm = "Price Modes";
extern string pm1 = " 0=close, 1=open, 2=high, 3=low";
extern string pm2 = " 4=median(high+low)/2";
extern string pm3 = " 5=typical(high+low+close)/3";
extern string pm4 = " 6=weighted(high+low+close+close)/4";
extern int FastMA_Mode = 1; //0=sma, 1=ema, 2=smma, 3=lwma, 4=lsma
extern int FastMA_Period = 5;
extern int FastPriceMode = 0;//0=close, 1=open, 2=high, 3=low, 4=median(high+low)/2, 5=typical(high+low+close)/3, 6=weighted(high+low+close+close)/4
extern int SlowMA_Mode = 1; //0=sma, 1=ema, 2=smma, 3=lwma, 4=lsma
extern int SlowMA_Period = 6;
extern int SlowPriceMode = 0;//0=close, 1=open, 2=high, 3=low, 4=median(high+low)/2, 5=typical(high+low+close)/3, 6=weighted(high+low+close+close)/4
double CrossUp[];
double CrossDown[];
int flagval1 = 0;
int flagval2 = 0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
SetIndexStyle(0, DRAW_ARROW, EMPTY, 3);
SetIndexArrow(0, 233);
SetIndexBuffer(0, CrossUp);
SetIndexStyle(1, DRAW_ARROW, EMPTY, 3);
SetIndexArrow(1, 234);
SetIndexBuffer(1, CrossDown);
GlobalVariableSet("AlertTime"+Symbol()+Period(),CurTime());
GlobalVariableSet("SignalType"+Symbol()+Period(),OP_SELLSTOP);
// GlobalVariableSet("LastAlert"+Symbol()+Period(),0);
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
GlobalVariableDel("AlertTime"+Symbol()+Period());
GlobalVariableDel("SignalType"+Symbol()+Period());
// GlobalVariableDel("LastAlert"+Symbol()+Period());
//----
return(0);
}
//+------------------------------------------------------------------+
//| LSMA with PriceMode |
//| PrMode 0=close, 1=open, 2=high, 3=low, 4=median(high+low)/2, |
//| 5=typical(high+low+close)/3, 6=weighted(high+low+close+close)/4 |
//+------------------------------------------------------------------+
double LSMA(int Rperiod, int prMode, int shift)
{
int i;
double sum, pr;
int length;
double lengthvar;
double tmp;
double wt;
length = Rperiod;
sum = 0;
for(i = length; i >= 1 ; i--)
{
lengthvar = length + 1;
lengthvar /= 3;
tmp = 0;
switch (prMode)
{
case 0: pr = Close[length-i+shift];break;
case 1: pr = Open[length-i+shift];break;
case 2: pr = High[length-i+shift];break;
case 3: pr = Low[length-i+shift];break;
case 4: pr = (High[length-i+shift] + Low[length-i+shift])/2;break;
case 5: pr = (High[length-i+shift] + Low[length-i+shift] + Close[length-i+shift])/3;break;
case 6: pr = (High[length-i+shift] + Low[length-i+shift] + Close[length-i+shift] + Close[length-i+shift])/4;break;
}
tmp = ( i - lengthvar)*pr;
sum+=tmp;
}
wt = sum*6/(length*(length+1));
return(wt);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start() {
int limit, i, counter;
double tmp=0, CurrentClose, PreviousClose;
double fastMAnow, slowMAnow, fastMAprevious, slowMAprevious;
double Range, AvgRange;
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++) {
counter=i;
Range=0;
AvgRange=0;
for (counter=i ;counter<=i+9;counter++)
{
AvgRange=AvgRange+MathAbs(High[counter]-Low[counter]);
}
Range=AvgRange/10;
if (FastMA_Mode == 4)
{
fastMAnow = LSMA(FastMA_Period, FastPriceMode, i);
fastMAprevious = LSMA(FastMA_Period, FastPriceMode, i+1);
}
else
{
fastMAnow = iMA(NULL, 0, FastMA_Period, 0, FastMA_Mode, FastPriceMode, i);
fastMAprevious = iMA(NULL, 0, FastMA_Period, 0, FastMA_Mode, FastPriceMode, i+1);
}
if (SlowMA_Mode == 4)
{
slowMAnow = LSMA( SlowMA_Period, SlowPriceMode, i);
slowMAprevious = LSMA( SlowMA_Period, SlowPriceMode, i+1);
}
else
{
slowMAnow = iMA(NULL, 0, SlowMA_Period, 0, SlowMA_Mode, SlowPriceMode, i);
slowMAprevious = iMA(NULL, 0, SlowMA_Period, 0, SlowMA_Mode, SlowPriceMode, i+1);
}
CurrentClose = iClose(NULL, 0, i);
PreviousClose = iClose(NULL, 0, i+1);
if ( (CurrentClose > fastMAnow) && (CurrentClose > slowMAnow) && ((PreviousClose < fastMAprevious) || (PreviousClose < slowMAprevious)))
{
if (i == 1 && flagval1==0){ flagval1=1; flagval2=0; }
CrossUp[i] = Low[i] - Range*0.75;
}
else if ( (CurrentClose < fastMAnow) && (CurrentClose < slowMAnow) && ((PreviousClose > fastMAprevious) || (PreviousClose > slowMAprevious)))
{
if (i == 1 && flagval2==0) { flagval2=1; flagval1=0; }
CrossDown[i] = High[i] + Range*0.75;
}
}
if (flagval1==1 && CurTime() > GlobalVariableGet("AlertTime"+Symbol()+Period()) && GlobalVariableGet("SignalType"+Symbol()+Period())!=OP_BUY)
{
// if (GlobalVariableGet("LastAlert"+Symbol()+Period()) < 0.5)
// {
if (SoundON) Alert("BUY signal at Ask=",Ask,"\n Bid=",Bid,"\n Time=",TimeToStr(CurTime(),TIME_DATE)," ",TimeHour(CurTime()),":",TimeMinute(CurTime()),"\n Symbol=",Symbol()," Period=",Period());
if (EmailON) SendMail("BUY signal alert","BUY signal at Ask="+DoubleToStr(Ask,4)+", Bid="+DoubleToStr(Bid,4)+", Date="+TimeToStr(CurTime(),TIME_DATE)+" "+TimeHour(CurTime())+":"+TimeMinute(CurTime())+" Symbol="+Symbol()+" Period="+Period());
// }
tmp = CurTime() + (Period()-MathMod(Minute(),Period()))*60;
GlobalVariableSet("AlertTime"+Symbol()+Period(),tmp);
GlobalVariableSet("SignalType"+Symbol()+Period(),OP_SELL);
// GlobalVariableSet("LastAlert"+Symbol()+Period(),1);
}
if (flagval2==1 && CurTime() > GlobalVariableGet("AlertTime"+Symbol()+Period()) && GlobalVariableGet("SignalType"+Symbol()+Period())!=OP_SELL) {
// if (GlobalVariableGet("LastAlert"+Symbol()+Period()) > -0.5)
// {
if (SoundON) Alert("SELL signal at Ask=",Ask,"\n Bid=",Bid,"\n Date=",TimeToStr(CurTime(),TIME_DATE)," ",TimeHour(CurTime()),":",TimeMinute(CurTime()),"\n Symbol=",Symbol()," Period=",Period());
if (EmailON) SendMail("SELL signal alert","SELL signal at Ask="+DoubleToStr(Ask,4)+", Bid="+DoubleToStr(Bid,4)+", Date="+TimeToStr(CurTime(),TIME_DATE)+" "+TimeHour(CurTime())+":"+TimeMinute(CurTime())+" Symbol="+Symbol()+" Period="+Period());
// }
tmp = CurTime() + (Period()-MathMod(Minute(),Period()))*60;
GlobalVariableSet("AlertTime"+Symbol()+Period(),tmp);
GlobalVariableSet("SignalType"+Symbol()+Period(),OP_BUY);
// GlobalVariableSet("LastAlert"+Symbol()+Period(),-1);
}
return(0);
}
Comments