Error OrderSend 4051

 

Hi guys!

Here is the simple EA. When I am trying to test the strategy it gives me an error OrderSend 4051, however my OrderVolume is normalized. Can you help me to find what is wrong? 

extern int SingleOrderRisk = 10; // in percents
extern int PeriodMA1 = 5; // period of the first MA
extern int PeriodMA2 = 7; // period of the second MA
extern int StopLoss = 100;
extern int TakeProfit = 100;
double OrderVolume = 1; // in lots
double OrdersArrayOld[50][8];
double OrdersArrayNew[50][8];
double OrdersType[2];
// -------------------------------------------------------------------------------
int start() // Main Function                                  
   {
     int signal = 0;
     Terminal();
     signal = TradeCriteria();
     OrderVolumeCalc();
     if (signal==11)
      OpenOrder(0);
     if (signal==10)
      CloseAllOrders(0);
     return;                          
   }
   
// Function for calculating order volume using user defined percentage without credit margin
bool OrderVolumeCalc() 
   {
    string Symb = Symbol();
    double One_Lot = MarketInfo(Symb,MODE_MARGINREQUIRED);
    double Min_Lot = MarketInfo(Symb,MODE_MINLOT);
    double Step = MarketInfo(Symb,MODE_LOTSTEP);
    double Free = AccountFreeMargin();
    if (SingleOrderRisk > 100)
      SingleOrderRisk = 100;
    if (SingleOrderRisk == 0)
      OrderVolume = Min_Lot;
    else 
      OrderVolume = NormalizeDouble((Free*SingleOrderRisk/100/One_Lot/Step)*Step,1);
    if (OrderVolume < Min_Lot)
      {
      Alert ("Insufficient funds!");
      return(false);
      }
    else
      return(true);
    }

// Function for checking trading criteria
int TradeCriteria()
   {
    if (Ask>iMA(NULL,0,PeriodMA1,0,MODE_SMA,PRICE_CLOSE,0)) 
    {
      return(11);
    }
    if (Bid<iMA(NULL,0,PeriodMA2,0,MODE_SMA,PRICE_CLOSE,0))   
    {
      return(10);
    }
    else return(0);
    }

// Orders accounting

int Terminal()
   {
   int Qnt = 0; //Quantity of orders
   ArrayCopy(OrdersArrayOld,OrdersArrayNew);
   Qnt = 0;
   ArrayInitialize(OrdersArrayNew,0);
   ArrayInitialize(OrdersType,0);
   for (int i=0; i<OrdersTotal(); i++)
      {
      if((OrderSelect(i,SELECT_BY_POS)==true)&&(OrderSymbol()==Symbol()))
         {
         Qnt++;
         OrdersArrayNew[Qnt][1]=OrderOpenPrice();
         OrdersArrayNew[Qnt][2]=OrderStopLoss();
         OrdersArrayNew[Qnt][3]=OrderTakeProfit();
         OrdersArrayNew[Qnt][4]=OrderTicket();
         OrdersArrayNew[Qnt][5]=OrderLots();
         OrdersType[OrderType()]++;
         OrdersArrayNew[Qnt][6]=OrderType();
         OrdersArrayNew[Qnt][7]=OrderMagicNumber();
         }
      }
    OrdersArrayNew[0][0]=Qnt;
    return;
    }
    
int OpenOrder(int Type)
{
 int    Ticket,
        MagicNumber;
 double SL,
        TP;
 while(OrdersType[Type]==0)
   {
   MagicNumber = TimeCurrent();
   if (Type == 0)// Buy order
      {
      SL = Bid - StopLoss*Point;
      TP = Bid + StopLoss*Point;
      NormalizeDouble(OrderVolume,1);
      Ticket = OrderSend(Symbol(),0,OrderVolume,Ask,2,SL,TP,"",MagicNumber);
      }
   Terminal();
   }
}

int CloseAllOrders(int Type)
{
 int Ticket = 0;
 double Lot = 0;
 double ClosePrice;
 while(OrdersType[Type]>0)
   {
   for(int i = 1; i <= OrdersArrayNew[0][0]; i++)
      {
      if (OrdersArrayNew[i][6]==Type && OrdersArrayNew[i][5] > Lot)
         {
         Lot = OrdersArrayNew[i][5];
         Ticket = OrdersArrayNew[i][4];
         }   
      }
   if (Type==0)ClosePrice = Bid;
   if (Type==1)ClosePrice = Ask;
   OrderClose(Ticket,Lot,ClosePrice,2);
   Terminal();
   }
  return;
}
 
      OrderVolume = NormalizeDouble((Free*SingleOrderRisk/100/One_Lot/Step)*Step,1);

Why divide by Step and then multiply by Step?

What if Step is 0.25 ? If the calculation calculates 0.25, it will then be normalised to 0.3 - an invalid lot size.

 What if Step is 0.01 ? If the calculation calculates anything less than 0.05, it will then be normalised to 0.0 - an invalid lot size.

bool OrderVolumeCalc() 

 If this function returns false, you still carry on and try to use the calculated (too small) lot size

If the OrderSend fails, print out the lot size, that will help you to find your error 

 
Tarkunian: it gives me an error OrderSend 4051, however my OrderVolume is normalized.

Do NOT use NormalizeDouble, EVER. For ANY Reason. It's a kludge, don't use it. It's use is always wrong (as you just proved.)
Reason: