Strange error MT5

 

I have range breakout EA work very well but i have error with symbol GER30 index, The EA some times work well with this symbol but some times send very huge volume size like 1800 lots and i got error invalid volume, I  need help.

//+------------------------------------------------------------------+
//| Include                                                          |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>

//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
input group "==== General Inputs ===="
input long InpMagicNumber = 2;      // Mn.

enum LOT_MODE_ENUM{
   LOT_MODE_FIXED,                  // Fixed lote
   LOT_MODE_MONEY,                  // Lots based on money
   LOT_MODE_PCT_ACCOUNT,            // Lots based on % of account
};
input LOT_MODE_ENUM InpLotMode = LOT_MODE_FIXED;   // Lot mode
input double InpLots = 0.01;        // Lot / Money / Percent

input int InpStopLoss =150;         // Stop loss in % of the range (0=off)
input int InpTakeProfit =200;       // Take profit in % of the range (0=off)

input group "==== Range Inputs ===="
input int InpRangeStart = 600;      // Range start time in minutes
input int InpRangeDuration = 120;   // Range duration in minutes
input int InpRangeClose = 1200;     // Range close time in minutes (-2=off)

enum BREAKOUT_MODE_ENUM {
   ONE_SIGNAL,                      // One breakout per range
   TWO_SIGNALS                      // High and low breakout
};
input BREAKOUT_MODE_ENUM InpBreakoutMode = ONE_SIGNAL;   // breakout mode

input group "==== Day of week filter ===="
input bool InpMonday = true;        // Range on monday
input bool InpTuesday = true;       // Range on tuesday
input bool InpWednesday = true;     // Range on wednesday
input bool InpThursday = true;      // Range on thursday
input bool InpFriday = true;        // Range on friday

//+------------------------------------------------------------------+
//| Global variables                                                           |
//+------------------------------------------------------------------+
struct RANGE_STRUCT{
   datetime start_time;       // start of the range
   datetime end_time;         // end of the range
   datetime close_time;       // close time
   double high;               // high of the range
   double low;                // low of the range
   bool f_entry;              // flag if we are inside the range
   bool f_high_breakout;      // flag if a high breakout occurred
   bool f_low_breakout;       // flag if a low breakout occurred
   
   RANGE_STRUCT() : start_time(0),end_time(0),close_time(0),high(0),low(DBL_MAX),f_entry(false),f_high_breakout(false),f_low_breakout(false) {};
};

RANGE_STRUCT range;
MqlTick prevTick, lastTick;
CTrade trade;


//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(){
   
   // check user inputs
   if(!CheckInputs()){return INIT_PARAMETERS_INCORRECT;}   
   
   // set magicnumber
   trade.SetExpertMagicNumber(InpMagicNumber);
   
   // calculated new range if inputs changed
   if(_UninitReason==REASON_PARAMETERS && CountOpenPositions()==0){
      CalculateRange();
   } 
   
   // draw objects
   Drawobjects();           
   
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
   
   // delete objects
   ObjectsDeleteAll(NULL,"range");
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(){

   // Get current tick
   prevTick = lastTick;
   SymbolInfoTick(_Symbol,lastTick);

   // range calculation
   if(lastTick.time >= range.start_time && lastTick.time < range.end_time){
      // set flag
      range.f_entry = true;
      // new high
      if(lastTick.ask > range.high){
         range.high = lastTick.ask;
         Drawobjects();
      }
      // new low
      if(lastTick.bid < range.low){
         range.low = lastTick.bid;
         Drawobjects();
      }
   }

   // close positions
   if(InpRangeClose >=0 && lastTick.time >= range.close_time){
      if(!ClosePositions()){return;}
   }

   // calculate new range if ...
   if(((InpRangeClose>=0 && lastTick.time>=range.close_time)                         // close time reached
      || (range.f_high_breakout && range.f_low_breakout)                             // bith breakout flags are true
      || (range.end_time==0)                                                         // range not calculated yet
      || (range.end_time!=0 && lastTick.time>range.end_time && !range.f_entry))      // there was a range calculated but no tick inside
      && CountOpenPositions()==0){
      
      CalculateRange();      
   }
   
   // check for breakouts
   CheckBreakouts();

}


