MACD_Signals_en
Download scriptThis script is a specialized technical analysis tool designed to enhance the standard MACD (Moving Average Convergence Divergence) indicator. It focuses on identifying high-quality trend reversals by filtering out "noise" and focusing on significant price movements.
Core Logic Overview
The indicator works by processing market data to identify specific patterns in momentum. Rather than just showing a basic moving average crossover, it applies several layers of logic to determine when a signal is truly meaningful:
1. Normalization and Data Processing The script takes the standard MACD calculation and "normalizes" it against a long-term moving average. This helps smooth out the data, making it easier to see the relative strength of the current price action compared to the overall trend.
2. Trend Tracking and Sequence Filtering One of the primary features of this logic is its ability to distinguish between minor fluctuations and significant trend changes:
- Directional Monitoring: The script constantly tracks whether the momentum is moving upward or downward.
- Sequence Requirements: It includes a "Sequence" filter. This means the indicator won't trigger a signal unless a certain amount of time (measured in bars) has passed since the last significant movement. This prevents the tool from giving multiple signals during a single choppy market move, ensuring that only distinct shifts in price action are highlighted.
3. Pattern Recognition The script looks for specific "extremum" patterns. It evaluates the current signal against previous historical values to confirm a reversal. Specifically:
- It checks if the previous movement was of a different direction than the current one.
- It compares the intensity (value) of these movements against historical peaks and valleys.
- If the logic detects a significant enough change in momentum that meets the "Sequence" criteria, it identifies a potential entry point.
4. Visual Signaling Once a valid pattern is identified based on the rules above, the script provides immediate visual feedback:
- Arrows: It places upward or downward arrows directly on the chart to indicate buy or sell opportunities.
- Color Coding: It utilizes a dual-histogram style (SkyBlue and FireBrick) to represent different momentum states.
- Alerts: It can be configured to send an audible alert when these specific conditions are met.
5. Automatic Cleanup To keep the chart clean, the script includes a management system that can automatically remove its drawn arrows if you decide to remove the indicator from your view, ensuring no "ghost" signals remain on your workspace.
//+------------------------------------------------------------------+
//| MyMACD_V2.mq4 |
//| Copyright © 2008, TheXpert |
//| theforexpert@gmail.com |
//+------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1 SkyBlue
#property indicator_color2 FireBrick
#property indicator_width1 2
#property indicator_width2 2
extern string Copyright = "Copyright (c) TheXpert, mailto:TheForEXpert@gmail.com";
extern string _1 = "Parameters for MACD";
extern int MaFast = 5;
extern int MaSlow = 73;
extern int MaSignal = 13;
extern string _2 = "Applied price (0, 1 ... 6)";
extern int Price = 3;
extern string _3 = "Extremum is valuable when distance in bars from previous valuable extremum to current is not less than <Sequence>";
extern int Sequence = 17;
extern string _4 = "Draw signal arrows or not";
extern bool DrawArrows = true;
extern string _5 = "Delete signal arrows when deleting indicator or not";
extern bool DeleteArrows = true;
extern string _6 = "Alert or not when signal appears";
extern bool UseAlert = false;
#define NONE 0
#define UP 1
#define DN -1
int Direction = NONE;
double Last = 0;
datetime LastTime;
//---- buffers
double UpValue[];
double DnValue[];
double PatternSignal[];
double Signal[];
double SignalDirection[];
string symbol;
int Length = 0;
int Prev = 0;
int PrevPrev = 0;
int PrevPrevPrev = 0;
double PrevValue = 0;
double PrevPrevValue = 0;
double PrevPrevPrevValue = 0;
double LastSignalValue = 0;
int LastSignal = 0;
bool IsLastSignal = false;
void PushBack(int Now, double NowValue)
{
if (Prev == Now)
{
PrevValue = NowValue;
}
else
{
PrevPrevPrev = PrevPrev;
PrevPrevPrevValue = PrevPrevValue;
PrevPrev = Prev;
PrevPrevValue = PrevValue;
Prev = Now;
PrevValue = NowValue;
}
}
int init()
{
IndicatorBuffers(5);
IndicatorShortName("-=<MyMACD>=-");
SetIndexBuffer(0, UpValue);
SetIndexBuffer(1, DnValue);
SetIndexBuffer(2, SignalDirection);
SetIndexBuffer(3, PatternSignal);
SetIndexBuffer(4, Signal);
SetIndexStyle(0, DRAW_HISTOGRAM);
SetIndexStyle(1, DRAW_HISTOGRAM);
symbol = Symbol();
LastTime = Time[0];
return(0);
}
int start()
{
if (LastTime > Time[0])
{
return(0);
}
LastTime = Time[0];
int ToCount = Bars - IndicatorCounted();
bool dataIsLoaded = false;
while (!dataIsLoaded)
{
double price = 0;
int error = 0;
dataIsLoaded = true;
for (int i = ToCount - 2; i >= 0; i--)
{
price = Open[i];
error = GetLastError();
if (4066 == error)
{
Sleep(1000);
dataIsLoaded = false;
break;
}
}
}
for (i = ToCount - 2; i >= 0; i--)
{
double ma = iMA(symbol, 0, MaSlow, 0, MODE_EMA, Price, i + 1);
if(ma == 0 || ma == EMPTY_VALUE) continue;
// normalizing MACD values
double now = iMACD(symbol, 0, MaFast, MaSlow, MaSignal, Price, MODE_SIGNAL, i + 1)/ma;
UpValue[i + 1] = now;
Signal[i + 1] = 0;
SignalDirection[i + 1] = SignalDirection[i + 2];
PatternSignal[i + 1] = 0;
if (Last == 0)
{
Last = now;
continue;
}
if (Direction == NONE)
{
if (Last > now) Direction = DN;
if (Last < now) Direction = UP;
Last = now;
Length = 1;
continue;
}
if ((now - Last)*Direction > 0)
{
Last = now;
Length++;
Signal[i + 1] = 0;
continue;
}
if ((now - Last)*Direction < 0)
{
Direction = -Direction;
Signal[i + 1] = Direction*UpValue[i + 1];
Last = now;
if (Prev == 0)
{
PushBack(Direction, now);
Length = 1;
continue;
}
else
{
if (IsLastSignal)
{
if (Length > Sequence)
{
PushBack(LastSignal, LastSignalValue);
PushBack(Direction, now);
IsLastSignal = false;
}
else
{
LastSignal = Direction;
LastSignalValue = now;
Length = 1;
continue;
}
}
else
{
if (Length > Sequence)
{
PushBack(Direction, now);
}
else
{
LastSignal = Direction;
LastSignalValue = now;
IsLastSignal = true;
Length = 1;
continue;
}
}
Length = 1;
// patterns
if ( Prev == 1
&& PrevValue > PrevPrevPrevValue) PatternSignal[i + 1] = 1;
if ( Prev == -1
&& PrevValue < PrevPrevPrevValue) PatternSignal[i + 1] = -1;
if ( Prev == 1
&& PrevValue > -0.1*PrevPrevValue) PatternSignal[i + 1] = 1;
if ( Prev == -1
&& PrevValue < -0.1*PrevPrevValue) PatternSignal[i + 1] = -1;
if (PatternSignal[i + 1] != 0)
{
if (PatternSignal[i + 1] > 0)
{
if (DrawArrows)
{
string name = "MyMACD_Arrow #" + Time[i + 1];
ObjectCreate(name, OBJ_ARROW, 0, Time[i], Open[i]);
ObjectSet(name, OBJPROP_ARROWCODE, SYMBOL_ARROWUP);
}
if (UseAlert)
{
Alert("Buy Signal");
}
SignalDirection[i + 1] = 1;
}
if (PatternSignal[i + 1] < 0)
{
if (DrawArrows)
{
name = "MyMACD_Arrow #" + Time[i + 1];
ObjectCreate(name, OBJ_ARROW, 0, Time[i], Open[i]);
ObjectSet(name, OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN);
}
if (UseAlert)
{
Alert("Sell signal");
}
SignalDirection[i + 1] = -1;
}
}
}
}
}
for (i = ToCount - 2; i >= 0; i--)
{
DnValue[i + 1] = EMPTY_VALUE;
if (SignalDirection[i + 1] == -1)
{
DnValue[i + 1] = UpValue[i + 1];
}
}
return(0);
}
int deinit ()
{
if (!DeleteArrows) return (0);
for (int i = ObjectsTotal() - 1; i >= 0; i--)
{
string name = ObjectName(i);
if (StringFind(name, "MyMACD_Arrow") != -1)
{
ObjectDelete(name);
}
}
}
Comments