Find the maximum number of lots that can be opened

 

I am making a EA that will run on accounts with low leverage. To avoid runtime errors, I am trying to find the maximum number of lots that can be opened given the available free margin.

Here's my attempt at the calculation.

double marginRequired;
double freeMargin;
double maxOpenLots;

void OnInit()
{
   string symbol = "EURUSD";
   double ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
   
   // margin required to open one lot
   marginRequired=EMPTY_VALUE;
   OrderCalcMargin(ORDER_TYPE_BUY, symbol, 1, ask, marginRequired);
   
   // free margin available in account
   freeMargin = AccountInfoDouble(ACCOUNT_MARGIN_FREE);
   
   // find the maximum number of lots that can be opened
   maxOpenLots = NormalizeDouble(freeMargin/marginRequired,2);
   
}

void OnTick()
{
  Comment("Account equity is: ", AccountInfoDouble(ACCOUNT_EQUITY), 
  "\nAccount leverage is: ", AccountInfoInteger(ACCOUNT_LEVERAGE),
  "\nMargin required to open a lot: ", marginRequired, 
  "\nNumber of lots that can be opened: ", maxOpenLots); 
}

I attached this EA to a MetaQuotes-Demo account with equity USD 12,000 and leverage 100:1. There were no open trades in the account.

According to the calculation, I can open 11 lots of EURUSD. However, when I tried placing an order for 11 lots, a "no money" error returned (see attachment). The actual number of lots I can open is 6.

I tried an online forex margin calculator. The margin required for opening 11 lots of EURUSD with leverage 100:1 is USD 11,953.

My questions are: why can I open 6 lots only, and how can I modify my code to arrive at this number?

Thank you in advance.

Files:
max_lots.png  96 kb
 

it's more easy to get the max lots when you use the SymbolInfo library


 #include <Trade/SymbolInfo.mqh>

CSymbolInfo m_symbol;   

double MaxLotsPermitted(){

   // calculate maximum volume
   m_symbol.Name(Symbol());
   double maxvol = m_symbol.LotsMax();
   
   return maxvol;
}
 

Hi

You should iclude also levarege of your account. Try something like this:

     double marginRequired=EMPTY_VALUE;
   OrderCalcMargin(ORDER_TYPE_BUY, Symbol(), 1,  SymbolInfoDouble(Symbol(), SYMBOL_ASK), marginRequired);
   lot =(MathRound((AccountInfoDouble(ACCOUNT_MARGIN_FREE))/(marginRequired*SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP)))*SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_STEP))*(AccountInfoInteger(ACCOUNT_LEVERAGE)/100);
Best Regards

 
Marzena Maria Szmit #:

Hi

You should iclude also levarege of your account. Try something like this:

Best Regards

Appreciate the code snippet. I tried running it and also returns 11 lots.

I studied the problem further. I believe in MetaQuotes-demo, margin required is not a linear function of lot size. The margin requirement for 6 lots is greater than 6 times the margin requirement for 1 lot.

Thanks both for your input.

 
It will depend on what type of asset you're trading. The initial margin required is known to be 100000 on forex currency pairs. This is a different value for indices markets and commodities because they are traded on a different exchange
 
bool CheckMoneyForTrade(string symb,double lots,ENUM_ORDER_TYPE type)
  {
//--- Getting the opening price
   MqlTick mqltick;
   SymbolInfoTick(symb,mqltick);
   double price=mqltick.ask;
   if(type==ORDER_TYPE_SELL)
      price=mqltick.bid;
//--- values of the required and free margin
   double margin,free_margin=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
   //--- call of the checking function
   if(!OrderCalcMargin(type,symb,lots,price,margin))
     {
      //--- something went wrong, report and return false
      Print("Error in ",__FUNCTION__," code=",GetLastError());
      return(false);
     }
   //--- if there are insufficient funds to perform the operation
   if(margin>free_margin)
     {
      //--- report the error and return false
      Print("Not enough money for ",EnumToString(type)," ",lots," ",symb," Error code=",GetLastError());
      return(false);
     }
//--- checking successful
   return(true);
  }

Check the link.

The checks a trading robot must pass before publication in the Market
The checks a trading robot must pass before publication in the Market
  • www.mql5.com
Before any product is published in the Market, it must undergo compulsory preliminary checks in order to ensure a uniform quality standard. This article considers the most frequent errors made by developers in their technical indicators and trading robots. An also shows how to self-test a product before sending it to the Market.
 

this is how I do it nowadays

#include <Trade/SymbolInfo.mqh>
CSymbolInfo m_symbol;   


double VolCalc(double riskPercentage){

    m_symbol.Name(Symbol());
    double lotSizeMin = m_symbol.LotsMin();
    double lotSizeMax = m_symbol.LotsMax();
    double lotStep = m_symbol.LotsStep();
     
    double currentEquity = AccountInfoDouble(ACCOUNT_EQUITY);
    double marginRequired = SymbolInfoDouble(Symbol(), SYMBOL_MARGIN_INITIAL);
    long currentLeverage = AccountInfoInteger(ACCOUNT_LEVERAGE);

    double maxLoss = riskPercentage / 100.0 * currentEquity; 
    double lotSize = maxLoss / (marginRequired / currentLeverage);   
    
   // Ensure lot size is within allowed limits
   if (lotSize < lotSizeMin) lotSize = lotSizeMin;
   if (lotSize > lotSizeMax) lotSize = lotSizeMax;
   
   lotSize = MathFloor(lotSize / lotStep) * lotStep;  
   
   if(marginRequired == 0.0){
      Print("The margin required could not be retrieved for " + Symbol() + " on this broker");
      lotSize = trade_volume;
   }
   
   return lotSize;
}