// check user inputs
bool CheckInputs(){

   if(InpMagicNumber <= 0){
      Alert("Magicnumber <= 0");
      return false;
   }
   if(InpLotMode==LOT_MODE_FIXED && (InpLots <=0 || InpLots > 50)){
      Alert("Lots <= 0 or > 50");
      return false;
   }
   if(InpLotMode==LOT_MODE_MONEY && (InpLots <=0 || InpLots > 100000)){
      Alert("Lots <= 0 or > 100000");
      return false;
   }
   if(InpLotMode==LOT_MODE_PCT_ACCOUNT && (InpLots <=0 || InpLots > 100)){
      Alert("Lots <= 0 or > 100");
      return false;
   }
   if((InpLotMode==LOT_MODE_MONEY || InpLotMode==LOT_MODE_PCT_ACCOUNT) && InpStopLoss==0){
      Alert("Selected lot mode needs a stop loss");
      return false;
   }
   if(InpStopLoss<0 || InpStopLoss>1000){
      Alert("Stop loss < 0 or stop loss > 1000");
      return false;
   }
   if(InpTakeProfit<0 || InpTakeProfit>1000){
      Alert("Take profit < 0 or take profit > 1000");
      return false;
   }
   if(InpRangeClose<0 && InpStopLoss==0){
      Alert("Close time and stop loss is off");
      return false;
   }
   if(InpRangeStart < 0 || InpRangeStart >= 1440){
      Alert("Range start < 0 or >= 1440");
      return false;
   }
   if(InpRangeDuration <= 0 || InpRangeDuration >= 1440){
      Alert("Range duration <= 0 or >= 1440");
      return false;
   }
   if(InpRangeClose >= 1440 || (InpRangeStart+InpRangeDuration)%1440 ==InpRangeClose){
      Alert("Close time >= 1440 or end time == close time");
      return false;
   }
   if(InpMonday+InpTuesday+InpWednesday+InpThursday+InpFriday==0){
      Alert("Range is prohibited on all days of the week");
      return false;
   }

   return true;
}


// calculate a new range
void CalculateRange()
{
   // reset range variables
   range.start_time = 0;
   range.end_time = 0;
   range.close_time = 0 ;
   range.high = 0.0;
   range.low = DBL_MAX;
   range.f_entry = false;
   range.f_high_breakout = false;
   range.f_low_breakout = false;


   // calculate range start time
   int time_cycle = 86400;
   range.start_time = (lastTick.time - (lastTick.time % time_cycle)) + InpRangeStart*60;
   for( int i=0; i<8; i++){
      MqlDateTime tmp;
      TimeToStruct(range.start_time,tmp);
      int dow = tmp.day_of_week;
      if(lastTick.time>=range.start_time || dow==6 || dow==0 || (dow==1 && !InpMonday)  || (dow==2 && !InpTuesday)  || (dow==3 && !InpWednesday)
         || (dow==4 && !InpThursday)  || (dow==5 && !InpFriday)){
         range.start_time += time_cycle;
      }
   }
   
   // calculate range end time
    range.end_time = range.start_time + InpRangeDuration*60;
   for( int i=0; i<2; i++){
      MqlDateTime tmp;
      TimeToStruct(range.end_time,tmp);
      int dow = tmp.day_of_week;
      if(dow==6 || dow==0){
         range.end_time += time_cycle;
      }
   }
   
   // calculate range close
      if(InpRangeClose>=0){
      range.close_time = (range.end_time - (range.end_time % time_cycle)) + InpRangeClose*60;
      for( int i=0; i<3; i++){
         MqlDateTime tmp;
         TimeToStruct(range.close_time,tmp);
         int dow = tmp.day_of_week;
         if(range.close_time<=range.end_time || dow==6 || dow==0){
            range.close_time += time_cycle;
         }
      } 
    } 
      
   // draw objects
   Drawobjects();         
}


// count all open positions
int CountOpenPositions(){

   int counter = 0;
   int total = PositionsTotal();
   for(int i=total-1; i>=0; i--){
      ulong ticket = PositionGetTicket(i);
      if(ticket<=0){Print("Failed to get position ticket"); return -1;}
      if(!PositionSelectByTicket(ticket)){Print("Failed to select position by ticket"); return -1;}
      ulong magicnumber;
      if(!PositionGetInteger(POSITION_MAGIC,magicnumber)){Print("Failed to get position magicnumber"); return -1;}
      if(InpMagicNumber==magicnumber){counter++;}
   }
   return counter;   
}


