DMI alert_and_email
Download scriptThis script is a specialized technical analysis tool designed for the MetaTrader trading platform. Its primary purpose is to monitor market trends and provide real-time notifications when specific shifts in price momentum occur.
Core Functionality
The script utilizes the Directional Movement Index (DMI) system to analyze price action. It breaks down market movement into three main components:
- +DI and -DI Lines: These track the strength of upward and downward trends, respectively. They help identify which direction the market is currently favoring.
- ADX (Average Directional Index): This measures the overall strength of a trend, regardless of its direction. It helps traders distinguish between a strong trending market and a weak, sideways market.
- ADXR: A smoothed version of the ADX used to filter out "noise" and provide a clearer picture of long-term trend stability.
How the Logic Works
The script processes historical price data (Highs, Lows, and Closes) to calculate these indicators using a customizable "smoothing" period. By analyzing how much the price moves up versus how much it moves down over a set number of bars, the script determines the prevailing market sentiment.
Automated Alert System
One of the key features of this script is its proactive notification system. It monitors the relationship between the upward (+DI) and downward (-DI) lines:
- Trend Crossovers: The logic constantly watches for a "crossover" event—this happens when the +DI line moves above the -DI line (potential bullish shift) or falls below it (potential bearish shift).
- Real-Time Notifications: When a crossover is detected on the current live candle, the script triggers multiple alerts simultaneously:
- Visual Alert: A pop-up message appears on the trading terminal.
- Audio Alert: An audible sound file plays to notify the user immediately.
- Email Notification: If enabled, it sends a detailed summary to the user's email, including the specific asset name, the current timeframe, and the exact closing price at the moment of the shift.
User Customization
The tool is designed to be flexible for different trading styles. It allows users to:
- Adjust the Smoothing period to make the analysis more or less sensitive to price changes.
- Toggle Visibility: Users can choose to hide specific lines (like ADX or DX) on the chart to declutter their workspace and focus only on the data points that matter to them.
- Control Alerts: Users can turn the entire notification system on or off based on their preference.
//+------------------------------------------------------------------+
//| 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 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 (AlertsEnabled) 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