is it OK ... or ... could be better ???

 
I'm just starting to learn coding in MQL4 and have a question to someone with much more experiences in that matter.
Thus, in this part of the script below ... OnTick() - function ...
I would like to disable any new orders as well as modification of already existing orders ...
whenever the spread is above nominal value. However, with one exception ... which is the 'earlier exit'.
So, I'm wondering about the operating speed of this EA  and got some doubts.
Should I keep the highlighted lines 'as is' or would be better to move it ... where EA calls directly for OrderSend(...) and/or OrderModify(...)
void OnTick(){
   RefreshRates();//» force to refresh price-data
   if(!IsTradeAllowed())return;
   yesterdayATR(); weeklyATR(); monthlyATR(); selectedATR(); SelectedATR(); SignalATR(); BandsExpands(); BandsCompress(); // each tick refresh value of parameters
   TakeProfitATR=NormalizeDouble(SelectedATR()*TargetATR/100/Point/digits(),Digits-4); // normalize & calculate value of Take-Profit as input(%) of smallest 'ATR'
   BandUPPER_0=NormalizeDouble(iBands(NULL,0,13,3,0,PRICE_CLOSE,MODE_UPPER,0),Digits); // normalize value of 'upper-iBand' for bar(0) --> at close of current-bar
   BandLOWER_0=NormalizeDouble(iBands(NULL,0,13,3,0,PRICE_CLOSE,MODE_LOWER,0),Digits); // normalize value of 'lower-iBand' for bar(0) --> at close of current-bar
   BandVALUE_0=NormalizeDouble(BandUPPER_0-BandLOWER_0,Digits); // normalize value of distance between upper & lower iBands for bar(0) --> the current-bar
   BandUPPER_1=NormalizeDouble(iBands(NULL,0,13,3,0,PRICE_CLOSE,MODE_UPPER,1),Digits); // normalize value of 'upper-iBand' for bar(1) --> at close of previous-bar
   BandLOWER_1=NormalizeDouble(iBands(NULL,0,13,3,0,PRICE_CLOSE,MODE_LOWER,1),Digits); // normalize value of 'lower-iBand' for bar(1) --> at close of previous-bar
   BandVALUE_1=NormalizeDouble(BandUPPER_1-BandLOWER_1,Digits); // normalize value of distance between upper & lower iBands for bar(1) --> the previous-bar
   BandUPPER_2=NormalizeDouble(iBands(NULL,0,13,3,0,PRICE_CLOSE,MODE_UPPER,2),Digits); // normalize value of 'upper-iBand' for bar(2) --> at close of former-bar
   BandLOWER_2=NormalizeDouble(iBands(NULL,0,13,3,0,PRICE_CLOSE,MODE_LOWER,2),Digits); // normalize value of 'lower-iBand' for bar(2) --> at close of former-bar
   BandVALUE_2=NormalizeDouble(BandUPPER_2-BandLOWER_2,Digits); // normalize value of distance between upper & lower iBands for bar(2) --> the former-bar
   if((OrderType()==OP_BUY)==True && OrderProfit()==False && Close[0]<OrderOpenPrice()){
      if(BandsCompress()==True)OrderCLOSE(MagicNumber,OP_BUY); // to force earlier exit from buy-order
   }else
   if((OrderType()==OP_SELL)==True && OrderProfit()==False && Close[0]>OrderOpenPrice()){
      if(BandsCompress()==True)OrderCLOSE(MagicNumber,OP_SELL); // to force earlier exit from sell-order
   }
   double maximumSpread=0.5; // maximum spread allowed to open new order and/or modify existing trade
   double currentSpread=MarketInfo(Symbol(),MODE_SPREAD)/digits(); // acquire value of current spread
   if(currentSpread>maximumSpread){ // while spread is greater than nominated --> withhold any action 'functions' below ... new entry or modify SL & TP
      while(RefreshRates()==False)Sleep(1); // wait for next tick & refresh price-data
      Comment(space,"»»»  current spread  (",currentSpread,")  exceeds maximum spread  allowed  (",maximumSpread,")  ... waiting for a new tick & rate.");
      return;
   }
   int signalATR=EntrySignal();
   if(getOrdersTotal(MagicNumber,OP_BUY)>0){
      orderStopLoss(MagicNumber,SupportATR(1));
      orderTakeProfit(MagicNumber,DOUBLE_VALUE);
   }else
   if(getOrdersTotal(MagicNumber,OP_SELL)>0){
      orderStopLoss(MagicNumber,ResistanceATR(1));
      orderTakeProfit(MagicNumber,DOUBLE_VALUE);
   }
   double initialLotSize=LotSize();
   if((OrderType()==OP_BUY)||(OrderType()==OP_SELL)==True){
      double OrderSize=OrderLots();
      double reducedLotSize=OrderSize/2;
      if(signalATR>0){     
         if(iBar<Time[0])OrderCLOSE(MagicNumber,OP_SELL);
         if(getOrdersTotal(MagicNumber,OP_BUY)==0 && directionATR!=+1){
               OrderOPEN(OP_BUY,initialLotSize,0,SupportATR(1),0);
               iBar=Time[0];
               directionATR=+1;
         }else{
            double lastPriceBUY=getPriceBUY();
            if(CompareDoubles(SupportATR(1),EMPTY_VALUE)==False && CompareDoubles(lastPriceBUY,EMPTY_VALUE)==False && SupportATR(1)>=lastPriceBUY){
               OrderOPEN(OP_BUY,reducedLotSize,0,SupportATR(1),0);
            }
         }
      }else
      if(signalATR<0){
         if(iBar<Time[0])OrderCLOSE(MagicNumber,OP_BUY);
         if(getOrdersTotal(MagicNumber,OP_SELL)==0 && directionATR!=-1){
               OrderOPEN(OP_SELL,initialLotSize,0,ResistanceATR(1),0);
               iBar=Time[0];
               directionATR=-1;
         }else{
            double lastPriceSELL=getPriceSELL();
            if(CompareDoubles(ResistanceATR(1),EMPTY_VALUE)==False && CompareDoubles(lastPriceSELL,EMPTY_VALUE)==False && ResistanceATR(1)<=lastPriceSELL){
               OrderOPEN(OP_SELL,reducedLotSize,0,ResistanceATR(1),0);
            }
         }
      }
   }
   Comment(space,"iBands:   expands (",BandsExpands(),")   &   compress (",BandsCompress(),")   ||   ",
   "Server date & time:   ",TimeToStr(TimeCurrent(),TIME_DATE),"   ",TimeToStr(TimeCurrent(),TIME_MINUTES),
   "   |   Local date & time:   ",TimeToStr(TimeLocal(),TIME_DATE),"   ",TimeToStr(TimeLocal(),TIME_SECONDS),
   "   |   Execution (ms)  Entry: ",executionEntry,"    Modify: ",executionModify,"    Exit: ",executionExit,
   "   |   ",Symbol(),"    ",Order,"   ",OrderLots(), " @ ",DoubleToStr(OrderOpenPrice(),Digits),
   "    S / L @  (",DoubleToStr(MathAbs(OrderOpenPrice()-OrderStopLoss())*(1/Point)/digits(),Digits-4),
   ")    T / P @  (",DoubleToStr(MathAbs(OrderOpenPrice()-OrderTakeProfit())*(1/Point)/digits(),Digits-4),")");
}
 

... just realised that, RefreshRates() in OnTick() function is totally unnecessary ... unless, I'm misunderstanding this. 

 
darelco:

... just realised that, RefreshRates() in OnTick() function is totally unnecessary ... unless, I'm misunderstanding this. 

I haven't read your code in your first post as it is wider than my screen.

RefreshRates may be a good idea when an order has been sent or when other code may have taken some time and some ticks may have been missed. It makes sure that you are working with up to date data. 

 
  1. BandVALUE_2=NormalizeDouble(BandUPPER_2-BandLOWER_2,Digits); // normalize 
    
    Do NOT use NormalizeDouble, EVER. For ANY Reason. It's a kludge, don't use it. It's use is always wrong
  2.   double maximumSpread=0.5; // maximum spread allowed to open new order and/or modify existing trade
    
    What does this mean? On EURUSD it is 5000 pips, On USDJPY it is 50 pips. Adjust Problems with a calculation - MQL4 forum
  3.    double currentSpread=MarketInfo(Symbol(),MODE_SPREAD)/digits(); // acquire value of current spread
    
    Why us a function call instead of just the predefined variables? What does the spread (in points) divided by 5 or 3 mean? Meaningless. You could use spreadpips2points or just compare directly
    maximumSpread = 5; // pips 
    if (Ask-Bid > maximumSpread * pips2dbl)
  4. Why are you looping and throwing away the next tick before returning? Just return. If you don't return then you must refresh rates.
  5. Are your books one column but two feet wide? No because that is unreadable. They are 6 inches, sometimes two columns, so you can read it easily. So should be your code. I'm not going to go scrolling back and forth trying to read it. Edit the post with formatted code and you might get additional help.
  6. if(CompareDoubles(ResistanceATR(1),EMPTY_VALUE)==False
    You would never write if( (2+2 == 4) == true) would you? if(2+2 == 4) is sufficient. So Don't write if(bool == true), just use if(bool) or if(!bool). Code becomes self documenting when you use meaningful variable names, like bool isLongEnabled. "if CompareDoubles " is an incomplete sentence. isEquivalent would make sense if you're testing approximate equal. Can price != price ? - MQL4 forum
 
Thank you guys for constructive comments ... all this is very useful for me, especially at current stage of my learning MQL coding ...
... to learn implementing those standard functions in correct way at the beginning, instead of just copying mistakes made in some other scripts.
If you don't mind to look into this piece of code again ... once, I'll correct it (in few days time) ... I would greatly appreciate your help.
Many Thanks.
 

OK ... this part of the script has been corrected ... and I hope it's alright.

double point2pip(){if(Digits==3||Digits==5)return(10); else return(1);}
//+------------------------------------------------------------------+
void OnTick(){
   if(!IsTradeAllowed())return;
   BandsCompress();
   BandsExpands();
   yesterdayATR();
   SelectedATR();
   selectedATR();
   monthlyATR();
   weeklyATR();
   SignalATR();
   TakeProfitATR=DoubleToStr(SelectedATR()*TargetATR/100,Digits);
   BandUPPER_0=iBands(NULL,0,13,3,0,PRICE_CLOSE,MODE_UPPER,0);
   BandLOWER_0=iBands(NULL,0,13,3,0,PRICE_CLOSE,MODE_LOWER,0);
   BandVALUE_0=DoubleToStr(BandUPPER_0-BandLOWER_0,Digits);
   BandUPPER_1=iBands(NULL,0,13,3,0,PRICE_CLOSE,MODE_UPPER,1);
   BandLOWER_1=iBands(NULL,0,13,3,0,PRICE_CLOSE,MODE_LOWER,1);
   BandVALUE_1=DoubleToStr(BandUPPER_1-BandLOWER_1,Digits);
   BandUPPER_2=iBands(NULL,0,13,3,0,PRICE_CLOSE,MODE_UPPER,2);
   BandLOWER_2=iBands(NULL,0,13,3,0,PRICE_CLOSE,MODE_LOWER,2);
   BandVALUE_2=DoubleToStr(BandUPPER_2-BandLOWER_2,Digits);
   int signalATR=EntrySignal();
   if(getOrdersTotal(MagicNumber,OP_BUY)>0){
      orderStopLoss(MagicNumber,SupportATR(1));
      orderTakeProfit(MagicNumber,TakeProfitATR);
   }else
   if(getOrdersTotal(MagicNumber,OP_SELL)>0){
      orderStopLoss(MagicNumber,ResistanceATR(1));
      orderTakeProfit(MagicNumber,TakeProfitATR);
   }
   double initialLotSize=LotSize();
   if((OrderType()==OP_BUY)||(OrderType()==OP_SELL)==True){
      double OrderSize=OrderLots();
      double reducedLotSize=OrderSize/2;
      if(signalATR>0){
         if(iBar<Time[0])OrderCLOSE(MagicNumber,OP_SELL);
         if(getOrdersTotal(MagicNumber,OP_BUY)==0 && directionATR!=+1){
               OrderOPEN(OP_BUY,initialLotSize,0,SupportATR(1),0);
               iBar=Time[0];
               directionATR=+1;
         }else{
            double lastPriceBUY=getPriceBUY();
            if(SupportATR(1)!=EMPTY_VALUE && lastPriceBUY!=EMPTY_VALUE && SupportATR(1)>=lastPriceBUY){
               OrderOPEN(OP_BUY,reducedLotSize,0,SupportATR(1),0);
            }
         }
      }else
      if(signalATR<0){
         if(iBar<Time[0])OrderCLOSE(MagicNumber,OP_BUY);
         if(getOrdersTotal(MagicNumber,OP_SELL)==0 && directionATR!=-1){
               OrderOPEN(OP_SELL,initialLotSize,0,ResistanceATR(1),0);
               iBar=Time[0];
               directionATR=-1;
         }else{
            double lastPriceSELL=getPriceSELL();
            if(ResistanceATR(1)!=EMPTY_VALUE && lastPriceSELL!=EMPTY_VALUE && ResistanceATR(1)<=lastPriceSELL){
               OrderOPEN(OP_SELL,reducedLotSize,0,ResistanceATR(1),0);
            }
         }
      }
   }
   if((OrderType()==OP_BUY)==True && OrderProfit()==False && Close[0]<OrderOpenPrice()){
      if(BandsCompress()==True)OrderCLOSE(MagicNumber,OP_BUY);
   }else
   if((OrderType()==OP_SELL)==True && OrderProfit()==False && Close[0]>OrderOpenPrice()){
      if(BandsCompress()==True)OrderCLOSE(MagicNumber,OP_SELL); 
   }
   double maximumSpread=0.5; // maximum spread (5 points)
   string currentSpread=DoubleToStr((Ask-Bid)/Point/point2pip(),1);
   if(currentSpread>(string)maximumSpread){ // while spread is greater than nominated
      orderSend=False; // disallow opening of any new trades
      Comment(space,"»»»  current spread  (",currentSpread,")  exceeds maximum spread  (",maximumSpread,")");
   }else
   Comment(space,"iBands:   expands (",BandsExpands(),")   &   compress (",BandsCompress(),")   ||   ",
   "Server date & time:   ",TimeToStr(TimeCurrent(),TIME_DATE),"   ",TimeToStr(TimeCurrent(),TIME_MINUTES),
   "   |   Local date & time:   ",TimeToStr(TimeLocal(),TIME_DATE),"   ",TimeToStr(TimeLocal(),TIME_SECONDS),
   "   |   Execution (ms)  Entry: ",executionEntry,"    Modify: ",executionModify,"    Exit: ",executionExit,
   "   |   ",Symbol(),"    ",Order,"   ",OrderLots(), " @ ",DoubleToStr(OrderOpenPrice(),Digits),
   "    S / L @  (",DoubleToStr(MathAbs(OrderOpenPrice()-OrderStopLoss())/Point/point2pip(),Digits-4),
   ")    T / P @  (",DoubleToStr(MathAbs(OrderOpenPrice()+OrderTakeProfit())/Point/point2pip(),Digits-4),")");
}
 
 So, if ... Do NOT use NormalizedDouble, EVER. For ANY Reason. It's a kludge, don't use it. It's use is always wrong
... I have some query in regards to NormalizedDouble within the comparison of two doubles ...

Should I also replace NormalizedDouble for something else ... or ... just in this particular case that's OK ???

//+------------------------------------------------------------------+
//|                                                       stdlib.mq4 |
//|                   Copyright 2005-2014, MetaQuotes Software Corp. |
//|                                              https://www.mql4.com |
//+------------------------------------------------------------------+
#property copyright "2005-2014, MetaQuotes Software Corp."
#property link      "https://www.mql4.com"
#property library
//+------------------------------------------------------------------+
//| right comparison of 2 doubles                                    |
//+------------------------------------------------------------------+
bool CompareDoubles(double number1,double number2)
  {
   if(NormalizeDouble(number1-number2,8)==0) return(true);
   else return(false);
  }
//+------------------------------------------------------------------+

 

 
darelco:
 So, if ... Do NOT use NormalizedDouble, EVER. For ANY Reason. It's a kludge, don't use it. It's use is always wrong
... I have some query in regards to NormalizedDouble within the comparison of two doubles ...

Should I also replace NormalizedDouble for something else ... or ... just in this particular case that's OK ???

 

You have to form your own opinion. Mine is : there is no problem with NormalizeDouble if properly used.
 
angevoyageur:
You have to form your own opinion. Mine is : there is no problem with NormalizeDouble if properly used.
I agree, the only trouble I have ever had with NormalizeDouble are the problems I caused.
 
  1. darelco:
     So, if ... Do NOT use NormalizedDouble, EVER. For ANY Reason. It's a kludge, don't use it. It's use is always wrong
    ... I have some query in regards to NormalizedDouble within the comparison of two doubles ...

    Should I also replace NormalizedDouble for something else ... or ... just in this particular case that's OK ???

     

    I gave you the links. You must understand double comparison.

  2. angevoyageur: You have to form your own opinion. Mine is : there is no problem with NormalizeDouble if properly used.
      if(NormalizeDouble(number1-number2,8)==0) return(true);
    Case in point. His function is used to compare two buffer values
    if(CompareDoubles(SupportATR(1),EMPTY_VALUE)==False

    Either it will be exactly EMPTY_VALUE or it will not. The use is unnecessary.

    If he uses the same function to compare two prices, the function fails when the differences is less than point/2 but greater than 10^-8.

    The problem is NormalizeDouble is never necessary, and is seldom used properly.

 

Thank you guys,

Well, as angevoyageur points out: I have to form mine own opinion. So, let it be ...
I reckon that a risk of some unintentional fault in calculation associated with NormalizeDouble outweighs any convenience ... and also, because ...
this so easily can be replaced by suitable Math function or DoubleToStr or even DoubleToStrMorePrecision whenever greater accuracy is required.
Thus, decisively I'm joining WHRoeder's camp ... and putting it from now on into a 'kludge' category ... perhaps together with the float.
Reason: