DMI alert_and_email_20_25_001

Download script
Author: Copyright � 2006, Fernando Gomes.
DMI alert_and_email_20_25_001

This script is a specialized technical analysis tool designed for the MetaTrader 4 platform. Its primary purpose is to monitor market trend strength and direction using the Directional Movement Index (DMI) system. It translates complex price movements into visual data and automated notifications for traders.

Core Functionality

The script calculates several key components of the DMI system to help identify whether a market is trending, ranging, or shifting in momentum:

  • Directional Indicators (+DI and -DI): These measure the strength of upward and downward price movements respectively. By comparing these two lines, the tool helps distinguish between bullish and bearish pressure.
  • ADX (Average Directional Index): This measures the overall strength of a trend regardless of its direction. A rising ADX suggests a strengthening trend, while a falling one may indicate a weakening move or a sideways market.
  • DX and ADXR: These are secondary calculations used to provide smoother perspectives on the directional movement and rate of change.

Key Features and Logic

1. Visual Customization The script allows users to choose which specific lines they want to see on their charts. Because the DMI system contains many variables (like ADX, DX, and various DI lines), this tool provides "Hide" toggles so traders can declutter their workspace and only view the data points most relevant to their strategy.

2. Dynamic Trend Detection The logic constantly calculates the difference between current highs and lows against previous closing prices. It specifically looks for "True Range" (TR)—the maximum price movement during a period—to ensure that the trend strength calculations are accurate and not skewed by insignificant price fluctuations.

3. Automated Alert System One of the primary functions of this script is its proactive notification system. It monitors the market in real-time for specific "crossovers":

  • Crossover Alerts: The script triggers an alert whenever the +DI line crosses over the -DI line (or vice versa), signaling a potential shift in momentum from bullish to bearish or vice versa.
  • Threshold Monitoring: Users can set specific "High" and "Low" levels. If a trend becomes exceptionally strong (e.g., the +DI exceeds a high threshold while the -DI remains low), the script can automatically send an email notification and play a sound alert.

4. Smart Notification Handling To ensure traders are not overwhelmed by constant noise, the script includes logic to prevent "alert spam." It tracks the time of the last alert to ensure that it only notifies the user once per candle, providing a clean, usable stream of information during live trading sessions.

Price Data Components
Series array that contains open time of each bar
Miscellaneous
Implements a curve of type %1It issuies visual alerts to the screenIt sends emailsIt plays sound alerts
12 Views
0 Downloads
0 Favorites
DMI alert_and_email_20_25_001
//+------------------------------------------------------------------+
//|                                                    DMI alert.mq4 |
//|                                Copyright © 2006, Fernando Gomes. |
//|                                    http://www.ciavox.com/~fgomes |
//+------------------------------------------------------------------+

#property copyright "Copyright © 2006, Fernando Gomes."
#property link      "http://www.ciavox.com/~fgomes"


//---- indicator settings
#property indicator_separate_window
#property indicator_buffers	5
#property indicator_color1	DodgerBlue
#property indicator_color2	Magenta
#property indicator_color3	Yellow
#property indicator_color4	DeepSkyBlue
#property indicator_color5	Blue

#property indicator_minimum	0
#property indicator_level1	20
#property indicator_level2	25
#property indicator_maximum	60


//---- indicator parameters

extern bool AlertsEnabled = false;
extern string AlertsSound = "alert.wav";
extern int HighLevel = 25;
extern int LowLevel = 20;

extern int Smooth   = 14;
extern bool Hide_DI_Plus  = False;
extern bool Hide_DI_Minus = False;
extern bool Hide_DX   = true;
extern bool Hide_ADX  = true;
extern bool Hide_ADXR = true;


//---- indicator buffers
double b_di_p[];     // buffer +DI
double b_di_m[];     // buffer -DI
double b_dmi[];      // buffer DMI
double b_adx[];      // buffer Average Directional indeX
double b_adxr[];     // buffer Average Directional indeX Rate


