here is the code
//+------------------------------------------------------------------+ //| Bands.mq4 | //| Copyright 2005-2014, MetaQuotes Software Corp. | //| http://www.mql4.com | //+------------------------------------------------------------------+ #property copyright "Peter Kreißl " #property link "http://peterkreissl.ibk.me/" #property description "Bollinger Bands with alert function" #property strict #include <MovingAverages.mqh> #property indicator_chart_window #property indicator_buffers 5 #property indicator_color1 Gold #property indicator_color2 Gold #property indicator_color3 Gold #property indicator_color4 LightSeaGreen #property indicator_color5 clrDarkViolet //--- indicator parameters input int InpBandsPeriod=18; // Bands Period input double InpBandsDeviations=2.0; // Bands Deviations input int InpBandsShift=0; // Bands Shift input int InpEMA_Period = 10; // EMA(10)) input int InpEMAShift = 0; // EMA(10)-Shift) input double InpSARStep=0.018; // Step input double InpSARMaximum=0.08; // Maximum //--- global variables double ExtSarStep; double ExtSarMaximum; string SignalText=""; //--- buffers double ExtMovingBuffer[]; double ExtUpperBuffer[]; double ExtLowerBuffer[]; double ExtStdDevBuffer[]; double ExtEMABuffer[]; double ExtSARBuffer[]; //--- Signal #define SIGNAL_NONE 0 #define SIGNAL_BUY 1 #define SIGNAL_SELL 2 //#define SIGNAL_X 3 //#define SIGNAL_Y 4 //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit(void) { if(InpSARStep<0.0001) { ExtSarStep=0.02; Print("Input parametr InpSARStep has incorrect value. Indicator will use value ", ExtSarStep," for calculations."); } else ExtSarStep=InpSARStep; if(InpSARMaximum<0.0001) { ExtSarMaximum=0.2; Print("Input parametr InpSARMaximum has incorrect value. Indicator will use value ", ExtSarMaximum," for calculations."); } else ExtSarMaximum=InpSARMaximum; //--- 1 additional buffer used for counting. IndicatorBuffers(6); IndicatorDigits(Digits); //--- middle line SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,1); SetIndexBuffer(0,ExtMovingBuffer); SetIndexShift(0,InpBandsShift); SetIndexLabel(0,"Bands SMA"); //--- upper band SetIndexStyle(1,DRAW_LINE,STYLE_DOT); SetIndexBuffer(1,ExtUpperBuffer); SetIndexShift(1,InpBandsShift); SetIndexLabel(1,"Bands Upper"); //--- lower band SetIndexStyle(2,DRAW_LINE,STYLE_DOT); SetIndexBuffer(2,ExtLowerBuffer); SetIndexShift(2,InpBandsShift); SetIndexLabel(2,"Bands Lower"); //--- work buffer SetIndexBuffer(5,ExtStdDevBuffer); //--- EMA Buffer SetIndexStyle(3,DRAW_LINE,STYLE_SOLID,1); SetIndexBuffer(3,ExtEMABuffer); SetIndexShift(3,InpEMAShift); SetIndexLabel(3,"EMA("+IntegerToString(InpEMA_Period)+")"); //--- PSAR Buffer // IndicatorDigits(Digits); IndicatorDigits(Digits); SetIndexStyle(4,DRAW_ARROW); SetIndexArrow(4,159); //---- indicator buffers SetIndexBuffer(4,ExtSARBuffer); //--- set short name // IndicatorShortName("SAR("+DoubleToString(ExtSarStep,2)+","+DoubleToString(ExtSarMaximum,2)+")"); SetIndexLabel(4,"PSAR"); //--- set global variables //--- check for input parameter if(InpBandsPeriod<=0) { Print("Wrong input parameter Bands Period=",InpBandsPeriod); return(INIT_FAILED); } //--- SetIndexDrawBegin(0,InpBandsPeriod+InpBandsShift); SetIndexDrawBegin(1,InpBandsPeriod+InpBandsShift); SetIndexDrawBegin(2,InpBandsPeriod+InpBandsShift); SetIndexDrawBegin(3,InpEMA_Period+InpEMAShift); int Fehlerziffer=CreateInfoBox("Infobox",4,10,"1M EUR/USD Bollinger Strategie"); Print(Fehlerziffer); //--- initialization done return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Bollinger Bands | //+------------------------------------------------------------------+ 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[]) { int i,pos; bool MailYN=false,VoiceYN=false,FensterNachVorn=false; double Tickwert=0; double Spreadwert=0; int Triggersignal=0; double Bolli_oben0=0,Bolli_unten0=0,Bolli_oben1=0,Bolli_unten1=0; double Preis0=0,Preis1=0; double ATRWert=0; double EMAWert0=0, EMAWert1=0; double SMAWert0=0, SMAWert1=0; double PSARWert0=0,PSARWert1=0; bool uptrend=true; int MainCounter=0; //--- Kommentarzeilen - BAsic Infoscreen: if(GlobalVariableGet("MailTrigger")==1)MailYN=true; else MailYN=false; if(GlobalVariableGet("AlarmTrigger")==1)VoiceYN=true; else VoiceYN=false; if(GlobalVariableGet("WindowToFront")==1)FensterNachVorn=true; else FensterNachVorn=false; if(OrdersTotal()>0)FensterNachVorn=false; if(OrdersTotal()==0)FensterNachVorn=true; Tickwert=SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE); Spreadwert=MarketInfo(Symbol(),MODE_SPREAD); XComment("\nMailTrigger: "+GetOnOffStatus(MailYN),true); XComment("\nAlarmtrigger: "+GetOnOffStatus(VoiceYN),false); XComment("\nATR_Span: "+DoubleToStr(GlobalVariableGet("ATRFactor"),2),false); XComment("\ninitial Risk: "+DoubleToStr(GlobalVariableGet("InitialRisk"),0)+"%",false); XComment("\nTickvalue: "+DoubleToStr(Tickwert,2),false); XComment("\nSpread: "+DoubleToStr(Spreadwert,0),false); //--- if(rates_total<3) return(0); if(rates_total<=InpBandsPeriod || InpBandsPeriod<=0) return(0); //--- counting from 0 to rates_total ArraySetAsSeries(ExtMovingBuffer,true); ArraySetAsSeries(ExtUpperBuffer,true); ArraySetAsSeries(ExtLowerBuffer,true); ArraySetAsSeries(ExtStdDevBuffer,true); ArraySetAsSeries(ExtEMABuffer,true); ArraySetAsSeries(close,true); ArraySetAsSeries(ExtSARBuffer,true); ArraySetAsSeries(high,true); ArraySetAsSeries(low,true); //--- initial zero if(prev_calculated<1) { for(i=0; i<InpBandsPeriod; i++) { ExtMovingBuffer[i]=EMPTY_VALUE; ExtUpperBuffer[i]=EMPTY_VALUE; ExtLowerBuffer[i]=EMPTY_VALUE; } for(i=0;i<InpEMA_Period;i++)ExtEMABuffer[i]=EMPTY_VALUE; } //--- starting calculation if(prev_calculated>1) pos=prev_calculated-1; else pos=0; if (rates_total > 400) MainCounter=400; else MainCounter=rates_total; //--- main cycle for(i=pos; i<MainCounter && !IsStopped(); i++) { //--- middle line //ExtMovingBuffer[i]=SimpleMA(i,InpBandsPeriod,close); ExtMovingBuffer[i]=iMA(NULL,0,InpBandsPeriod,InpBandsShift,MODE_SMA,PRICE_CLOSE,i); //ExtMovingBuffer[i]=iMA(NULL,0,InpBandsPeriod,InpBandsShift,MODE_SMA,PRICE_CLOSE,i); //--- calculate and write down StdDev ExtStdDevBuffer[i]=iStdDev(NULL,0,InpBandsPeriod,InpBandsShift,MODE_SMA,PRICE_CLOSE,i); //ExtStdDevBuffer[i]=StdDev_Func(i,close,ExtMovingBuffer,InpBandsPeriod); //--- upper line ExtUpperBuffer[i]=ExtMovingBuffer[i]+InpBandsDeviations*ExtStdDevBuffer[i]; //--- lower line ExtLowerBuffer[i]=ExtMovingBuffer[i]-InpBandsDeviations*ExtStdDevBuffer[i]; //--- EMA BUffer ExtEMABuffer[i]=iMA(NULL,0,InpEMA_Period,InpEMAShift,MODE_EMA,PRICE_CLOSE,i); //ExtEMABuffer[i]=close[i]+InpBandsDeviations*ExtStdDevBuffer[i]; //ExponentialMAOnBuffer(rates_total,prev_calculated,1,InpEMA_Period,close,ExtEMABuffer); //--- PSAR Buffer ExtSARBuffer[i]=iSAR(NULL,0,InpSARStep,InpSARMaximum,i); } for(i=pos; i<MainCounter && !IsStopped(); i++) { //--- close Bolli_oben1=ExtUpperBuffer[i-1]; Bolli_unten1= ExtLowerBuffer[i-1]; Bolli_oben0 = ExtUpperBuffer[i]; Bolli_unten0= ExtLowerBuffer[i]; Preis1 = close[i-1]; Preis0 = close[i]; SMAWert0=ExtMovingBuffer[i]; SMAWert1=ExtMovingBuffer[i-1]; EMAWert0=ExtEMABuffer[i]; EMAWert1=ExtEMABuffer[i-1]; PSARWert0=ExtSARBuffer[i]; PSARWert1=ExtSARBuffer[i-1]; } //--- SIGNAL Trigger Generieren - Cross Up - Cross Down if(Preis0>PSARWert0)uptrend=true;else uptrend=false; if(Preis1<Bolli_unten1 && Preis0>Bolli_unten0) {Triggersignal=SIGNAL_BUY; SignalText="BOLLINGER BUY Signal: ";} if(Preis1>Bolli_oben1 && Preis0<Bolli_oben0) {Triggersignal=SIGNAL_SELL; SignalText="BOLLINGER SELL Signal: ";} if(EMAWert1<SMAWert1 && EMAWert0>SMAWert0 && uptrend) {Triggersignal=SIGNAL_BUY;SignalText="EMA SMA Cross BUY: ";} if(EMAWert1>SMAWert1 && EMAWert0<SMAWert0 && !uptrend) {Triggersignal=SIGNAL_BUY;SignalText="EMA SMA Cross SELL: ";} if(Preis1<PSARWert1 && Preis0>PSARWert0) {Triggersignal=SIGNAL_BUY; SignalText="Parabolic SAR Flip UP";} if(Preis1>PSARWert1 && Preis0<PSARWert0) {Triggersignal=SIGNAL_SELL; SignalText="Parabolic SAR Flip DOWN";} //--- //--- Was geschieht im Signalfall if(Triggersignal==SIGNAL_BUY && NewBar()) { if(VoiceYN)Alert(SignalText+Symbol()+" M"+IntegerToString(Period())); if(MailYN)SendeEmail(SignalText,Symbol(),"Bollinger Cross UP",""); if(FensterNachVorn)ChartBringToTop(ChartID()); Sleep(5000); Triggersignal=SIGNAL_NONE; } if(Triggersignal==SIGNAL_SELL && NewBar()) { if(VoiceYN)Alert(SignalText+Symbol()+" M"+IntegerToString(Period())); if(MailYN)SendeEmail(SignalText,Symbol(),"Bollinger Cross Down",""); if(FensterNachVorn)ChartBringToTop(ChartID()); Sleep(5000); Triggersignal=SIGNAL_NONE; } ATRWert=iATR(NULL,0,14,0)/Point; XComment("\nATR Wert: "+DoubleToStr(ATRWert,2),false); //---- OnCalculate done. Return new prev_calculated. return(MainCounter); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Erstelle eine INFOBOX | //+------------------------------------------------------------------+ int CreateInfoBox(string BoxName, int Ecke, int Abstand, string Infotext ) { ObjectCreate(BoxName,OBJ_LABEL,0,0,0); ObjectSetText(BoxName,Infotext,10,"Arial",clrAqua); ObjectSet(BoxName,OBJPROP_CORNER,Ecke); ObjectSet(BoxName,OBJPROP_XDISTANCE,Abstand); ObjectSet(BoxName,OBJPROP_YDISTANCE,Abstand); int lasterror=GetLastError(); return (lasterror); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Wait for Tick and new bar -- for signal output | //+------------------------------------------------------------------+ bool NewBar() { static datetime dt=0; if(dt!=Time[0]) { dt=Time[0]; Sleep(100); // wait for tick return(true); } return(false); } //+------------------------------------------------------------------+ //| SendeMail Funktion | //+------------------------------------------------------------------+ int SendeEmail(string buysellt,string symbolt,string bidaskt,string balancet) { SendMail(buysellt+" "+symbolt,buysellt+" ["+symbolt+"] "+bidaskt+" TradeBalance: "+balancet+" Pips"); return(0); } //+------------------------------------------------------------------+ //| bring Window to front | //+------------------------------------------------------------------+ bool ChartBringToTop(const long chart_ID=0) { //--- reset the error value ResetLastError(); //--- show the chart on top of all others if(!ChartSetInteger(chart_ID,CHART_BRING_TO_TOP,0,true)) { //--- display the error message in Experts journal Print(__FUNCTION__+", Error Code = ",GetLastError()); return(false); } //--- successful execution return(true); } //+------------------------------------------------------------------+ string GetOnOffStatus(bool trigger) { string returntext; if(trigger)returntext="ON";else returntext="OFF"; return(returntext); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Kommentar-Funktion | //+------------------------------------------------------------------+ void XComment(string Text,bool ResetText=false) { static string ExistingComment = ""; if(ResetText) ExistingComment = ""; ExistingComment=ExistingComment+Text; Comment(ExistingComment); } //--------------------------------------------------------------------
When using built-in functions in MT4, it's better to count down to zero.
//--- counting from 0 to rates_total //ArraySetAsSeries(ExtMovingBuffer,true); //ArraySetAsSeries(ExtUpperBuffer,true); //ArraySetAsSeries(ExtLowerBuffer,true); //ArraySetAsSeries(ExtStdDevBuffer,true); //ArraySetAsSeries(ExtEMABuffer,true); <--not necessary //ArraySetAsSeries(close,true); //ArraySetAsSeries(ExtSARBuffer,true); //ArraySetAsSeries(high,true); //ArraySetAsSeries(low,true); //--- starting calculation if(prev_calculated>1) pos=rates_total-prev_calculated; else pos=MathMin(rates_total-1,400); //--- initial zero if(prev_calculated<1) { for(i=rates_total-1; i>pos; i--) { ExtMovingBuffer[i]=EMPTY_VALUE; ExtUpperBuffer[i]=EMPTY_VALUE; ExtLowerBuffer[i]=EMPTY_VALUE; } for(i=rates_total-1;i>pos+InpEMA_Period;i--)ExtEMABuffer[i]=EMPTY_VALUE; } //if (rates_total > 400) MainCounter=400; else MainCounter=rates_total; //--- main cycle for(i=pos; i>=0 && !IsStopped(); i--) { //--- middle line //ExtMovingBuffer[i]=SimpleMA(i,InpBandsPeriod,close); ExtMovingBuffer[i]=iMA(NULL,0,InpBandsPeriod,InpBandsShift,MODE_SMA,PRICE_CLOSE,i); //ExtMovingBuffer[i]=iMA(NULL,0,InpBandsPeriod,InpBandsShift,MODE_SMA,PRICE_CLOSE,i); //--- calculate and write down StdDev ExtStdDevBuffer[i]=iStdDev(NULL,0,InpBandsPeriod,InpBandsShift,MODE_SMA,PRICE_CLOSE,i); //ExtStdDevBuffer[i]=StdDev_Func(i,close,ExtMovingBuffer,InpBandsPeriod); //--- upper line ExtUpperBuffer[i]=ExtMovingBuffer[i]+InpBandsDeviations*ExtStdDevBuffer[i]; //--- lower line ExtLowerBuffer[i]=ExtMovingBuffer[i]-InpBandsDeviations*ExtStdDevBuffer[i]; //--- EMA BUffer ExtEMABuffer[i]=iMA(NULL,0,InpEMA_Period,InpEMAShift,MODE_EMA,PRICE_CLOSE,i); //ExtEMABuffer[i]=close[i]+InpBandsDeviations*ExtStdDevBuffer[i]; //ExponentialMAOnBuffer(rates_total,prev_calculated,1,InpEMA_Period,close,ExtEMABuffer); //--- PSAR Buffer ExtSARBuffer[i]=iSAR(NULL,0,InpSARStep,InpSARMaximum,i); } for(i=pos; i>=0 && !IsStopped(); i--) { //--- close Bolli_oben1=ExtUpperBuffer[i+1]; Bolli_unten1= ExtLowerBuffer[i+1]; Bolli_oben0 = ExtUpperBuffer[i]; Bolli_unten0= ExtLowerBuffer[i]; Preis1 = close[i+1]; Preis0 = close[i]; SMAWert0=ExtMovingBuffer[i]; SMAWert1=ExtMovingBuffer[i+1]; EMAWert0=ExtEMABuffer[i]; EMAWert1=ExtEMABuffer[i+1]; PSARWert0=ExtSARBuffer[i]; PSARWert1=ExtSARBuffer[i+1]; }
![MQL5 - Language of trade strategies built-in the MetaTrader 5 client terminal](https://c.mql5.com/i/registerlandings/logo-2.png)
You are missing trading opportunities:
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
Registration
Log in
You agree to website policy and terms of use
If you do not have an account, please register
Hello fellow MQL4 programmers,
I need your help please. The indicator stated below seems to work fine on first hand but I do have an issue - it doesn't refresh the last bar value - it simply ends and there delivers no signals.
I found the culprit: Question solved:
The position check of value "pos" forced the indicator to stop.
Please help me, I think my error lies within the main loop and filling the extBuffers[i].
Thank you,
Peter