MT5 integration with Python, function: order_calc_margin() get error!!!!

 

import MetaTrader5 as mt5

mt5.order_calc_margin(mt5.ORDER_TYPE_BUY,"AUDCAD",1,1) #761.96

mt5.order_calc_margin(mt5.ORDER_TYPE_BUY,"AUDCAD",1,2) #761.96

mt5.order_calc_margin(mt5.ORDER_TYPE_BUY,"AUDCAD",1,3) #761.96


I tested the cross currency exchange, different price but the result is same!

Please fix this bug as soon as possible, otherwise cross currency exchange cannot be used!

 
Margin requirements change with price?

Well, I thought margin requirement is bound to volume.

Please elaborate... I would like to understand.
 
Dominik Egert:
Margin requirements change with price?

Well, I thought margin requirement is bound to volume.

Please elaborate... I would like to understand.
Margin requirements change with price and volume. You can test it on EURUSD.
 

Maybe this helps your issue.

I had similar issues. 

you will need to replace some things to fit your needs. ie: LIB_USER_INPUT(CustomSymbol)



        /*
        *********************************************************************************************************
        *  Margin calculator                                                                                                                                                                    *
        *********************************************************************************************************
        */

        const double mm_calc_margin_required(const double _vol = NULL, const bool bShort = false)
        {
                // Local init

                        const string    account_currency        = AccountInfoString(ACCOUNT_CURRENCY);
                        const string    margin_currency         = SymbolInfoString(LIB_USER_INPUT(CustomSymbol), SYMBOL_CURRENCY_MARGIN);
                        const string    profit_currency         = SymbolInfoString(LIB_USER_INPUT(CustomSymbol), SYMBOL_CURRENCY_PROFIT);
                        const double    vol_size                        = SymbolInfoDouble(LIB_USER_INPUT(CustomSymbol), SYMBOL_TRADE_CONTRACT_SIZE) * MathRange(_vol, SymbolInfoDouble(LIB_USER_INPUT(CustomSymbol), SYMBOL_VOLUME_MIN), SymbolInfoDouble(LIB_USER_INPUT(CustomSymbol), SYMBOL_VOLUME_MAX));
                        bool                    rev_quote                       = (profit_currency == account_currency);
                        double                  calc_price                      = NULL;
                        double                  margin_required         = NULL;
                        string                  calc_currency           = NULL;

                        MqlTick tick = {0};
                        ZeroMemory(tick);


                // Profit currency equals account currency

                        if(profit_currency == account_currency)
                        { calc_currency = LIB_USER_INPUT(CustomSymbol); }


                // Margin currency equals account currency

                        if(margin_currency == account_currency)
                        {
                                // Calculation currency
                                calc_currency = LIB_USER_INPUT(CustomSymbol);

                                // Just return the contract value, multiplied by the number of lots
                                return(mm_calc_margin_mode(vol_size));
                        }


                // Cross currency pair
                // Find calculation currency

                        if( (StringLen(calc_currency) < 2)
                         && (!mm_calc_margin_currency(margin_currency, account_currency, calc_currency, rev_quote)))
                        {
                                err_SetUserError(MM_ERR_CURRENCY_NOTFOUND);
                                return(NULL);
                        }


                // Quote of last calculation currency

                        SymbolInfoTick(calc_currency, tick);


                // Evaluate price value

                        calc_price      = (tick.ask      * inline_BooleanDouble(bShort && rev_quote))
                                                        + ((1.0 / tick.bid) * inline_BooleanDouble(bShort && !rev_quote))
                                                        + (tick.bid * inline_BooleanDouble(!bShort && rev_quote))
                                                        + ((1.0 / tick.ask) * inline_BooleanDouble(!bShort && !rev_quote));


                // Calculate required margin

                        margin_required = mm_calc_margin_mode(vol_size, bShort) * calc_price;

                        if(margin_required > NULL)
                        { err_SetUserError(MM_SUCCESS); }
                        else
                        { err_SetUserError(MM_ERR_MARGIN_REQUIREMENT); }


                // Return
                return(margin_required);
        }


        const double mm_calc_margin_mode(const double vol_size, const bool bShort = false)
        {
                // Local init

                        const int               account_leverage        = (int)AccountInfoInteger(ACCOUNT_LEVERAGE);
                        const double    _price                          = (bShort) ? SymbolInfoDouble(LIB_USER_INPUT(CustomSymbol), SYMBOL_BID) : SymbolInfoDouble(LIB_USER_INPUT(CustomSymbol), SYMBOL_ASK);
                        double                  margin_rate                     = NULL;
                        double                  maintenance_rate        = NULL;

                        if(!SymbolInfoMarginRate(LIB_USER_INPUT(CustomSymbol), ((bShort) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY), margin_rate, maintenance_rate) && OnError("MARGIN_RATE"))
                        { return(NULL); }


                // Select calculation type

                        switch((ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(LIB_USER_INPUT(CustomSymbol), SYMBOL_TRADE_CALC_MODE))
                        {
                                case SYMBOL_CALC_MODE_FOREX:                                    return((vol_size / account_leverage) * margin_rate);
                                case SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE:                return(vol_size * margin_rate);
                                case SYMBOL_CALC_MODE_CFD:                                              return(vol_size * _price * margin_rate);
                                case SYMBOL_CALC_MODE_CFDINDEX:                                 return((vol_size * _price) * (SymbolInfoDouble(LIB_USER_INPUT(CustomSymbol), SYMBOL_POINT) / SymbolInfoDouble(LIB_USER_INPUT(CustomSymbol), SYMBOL_TRADE_TICK_SIZE)) * margin_rate);
                                case SYMBOL_CALC_MODE_CFDLEVERAGE:                              return((vol_size * _price) / (account_leverage * margin_rate));
                                case SYMBOL_CALC_MODE_EXCH_STOCKS:                              return(vol_size * _price * margin_rate);

                                // Not implemented
                                case SYMBOL_CALC_MODE_FUTURES:
                                case SYMBOL_CALC_MODE_EXCH_FUTURES:
                                case SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS:
                                case SYMBOL_CALC_MODE_EXCH_BONDS:
                                case SYMBOL_CALC_MODE_EXCH_STOCKS_MOEX:
                                case SYMBOL_CALC_MODE_EXCH_BONDS_MOEX:
                                case SYMBOL_CALC_MODE_SERV_COLLATERAL:
                                        break;
                        }

                // Return error
                return(NULL);
        }


        const bool mm_calc_margin_currency(const string margin_currency, const string profit_currency, string& calculation_currency, bool& rev_quote)
        {
                // Local init

                        bool    custom_symbol   = false;
                        string  symbolname              = NULL;
                        string  m_cur                   = NULL;
                        string  p_cur                   = NULL;


                // Initially try guess a symbol

                        if( (SymbolExist(margin_currency + profit_currency, custom_symbol))
                         && (!custom_symbol))
                        { calculation_currency = margin_currency + profit_currency; rev_quote = true; return(true); }

                        if( (SymbolExist(profit_currency + margin_currency, custom_symbol))
                         && (!custom_symbol))
                        { calculation_currency = profit_currency + margin_currency; rev_quote = false; return(true); }


                // Search all available symbols for a match

                        for(int cnt = 0; (cnt < SymbolsTotal(false)) && !IsStopped(); cnt++)
                        {
                                // Get symbol name
                                symbolname = SymbolName(cnt, false);

                                // Get margin currency
                                m_cur = SymbolInfoString(symbolname, SYMBOL_CURRENCY_MARGIN);

                                // Get profit currency (profit on price change)
                                p_cur = SymbolInfoString(symbolname, SYMBOL_CURRENCY_PROFIT);

                                // Check if found
                                if(      ( (m_cur == margin_currency)
                                        && (p_cur == profit_currency))
                                 ||      ( (p_cur == margin_currency)
                                        && (m_cur == profit_currency)) )
                                 {
                                        calculation_currency = symbolname;
                                        if(SymbolExist(calculation_currency, custom_symbol) && (!custom_symbol))
                                        {
                                                rev_quote = (m_cur == margin_currency);
                                                return(true);
                                        }
                                 }
                        }


                // Return failure
                return(false);
        }

Reason: