_MA_Crossover_Alert__001

Download script
Author: Copyright � 2005, Jason Robinson (jnrtrading)
_MA_Crossover_Alert__001

This script is designed to identify specific trend reversals in financial markets by monitoring the interaction between two different moving averages. It serves as a visual and audible notification system for traders who want to be alerted when momentum shifts from one direction to another.

Core Logic and Functionality

1. Moving Average Analysis The tool tracks two distinct "Moving Averages" simultaneously: a Fast average (designed to react quickly to price changes) and a Slow average (designed to track the broader trend). Users can customize these averages based on several factors:

  • Calculation Type: The user can choose between different mathematical methods for smoothing out price data (such as Simple, Exponential, Linear Weighted, or Least Squares averages).
  • Price Source: Instead of just looking at closing prices, the script can be configured to calculate these averages based on the high, low, open, or a weighted average of all these values.

2. Crossover Detection The primary logic of the script is identifying "Crossovers."

  • Buy Signals: When the Fast average moves from below the Slow average to above it, the script recognizes an upward momentum shift.
  • Sell Signals: When the Fast average moves from above the Slow average to below it, the script recognizes a downward momentum shift.

3. Visual Markers When a crossover is detected, the script places specific visual markers (arrows) directly on the price chart:

  • Upward signals are placed slightly below the current candle's low price.
  • Downward signals are placed slightly above the current candle's high price. The distance of these markers from the candles is automatically calculated based on the recent price range to ensure they remain visible and do not overlap with the candles themselves.

4. Automated Alerts Beyond visual markers, the script provides real-time notifications to keep the trader informed without needing to watch the screen constantly:

  • Audio Alerts: If enabled, the software will trigger a sound notification immediately upon a crossover.
  • Email Notifications: The script can be configured to send an automated email containing the specific price (Ask/Bid), the time of the event, and the current currency pair or asset being traded.

5. Smart Filtering To prevent the system from sending constant, repetitive alerts for every single price tick, the script includes a memory function. It tracks the "Alert Time" and the "Signal Type." This ensures that once an alert is triggered, it won't send a duplicate notification until a new, opposing signal occurs, thereby reducing noise and ensuring only significant trend changes are reported.

Price Data Components
Series array that contains open time of each bar
Indicators Used
Moving average indicator
Miscellaneous
Implements a curve of type %1It issuies visual alerts to the screenIt sends emails
12 Views
0 Downloads
0 Favorites
_MA_Crossover_Alert__001
//+------------------------------------------------------------------+
//|                                           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 int FastMA_Mode = 3; //0=sma, 1=ema, 2=smma, 3=lwma, 4=lsma
extern int FastMA_Period =   3;
extern int FastPriceMode = 6;//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 = 3; //0=sma, 1=ema, 2=smma, 3=lwma, 4=lsma
extern int SlowMA_Period =   34;
extern int SlowPriceMode = 6;//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;
   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);
      }
      
      if ((fastMAnow > slowMAnow) && (fastMAprevious < slowMAprevious))
      {
         if (i == 1 && flagval1==0){  flagval1=1; flagval2=0; }
         CrossUp[i] = Low[i] - Range*0.75;
      }
      else if ((fastMAnow < slowMAnow) && (fastMAprevious > 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