//---- NOTICE that these arrays must be included in ArraySetAsSeries()
double dm_p_avg[];
double dm_m_avg[];
double tr_avg[];


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void init()
{
	//---- indicator buffers mapping
	IndicatorBuffers(8);
	if (   !SetIndexBuffer(0, b_di_p)
		&& !SetIndexBuffer(1, b_di_m)
		&& !SetIndexBuffer(2, b_dmi)
		&& !SetIndexBuffer(3, b_adx)
		&& !SetIndexBuffer(4, b_adxr)
		&& !SetIndexBuffer(5, dm_p_avg)
		&& !SetIndexBuffer(6, dm_m_avg)
		&& !SetIndexBuffer(7, tr_avg)) {
		
		Print("cannot set indicator buffers!");
		return;
	}
	
	//---- name for DataWindow and indicator subwindow label
	IndicatorShortName("DMI alert(" + Smooth + ")");
	SetIndexLabel(0, "+DI");
	SetIndexLabel(1, "-DI");
	SetIndexLabel(2, "DX");
	SetIndexLabel(3, "ADX");
	SetIndexLabel(4, "ADXR");
	
	//----
	SetIndexStyle(0, DRAW_LINE + Hide_DI_Plus*DRAW_NONE, STYLE_SOLID, 1, indicator_color1);
	SetIndexStyle(1, DRAW_LINE + Hide_DI_Minus*DRAW_NONE, STYLE_SOLID, 1, indicator_color2);
	SetIndexStyle(2, DRAW_LINE + Hide_DX*DRAW_NONE, STYLE_SOLID, 1, indicator_color3);
	SetIndexStyle(3, DRAW_LINE + Hide_ADX*DRAW_NONE, STYLE_SOLID, 1, indicator_color4);
	SetIndexStyle(4, DRAW_LINE + Hide_ADXR*DRAW_NONE, STYLE_SOLID, 1, indicator_color5);
	
	//----
	SetIndexDrawBegin(0, Smooth);
	SetIndexDrawBegin(1, Smooth);
	SetIndexDrawBegin(2, Smooth);
	SetIndexDrawBegin(3, 2*Smooth);
	SetIndexDrawBegin(4, 3*Smooth);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
	static datetime AlertTime = 0;
	
	int counted_bars = IndicatorCounted();
	if (counted_bars < 0) return(-1);
	if (Bars < 2) return(-1);
	if (Smooth < 2) return(-1);
	int limit = Bars - 1 - counted_bars;
	
	double smooth = 1.0/(Smooth*1.0);
	
	int firstDMI  = Bars-1-Smooth;
	int firstADX  = Bars-1-(2*Smooth);
	int firstADXR = Bars-1-(3*Smooth);

	for (int i = limit; i >= 0; i--) {
		double high;
		double low;
		double dm_p;
		double dm_m;
		
		if (i < firstDMI) {
			high = High[i]  - High[i+1];
			low  = Low[i+1] - Low[i];
			dm_p = 0.0;
			dm_m = 0.0;
			if ((high > low) && (high > 0.0))
				dm_p = high;
			else
				if ((low > high) && (low > 0.0))
					dm_m = low;
			
			// calculate averages (cumulative formula)
			dm_p_avg[i] = dm_p_avg[i+1] - ( smooth * dm_p_avg[i+1] ) + dm_p;
			dm_m_avg[i] = dm_m_avg[i+1] - ( smooth * dm_m_avg[i+1] ) + dm_m;
			tr_avg[i]   = tr_avg[i+1]   - ( smooth * tr_avg[i+1] ) + calcTR(i);
			
		} else if (i == firstDMI) {
			double sum_dm_p = 0.0;
			double sum_dm_m = 0.0;
			double sum_tr   = 0.0;
			for (int j = i; j < i + Smooth; j++) {
				high = High[j]  - High[j+1];
				low  = Low[j+1] - Low[j];
				dm_p = 0.0 ;
				dm_m = 0.0 ;
				if ((high > low) && (high > 0.0))
					dm_p = high;
				else
					if ((low > high) && (low > 0.0))
						dm_m = low;
				
				sum_dm_p = sum_dm_p + dm_p;
				sum_dm_m = sum_dm_m + dm_m;
				sum_tr   = sum_tr   + calcTR(j);
			}
		
			// define current values
      		dm_p_avg[i] = sum_dm_p * smooth;
      		dm_m_avg[i] = sum_dm_m * smooth;
      		tr_avg[i]   = sum_tr   * smooth;
		} else {
			tr_avg[i] = 0.0;
		}
		
		// Calculate +DI and -DI
		if (tr_avg[i] > 0.0) {
			b_di_p[i] = 100.0 * dm_p_avg[i] / tr_avg[i];
			b_di_m[i] = 100.0 * dm_m_avg[i] / tr_avg[i];
		} else {
			b_di_p[i] = 0.0;
			b_di_m[i] = 0.0;
		}
		
		// calcule DMI
		double sum  = b_di_p[i] + b_di_m[i];
		double diff = MathAbs(b_di_p[i] - b_di_m[i]);
		if (sum > 0.0)
			b_dmi[i] = 100.0*diff/sum;
		else
			b_dmi[i] = 0.0 ;
		
		// Calculate ADX
		if (i<firstADX) {   
			b_adx[i] = smooth*(b_adx[i+1]*(Smooth-1) + b_dmi[i]);
		} else if (i==firstADX) {
			double sum_dmi = 0.0;
			for (int k=i+Smooth+1; k>i; k--) {
				sum_dmi = sum_dmi + b_dmi[k];
			}
			b_adx[i] = smooth * sum_dmi;
		} else {
			b_adx[i] = 0.0;
		}
		
		// Calculate ADXR
		if (i<=firstADXR) {   
			b_adxr[i] = (b_adx[i] + b_adx[i+Smooth]) / 2;
		} else {
			b_adxr[i] = 0.0;
		}
		
		if (AlertsEnabled && i == 0 && AlertTime != Time[0]) {
		   string AlertMSG;
			if ((b_di_p[0] > b_di_m[0] && b_di_p[1] <= b_di_m[1]) || (b_di_p[0] < b_di_m[0] && b_di_p[1] >= b_di_m[1])) {
				AlertTime = Time[0];
				Alert("DMI Indicator! ", Symbol(), " M", Period());
				AlertMSG="DMI indicator  "+Symbol()+" - "+Period()+"  at  "+ DoubleToStr(Close[0],Digits)+ "  -  "+ TimeToStr(CurTime(),TIME_SECONDS);
				if (b_di_p[0] > HighLevel && b_di_m[0] < LowLevel) SendMail(AlertMSG,AlertMSG);
				if (b_di_p[0] < LowLevel && b_di_m[0] > HighLevel) SendMail(AlertMSG,AlertMSG);
				if (StringLen(AlertsSound) > 0)
					PlaySound(AlertsSound);
			}
		}
	} // for
}

double calcTR(int bar)
{
  double a = High[bar] - Low[bar];              // A = Today's High -Today's Low
  double b = MathAbs(Close[bar+1] - High[bar]); // B = Yesterday's Close - Today's High
  double c = MathAbs(Close[bar+1] - Low[bar]);  // C = Yesterday's Close - Today's Low
  return(MathMax(MathMax(a,b),c));
}

Comments