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 one example where the iCustom Function would not actually work and that will set up next Tuesday’s article.
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.
//+------------------------------------------------------------------+ //| RegularPivot.mq4 | //| Copyright © 2018, Freevestor | //| | //+------------------------------------------------------------------+ #property copyright "Copyright © 2018, Freevestor" #property link "" #property indicator_chart_window #property indicator_buffers 8 #property indicator_color1 Maroon #property indicator_color2 Maroon #property indicator_color3 Maroon #property indicator_color4 Green #property indicator_color5 Navy #property indicator_color6 Navy #property indicator_color7 Navy #property indicator_color8 LimeGreen #property indicator_style1 STYLE_SOLID #property indicator_style2 STYLE_SOLID #property indicator_style3 STYLE_SOLID #property indicator_style4 STYLE_SOLID #property indicator_style5 STYLE_SOLID #property indicator_style6 STYLE_SOLID #property indicator_style7 STYLE_SOLID #property indicator_style8 STYLE_SOLID //---- input parameters extern int StartHour=0; extern int StartMinute=0; extern int DaysToPlot=15; //---- buffers double Res3[]; double Res2[]; double Res1[]; double Pivot[]; double Supp1[]; double Supp2[]; double Supp3[]; double Extra1[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { //---- indicators SetIndexStyle(0,DRAW_LINE,STYLE_SOLID); SetIndexBuffer(0,Res3); SetIndexStyle(1,DRAW_LINE,STYLE_SOLID); SetIndexBuffer(1,Res2); SetIndexStyle(2,DRAW_LINE,STYLE_SOLID); SetIndexBuffer(2,Res1); SetIndexStyle(3,DRAW_LINE,STYLE_SOLID,1); SetIndexBuffer(3,Pivot); SetIndexStyle(4,DRAW_LINE,STYLE_SOLID); SetIndexBuffer(4,Supp1); SetIndexStyle(5,DRAW_LINE,STYLE_SOLID); SetIndexBuffer(5,Supp2); SetIndexStyle(6,DRAW_LINE,STYLE_SOLID); SetIndexBuffer(6,Supp3); SetIndexStyle(7,DRAW_LINE,STYLE_SOLID); SetIndexBuffer(7,Extra1); //---- return(0); }
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.
- double [Variable of Choice Name] =
- iCustom(
- For the Symbol, you have two options:
- 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.
- A specific symbol. “EURUSD”, “USDJPY”,”JP225USD”, etc. You can only choose one at a time.
- The Timeframe you want this to apply, you have two options:
- “0” – Whatever the chart timeframe may be or the Strategy Tester setting is as far as timeframe.
- A specific timeframe for your chart. PERIOD_D1, PERIOD_H1, PERIOD_M1, etc. are just examples.
- The exact name of your timeframe in quotes. “RegularPivot”
- 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.
- 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.
double S2 = iCustom(Symbol(), PERIOD_H1, "RegularPivot", 5, 1);
Want to call “RegularPivot” for EURUSD from two candles ago on a 5 Minute Chart as it relates to the 1st Resistance Level?
double R1 = iCustom("EURUSD", PERIOD_M5, "RegularPivot", 2, 2);
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?
#property description "Displays Supply and Demand zones.." #property version "2.33" #property indicator_chart_window #property indicator_buffers 6 input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1; input bool DrawZones = true; input bool SolidZones = true; input bool SolidRetouch = true; input bool RecolorRetouch = true; input bool RecolorWeakRetouch = true; input bool ZoneStrength = true; input bool NoWeakZones = true; input bool DrawEdgePrice = true; input int ZoneWidth = 1; input bool ZoneFibs = false; input int FibStyle = 0; input bool HUDOn = false; input bool TimerOn = true; input int LayerZone = 0; input int LayerHUD = 20; input ENUM_BASE_CORNER CornerHUD = 2; input int PosX = 100; input int PosY = 20; input bool AlertOn = false; input bool AlertPopup = false; input string AlertSound = "alert.wav"; input color ColorSupStrong = clrCrimson; input color ColorSupWeak = clrYellow; input color ColorSupRetouch = clrOrange; input color ColorDemStrong = clrViolet; input color ColorDemWeak = clrBlue; input color ColorDemRetouch = clrIndigo; input color ColorFib = clrDodgerBlue; input color ColorHUDTF = clrNavy; input color ColorArrowUp = clrSeaGreen; input color ColorArrowDn = clrCrimson; input color ColorTimerBack = clrDarkGray; input color ColorTimerBar = clrRed; input color ColorShadow = clrDarkSlateGray; input bool LimitZoneVis = false; input bool SameTFVis = true; input bool ShowOnM1 = false; input bool ShowOnM5 = true; input bool ShowOnM15 = false; input bool ShowOnM30 = false; input bool ShowOnH1 = false; input bool ShowOnH4 = false; input bool ShowOnD1 = false; input bool ShowOnW1 = false; input bool ShowOnMN = false; input int PriceWidth = 1; input int TimeOffset = 0; input bool GlobalVars = false; double BufferSupport1[]; double BufferSupport2[]; double BufferSupport3[]; double BufferResistance1[]; double BufferResistance2[]; double BufferResistance3[]; double SupRR[4]; double DemRR[4]; double SupWidth,DemWidth; string lhud,lzone; int HUDx,LayerHUD0,LayerZone0; ENUM_BASE_CORNER CornerHUD0; string FontHUD = "Comic Sans MS"; int FontHUDsize = 20; string FontHUDprice = "Arial Bold"; int FontHUDPriceSize = 12; int ArrowUP = 0x70; int ArrowDN = 0x71; string FontArrow = "WingDings 3"; int FontArrowSize = 40; int FontPairSize = 8; string ArrowGlance; color ColorArrow; int visible; int rotation=270; int lenbase; string s_base="|||||||||||||||||||||||"; string TimerFont="Arial"; int SizeTimerFont=8; double min,max; double iPeriod[4] = {3,8,13,34}; int Dev[4] = {2,5,8,13}; int Step[4] = {2,3,5,8}; datetime h1,h2; double p1,p2; string pair; double point; int digits; ENUM_TIMEFRAMES tf; string TAG; double FibSup,FibDem; int SupCount,DemCount; int SupAlert,DemAlert; double UpCur,DnCur; 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}; 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%"}; int HUDTimerX,HUDTimerY,HUDArrowX,HUDArrowY,HUDTFX,HUDTFY; int HUDsupX,HUDsupY,HUDdemX,HUDdemY; int HUDtimersX,HUDtimersY,HUDarrowsX,HUDarrowsY,HUDtfsX,HUDtfsY; int HUDsupsX,HUDsupsY,HUDdemsX,HUDdemsY; void OnInit() {int t1; t1=0; SetIndexBuffer(t1,BufferResistance1); SetIndexEmptyValue(t1,0.0); SetIndexStyle(t1,DRAW_NONE); t1+=1; SetIndexBuffer(t1,BufferResistance2); SetIndexEmptyValue(t1,0.0); SetIndexStyle(t1,DRAW_NONE); t1+=1; SetIndexBuffer(t1,BufferResistance3); SetIndexEmptyValue(t1,0.0); SetIndexStyle(t1,DRAW_NONE); t1+=1; SetIndexBuffer(t1,BufferSupport1); SetIndexEmptyValue(t1,0.0); SetIndexStyle(t1,DRAW_NONE); t1+=1; SetIndexBuffer(t1,BufferSupport2); SetIndexEmptyValue(t1,0.0); SetIndexStyle(t1,DRAW_NONE); t1+=1; SetIndexBuffer(t1,BufferSupport3); SetIndexEmptyValue(t1,0.0); SetIndexStyle(t1,DRAW_NONE); LayerHUD0=MathMin(LayerHUD,25); lhud = CharToStr(0x61+LayerHUD0); LayerZone0=MathMin(LayerZone,25); lzone = CharToStr(0x61+LayerZone0); CornerHUD0=CornerHUD; pair=Symbol(); if(TimeFrame != 0) tf = TimeFrame; else tf = PERIOD_CURRENT; point = Point; digits = MarketInfo(Symbol(), MODE_DIGITS); //Digits; if(digits == 3 || digits == 5) point*=10; if(HUDOn && !DrawZones) TAG = "II_HUD"+tf; else TAG = "II_SupDem"+tf; lenbase=StringLen(s_base); if(HUDOn) setHUD(); if(LimitZoneVis) setVisibility(); ObDeleteObjectsByPrefix(lhud+TAG); ObDeleteObjectsByPrefix(lzone+TAG); DoLogo();} void OnDeinit(const int reason) { ObDeleteObjectsByPrefix(lhud+TAG); ObDeleteObjectsByPrefix(lzone+TAG); Comment("");} int start() { if (NewBar()) { SupAlert = 1; DemAlert = 1; ObDeleteObjectsByPrefix(lzone+TAG); CountZZ(BufferSupport1,BufferResistance1,iPeriod[0],Dev[0],Step[0]); // Comment("iPeriod[0]",iPeriod[0]); GetValid(BufferSupport1,BufferResistance1); Draw(); if(HUDOn) HUD(); } if(HUDOn && TimerOn) {BarTimer();} if(AlertOn) {CheckAlert();} return(0); } void CheckAlert(){ // SupCount DemCount // SupAlert DemAlert double price = ObjectGet(lzone+TAG+"UPAR"+SupAlert,OBJPROP_PRICE1); if(Close[0] > price && price > point){ if(AlertPopup) Alert(pair+" "+TimeFrameToString(tf)+" Supply Zone Entered at "+DoubleToStr(price,Digits)); PlaySound(AlertSound); SupAlert++; } price = ObjectGet(lzone+TAG+"DNAR"+DemAlert,OBJPROP_PRICE1); if(Close[0] point){ retouch = false; valid = false; h1 = iTime(pair,tf,i); h2 = Time[0]; p2 = MathMin(iClose(pair,tf,i),iOpen(pair,tf,i)); if(i>0) p2 = MathMax(p2,MathMax(iLow(pair,tf,i-1),iLow(pair,tf,i+1))); if(i>0) p2 = MathMax(p2,MathMin(iOpen(pair,tf,i-1),iClose(pair,tf,i-1))); p2 = MathMax(p2,MathMin(iOpen(pair,tf,i+1),iClose(pair,tf,i+1))); draw=true; if(RecolorRetouch || !SolidRetouch){ exit = false; for(j=i;j>=0;j--){ if(j==0 && !exit) {draw=false; break;} if(!exit && iHigh(pair,tf,j)p2) { retouch = true; if(ZoneFibs && FibSupHIT==0){ FibSup = p2; FibSupHIT = j;} break; } } } if(SupCount != 0) val = ObjectGet(TAG+"UPZONE"+SupCount,OBJPROP_PRICE2); //final sema cull else val=0; if(draw && BufferResistance1[i]!=val) { valid=true; c = ColorSupStrong; if(ZoneStrength && (retouch || !RecolorRetouch)){ countstrong=0; countweak=0; for(j=i;jBufferResistance1[i]) countweak++; if(countstrong > 1) break; else if(countweak > 1){ c=ColorSupWeak; if(NoWeakZones) draw = false; break; } } } // if(c == ColorSupWeak && !NoWeakZones) draw = false; BufferResistance2[i]=(BufferResistance1[i]>0)*p2; BufferResistance3[i]=(BufferResistance1[i]>0)*draw; if(DrawZones && draw){ if(RecolorRetouch && retouch && countweak1) c = ColorSupRetouch; SupCount++; if(DrawEdgePrice){ s = lzone+TAG+"UPAR"+SupCount; ObjectCreate(s,OBJ_ARROW,0,0,0); ObjectSet(s,OBJPROP_ARROWCODE,SYMBOL_RIGHTPRICE); ObjectSet(s, OBJPROP_TIME1, h2); ObjectSet(s, OBJPROP_PRICE1, p2); ObjectSet(s,OBJPROP_COLOR,c); ObjectSet(s,OBJPROP_WIDTH,PriceWidth); if(LimitZoneVis) ObjectSet(s,OBJPROP_TIMEFRAMES,visible); } s = lzone+TAG+"UPZONE"+SupCount; ObjectCreate(s,OBJ_RECTANGLE,0,0,0,0,0); ObjectSet(s,OBJPROP_TIME1,h1); ObjectSet(s,OBJPROP_PRICE1,BufferResistance1[i]); ObjectSet(s,OBJPROP_TIME2,h2); ObjectSet(s,OBJPROP_PRICE2,p2); ObjectSet(s,OBJPROP_COLOR,c); ObjectSet(s,OBJPROP_BACK,true); if(LimitZoneVis) ObjectSet(s,OBJPROP_TIMEFRAMES,visible); if(!SolidZones) {ObjectSet(s,OBJPROP_BACK,false);ObjectSet(s,OBJPROP_WIDTH,ZoneWidth);} if(!SolidRetouch && retouch) {ObjectSet(s,OBJPROP_BACK,false);ObjectSet(s,OBJPROP_WIDTH,ZoneWidth);} if(GlobalVars){ GlobalVariableSet(TAG+"S.PH"+SupCount,BufferResistance1[i]); GlobalVariableSet(TAG+"S.PL"+SupCount,p2); GlobalVariableSet(TAG+"S.T"+SupCount,iTime(pair,tf,i)); } if(!fhe && c!=ColorDemRetouch){fhe=true; GlobalVariableSet(TAG+"GOSHORT",p2);} } } if(draw && sc point){ retouch = false; valid=false; h1 = iTime(pair,tf,i); h2 = Time[0]; p2 = MathMax(iClose(pair,tf,i),iOpen(pair,tf,i)); if(i>0) p2 = MathMin(p2,MathMin(iHigh(pair,tf,i+1),iHigh(pair,tf,i-1))); if(i>0) p2 = MathMin(p2,MathMax(iOpen(pair,tf,i-1),iClose(pair,tf,i-1))); p2 = MathMin(p2,MathMax(iOpen(pair,tf,i+1),iClose(pair,tf,i+1))); c = ColorDemStrong; draw=true; if(RecolorRetouch || !SolidRetouch){ exit = false; for(j=i;j>=0;j--) { if(j==0 && !exit) {draw=false;break;} if(!exit && iLow(pair,tf,j)>p2) {exit=true;continue;} if(exit && iLow(pair,tf,j) p2) countstrong++; if(iLow(pair,tf,j+1) 1) break; else if(countweak > 1){ if(NoWeakZones) draw = false; c=ColorDemWeak; break; } } } BufferSupport2[i]=(BufferSupport1[i]>0)*p2; BufferSupport3[i]=(BufferSupport1[i]>0)*draw; if(DrawZones && draw){ if(RecolorRetouch && retouch && countweak1) c = ColorDemRetouch; DemCount++; if(DrawEdgePrice){ s = lzone+TAG+"DNAR"+DemCount; ObjectCreate(s,OBJ_ARROW,0,0,0); ObjectSet(s,OBJPROP_ARROWCODE,SYMBOL_RIGHTPRICE); ObjectSet(s, OBJPROP_TIME1, h2); ObjectSet(s, OBJPROP_PRICE1, p2); ObjectSet(s,OBJPROP_COLOR,c); ObjectSet(s,OBJPROP_WIDTH,PriceWidth); if(LimitZoneVis) ObjectSet(s,OBJPROP_TIMEFRAMES,visible); } s = lzone+TAG+"DNZONE"+DemCount; ObjectCreate(s,OBJ_RECTANGLE,0,0,0,0,0); ObjectSet(s,OBJPROP_TIME1,h1); ObjectSet(s,OBJPROP_PRICE1,p2); ObjectSet(s,OBJPROP_TIME2,h2); ObjectSet(s,OBJPROP_PRICE2,BufferSupport1[i]); ObjectSet(s,OBJPROP_COLOR,c); ObjectSet(s,OBJPROP_BACK,true); if(LimitZoneVis) ObjectSet(s,OBJPROP_TIMEFRAMES,visible); if(!SolidZones) {ObjectSet(s,OBJPROP_BACK,false);ObjectSet(s,OBJPROP_WIDTH,ZoneWidth);} if(!SolidRetouch && retouch) {ObjectSet(s,OBJPROP_BACK,false);ObjectSet(s,OBJPROP_WIDTH,ZoneWidth);} if(GlobalVars){ GlobalVariableSet(TAG+"D.PL"+DemCount,BufferSupport1[i]); GlobalVariableSet(TAG+"D.PH"+DemCount,p2); GlobalVariableSet(TAG+"D.T"+DemCount,iTime(pair,tf,i)); } if(!fle && c!=ColorDemRetouch){fle=true;GlobalVariableSet(TAG+"GOLONG",p2);} } } if(draw && dcFibSup && sr==0) sr = i; if(iHigh(pair,tf,i)>SupRR[0] && s1==0) s1 = i; if(iLow(pair,tf,i) =0; t1--){ val = iLow(pair,tf,iLowest(pair,tf,MODE_LOW,ExtDepth,t1)); if(val==lastlow) val=0.0; else { lastlow=val; if((iLow(pair,tf,t1)-val)>(ExtDeviation*point)) val=0.0; else{ for(back=1; backval)) ExtMapBuffer[t1+back]=0.0; } } } ExtMapBuffer[t1]=val; //--- high val=iHigh(pair,tf,iHighest(pair,tf,MODE_HIGH,ExtDepth,t1)); if(val==lasthigh) val=0.0; else { lasthigh=val; if((val-iHigh(pair,tf,t1))>(ExtDeviation*point)) val=0.0; else{ for(back=1; back=0; t1--){ curlow=ExtMapBuffer[t1]; curhigh=ExtMapBuffer2[t1]; if((curlow==0)&&(curhigh==0)) continue; //--- if(curhigh!=0){ if(lasthigh>0) { if(lasthigh 0){ if(lastlow>curlow) ExtMapBuffer[lastlowpos]=0; else ExtMapBuffer[t1]=0; } //--- if((curlow =0; t1--){ if(t1>=count) ExtMapBuffer[t1]=0.0; else { res=ExtMapBuffer2[t1]; if(res!=0.0) ExtMapBuffer2[t1]=res; } } } void GetValid(double& ExtMapBuffer[], double& ExtMapBuffer2[]){ UpCur = 0; int upbar = 0; DnCur = 0; int dnbar = 0; double CurHi = 0; double CurLo = 0; double LastUp = 0; double LastDn = 0; double LowDn = 0; double HiUp = 0; int i; for(i=0;i 0){ UpCur = ExtMapBuffer[i]; CurLo = ExtMapBuffer[i]; LastUp = CurLo; break; } for(i=0;i 0){ DnCur = ExtMapBuffer2[i]; CurHi = ExtMapBuffer2[i]; LastDn = CurHi; break; } for(i=0;i = LastDn) { LastDn = ExtMapBuffer2[i]; dnbar = i; } else ExtMapBuffer2[i] = 0.0; if(ExtMapBuffer2[i] 0.0) ExtMapBuffer2[i] = 0.0; if(ExtMapBuffer[i] 0) { LastUp = ExtMapBuffer[i]; upbar = i; } else ExtMapBuffer[i] = 0.0; if(ExtMapBuffer[i] > UpCur) ExtMapBuffer[i] = 0.0; } LowDn = MathMin(iOpen(pair,tf,dnbar),iClose(pair,tf,dnbar)); HiUp = MathMax(iOpen(pair,tf,upbar),iClose(pair,tf,upbar)); for(i=MathMax(upbar,dnbar);i>=0;i--) {// work back to zero and remove reentries into s/d if(ExtMapBuffer2[i] > LowDn && ExtMapBuffer2[i] != LastDn) ExtMapBuffer2[i] = 0.0; else if(ExtMapBuffer2[i] > 0) { LastDn = ExtMapBuffer2[i]; LowDn = MathMin(iClose(pair,tf,i),iOpen(pair,tf,i)); if(i>0) LowDn = MathMax(LowDn,MathMax(iLow(pair,tf,i-1),iLow(pair,tf,i+1))); if(i>0) LowDn = MathMax(LowDn,MathMin(iOpen(pair,tf,i-1),iClose(pair,tf,i-1))); LowDn = MathMax(LowDn,MathMin(iOpen(pair,tf,i+1),iClose(pair,tf,i+1))); } if(ExtMapBuffer[i] 0 && ExtMapBuffer[i] != LastUp) ExtMapBuffer[i] = 0.0; else if(ExtMapBuffer[i] > 0){ LastUp = ExtMapBuffer[i]; HiUp = MathMax(iClose(pair,tf,i),iOpen(pair,tf,i)); if(i>0) HiUp = MathMin(HiUp,MathMin(iHigh(pair,tf,i+1),iHigh(pair,tf,i-1))); if(i>0) HiUp = MathMin(HiUp,MathMax(iOpen(pair,tf,i-1),iClose(pair,tf,i-1))); HiUp = MathMin(HiUp,MathMax(iOpen(pair,tf,i+1),iClose(pair,tf,i+1))); } } } void HUD() { string s = TimeFrameToString(tf); string u = DoubleToStr(ObjectGet(lzone+TAG+"UPAR"+1,OBJPROP_PRICE1),Digits); string d = DoubleToStr(ObjectGet(lzone+TAG+"DNAR"+1,OBJPROP_PRICE1),Digits); string l = "b"; DrawText(l,s,HUDTFX,HUDTFY,ColorHUDTF,FontHUD,FontHUDsize,CornerHUD0); DrawText(l,ArrowGlance,HUDArrowX,HUDArrowY,ColorArrow,FontArrow,FontArrowSize,CornerHUD0,0,true); DrawText(l,u,HUDsupX,HUDsupY,ColorSupStrong,FontHUDprice,FontHUDPriceSize,CornerHUD0); DrawText(l,d,HUDdemX,HUDdemY,ColorDemStrong,FontHUDprice,FontHUDPriceSize,CornerHUD0); l = "a"; DrawText(l,s,HUDtfsX,HUDtfsY,ColorShadow,FontHUD,FontHUDsize,CornerHUD0); DrawText(l,ArrowGlance,HUDarrowsX,HUDarrowsY,ColorShadow,FontArrow,FontArrowSize,CornerHUD0,0,true); DrawText(l,u,HUDsupsX,HUDsupsY,ColorShadow,FontHUDprice,FontHUDPriceSize,CornerHUD0); DrawText(l,d,HUDdemsX,HUDdemsY,ColorShadow,FontHUDprice,FontHUDPriceSize,CornerHUD0); } void BarTimer() // Original Code by Vasyl Gumenyak { int i=0,sec=0; double pc=0.0; string time="",s_end="",s; s = lhud+TAG+"btimerback"; 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, s_base, SizeTimerFont, TimerFont, ColorTimerBack); } sec=TimeCurrent()-iTime(pair,tf,0); i=(lenbase-1)*sec/(tf*60); pc=100-(100.0*sec/(tf*60)); if(i>lenbase-1) i=lenbase-1; if(i 3) {CornerHUD0=0;} if(CornerHUD0 == 0 || CornerHUD0 == 2) rotation = 90; switch(CornerHUD0){ case 0 : HUDTFX = PosX-HUDx+10; HUDTFY = PosY+18; HUDArrowX = PosX-2; HUDArrowY = PosY+7; HUDsupX = PosX; HUDsupY = PosY; HUDdemX = PosX; HUDdemY = PosY+56; HUDTimerX = PosX+50; HUDTimerY = PosY+72; HUDtfsX = HUDTFX+1; HUDtfsY = HUDTFY+1; HUDarrowsX = HUDArrowX+1; HUDarrowsY = HUDArrowY+1; HUDsupsX = HUDsupX+1; HUDsupsY = HUDsupY+1; HUDdemsX = HUDdemX+1; HUDdemsY = HUDdemY+1; break; case 1 : HUDTFX = PosX+HUDx; HUDTFY = PosY+18; HUDArrowX = PosX+2; HUDArrowY = PosY+7; HUDsupX = PosX; HUDsupY = PosY; HUDdemX = PosX; HUDdemY = PosY+56; HUDTimerX = PosX-15; HUDTimerY = PosY+71; HUDtfsX = HUDTFX-1; HUDtfsY = HUDTFY+1; HUDarrowsX = HUDArrowX-1; HUDarrowsY = HUDArrowY+1; HUDsupsX = HUDsupX-1; HUDsupsY = HUDsupY+1; HUDdemsX = HUDdemX-1; HUDdemsY = HUDdemY+1; break; case 2 : HUDTFX = PosX-HUDx; HUDTFY = PosY+20; HUDArrowX = PosX-2; HUDArrowY = PosY+7; HUDsupX = PosX; HUDsupY = PosY+56; HUDdemX = PosX; HUDdemY = PosY; HUDTimerX = PosX+62; HUDTimerY = PosY+3; HUDtfsX = HUDTFX+1; HUDtfsY = HUDTFY-1; HUDarrowsX = HUDArrowX+1; HUDarrowsY = HUDArrowY-1; HUDsupsX = HUDsupX+1; HUDsupsY = HUDsupY-1; HUDdemsX = HUDdemX+1; HUDdemsY = HUDdemY-1; break; case 3 : HUDTFX = PosX+HUDx; HUDTFY = PosY+20; HUDArrowX = PosX+2; HUDArrowY = PosY+7; HUDsupX = PosX; HUDsupY = PosY+56; HUDdemX = PosX; HUDdemY = PosY; HUDTimerX = PosX-2; HUDTimerY = PosY+3; HUDtfsX = HUDTFX-1; HUDtfsY = HUDTFY-1; HUDarrowsX = HUDArrowX-1; HUDarrowsY = HUDArrowY-1; HUDsupsX = HUDsupX-1; HUDsupsY = HUDsupY-1; HUDdemsX = HUDdemX-1; HUDdemsY = HUDdemY-1; break; } } void DoLogo(){ string s7 = CharToStr(0x61+27)+"II_Logo"; if( ObjectFind(s7+"ZZ"+0) >= 0 && ObjectFind(s7+"ZZ"+1) >= 0 && ObjectFind(s7+"ZZ"+2) >= 0 && ObjectFind(s7+"AZ"+0) >= 0 && ObjectFind(s7+"AZ"+1) >= 0 && ObjectFind(s7+"AZ"+2) >= 0 ) return; string str[3] = {".","."}; int Size[3] = {0,0,0}; int PositionX[3] = {0,0,0}; int PositionY[3] = {0,0,0}; int PosXs[3] = {0,0,0}; int PosYs[3] = {0,0,0}; for(int i=0;i 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.
The post iCustom Function in MetaTrader 4 (MQL4 Language) Complete Guide appeared first on FREEVESTOR.