To write an indicator drawing support and resistance lines you need a set of rules that a computer can follow to create those lines. This technique uses the ZigZag indicator to find potential S/R levels and then refines further by finding multiple points.
The code here is a combination for MT4 and MT5. Most code is the same and I show where there are differences.
Start with the input statements, these are common for MT4 and MT5. The first block of inputs are just for the values that will be used by the ZigZag indicator.
[cpp title=”MT4 and MT5″] // Zigzag inputsinput int InpDepth = 12; // Depth
input int InpDeviation = 5; // Deviation
input int InpBackstep = 3; // Backstep
[/cpp]
Next capture inputs to set the gap between points where multiple points would be considered part of a level, the minimum number of points needed to set a level, and how many ZIgZag points to capture to draw S/R lines
[java title=”MT4 and MT5″] // Peak analysis inputsinput int InpGapPoints = 100; // Minimum gap between peaks in points
input int InpSensitivity = 2; // Peak sensitivity
input int InpLookback = 50; // Lookback
[/java]
The last set of inputs are just used to set the common prefix name for the support and resistance line objects, colour and size of the lines
[java title=”MT4 and MT5″] // Drawing inputsinput string InpPrefix = "SRLevel_"; // Object name prefix
input color InpLineColour = clrYellow; // Line colour
input int InpLineWeight = 2; // Line weight
[/java]
Then I define an array to hold the S/R line prices
[java title=”MT4 and MT5″] // For the levelsdouble SRLevels[];
[/java]
and for MT5 create a handle for the ZigZag indicator and a buffer to hold the values form the ZigZag indicator.
[java title=”MT5 Only”] // For the MT5 ZigZag indicatordouble Buffer[];
int Handle;
[/java]
In the OnInit section for MT5 initialise the indicator handle and set up the buffer to hold ZZ values.
[java title=”MT4 and MT5″] int OnInit() {[/java]
[java title=”MT5 Only”] // Init the zz indicator
Handle = iCustom(Symbol(), Period(), "Examples\\ZigZag", InpDepth, InpDeviation, InpBackstep);
if (Handle==INVALID_HANDLE) {
Print("Could not create a handle to zigzag indicator");
return(INIT_FAILED);
}
ArraySetAsSeries(Buffer, true);
[/java]
Also in the OnInit section, for both MT4 and MT5 add some code to clean up in case an earlier indicator has left SR lines showing on the chart and set up the SRLevels array to hold the maximum number of levels.
[java title=”MT4 and MT5″] // Clean up any sr levels left from earlier indicatorsObjectsDeleteAll(0, InpPrefix, 0, OBJ_HLINE);
ChartRedraw(0);
ArrayResize(SRLevels, InpLookback);
return(INIT_SUCCEEDED);
} // end OnInit
[/java]
In OnDeInit for MT5 release the handle to the ZigZag indicator.
[java title=”MT4 and MT5″] void OnDeinit(const int reason) {[/java]
[java title=”MT5 Only”] IndicatorRelease(Handle);
[/java]
and for both MT4 and MT5 again clean up the S/R level lines on exit
[java title=”MT4 and MT5″] ObjectsDeleteAll(0, InpPrefix, 0, OBJ_HLINE);ChartRedraw(0);
} // end OnDeInit
[/java]
The OnCalculate function then is where most of the code happens. To begin for both MT4 and MT5 convert the gap size in points entered in the inputs into a price based gap, check that this is a new bar by comparing rates_total and prev_calculated (this indicator only processes on a new bar) and set up an array to hold peak values from the ZigZag indicator.
[java title=”MT4 and MT5″] int OnCalculate(const int rates_total,const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[]) {
// One time convert points to a price gap
static double levelGap = InpGapPoints*SymbolInfoDouble(Symbol(), SYMBOL_POINT);
// Only do this on a new bar
if (rates_total==prev_calculated) return(rates_total);
// Get the most recent <lookback> peaks
double zz = 0;
double zzPeaks[];
int zzCount = 0;
ArrayResize(zzPeaks, InpLookback);
ArrayInitialize(zzPeaks, 0.0);
[/java]
The following section gathers values from the ZigZag indicator and it is different between MT4 and MT5 due to the different way the products handle indicators. First for MT4 simply look through and use iCustom to get values from the indicator, bars that are not peaks will return zero or empty values
[java title=”MT4 Only”] for (int i=1; i<rates_total && zzCount<InpLookback; i++) {zz = iCustom(Symbol(), Period(), "ZigZag", InpDepth, InpDeviation, InpBackstep, 0, i);
if (zz!=0 && zz!=EMPTY_VALUE) {
zzPeaks[zzCount] = zz;
zzCount++;
}
}
ArraySort(zzPeaks);
[/java]
For MT5 iCustom was set up in the initialisation and we only need to copy information from the indicator handle. The MT5 version also checks that the handle is ready and values are available and exits the loop early if not
[java title=”MT5 Only”] int count = CopyBuffer(Handle, 0, 0, rates_total, Buffer);if (count<0) {
int err=GetLastError();
return(0);
}
for (int i=1; i<rates_total && zzCount<InpLookback; i++) {
zz = Buffer[i];
if (zz!=0 && zz!=EMPTY_VALUE) {
zzPeaks[zzCount] = zz;
zzCount++;
}
}
ArraySort(zzPeaks);
[/java]
The final line in both of the above just places the peaks in ascending ordder to make finding peaks at the same level easier.
The remaining code is common to MT4 and MT5.
This code will loop through the ZigZag peaks array, matching prices within the range specified in the inputs and counting the number of peaks in each range. If enough peaks are found the average price is calculated and that price is set as a S/R level.
[java title=”MT4 and MT5″] // Search for groupings and set levelsint srCounter = 0;
double price = 0;
int priceCount = 0;
ArrayInitialize(SRLevels, 0.0);
for (int i=InpLookback-1; i>=0; i–) {
if (zzPeaks[i]>0) {
price += zzPeaks[i];
priceCount++;
}
if (i==0 || (zzPeaks[i]-zzPeaks[i-1])>levelGap) {
if (priceCount>=InpSensitivity) {
price = price/priceCount;
SRLevels[srCounter] = price;
srCounter++;
}
price = 0;
priceCount = 0;
}
}
DrawLevels();
//— return value of prev_calculated for next call
return(rates_total);
} // end OnCalculate
[/java]
The DrawLevels function called above will scan through the SRLevels array, move any existing lines to any changed prices, draw new lines where needed and clean up any extra lines.
[java title=”MT4 and MT5″] void DrawLevels() {for (int i=0; i<InpLookback; i++) {
string name = InpPrefix + IntegerToString(i);
if (SRLevels[i]==0) {
ObjectDelete(0, name);
continue;
}
if (ObjectFind(0, name)<0) {
ObjectCreate(0, name, OBJ_HLINE, 0, 0, SRLevels[i]);
ObjectSetInteger(0, name, OBJPROP_COLOR, InpLineColour);
ObjectSetInteger(0, name, OBJPROP_WIDTH, InpLineWeight);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, true);
} else {
ObjectSetDouble(0, name, OBJPROP_PRICE, SRLevels[i]);
}
}
ChartRedraw(0);
} // end DrawLevels
[/java]