//  Check for breakouts
void CheckBreakouts(){

   // check if we are after the range end
   if(lastTick.time >= range.end_time && range.end_time>0 && range.f_entry){
   
      // check for high breakout   
      if(!range.f_high_breakout && lastTick.ask >= range.high){
      range.f_high_breakout = true;
      if(InpBreakoutMode==ONE_SIGNAL){range.f_low_breakout = true;}
      
      // calculate stop loss and take profit      
      double sl = InpStopLoss == 0 ? 0 : NormalizeDouble(lastTick.bid - ((range.high-range.low) * InpStopLoss * 0.01),_Digits);
      double tp = InpTakeProfit == 0 ? 0 : NormalizeDouble(lastTick.bid + ((range.high-range.low) * InpTakeProfit * 0.01),_Digits); 
 
      // calculate lots
      double lots;
      if(!CalculateLots(lastTick.bid-sl,lots)){return;} 
         
         // open buy position
         trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,lots,lastTick.ask,sl,tp,"Time range EA");
      }
      
      // check for low breakout   
      if(!range.f_low_breakout && lastTick.bid <= range.low){
         range.f_low_breakout = true;
         if(InpBreakoutMode==ONE_SIGNAL){range.f_high_breakout = true;}
         
         // calculate stop loss and take profit      
         double sl = InpStopLoss == 0 ? 0 : NormalizeDouble(lastTick.ask + ((range.high-range.low) * InpStopLoss * 0.01),_Digits);
         double tp = InpTakeProfit == 0 ? 0 :  NormalizeDouble(lastTick.ask - ((range.high-range.low) * InpTakeProfit * 0.01),_Digits); 
     
         // calculate lots
         double lots;
         if(!CalculateLots(sl-lastTick.ask,lots)){return;} 

         // open sell position
         trade.PositionOpen(_Symbol,ORDER_TYPE_SELL,lots,lastTick.bid,sl,tp,"Time range EA");
      }
   }
}


// calculate lots
bool CalculateLots(double slDistance, double &lots){

   lots = 0.0;
   if(InpLotMode==LOT_MODE_FIXED){
      lots = InpLots;
   }
   else{
      double tickSize   = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
      double tickValue  = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);   
      double volumeStep = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);    
   
      double riskMoney = InpLotMode==LOT_MODE_MONEY ? InpLots : AccountInfoDouble(ACCOUNT_EQUITY) * InpLots * 0.01;
      double moneyVolumeStep = (slDistance / tickSize) * tickValue * volumeStep;
   
      lots = MathFloor(riskMoney/moneyVolumeStep) * volumeStep;  
   }
   
   // check calculated lots
   if(!CheckLots(lots)){return false;}   

   return true;
}


// check lots for min, max and step
bool CheckLots(double &lots){

   double min  = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);   
   double max  = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
   double step = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);

   if(lots<min){
      Print("Lot size will be set to the minimum allowable volume");
      lots = min;
      return true;
   }
   if(lots>max){
      Print("Lot size greater than the maximum allowable volume. lots:",lots,"max:",max);
      return false;
   }   
   
   lots = (int)MathFloor(lots/step) * step; 

   return true;
}



// Close all open positions
bool ClosePositions(){

   int total = PositionsTotal();
   for(int i=total-1; i>=0; i--){
      if(total!=PositionsTotal()){total=PositionsTotal(); i=total; continue;}
      ulong ticket = PositionGetTicket(i);   // select position
      if(ticket<=0){Print("Failed to get position ticket"); return false;}
      if(!PositionSelectByTicket(ticket)){Print("Failed to select position by ticket");return false;}
      long magicnumber;
      if(!PositionGetInteger(POSITION_MAGIC,magicnumber)){Print("Failed to get position magicnumber");return false;}
      if(magicnumber == InpMagicNumber){
         trade.PositionClose(ticket);     
         if(trade.ResultRetcode() !=TRADE_RETCODE_DONE){
            Print("Failed to close position. Result: "+(string)trade.ResultRetcode()+":"+trade.ResultRetcodeDescription());
            return false;  
         }
      }
   }

   return true;
}


// draw chart objects
void Drawobjects()
{
   // start time
   ObjectDelete(NULL,"range start");
   if(range.start_time>0){
      ObjectCreate(NULL,"range start",OBJ_VLINE,0,range.start_time,0);
      ObjectSetString(NULL,"range start",OBJPROP_TOOLTIP,"start of the range \n"+TimeToString(range.start_time,TIME_DATE|TIME_MINUTES));
      ObjectSetInteger(NULL,"range start",OBJPROP_COLOR,clrPlum);
      ObjectSetInteger(NULL,"range start",OBJPROP_WIDTH,2);
      ObjectSetInteger(NULL,"range start",OBJPROP_BACK,true);
   }
   
   // end time
   ObjectDelete(NULL,"range end");
   if(range.end_time>0){
      ObjectCreate(NULL,"range end",OBJ_VLINE,0,range.end_time,0);
      ObjectSetString(NULL,"range end",OBJPROP_TOOLTIP,"end of the range \n"+TimeToString(range.end_time,TIME_DATE|TIME_MINUTES));
      ObjectSetInteger(NULL,"range end",OBJPROP_COLOR,clrPlum);
      ObjectSetInteger(NULL,"range end",OBJPROP_WIDTH,2);
      ObjectSetInteger(NULL,"range end",OBJPROP_BACK,true);
   }
   
   // close time
   ObjectDelete(NULL,"range close");
   if(range.close_time>0){
      ObjectCreate(NULL,"range close",OBJ_VLINE,0,range.close_time,0);
      ObjectSetString(NULL,"range close",OBJPROP_TOOLTIP,"close of the range \n"+TimeToString(range.close_time,TIME_DATE|TIME_MINUTES));
      ObjectSetInteger(NULL,"range close",OBJPROP_COLOR,clrPlum);
      ObjectSetInteger(NULL,"range close",OBJPROP_WIDTH,2);
      ObjectSetInteger(NULL,"range close",OBJPROP_BACK,true);
   }
      
   // high
   ObjectsDeleteAll(NULL,"range high");
   if(range.high>0){
      ObjectCreate(NULL,"range high",OBJ_TREND,0,range.start_time,range.high,range.end_time,range.high);
      ObjectSetString(NULL,"range high",OBJPROP_TOOLTIP,"high of the range \n"+DoubleToString(range.high,_Digits));
      ObjectSetInteger(NULL,"range high",OBJPROP_COLOR,clrPlum);
      ObjectSetInteger(NULL,"range high",OBJPROP_WIDTH,2);
      ObjectSetInteger(NULL,"range high",OBJPROP_BACK,true);

      ObjectCreate(NULL,"range high ",OBJ_TREND,0,range.end_time,range.high,InpRangeClose>=0 ? range.close_time : INT_MAX,range.high);
      ObjectSetString(NULL,"range high ",OBJPROP_TOOLTIP,"high of the range \n"+DoubleToString(range.high,_Digits));
      ObjectSetInteger(NULL,"range high ",OBJPROP_COLOR,clrPlum);
      ObjectSetInteger(NULL,"range high ",OBJPROP_BACK,true);
      ObjectSetInteger(NULL,"range high ",OBJPROP_STYLE,STYLE_DOT);
   }
   
   // low
   ObjectsDeleteAll(NULL,"range low");
   if(range.low<DBL_MAX){
      ObjectCreate(NULL,"range low",OBJ_TREND,0,range.start_time,range.low,range.end_time,range.low);
      ObjectSetString(NULL,"range low",OBJPROP_TOOLTIP,"low of the range \n"+DoubleToString(range.low,_Digits));
      ObjectSetInteger(NULL,"range low",OBJPROP_COLOR,clrPlum);
      ObjectSetInteger(NULL,"range low",OBJPROP_WIDTH,2);
      ObjectSetInteger(NULL,"range low",OBJPROP_BACK,true);
      
      ObjectCreate(NULL,"range low ",OBJ_TREND,0,range.end_time,range.low,InpRangeClose>=0 ? range.close_time : INT_MAX,range.low);
      ObjectSetString(NULL,"range low ",OBJPROP_TOOLTIP,"low of the range \n"+DoubleToString(range.low,_Digits));
      ObjectSetInteger(NULL,"range low ",OBJPROP_COLOR,clrPlum);
      ObjectSetInteger(NULL,"range low ",OBJPROP_BACK,true);
      ObjectSetInteger(NULL,"range low ",OBJPROP_STYLE,STYLE_DOT);
   }

   // refresh chart
   ChartRedraw();
}
[Deleted]  
Your topic has been moved to the section: Expert Advisors and Automated Trading
Please consider which section is most appropriate — https://www.mql5.com/en/forum/172166/page6#comment_49114893