Calculate the Margin

 

Hi,


I'm trying to determinate how many margin I need to open 1 lot of a cross.

For example, I want to open 1 lot of EURUSD. I would like to know the margin I need to open this lot.


It seems easy but it's not the case for me...


Here are the possibilities:


1. Margin = MarketInfo("EURUSD", MODE_MARGINREQUIRED);

But does it count the Margin needed for the 2 spreads (for opening and closing the order) ?

OR

2. Margin = MarketInfo("EURUSD", MODE_MARGINREQUIRED) + (2 * Spread * MarginNeedForTheSpread)


Moreover for what is used MODE_MARGININIT? What is the initial margin?


Thanks!

 

For margin requirements there are two types of crosses...and it comes down to determining how the base currency of the cross-pair is related to the account's denomination.

For what its worth, the post I made here contains a rar file which has code in it that correctly computes the required margin.

Look inside the "Analyze Currency Symbol 2010.06.07.mqh" file, the AnalyzeSymbol() function contains a stretch of code that determines margin:

   switch(CalculatedSymbolType) // Determine the margin required to open 1 lot position for the financial instrument based on the instrument's SymbolType (major, cross, etc)
      {
      case 1   :  CalculatedMarginRequiredLong=NormalizeDouble(MarketInfo(CurrentSymbol,MODE_LOTSIZE)/CalculatedLeverage,2);
                  Print("Calculated MARGINREQUIRED = ",CalculatedMarginRequiredLong," (Free margin required to open 1 lot for buying)");
                  Print("Calculated Leverage = ",CalculatedLeverage,":1 for this specific financial instrument (",CurrentSymbol,")"); break;
      case 2   :  CalculatedMarginRequiredLong=NormalizeDouble(MarketInfo(CurrentSymbol,MODE_ASK)*MarketInfo(CurrentSymbol,MODE_LOTSIZE)/CalculatedLeverage,2);
                  CalculatedMarginRequiredShort=NormalizeDouble(MarketInfo(CurrentSymbol,MODE_BID)*MarketInfo(CurrentSymbol,MODE_LOTSIZE)/CalculatedLeverage,2);
                  Print("Calculated MARGINREQUIRED = ",CalculatedMarginRequiredLong," for Buy (free margin required to open 1 lot position as long), and Calculated MARGINREQUIRED = ",CalculatedMarginRequiredShort," for Sell (free margin required to open 1 lot position as short)");
                  Print("Calculated Leverage = ",CalculatedLeverage,":1 for this specific financial instrument (",CurrentSymbol,")"); break;
      case 3   :  CalculatedMarginRequiredLong=NormalizeDouble(2*MarketInfo(CurrentSymbol,MODE_LOTSIZE)/((MarketInfo(CalculatedBasePairForCross,MODE_BID)+MarketInfo(CalculatedBasePairForCross,MODE_ASK))*CalculatedLeverage),2);
                  Print("Calculated MARGINREQUIRED = ",CalculatedMarginRequiredLong," (Free margin required to open 1 lot for buying)");
                  Print("Calculated Leverage = ",CalculatedLeverage,":1 for this specific financial instrument (",CurrentSymbol,")"); break;
      case 4   :  CalculatedMarginRequiredLong=NormalizeDouble(MarketInfo(CurrentSymbol,MODE_LOTSIZE)*(MarketInfo(CalculatedBasePairForCross,MODE_BID)+MarketInfo(CalculatedBasePairForCross,MODE_ASK))/(2*CalculatedLeverage),2);
                  Print("Calculated MARGINREQUIRED = ",CalculatedMarginRequiredLong," (Free margin required to open 1 lot for buying)");
                  Print("Calculated Leverage = ",CalculatedLeverage,":1 for this specific financial instrument (",CurrentSymbol,")"); break;
      case 5   :  CalculatedMarginRequiredLong=NormalizeDouble(MarketInfo(CurrentSymbol,MODE_LOTSIZE)*(MarketInfo(CalculatedBasePairForCross,MODE_BID)+MarketInfo(CalculatedBasePairForCross,MODE_ASK))/(2*CalculatedLeverage),2);
                  Print("Calculated MARGINREQUIRED = ",CalculatedMarginRequiredLong," (Free margin required to open 1 lot for buying)");
                  Print("Calculated Leverage = ",CalculatedLeverage,":1 for this specific financial instrument (",CurrentSymbol,")"); break;
      default  :  Print("Error encountered in the SWITCH routine for calculating required margin for financial instrument ",CurrentSymbol); // The expression did not generate a case value
      }
Now some brokers, IBFX is one, just use manually set values for margin requirements regardless how the "margin, price, leverage" would have determined margin required (basically they let the actual leverage float). So for example for a given cross the computed margin required might be $453.42 but IBFX will just hard-code the margin as $500 per lot, etc.
 

Thanks 1005philip for your great answer.


However I do not understand why you do not use the MarketInfo(Symbol, MODE_MARGINREQUIRED)?

It should return the margin in the account currency? No?

Isn't that function done for that?

 

Another question, why don't you calculate the spreads needed for the order?

Btw does MODE_MARGINREQUIRED includes the spreads margin needed?

 

When margin requirements depend on the market price of a currency pair then you really ought to calculate margin based on the trade direction of the position. Short postion will have a different margin required versus a long position.

The difference will be a matter of pennies because the difference is merely a matter of the spread, but for people who like to have analytically robust and complete algorithms for making these computations it matters.

For currency pairs that involve the account's denomination, for example EURUSD when the account is USD based, it is straightforward to calculate the margin based on position direction. That is what this code does:

case 2   :  CalculatedMarginRequiredLong=NormalizeDouble(MarketInfo(CurrentSymbol,MODE_ASK)*MarketInfo(CurrentSymbol,MODE_LOTSIZE)/CalculatedLeverage,2);
            CalculatedMarginRequiredShort=NormalizeDouble(MarketInfo(CurrentSymbol,MODE_BID)*MarketInfo(CurrentSymbol,MODE_LOTSIZE)/CalculatedLeverage,2);
            Print("Calculated MARGINREQUIRED = ",CalculatedMarginRequiredLong," for Buy (free margin required to open 1 lot position as long), and Calculated MARGINREQUIRED = ",CalculatedMarginRequiredShort," for Sell (free margin required to open 1 lot position as short)");
            Print("Calculated Leverage = ",CalculatedLeverage,":1 for this specific financial instrument (",CurrentSymbol,")"); break;
If your trade direction is a long then you'd use the Ask price in your margin calculation. If you are trading a short then you'd use the bid. (only in this example, EURUSD with USD-based account)

For cross-currency pairs the spread is accounted for by averaging the bid and ask prices. Take note of the use of both bid and ask prices in this case:
case 4   :  CalculatedMarginRequiredLong=NormalizeDouble(MarketInfo(CurrentSymbol,MODE_LOTSIZE)*(MarketInfo(CalculatedBasePairForCross,MODE_BID)+MarketInfo(CalculatedBasePairForCross,MODE_ASK))/(2*CalculatedLeverage),2);
            Print("Calculated MARGINREQUIRED = ",CalculatedMarginRequiredLong," (Free margin required to open 1 lot for buying)");
            Print("Calculated Leverage = ",CalculatedLeverage,":1 for this specific financial instrument (",CurrentSymbol,")"); break;

In the case of these cross-currency pairs it turns out the brokers don't require you to deal with trade direction for purposes of margin calculation, they implement an average price based on the mid-point of the spread and they go with that.

The reason I don't use the MODE_MARGINREQUIRED is because many of the marketinfo values are valid only for long-positions and are not correct if you take a position in the opposite direction.

They are "close enough" for most folks, the difference is just a matters of pennies, but in my case I wanted to know exactly what the values were and exactly how they are computed...once I finished that journey there was really no reason for me to not take advantage of the fruits of my labor. For other people the journey just isn't worth the time/effort to them, so they use MODE_MARGINREQUIRED and are content with it.

 

A big thanks for your time and a big thanks for your answer!

 

A big thank you - Mr. JanClaudus and Mr. Phillip.

Mr. Phillip, your program is very helpful for my EA. Thanks again.

Mr. Janclaudus, did your EA complete? and does it give you profit?

 
EAPro:

Mr. Phillip, your program is very helpful for my EA. Thanks again.


Thanks for letting me know! Happy to hear it helped you :)
 
I also use AccountFreeMarginCheck():
    double  maxLossPerLot   = SLpoints * PointValuePerLot(),
    /* Number of lots wanted = at.risk / maxLossPerLot rounded/truncated to
     * nearest lotStep size.
     *
     * However, the broker doesn't care about the at.risk/account balance. They
     * care about margin. Margin used=lots used*marginPerLot and that must be
     * less than free margin available. */
            marginFree      = AccountFreeMargin(),//*0.95, // Allow some slack
            marginPerLot    = MarketInfo( Symbol(), MODE_MARGINREQUIRED ),
    // So I use, the lesser of either.
            size = MathMin(marginFree / marginPerLot, at.risk / maxLossPerLot),
            minLot  = MarketInfo(Symbol(), MODE_MINLOT),
            LotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
    /*---- Compute lot size based on account balance and MM mode*/}
    double  adjFact = IfD(MathMin(1, TEF.value), 1, TEF.Enable01);
    while (true){   // Adjust for broker, test for margin, combine with TEF
        size =  MathFloor(size/LotStep)*LotStep;
        if (size < minLot){ // Insufficient margin.
            Print(
            "LotSize(SL=", DoubleToStr(SLpoints/pips2dbl, Digits.pips), ")=",
            size, " [risk=", at.risk, AccountCurrency(),    "/", maxLossPerLot,
                    ", margin=",    marginFree,             "/", marginPerLot,
                    ", MMM=",       Money.Management.F0M1G2,"x",
                    Money.Management.Multiplier,
                    ", ExtraOO=",   OrdersTotal(),
                "]" );
            size=0; break;  }
        /* size<minLot should be sufficient, but the tester was generating error
         * 134 even when marginFree should have been OK. So I also use
         * AccountFreeMarginCheck which aggrees with the tester.
         * https://www.mql5.com/en/forum/128506 */
        double AFMC = AccountFreeMarginCheck(Symbol(), op.code, size);
        /**/ if (AFMC < 0)      size *= 0.95;
        else if (adjFact < 1){  size  = MathMax(minLot,size*adjFact);adjFact=1;}
        else break; // We're good to go.
    }
Reason: