DMI_Levels_alert_and_email
Download scriptThis script is a technical analysis tool designed for the MetaTrader 4 platform. It functions as an enhanced version of the Directional Movement Index (DMI), a popular indicator used by traders to determine the strength and direction of market trends.
Core Functionality
The script analyzes price action by comparing the current period's highs and lows against previous ones to identify whether the market is moving predominantly upward, downward, or sideways. It processes this data into several distinct components:
- Directional Indicators (+DI and -DI): These represent the strength of upward and downward momentum, respectively.
- DMI (DX): This measures the overall "difference" between the positive and negative movements, helping to visualize how much the market is trending in one specific direction versus the other.
- ADX and ADXR: These are advanced smoothing calculations that filter out "market noise." They are primarily used to determine the intensity of a trend—telling you not just where the price is going, but how strong that movement really is.
Key Features and Customization
The script includes several user-friendly options to tailor the visual experience:
- Visual Filtering: Users can choose to hide specific components (like ADX or DX) from the chart if they prefer a cleaner view, allowing you to focus only on the data points most relevant to your strategy.
- Smoothing Control: A "Smooth" parameter allows you to adjust how much historical data is factored into the calculations, helping to balance sensitivity against reliability.
- Dynamic Alerts: One of the primary functions of this script is its automated notification system. It monitors the market in real-time and triggers an alert (via sound, on-screen pop-up, or email) when specific trend conditions are met.
Alert Logic
The "Alert" system is designed to notify you when there is a significant divergence in trend strength. Specifically, it looks for instances where:
- The Positive Directional Index (+DI) rises above a high threshold while the Negative Directional Index (-DI) stays below a low threshold (indicating a strong bullish move).
- OR the Negative Directional Index (-DI) rises above the high threshold while the Positive Directional Index (+DI) remains below the low threshold (indicating a strong bearish move).
When these conditions occur, the script provides an immediate notification including the current price, the timeframe, and the specific symbol, allowing for faster reaction times in live trading.
//+------------------------------------------------------------------+
//| 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] > HighLevel && b_di_m[0] < LowLevel) || (b_di_m[0] > HighLevel && b_di_p[0] < LowLevel)) {
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