OrderCalcMargin() always returns true and margin 0 - page 3

 
amrali #:

Can you make short sell orders manually through GUI? I suspect that short-selling may be disabled for that symbol.

Please check the symbol specifications dialog:

 

I am not using fancy symbols. For the test I used EURUSD. All types of orders are allowed for that.

 

You can calculate the margin required using a custom function:

#include "Functions.mqh"   // https://www.mql5.com/en/code/28029

//+------------------------------------------------------------------+
//| Calculate the required margin for the trade operation planned.   |
//| The OrderCalcMargin() function is prohibited in indicators.      |
//+------------------------------------------------------------------+
bool  OrderCalcMarginCustom(
   ENUM_ORDER_TYPE       action,           // type of order
   string                symbol,           // symbol name
   double                volume,           // volume
   double                price,            // open price
   double&               margin            // variable for obtaining the margin value
)
  {
//--- https://www.metatrader5.com/en/terminal/help/trading_advanced/margin_forex
//--- https://www.mql5.com/en/docs/constants/environment_state/marketinfoconstants#enum_symbol_calc_mode
   double initial_margin_rate=0.0;
   double maintenance_margin_rate=0.0;
   if(SymbolInfoMarginRate(symbol, (ENUM_ORDER_TYPE)action, initial_margin_rate, maintenance_margin_rate))
     {
      double initial_margin=0.0;
      if(!SymbolInfoDouble(symbol, SYMBOL_MARGIN_INITIAL, initial_margin))
         return false;

      long CalcMode=-1;
      if(!SymbolInfoInteger(symbol, SYMBOL_TRADE_CALC_MODE, CalcMode))
         return false;

      //--- fixed margin is specified
      if(initial_margin > 0.0)
        {
         switch((ENUM_SYMBOL_CALC_MODE) CalcMode)
           {
            case SYMBOL_CALC_MODE_FOREX:
            case SYMBOL_CALC_MODE_CFDLEVERAGE:
               margin = (volume * initial_margin * initial_margin_rate / AccountInfoInteger(ACCOUNT_LEVERAGE)); //in margin currency
               break;

            default:
               margin = (volume * initial_margin * initial_margin_rate); //in margin currency
               break;
           }
        }
      else
        {
         switch((ENUM_SYMBOL_CALC_MODE) CalcMode)
           {
            case SYMBOL_CALC_MODE_FOREX:
              {
               const double contract_size = SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE);
               margin = (volume * contract_size * initial_margin_rate / AccountInfoInteger(ACCOUNT_LEVERAGE)); //in margin currency
              }
            break;

            case SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE:
              {
               const double contract_size = SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE);
               margin = (volume * contract_size * initial_margin_rate); //in margin currency
              }
            break;

            case SYMBOL_CALC_MODE_CFD:
              {
               const double contract_size = SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE);
               margin = (volume * contract_size * price * initial_margin_rate); //in margin currency
              }
            break;

            case SYMBOL_CALC_MODE_CFDLEVERAGE:
              {
               const double contract_size = SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE);
               margin = (volume * contract_size * price * initial_margin_rate / AccountInfoInteger(ACCOUNT_LEVERAGE)); //in margin currency
              }
            break;

            case SYMBOL_CALC_MODE_CFDINDEX:
              {
               const double contract_size = SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE);
               //const double TickPrice = SymbolInfoDouble(symbol, (action == ORDER_TYPE_BUY) ? SYMBOL_TRADE_TICK_VALUE_LOSS : SYMBOL_TRADE_TICK_VALUE_PROFIT);
               const double TickPrice = mTickValue(symbol,(bool)action); // fix for non-forex symbols
               const double TickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
               margin = (volume * contract_size * price * TickPrice / TickSize * initial_margin_rate); //in margin currency
              }
            break;

            // not implemented.
            default:
               return false;
           }
        }
      //--- converting into deposit currency (common step for all calculation types)
      const string MarginCurrency = SymbolInfoString(symbol, SYMBOL_CURRENCY_MARGIN);
      const string AccountCurrency = AccountInfoString(ACCOUNT_CURRENCY);
      if(MarginCurrency != AccountCurrency)
        {
         const double CrossRate = GetExchangeRate(MarginCurrency, AccountCurrency, action);
         margin *= CrossRate; //in account currency
        }
      //---
      margin = NormalizeDouble(margin, (int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS));
      return true;
     }
//---
   else
      return false;
  }

To calculate margin for the affected symbol:

void OnStart()
  {
   double margin=0.0;
   double margin_custom=0.0;

   if(OrderCalcMargin(ORDER_TYPE_SELL, Symbol(), 1.0, SymbolInfoDouble(Symbol(),SYMBOL_BID), margin))
      Print("margin = ", margin);

   if(OrderCalcMarginCustom(ORDER_TYPE_SELL, Symbol(), 1.0, SymbolInfoDouble(Symbol(),SYMBOL_BID), margin_custom))
      Print("margin_custom = ", margin_custom);
  }
 
amrali #:

You can calculate the margin required using a custom function:

To calculate margin for the affected symbol:

  Thanks man. But i'd prefer to negotiate the bugfix than to workaround core components. Functions affected by this bug are cascading and ruining a lot of things including test results calculations, balance calculations, etc etc.

 

This bug reappeared in the latest update I got  (MT5, version 5.00 build 4270, 5 Apr 2024). I get reqMargin=0.

   PRINTVAR5(ordType,g_symbolName,short_lot,atprice,reqMargin);
   bool marginCheck=OrderCalcMargin(ordType,g_symbolName,short_lot,atprice,reqMargin);
   PRINTVAR5(ordType,g_symbolName,short_lot,atprice,reqMargin);

the output, before and after calling OrderCalcMargin, is (ordType is a ENUM_ORDER_TYPE variable):


ordType = 1, g_symbolName = GBPUSD, short_lot = 6.63, atprice = 1.24438, reqMargin = 0.0

ordType = 1, g_symbolName = GBPUSD, short_lot = 6.63, atprice = 1.24438, reqMargin = 0.0


and the boolean marginCheck is true.