The iCustom Function in MetaTrader 4's MQL4 Language is extremely useful.

The iCustom Function in MQL4 is great for the inclusion of custom indicators in your Expert Advisor.  It is also a good way to verify that an indicator works as it is supposed to do.  Using the iCustom Function can help with backtesting certain so-called "sure-fire" systems and indicators that are found on forums.  Your ability to use the iCustom Function can be incredibly useful in dictating your automated trading experience.  This function can also help you understand whether an indicator is actually coded well, which is very good knowledge to have if or when you choose to create your own indicator.

Why the MQL4 iCustom Function Exists in the First Place

MQL4 has different functions that automatically act upon a set of parameters and there are some pre-set functions based on the most "popular" indicators and oscillators.  The way the non-custom indicators are singled out is by the i[insert function] here.  Here is a list of the recognized indicator function calls, iCustom does not apply to these functions.

    • iAC:  Bill Williams' Accelerator/Decelerator oscillator
    • iAD:  Accumulation/Distribution
    • iADX:  Average Directional Movement Index
    • iAlligator:  Alligator Indicator
    • iAO:  Awesome Oscillator
    • iATR:  Average True Range
    • iBearsPower:  Bears Power Indicator
    • iBands:  Bollinger Bands
    • iBandsOnArray:  Bollinger Bands on an Array
    • iBullsPower:  Bulls Power Indicator
    • iCCI:  Commodity Channel Index Indicator
    • iCCIOnArray:  Commodity Channel Index Indicator on an Array
    • iDeMarker:  DeMarker Indicator
    • iEnvelopes:  Envelopes Indicator
    • iEnvelopesOnArray:  Envelopes Indicator on an Array
    • iForce:  Force Index Indicator
    • iFractals:  Fractors Indicator
    • iGator:  Gator Oscillator
    • iIchimoku:  Ichimoku Cloud Indicator
    • iBWMFI:  Market Facilitation Index indicator
    • iMomentum:  Momentum Indicator
    • iMomentumOnArray:  Momentum Indicator on an Array
    • iMFI:  Money Flow Index Oscillator
    • iMA:  Moving Average
    • iMAOnArray:  Moving Average on an Array
    • iOsMA:  Moving Average of Oscillator indicator
    • iMACD:  Moving Averages Convergence/Divergence indicator
    • iOBV:  On Balance Volume indicator
    • iSAR:  Parabolic SAR Indicator
    • iRSI:  Relative Strength Indicator
    • iRSIOnArray:  Relative Strength Indicator on an Array
    • iRVI:  Relative Vigor Index indicator
    • iStdDev:  Standard Deviation
    • iStdDevOnArray:  Standard Deviation of an Array
    • iStochastic:  Stochastic Oscillator
    • iWPR:  Larry Williams' Percent Range

Any other indicator requires iCustom to be called in an Expert Advisor Program.  It is a Function that is not explained very well, but within the context of a few examples, it will become very easy to understand.   In fact, there is a case where the iCustom Function would not actually work.

The MQL4 iCustom Function Broken Down

The iCustom Function has several parameters inside of it and this is the way that it is presented in the manual by MetaQuotes.

It's a bit on the confusing side, especially with the '...' in the Function, which would seem to indicate that the Function has an indefinite number of parameters to fill and it is very difficult to know how to fill them.  Here's an example of how to use iCustom.

What we first need is a custom indicator and we have one, it is called "RegularPivot".  "RegularPivot" creates Support and Resistance Lines along with a Pivot Point.  These Support and Resistance Lines are S1, S2, S3, Pivot Point, R1, R2, and R3.

</p>
<p>//+------------------------------------------------------------------+<br />
//| RegularPivot.mq4 |<br />
//| Copyright © 2018, Freevestor |<br />
//| |<br />
//+------------------------------------------------------------------+<br />
#property copyright "Copyright © 2018, Freevestor"<br />
#property link ""</p>
<p>#property indicator_chart_window<br />
#property indicator_buffers 8<br />
#property indicator_color1 Maroon<br />
#property indicator_color2 Maroon<br />
#property indicator_color3 Maroon<br />
#property indicator_color4 Green<br />
#property indicator_color5 Navy<br />
#property indicator_color6 Navy<br />
#property indicator_color7 Navy<br />
#property indicator_color8 LimeGreen<br />
#property indicator_style1 STYLE_SOLID<br />
#property indicator_style2 STYLE_SOLID<br />
#property indicator_style3 STYLE_SOLID<br />
#property indicator_style4 STYLE_SOLID<br />
#property indicator_style5 STYLE_SOLID<br />
#property indicator_style6 STYLE_SOLID<br />
#property indicator_style7 STYLE_SOLID<br />
#property indicator_style8 STYLE_SOLID</p>
<p>//---- input parameters<br />
extern int StartHour=0;<br />
extern int StartMinute=0;<br />
extern int DaysToPlot=15;<br />
//---- buffers<br />
double Res3[];<br />
double Res2[];<br />
double Res1[];<br />
double Pivot[];<br />
double Supp1[];<br />
double Supp2[];<br />
double Supp3[];<br />
double Extra1[];<br />
//+------------------------------------------------------------------+<br />
//| Custom indicator initialization function |<br />
//+------------------------------------------------------------------+<br />
int init()<br />
{<br />
//---- indicators<br />
SetIndexStyle(0,DRAW_LINE,STYLE_SOLID);<br />
SetIndexBuffer(0,Res3);<br />
SetIndexStyle(1,DRAW_LINE,STYLE_SOLID);<br />
SetIndexBuffer(1,Res2);<br />
SetIndexStyle(2,DRAW_LINE,STYLE_SOLID);<br />
SetIndexBuffer(2,Res1);<br />
SetIndexStyle(3,DRAW_LINE,STYLE_SOLID,1);<br />
SetIndexBuffer(3,Pivot);<br />
SetIndexStyle(4,DRAW_LINE,STYLE_SOLID);<br />
SetIndexBuffer(4,Supp1);<br />
SetIndexStyle(5,DRAW_LINE,STYLE_SOLID);<br />
SetIndexBuffer(5,Supp2);<br />
SetIndexStyle(6,DRAW_LINE,STYLE_SOLID);<br />
SetIndexBuffer(6,Supp3);<br />
SetIndexStyle(7,DRAW_LINE,STYLE_SOLID);<br />
SetIndexBuffer(7,Extra1);<br />
//----<br />
return(0);<br />
}</p>
<p>

The pre-initialization and initialization sections of the code will provide you with all of the information you need to extract the necessary parameters.

To call the "RegularPivot" indicator in the code, you need to do the following.  It is broken down into parts.

  1. double [Variable of Choice Name] =
  2. iCustom(
  3. For the Symbol, you have two options:
    1. Symbol(), which means the symbol upon which chart the Expert Advisor is applied.  This means that it can work for any symbol as long as it is applied to the particular chart. It can be used for USDJPY, EURUSD, GBPCHF, etc.  It is currency pair/CFD/indice agnostic.
    2. A specific symbol.  "EURUSD", "USDJPY","JP225USD", etc.  You can only choose one at a time.
  4. The Timeframe you want this to apply, you have two options:
    1. "0" - Whatever the chart timeframe may be or the Strategy Tester setting is as far as timeframe.
    2. A specific timeframe for your chart.  PERIOD_D1, PERIOD_H1, PERIOD_M1, etc. are just examples.
  5. The exact name of your timeframe in quotes.  "RegularPivot"
  6. The Line Buffer, which is where you look at the number associated with the particular line.  Sometimes, it is made easy and other times, it is a bit more difficult to determine.  Look at the indicator in question and find the applicable SetIndexBuffer number for the characteristic.  This particular indicator made it easy.
  7. The Bar Shift.  The current candle is 0, the candle that came before it is 1, the candle that came before the candle that came before the current is 2 and it goes on from there.

Those that wish to call "RegularPivot" for any currency pair from the prior candle on a 1 Hour Chart as it relates to the 2nd Support Level would simply do this.

</p>
<p>double S2 = iCustom(Symbol(), PERIOD_H1, "RegularPivot", 5, 1);</p>
<p>

Want to call "RegularPivot" for EURUSD from two candles ago on a 5 Minute Chart as it relates to the 1st Resistance Level?

 </p>
<p>double R1 = iCustom("EURUSD", PERIOD_M5, "RegularPivot", 2, 2); </p>
<p>

Generally speaking, most of the time the iCustom Function will be called like the way it is presented here.  This is the most basic way to call an indicator in an Expert Advisor.  However, it can get more specific based on the inputs.

How can one customize these extra inputs that could be very useful in the Expert Advisor beyond what is standard in the most basic structure?  Go in order from top-to-bottom and include ALL of these inputs.  If a coder wishes to use one of the inputs, the coder must include all of them, even if it is a default value.  It would resemble something that looks like this for "RegularPivot" if one wanted to apply it to an Expert Advisor for AUDJPY for a 1 Hour Period that would trigger two candles prior and

double R2 = iCustom("AUDJPY", PERIOD_H1, "RegularPivot", StartHour, StartMinute, DaysToPlot, 1, 2);

It is a matter of just inserting the desired numbers or criteria that is expected in the inputs that change how the indicator functions rather than how the particular indicator fits within the goals of the Expert Advisor.  The StartHour, StartMinute, and DaysToPlot would change how the actual indicator behaves and perceives Support and Resistance Lines.  If the default settings work for the Expert Advisor, then these extra parameters are not needed to be added.

However, think of it like a sandwich. The standard parts are the bread, they are on the outside and they could apply to ANY indicators.  These extra parameter inputs that were placed in bold above are the inputs that are totally unique to the indicator, they are the meat, dressing, cheese and condiments to the sandwich.

However, there are some indicators that do not behave this way.  In fact, it would result in a very frustrating experience filled with backtesting and forward testing experiences that do not make much sense.  After all, what does one do with code that looks like this?


 

</p>
<p>#property description "Displays Supply and Demand zones.."<br />
#property version     "2.33"</p>
<p>#property indicator_chart_window<br />
#property indicator_buffers 6<br />
input ENUM_TIMEFRAMES       TimeFrame                        = PERIOD_H1;<br />
input bool                  DrawZones                        = true;<br />
input bool                  SolidZones                       = true;<br />
input bool                  SolidRetouch                     = true;<br />
input bool                  RecolorRetouch                   = true;<br />
input bool                  RecolorWeakRetouch               = true;<br />
input bool                  ZoneStrength                     = true;<br />
input bool                  NoWeakZones                      = true;<br />
input bool                  DrawEdgePrice                    = true;<br />
input int                   ZoneWidth                        = 1;<br />
input bool                  ZoneFibs                         = false;<br />
input int                   FibStyle                         = 0;<br />
input bool                  HUDOn                            = false;<br />
input bool                  TimerOn                          = true;<br />
input int                   LayerZone                        = 0;<br />
input int                   LayerHUD                         = 20;<br />
input ENUM_BASE_CORNER      CornerHUD                        = 2;<br />
input int                   PosX                             = 100;<br />
input int                   PosY                             = 20;<br />
input bool                  AlertOn                          = false;<br />
input bool                  AlertPopup                       = false;<br />
input string                AlertSound                       = "alert.wav";<br />
input color                 ColorSupStrong                   = clrCrimson;<br />
input color                 ColorSupWeak                     = clrYellow;<br />
input color                 ColorSupRetouch                  = clrOrange;<br />
input color                 ColorDemStrong                   = clrViolet;<br />
input color                 ColorDemWeak                     = clrBlue;<br />
input color                 ColorDemRetouch                  = clrIndigo;<br />
input color                 ColorFib                         = clrDodgerBlue;<br />
input color                 ColorHUDTF                       = clrNavy;<br />
input color                 ColorArrowUp                     = clrSeaGreen;<br />
input color                 ColorArrowDn                     = clrCrimson;<br />
input color                 ColorTimerBack                   = clrDarkGray;<br />
input color                 ColorTimerBar                    = clrRed;<br />
input color                 ColorShadow                      = clrDarkSlateGray;<br />
input bool                  LimitZoneVis                     = false;<br />
input bool                  SameTFVis                        = true;<br />
input bool                  ShowOnM1                         = false;<br />
input bool                  ShowOnM5                         = true;<br />
input bool                  ShowOnM15                        = false;<br />
input bool                  ShowOnM30                        = false;<br />
input bool                  ShowOnH1                         = false;<br />
input bool                  ShowOnH4                         = false;<br />
input bool                  ShowOnD1                         = false;<br />
input bool                  ShowOnW1                         = false;<br />
input bool                  ShowOnMN                         = false;<br />
input int                   PriceWidth                       = 1;<br />
input int                   TimeOffset                       = 0;<br />
input bool                  GlobalVars                       = false;</p>
<p>double BufferSupport1[];<br />
double BufferSupport2[];<br />
double BufferSupport3[];<br />
double BufferResistance1[];<br />
double BufferResistance2[];<br />
double BufferResistance3[];</p>
<p>double SupRR[4];<br />
double DemRR[4];<br />
double SupWidth,DemWidth;</p>
<p>string lhud,lzone;<br />
int HUDx,LayerHUD0,LayerZone0;<br />
ENUM_BASE_CORNER CornerHUD0;<br />
string FontHUD = "Comic Sans MS";<br />
int FontHUDsize = 20;<br />
string FontHUDprice = "Arial Bold";<br />
int FontHUDPriceSize = 12;<br />
int ArrowUP = 0x70;<br />
int ArrowDN = 0x71;<br />
string FontArrow = "WingDings 3";<br />
int FontArrowSize = 40;<br />
int FontPairSize = 8;</p>
<p>string ArrowGlance;<br />
color ColorArrow;<br />
int visible;<br />
int rotation=270;<br />
int lenbase;<br />
string s_base="|||||||||||||||||||||||";<br />
string TimerFont="Arial";<br />
int SizeTimerFont=8;</p>
<p>double min,max;<br />
double iPeriod[4] = {3,8,13,34};<br />
int Dev[4] = {2,5,8,13};<br />
int Step[4] = {2,3,5,8};<br />
datetime h1,h2;<br />
double p1,p2;<br />
string pair;<br />
double point;<br />
int digits;<br />
ENUM_TIMEFRAMES tf;<br />
string TAG;</p>
<p>double FibSup,FibDem;<br />
int SupCount,DemCount;<br />
int SupAlert,DemAlert;<br />
double UpCur,DnCur;<br />
double FibLevelArray[13]={0,0.236,0.386,0.5,0.618,0.786,1,1.276,1.618,2.058,2.618,3.33,4.236};<br />
string FibLevelDesc[13]={"0","23.6%","38.6%","50%","61.8%","78.6%","100%","127.6%","161.8%","205.8%","261.80%","333%","423.6%"};</p>
<p>int HUDTimerX,HUDTimerY,HUDArrowX,HUDArrowY,HUDTFX,HUDTFY;<br />
int HUDsupX,HUDsupY,HUDdemX,HUDdemY;<br />
int HUDtimersX,HUDtimersY,HUDarrowsX,HUDarrowsY,HUDtfsX,HUDtfsY;<br />
int HUDsupsX,HUDsupsY,HUDdemsX,HUDdemsY;</p>
<p>void OnInit()<br />
{int t1;</p>
<p>t1=0; SetIndexBuffer(t1,BufferResistance1); SetIndexEmptyValue(t1,0.0); SetIndexStyle(t1,DRAW_NONE);<br />
t1+=1; SetIndexBuffer(t1,BufferResistance2); SetIndexEmptyValue(t1,0.0); SetIndexStyle(t1,DRAW_NONE);<br />
t1+=1; SetIndexBuffer(t1,BufferResistance3); SetIndexEmptyValue(t1,0.0); SetIndexStyle(t1,DRAW_NONE);<br />
t1+=1; SetIndexBuffer(t1,BufferSupport1); SetIndexEmptyValue(t1,0.0); SetIndexStyle(t1,DRAW_NONE);<br />
t1+=1; SetIndexBuffer(t1,BufferSupport2); SetIndexEmptyValue(t1,0.0); SetIndexStyle(t1,DRAW_NONE);<br />
t1+=1; SetIndexBuffer(t1,BufferSupport3); SetIndexEmptyValue(t1,0.0); SetIndexStyle(t1,DRAW_NONE);</p>
<p>LayerHUD0=MathMin(LayerHUD,25);<br />
lhud = CharToStr(0x61+LayerHUD0);<br />
LayerZone0=MathMin(LayerZone,25);<br />
lzone = CharToStr(0x61+LayerZone0);<br />
CornerHUD0=CornerHUD;<br />
pair=Symbol(); </p>
<p>   if(TimeFrame != 0) tf = TimeFrame;<br />
else tf = PERIOD_CURRENT;<br />
point = Point;<br />
digits = MarketInfo(Symbol(), MODE_DIGITS);  //Digits;<br />
if(digits == 3 || digits == 5) point*=10;</p>
<p>   if(HUDOn && !DrawZones) TAG = "II_HUD"+tf;<br />
else TAG = "II_SupDem"+tf;<br />
lenbase=StringLen(s_base);</p>
<p>   if(HUDOn) setHUD();<br />
if(LimitZoneVis) setVisibility();<br />
ObDeleteObjectsByPrefix(lhud+TAG);<br />
ObDeleteObjectsByPrefix(lzone+TAG);<br />
DoLogo();}</p>
<p>void OnDeinit(const int reason)<br />
{<br />
ObDeleteObjectsByPrefix(lhud+TAG);<br />
ObDeleteObjectsByPrefix(lzone+TAG);<br />
Comment("");}</p>
<p>int start()<br />
{<br />
if (NewBar())<br />
{<br />
SupAlert = 1;<br />
DemAlert = 1;<br />
ObDeleteObjectsByPrefix(lzone+TAG);<br />
CountZZ(BufferSupport1,BufferResistance1,iPeriod[0],Dev[0],Step[0]);<br />
// Comment("iPeriod[0]",iPeriod[0]);<br />
GetValid(BufferSupport1,BufferResistance1);<br />
Draw();<br />
if(HUDOn) HUD();<br />
}<br />
if(HUDOn && TimerOn) {BarTimer();}<br />
if(AlertOn) {CheckAlert();}<br />
return(0);<br />
}</p>
<p>void CheckAlert(){<br />
//   SupCount DemCount<br />
//   SupAlert DemAlert<br />
double price = ObjectGet(lzone+TAG+"UPAR"+SupAlert,OBJPROP_PRICE1);<br />
if(Close[0] > price && price > point){<br />
if(AlertPopup) Alert(pair+" "+TimeFrameToString(tf)+" Supply Zone Entered at "+DoubleToStr(price,Digits));<br />
PlaySound(AlertSound);<br />
SupAlert++;<br />
}<br />
price = ObjectGet(lzone+TAG+"DNAR"+DemAlert,OBJPROP_PRICE1);<br />
if(Close[0] < price){
Alert(pair+" "+TimeFrameToString(tf)+" Demand Zone Entered at "+DoubleToStr(price,Digits));
PlaySound(AlertSound);
DemAlert++;
}
}
void Draw()
{
int FibSupHIT=0;
int FibDemHIT=0;
int sc=0,dc=0; 
int i,j,countstrong,countweak;
color c;
string s;
bool exit,draw,fle,fhe,retouch;
bool valid;
double val;
fhe=false;
fle=false;
SupCount=0;
DemCount=0;
FibSup=0;
FibDem=0;
for(i=0;i<iBars(pair,tf);i++){ if(BufferResistance1&#91;i&#93; > point){<br />
retouch = false;<br />
valid = false;<br />
h1 = iTime(pair,tf,i);<br />
h2 = Time[0];<br />
p2 = MathMin(iClose(pair,tf,i),iOpen(pair,tf,i));<br />
if(i>0) p2 = MathMax(p2,MathMax(iLow(pair,tf,i-1),iLow(pair,tf,i+1)));<br />
if(i>0) p2 = MathMax(p2,MathMin(iOpen(pair,tf,i-1),iClose(pair,tf,i-1)));<br />
p2 = MathMax(p2,MathMin(iOpen(pair,tf,i+1),iClose(pair,tf,i+1)));</p>
<p>         draw=true;<br />
if(RecolorRetouch || !SolidRetouch){<br />
exit = false;<br />
for(j=i;j>=0;j--){<br />
if(j==0 && !exit) {draw=false; break;}<br />
if(!exit && iHigh(pair,tf,j)<p2 ) {exit=true; continue;} if(exit && iHigh(pair,tf,j)>p2) {<br />
retouch = true;<br />
if(ZoneFibs && FibSupHIT==0){ FibSup = p2; FibSupHIT = j;}<br />
break;<br />
}<br />
}<br />
}<br />
if(SupCount != 0) val = ObjectGet(TAG+"UPZONE"+SupCount,OBJPROP_PRICE2); //final sema cull<br />
else val=0;<br />
if(draw && BufferResistance1[i]!=val) {<br />
valid=true;<br />
c = ColorSupStrong;<br />
if(ZoneStrength && (retouch || !RecolorRetouch)){<br />
countstrong=0;<br />
countweak=0;<br />
for(j=i;j&lt;1000000;j++){
if(iHigh(pair,tf,j+1)</p2><p2 ) countstrong++; if(iHigh(pair,tf,j+1)>BufferResistance1[i]) countweak++;<br />
if(countstrong > 1) break;<br />
else if(countweak > 1){<br />
c=ColorSupWeak;<br />
if(NoWeakZones) draw = false;<br />
break;<br />
}<br />
}<br />
}<br />
//         if(c == ColorSupWeak && !NoWeakZones) draw = false;<br />
BufferResistance2[i]=(BufferResistance1[i]>0)*p2; BufferResistance3[i]=(BufferResistance1[i]>0)*draw;</p2></p>
<p>         if(DrawZones && draw){<br />
if(RecolorRetouch && retouch && countweak&lt;2) c = ColorSupRetouch; else if(RecolorWeakRetouch && retouch && countweak>1) c = ColorSupRetouch;<br />
SupCount++;<br />
if(DrawEdgePrice){<br />
s = lzone+TAG+"UPAR"+SupCount;<br />
ObjectCreate(s,OBJ_ARROW,0,0,0);<br />
ObjectSet(s,OBJPROP_ARROWCODE,SYMBOL_RIGHTPRICE);<br />
ObjectSet(s, OBJPROP_TIME1, h2);<br />
ObjectSet(s, OBJPROP_PRICE1, p2);<br />
ObjectSet(s,OBJPROP_COLOR,c);<br />
ObjectSet(s,OBJPROP_WIDTH,PriceWidth);<br />
if(LimitZoneVis) ObjectSet(s,OBJPROP_TIMEFRAMES,visible);<br />
}<br />
s = lzone+TAG+"UPZONE"+SupCount;<br />
ObjectCreate(s,OBJ_RECTANGLE,0,0,0,0,0);<br />
ObjectSet(s,OBJPROP_TIME1,h1);<br />
ObjectSet(s,OBJPROP_PRICE1,BufferResistance1[i]);<br />
ObjectSet(s,OBJPROP_TIME2,h2);<br />
ObjectSet(s,OBJPROP_PRICE2,p2);<br />
ObjectSet(s,OBJPROP_COLOR,c);<br />
ObjectSet(s,OBJPROP_BACK,true);<br />
if(LimitZoneVis) ObjectSet(s,OBJPROP_TIMEFRAMES,visible);<br />
if(!SolidZones) {ObjectSet(s,OBJPROP_BACK,false);ObjectSet(s,OBJPROP_WIDTH,ZoneWidth);}<br />
if(!SolidRetouch && retouch) {ObjectSet(s,OBJPROP_BACK,false);ObjectSet(s,OBJPROP_WIDTH,ZoneWidth);}</p>
<p>            if(GlobalVars){<br />
GlobalVariableSet(TAG+"S.PH"+SupCount,BufferResistance1[i]);<br />
GlobalVariableSet(TAG+"S.PL"+SupCount,p2);<br />
GlobalVariableSet(TAG+"S.T"+SupCount,iTime(pair,tf,i));<br />
}<br />
if(!fhe && c!=ColorDemRetouch){fhe=true; GlobalVariableSet(TAG+"GOSHORT",p2);}<br />
}<br />
}<br />
if(draw && sc&lt;4 && HUDOn && valid){ if(sc==0) SupWidth = BufferResistance1[i] - p2; SupRR[sc] = p2; sc++; } } if(BufferSupport1[i] > point){<br />
retouch = false;<br />
valid=false;<br />
h1 = iTime(pair,tf,i);<br />
h2 = Time[0];<br />
p2 = MathMax(iClose(pair,tf,i),iOpen(pair,tf,i));<br />
if(i>0) p2 = MathMin(p2,MathMin(iHigh(pair,tf,i+1),iHigh(pair,tf,i-1)));<br />
if(i>0) p2 = MathMin(p2,MathMax(iOpen(pair,tf,i-1),iClose(pair,tf,i-1)));<br />
p2 = MathMin(p2,MathMax(iOpen(pair,tf,i+1),iClose(pair,tf,i+1)));</p>
<p>         c = ColorDemStrong;<br />
draw=true;<br />
if(RecolorRetouch || !SolidRetouch){<br />
exit = false;<br />
for(j=i;j>=0;j--) {<br />
if(j==0 && !exit) {draw=false;break;}<br />
if(!exit && iLow(pair,tf,j)>p2) {exit=true;continue;}<br />
if(exit && iLow(pair,tf,j)<p2 ) {
retouch = true;
if(ZoneFibs && FibDemHIT==0){FibDem = p2; FibDemHIT = j; }
break;
}
}
}
if(DemCount != 0) val = ObjectGet(TAG+"DNZONE"+DemCount,OBJPROP_PRICE2); //final sema cull
else val=0;
if(draw && BufferSupport1&#91;i&#93;!=val){
valid = true;
if(ZoneStrength && (retouch || !RecolorRetouch)){
countstrong=0;
countweak=0;
for(j=i;j&lt;1000000;j++){ if(iLow(pair,tf,j+1)>p2) countstrong++;<br />
if(iLow(pair,tf,j+1)<buffersupport1 &#91;i&#93;) countweak++; if(countstrong > 1) break;<br />
else if(countweak > 1){<br />
if(NoWeakZones) draw = false;<br />
c=ColorDemWeak;<br />
break;<br />
}<br />
}<br />
}<br />
BufferSupport2[i]=(BufferSupport1[i]>0)*p2; BufferSupport3[i]=(BufferSupport1[i]>0)*draw; </buffersupport1></p2></p>
<p>            if(DrawZones && draw){<br />
if(RecolorRetouch && retouch && countweak&lt;2) c = ColorDemRetouch; else if(RecolorWeakRetouch && retouch && countweak>1) c = ColorDemRetouch;</p>
<p>            DemCount++;<br />
if(DrawEdgePrice){<br />
s = lzone+TAG+"DNAR"+DemCount;<br />
ObjectCreate(s,OBJ_ARROW,0,0,0);<br />
ObjectSet(s,OBJPROP_ARROWCODE,SYMBOL_RIGHTPRICE);<br />
ObjectSet(s, OBJPROP_TIME1, h2);<br />
ObjectSet(s, OBJPROP_PRICE1, p2);<br />
ObjectSet(s,OBJPROP_COLOR,c);<br />
ObjectSet(s,OBJPROP_WIDTH,PriceWidth);<br />
if(LimitZoneVis) ObjectSet(s,OBJPROP_TIMEFRAMES,visible);<br />
}<br />
s = lzone+TAG+"DNZONE"+DemCount;<br />
ObjectCreate(s,OBJ_RECTANGLE,0,0,0,0,0);<br />
ObjectSet(s,OBJPROP_TIME1,h1);<br />
ObjectSet(s,OBJPROP_PRICE1,p2);<br />
ObjectSet(s,OBJPROP_TIME2,h2);<br />
ObjectSet(s,OBJPROP_PRICE2,BufferSupport1[i]);<br />
ObjectSet(s,OBJPROP_COLOR,c);<br />
ObjectSet(s,OBJPROP_BACK,true);<br />
if(LimitZoneVis) ObjectSet(s,OBJPROP_TIMEFRAMES,visible);<br />
if(!SolidZones) {ObjectSet(s,OBJPROP_BACK,false);ObjectSet(s,OBJPROP_WIDTH,ZoneWidth);}<br />
if(!SolidRetouch && retouch) {ObjectSet(s,OBJPROP_BACK,false);ObjectSet(s,OBJPROP_WIDTH,ZoneWidth);}<br />
if(GlobalVars){<br />
GlobalVariableSet(TAG+"D.PL"+DemCount,BufferSupport1[i]);<br />
GlobalVariableSet(TAG+"D.PH"+DemCount,p2);<br />
GlobalVariableSet(TAG+"D.T"+DemCount,iTime(pair,tf,i));<br />
}<br />
if(!fle && c!=ColorDemRetouch){fle=true;GlobalVariableSet(TAG+"GOLONG",p2);}<br />
}<br />
}<br />
if(draw && dc&lt;4 && HUDOn && valid){
if(dc==0) DemWidth = p2-BufferSupport1[i];
DemRR[dc] = p2;
dc++;
}
}
}
if(ZoneFibs || HUDOn){
double a,b;
int dr=0;
int sr=0;
int d1=0;
int s1=0;
for(i=0;i&lt;100000;i++){ if(iHigh(pair,tf,i)>FibSup && sr==0) sr = i;<br />
if(iHigh(pair,tf,i)>SupRR[0] && s1==0) s1 = i;<br />
if(iLow(pair,tf,i)=0; t1--){<br />
val = iLow(pair,tf,iLowest(pair,tf,MODE_LOW,ExtDepth,t1));<br />
if(val==lastlow) val=0.0;<br />
else {<br />
lastlow=val;<br />
if((iLow(pair,tf,t1)-val)>(ExtDeviation*point)) val=0.0;<br />
else{<br />
for(back=1; back< =ExtBackstep; back++){ res=ExtMapBuffer&#91;t1+back&#93;; if((res!=0)&&(res>val)) ExtMapBuffer[t1+back]=0.0;<br />
}<br />
}<br />
} </p>
<p>          ExtMapBuffer[t1]=val;<br />
//--- high<br />
val=iHigh(pair,tf,iHighest(pair,tf,MODE_HIGH,ExtDepth,t1));</p>
<p>      if(val==lasthigh) val=0.0;<br />
else {<br />
lasthigh=val;<br />
if((val-iHigh(pair,tf,t1))>(ExtDeviation*point)) val=0.0;<br />
else{<br />
for(back=1; back< =ExtBackstep; back++){
res=ExtMapBuffer2&#91;t1+back&#93;;
if((res!=0)&&(res<val)) ExtMapBuffer2&#91;t1+back&#93;=0.0; } } } ExtMapBuffer2&#91;t1&#93;=val; } // final cutting lasthigh=-1; lasthighpos=-1; lastlow=-1; lastlowpos=-1; for(t1=count; t1>=0; t1--){<br />
curlow=ExtMapBuffer[t1];<br />
curhigh=ExtMapBuffer2[t1];<br />
if((curlow==0)&&(curhigh==0)) continue;<br />
//---<br />
if(curhigh!=0){<br />
if(lasthigh>0) {<br />
if(lasthigh<curhigh ) ExtMapBuffer2&#91;lasthighpos&#93;=0;
else ExtMapBuffer2&#91;t1&#93;=0;
}
//---
if(lasthigh0){
if(lastlow>curlow) ExtMapBuffer[lastlowpos]=0;<br />
else ExtMapBuffer[t1]=0;<br />
}<br />
//---<br />
if((curlow<lastlow )||(lastlow&lt;0)){ lastlow=curlow; lastlowpos=t1; } lasthigh=-1; } } // section deleted but reinstated // for(t1=iBars(pair,tf)-1; t1>=0; t1--){<br />
if(t1>=count) ExtMapBuffer[t1]=0.0;<br />
else {<br />
res=ExtMapBuffer2[t1];<br />
if(res!=0.0) ExtMapBuffer2[t1]=res;<br />
}<br />
}</lastlow></curhigh></p>
<p>}</p>
<p>void GetValid(double& ExtMapBuffer[], double& ExtMapBuffer2[]){<br />
UpCur = 0;<br />
int upbar = 0;<br />
DnCur = 0;<br />
int dnbar = 0;<br />
double CurHi = 0;<br />
double CurLo = 0;<br />
double LastUp = 0;<br />
double LastDn = 0;<br />
double LowDn = 0;<br />
double HiUp = 0;<br />
int i;<br />
for(i=0;i<ibars (pair,tf);i++) if(ExtMapBuffer&#91;i&#93; > 0){<br />
UpCur = ExtMapBuffer[i];<br />
CurLo = ExtMapBuffer[i];<br />
LastUp = CurLo;<br />
break;<br />
}<br />
for(i=0;i</ibars><ibars (pair,tf);i++) if(ExtMapBuffer2&#91;i&#93; > 0){<br />
DnCur = ExtMapBuffer2[i];<br />
CurHi = ExtMapBuffer2[i];<br />
LastDn = CurHi;<br />
break;<br />
}</ibars></p>
<p>   for(i=0;i<ibars (pair,tf);i++) // remove higher lows and lower highs { if(ExtMapBuffer2&#91;i&#93; >= LastDn) {<br />
LastDn = ExtMapBuffer2[i];<br />
dnbar = i;<br />
}<br />
else ExtMapBuffer2[i] = 0.0;<br />
if(ExtMapBuffer2[i] < = DnCur && ExtMapBuffer&#91;i&#93; > 0.0) ExtMapBuffer2[i] = 0.0;<br />
if(ExtMapBuffer[i] < = LastUp && ExtMapBuffer&#91;i&#93; > 0) {<br />
LastUp = ExtMapBuffer[i];<br />
upbar = i;<br />
}<br />
else ExtMapBuffer[i] = 0.0;<br />
if(ExtMapBuffer[i] > UpCur) ExtMapBuffer[i] = 0.0;<br />
}<br />
LowDn = MathMin(iOpen(pair,tf,dnbar),iClose(pair,tf,dnbar));<br />
HiUp = MathMax(iOpen(pair,tf,upbar),iClose(pair,tf,upbar));<br />
for(i=MathMax(upbar,dnbar);i>=0;i--) {// work back to zero and remove reentries into s/d<br />
if(ExtMapBuffer2[i] > LowDn && ExtMapBuffer2[i] != LastDn) ExtMapBuffer2[i] = 0.0;<br />
else if(ExtMapBuffer2[i] > 0) {<br />
LastDn = ExtMapBuffer2[i];<br />
LowDn = MathMin(iClose(pair,tf,i),iOpen(pair,tf,i));<br />
if(i>0) LowDn = MathMax(LowDn,MathMax(iLow(pair,tf,i-1),iLow(pair,tf,i+1)));<br />
if(i>0) LowDn = MathMax(LowDn,MathMin(iOpen(pair,tf,i-1),iClose(pair,tf,i-1)));<br />
LowDn = MathMax(LowDn,MathMin(iOpen(pair,tf,i+1),iClose(pair,tf,i+1)));<br />
}<br />
if(ExtMapBuffer[i] < = HiUp && ExtMapBuffer&#91;i&#93; > 0 && ExtMapBuffer[i] != LastUp) ExtMapBuffer[i] = 0.0;<br />
else if(ExtMapBuffer[i] > 0){<br />
LastUp = ExtMapBuffer[i];<br />
HiUp = MathMax(iClose(pair,tf,i),iOpen(pair,tf,i));<br />
if(i>0) HiUp = MathMin(HiUp,MathMin(iHigh(pair,tf,i+1),iHigh(pair,tf,i-1)));<br />
if(i>0) HiUp = MathMin(HiUp,MathMax(iOpen(pair,tf,i-1),iClose(pair,tf,i-1)));<br />
HiUp = MathMin(HiUp,MathMax(iOpen(pair,tf,i+1),iClose(pair,tf,i+1)));<br />
}<br />
}<br />
}</ibars></p>
<p>void HUD()<br />
{<br />
string s = TimeFrameToString(tf);<br />
string u = DoubleToStr(ObjectGet(lzone+TAG+"UPAR"+1,OBJPROP_PRICE1),Digits);<br />
string d = DoubleToStr(ObjectGet(lzone+TAG+"DNAR"+1,OBJPROP_PRICE1),Digits);<br />
string l = "b";<br />
DrawText(l,s,HUDTFX,HUDTFY,ColorHUDTF,FontHUD,FontHUDsize,CornerHUD0);<br />
DrawText(l,ArrowGlance,HUDArrowX,HUDArrowY,ColorArrow,FontArrow,FontArrowSize,CornerHUD0,0,true);<br />
DrawText(l,u,HUDsupX,HUDsupY,ColorSupStrong,FontHUDprice,FontHUDPriceSize,CornerHUD0);<br />
DrawText(l,d,HUDdemX,HUDdemY,ColorDemStrong,FontHUDprice,FontHUDPriceSize,CornerHUD0);</p>
<p>   l = "a";<br />
DrawText(l,s,HUDtfsX,HUDtfsY,ColorShadow,FontHUD,FontHUDsize,CornerHUD0);<br />
DrawText(l,ArrowGlance,HUDarrowsX,HUDarrowsY,ColorShadow,FontArrow,FontArrowSize,CornerHUD0,0,true);<br />
DrawText(l,u,HUDsupsX,HUDsupsY,ColorShadow,FontHUDprice,FontHUDPriceSize,CornerHUD0);<br />
DrawText(l,d,HUDdemsX,HUDdemsY,ColorShadow,FontHUDprice,FontHUDPriceSize,CornerHUD0);</p>
<p>}</p>
<p>void BarTimer() // Original Code by Vasyl Gumenyak<br />
{<br />
int i=0,sec=0;<br />
double pc=0.0;<br />
string time="",s_end="",s;<br />
s = lhud+TAG+"btimerback";<br />
if (ObjectFind(s) == -1) {<br />
ObjectCreate(s , OBJ_LABEL,0,0,0);<br />
ObjectSet(s, OBJPROP_XDISTANCE, HUDTimerX);<br />
ObjectSet(s, OBJPROP_YDISTANCE, HUDTimerY);<br />
ObjectSet(s, OBJPROP_CORNER, CornerHUD0);<br />
ObjectSet(s, OBJPROP_ANGLE, rotation);<br />
ObjectSetText(s, s_base, SizeTimerFont, TimerFont, ColorTimerBack);<br />
}</p>
<p>   sec=TimeCurrent()-iTime(pair,tf,0);<br />
i=(lenbase-1)*sec/(tf*60);<br />
pc=100-(100.0*sec/(tf*60));<br />
if(i>lenbase-1) i=lenbase-1;<br />
if(i<lenbase -1) s_end=StringSubstr(s_base,i+1,lenbase-i-1); time=StringConcatenate("|",s_end); s = lhud+TAG+"timerfront"; if (ObjectFind(s) == -1) { ObjectCreate(s , OBJ_LABEL,0,0,0); ObjectSet(s, OBJPROP_XDISTANCE, HUDTimerX); ObjectSet(s, OBJPROP_YDISTANCE, HUDTimerY); ObjectSet(s, OBJPROP_CORNER, CornerHUD0); ObjectSet(s, OBJPROP_ANGLE, rotation); } ObjectSetText(s, time, SizeTimerFont, TimerFont, ColorTimerBar); } void DrawText(string l, string t, int x, int y, color c, string f, int s, int k=0, int a=0, bool b=false) { string tag = lhud+TAG+l+x+y; ObjectDelete(tag); ObjectCreate(tag,OBJ_LABEL,0,0,0); ObjectSetText(tag,t,s,f,c); ObjectSet(tag,OBJPROP_XDISTANCE,x); ObjectSet(tag,OBJPROP_YDISTANCE,y); ObjectSet(tag,OBJPROP_CORNER,k); ObjectSet(tag,OBJPROP_ANGLE,a); if(b) ObjectSet(tag,OBJPROP_BACK,true); } string TimeFrameToString(int x1) //code by TRO { string tfs; switch(x1) { case PERIOD_M1: tfs="M1" ; break; case PERIOD_M5: tfs="M5" ; break; case PERIOD_M15: tfs="M15" ; break; case PERIOD_M30: tfs="M30" ; break; case PERIOD_H1: tfs="H1" ; break; case PERIOD_H4: tfs="H4" ; break; case PERIOD_D1: tfs="D1" ; break; case PERIOD_W1: tfs="W1" ; break; case PERIOD_MN1: tfs="MN"; } return(tfs); } void setHUD() { switch(tf) { case PERIOD_M1: HUDx=7 ; break; case PERIOD_M5: HUDx=7 ; break; case PERIOD_M15: HUDx=3 ; break; case PERIOD_M30: HUDx=2 ; break; case PERIOD_H1: HUDx=12 ; break; case PERIOD_H4: HUDx=8 ; break; case PERIOD_D1 : HUDx=12 ; break; case PERIOD_W1: HUDx=8 ; break; case PERIOD_MN1: HUDx=7 ; break; } if(CornerHUD0 > 3) {CornerHUD0=0;}<br />
if(CornerHUD0 == 0 || CornerHUD0 == 2) rotation = 90;<br />
switch(CornerHUD0){<br />
case 0 : HUDTFX = PosX-HUDx+10;<br />
HUDTFY = PosY+18;<br />
HUDArrowX = PosX-2;<br />
HUDArrowY = PosY+7;<br />
HUDsupX = PosX;<br />
HUDsupY = PosY;<br />
HUDdemX = PosX;<br />
HUDdemY = PosY+56;<br />
HUDTimerX = PosX+50;<br />
HUDTimerY = PosY+72;<br />
HUDtfsX = HUDTFX+1;<br />
HUDtfsY = HUDTFY+1;<br />
HUDarrowsX = HUDArrowX+1;<br />
HUDarrowsY = HUDArrowY+1;<br />
HUDsupsX = HUDsupX+1;<br />
HUDsupsY = HUDsupY+1;<br />
HUDdemsX = HUDdemX+1;<br />
HUDdemsY = HUDdemY+1;<br />
break;<br />
case 1 : HUDTFX = PosX+HUDx;<br />
HUDTFY = PosY+18;<br />
HUDArrowX = PosX+2;<br />
HUDArrowY = PosY+7;<br />
HUDsupX = PosX;<br />
HUDsupY = PosY;<br />
HUDdemX = PosX;<br />
HUDdemY = PosY+56;<br />
HUDTimerX = PosX-15;<br />
HUDTimerY = PosY+71;<br />
HUDtfsX = HUDTFX-1;<br />
HUDtfsY = HUDTFY+1;<br />
HUDarrowsX = HUDArrowX-1;<br />
HUDarrowsY = HUDArrowY+1;<br />
HUDsupsX = HUDsupX-1;<br />
HUDsupsY = HUDsupY+1;<br />
HUDdemsX = HUDdemX-1;<br />
HUDdemsY = HUDdemY+1;<br />
break;<br />
case 2 : HUDTFX = PosX-HUDx;<br />
HUDTFY = PosY+20;<br />
HUDArrowX = PosX-2;<br />
HUDArrowY = PosY+7;<br />
HUDsupX = PosX;<br />
HUDsupY = PosY+56;<br />
HUDdemX = PosX;<br />
HUDdemY = PosY;<br />
HUDTimerX = PosX+62;<br />
HUDTimerY = PosY+3;<br />
HUDtfsX = HUDTFX+1;<br />
HUDtfsY = HUDTFY-1;<br />
HUDarrowsX = HUDArrowX+1;<br />
HUDarrowsY = HUDArrowY-1;<br />
HUDsupsX = HUDsupX+1;<br />
HUDsupsY = HUDsupY-1;<br />
HUDdemsX = HUDdemX+1;<br />
HUDdemsY = HUDdemY-1;<br />
break;<br />
case 3 : HUDTFX = PosX+HUDx;<br />
HUDTFY = PosY+20;<br />
HUDArrowX = PosX+2;<br />
HUDArrowY = PosY+7;<br />
HUDsupX = PosX;<br />
HUDsupY = PosY+56;<br />
HUDdemX = PosX;<br />
HUDdemY = PosY;<br />
HUDTimerX = PosX-2;<br />
HUDTimerY = PosY+3;<br />
HUDtfsX = HUDTFX-1;<br />
HUDtfsY = HUDTFY-1;<br />
HUDarrowsX = HUDArrowX-1;<br />
HUDarrowsY = HUDArrowY-1;<br />
HUDsupsX = HUDsupX-1;<br />
HUDsupsY = HUDsupY-1;<br />
HUDdemsX = HUDdemX-1;<br />
HUDdemsY = HUDdemY-1;<br />
break;<br />
}<br />
}</lenbase></p>
<p>void DoLogo(){<br />
string s7 = CharToStr(0x61+27)+"II_Logo";<br />
if( ObjectFind(s7+"ZZ"+0) >= 0 && ObjectFind(s7+"ZZ"+1) >= 0 && ObjectFind(s7+"ZZ"+2) >= 0  &&<br />
ObjectFind(s7+"AZ"+0) >= 0 && ObjectFind(s7+"AZ"+1) >= 0 && ObjectFind(s7+"AZ"+2) >= 0 ) return;<br />
string str[3] = {".","."};<br />
int Size[3] = {0,0,0};<br />
int PositionX[3] = {0,0,0};<br />
int PositionY[3] = {0,0,0};<br />
int PosXs[3] = {0,0,0};<br />
int PosYs[3] = {0,0,0};<br />
for(int i=0;i&lt;3;i++){
string n = s7+"ZZ"+i;
ObjectDelete(n);
ObjectCreate(n,OBJ_LABEL,0,0,0);
ObjectSetText(n,str[i],Size[i],"Pieces Of Eight",AliceBlue);
ObjectSet(n,OBJPROP_XDISTANCE,PositionX[i]);
ObjectSet(n,OBJPROP_YDISTANCE,PositionY[i]);
ObjectSet(n,OBJPROP_CORNER,3);
n = s7+"AZ"+i;
ObjectDelete(n);
ObjectCreate(n,OBJ_LABEL,0,0,0);
ObjectSetText(n,str[i],Size[i],"Pieces Of Eight",Black);
ObjectSet(n,OBJPROP_XDISTANCE,PosXs[i]);
ObjectSet(n,OBJPROP_YDISTANCE,PosYs[i]);
ObjectSet(n,OBJPROP_CORNER,3);
}
}
void setVisibility()
{
int per = Period();
visible=0;
if(SameTFVis){
if(TimeFrame == per || TimeFrame == 0){
switch(per){
case PERIOD_M1:  visible= 0x0001 ; break;
case PERIOD_M5:  visible= 0x0002 ; break;
case PERIOD_M15: visible= 0x0004 ; break;
case PERIOD_M30: visible= 0x0008 ; break;
case PERIOD_H1:  visible= 0x0010 ; break;
case PERIOD_H4:  visible= 0x0020 ; break;
case PERIOD_D1:  visible= 0x0040 ; break;
case PERIOD_W1:  visible= 0x0080 ; break;
case PERIOD_MN1: visible= 0x0100 ;  	   
}
}
} else {
if(ShowOnM1) visible += 0x0001;
if(ShowOnM5) visible += 0x0002;
if(ShowOnM15) visible += 0x0004;
if(ShowOnM30) visible += 0x0008;
if(ShowOnH1) visible += 0x0010;
if(ShowOnH4) visible += 0x0020;
if(ShowOnD1) visible += 0x0040;
if(ShowOnW1) visible += 0x0080;
if(ShowOnMN) visible += 0x0100;
}
}

This is not going to work with the iCustom model explained and it will act irrationally.  How does one make use of such an indicator?  That's for next Tuesday's article.  Try to see what happens in a backtest when running the above code in the fashion learned in this article, it is going to not result very well.   To get the desired result with this particular indicator, it requires a different function because you will be looking to have the Expert Advisor take action when the price does or does not do something within the parameters created.  It's a different sort of a code that is more object-heavy rather than a mere calculation.