Serious bug in the OrderCalcProfit() function - page 3

 

Alain, let's make it clear:

1. In the example above both orders are in profit. If the naming was correct, then according to the documentation only SYMBOL_TRADE_TICK_VALUE_PROFIT should be used for both orders ( this is not the case here ).

2. Actually, all buy orders uses -> TV_LOSS, all sell use -> TV_PROFIT. (the order_type decides which tick value to use.)

3. No correlation between the tick_value names (TV_PROFIT/LOSS) and the price type (BID/ASK) of profit/account currency conversion rate, exactly as you mentioned in your comment.

4. the price type (BID/ASK) of the profit/account conversion pair depends to two things: (a) the type of the order (b) position of account currency in the pair (first or second).

https://www.mql5.com/en/code/viewcode/28029/267359/functions.mqh

//+------------------------------------------------------------------+
//| Returns the exchange rate for the "CCY1/CCY2" currency pair.     |
//+------------------------------------------------------------------+
double GetExchangeRate(string CCY1, string CCY2, ENUM_ORDER_TYPE OrderType)
  {
   string symbol = NULL;
//---
   if(CCY1 != CCY2)
     {
      //--- Try the direct rate
      symbol = GetSymbolByCurrencies(CCY1, CCY2);
      if(symbol != NULL)
        {
         if(OrderType == ORDER_TYPE_SELL)
            return SymbolInfoDouble(symbol, SYMBOL_BID);
         else
            return SymbolInfoDouble(symbol, SYMBOL_ASK);
        }
      //--- Try the indirect rate
      symbol = GetSymbolByCurrencies(CCY2, CCY1);
      if(symbol != NULL)
        {
         if(OrderType == ORDER_TYPE_SELL)
            return safeDiv(1.0, SymbolInfoDouble(symbol, SYMBOL_ASK));
         else
            return safeDiv(1.0, SymbolInfoDouble(symbol, SYMBOL_BID));
        }
      //--- Get the cross rate through US dollar
      return GetExchangeRate(CCY1, "USD", OrderType) * GetExchangeRate("USD", CCY2, OrderType);
     }
//---
   return (1.0);
  }


OrderCalcProfit() actually calculates profit like this:

   if(ordertype == ORDER_TYPE_BUY)  
       profit = lots * SYMBOL_TRADE_CONTRACT_SIZE * (price_close - price_open) * GetExchangeRate(ProfitCurrency, AccountCurrency, ORDER_TYPE_BUY);
       
   if(ordertype == ORDER_TYPE_SELL) 
       profit = lots * SYMBOL_TRADE_CONTRACT_SIZE * (price_open - price_close) * GetExchangeRate(ProfitCurrency, AccountCurrency, ORDER_TYPE_SELL);

Please refer to post #11 https://www.mql5.com/en/forum/439319#comment_45097701


Edit:

5. TICK_VALUE_XXX is a shortcut to avoid all of these calculations. (the value itself is calculated internally in the software as follows):

   if(ordertype == ORDER_TYPE_BUY)  
       SYMBOL_TRADE_TICK_VALUE_LOSS = 1.0 * SYMBOL_TRADE_CONTRACT_SIZE * SYMBOL_TRADE_TICK_SIZE * GetExchangeRate(ProfitCurrency, AccountCurrency, ORDER_TYPE_BUY);
       
   if(ordertype == ORDER_TYPE_SELL) 
       SYMBOL_TRADE_TICK_VALUE_PROFIT = 1.0 * SYMBOL_TRADE_CONTRACT_SIZE * SYMBOL_TRADE_TICK_SIZE * GetExchangeRate(ProfitCurrency, AccountCurrency, ORDER_TYPE_SELL);


6. So, you can calculate profit using a simple calculation like:

   if(ordertype == ORDER_TYPE_BUY)  
       profit = lots * (price_close - price_open) / SYMBOL_TRADE_TICK_SIZE * SYMBOL_TRADE_TICK_VALUE_LOSS;
       
   if(ordertype == ORDER_TYPE_SELL) 
       profit = lots * (price_open - price_close) / SYMBOL_TRADE_TICK_SIZE * SYMBOL_TRADE_TICK_VALUE_PROFIT;

Serious bug in the OrderCalcProfit() function - A serious bug in an important trading function in the platform’s platform
Serious bug in the OrderCalcProfit() function - A serious bug in an important trading function in the platform’s platform
  • 2023.01.07
  • www.mql5.com
And, for the order_type_sell orders, regardless profitable or not, it calculates with the value of symbol_trade_tick_value_profit. Yes, and it is not counter intuitive because as i mentioned in my post #1
 
amrali #:

Alain, let's make it clear:

1. In the example above both orders are in profit. If the naming was correct, then according to the documentation only SYMBOL_TRADE_TICK_VALUE_PROFIT should be used for both orders ( this is not the case here ).

Amrali, the naming is correct. Your topic is about OrderCalcProfit() bug, now you are saying there is no bug but the problem relies on SYMBOL_TRADE_TICK_VALUE_PROFIT and SYMBOL_TRADE_TICK_VALUE_LOSS. Make your mind !

2. Actually, all buy orders uses -> TV_LOSS, all sell use -> TV_PROFIT. (the order_type decides which tick value to use.)

3. No correlation between the tick_value names (TV_PROFIT/LOSS) and the price type (BID/ASK) of profit/account currency conversion rate, exactly as you mentioned in your comment.

4. the price type (BID/ASK) of the profit/account conversion pair depends to two things: (a) the type of the order (b) position of account currency in the pair (first or second).

Again, I have to repeat the type of the order (of the trade), is totally not linked to the conversion.

If you have open and close price of your course you need to know the order type to calculate if it's a profit or loss trade, but it has nothing to do with the conversion.

https://www.mql5.com/en/code/viewcode/28029/267359/functions.mqh


OrderCalcProfit() actually calculates profit like this:

Please refer to post #11 https://www.mql5.com/en/forum/439319#comment_45097701

Actually, I don't care about OrderCalcProfit(), most of the time, even if the calculation is correctly done, you can't know the final profit or loss before a trade is closed.

Edit:

5. TICK_VALUE_XXX is a shortcut to avoid all of these calculations. (the value itself is calculated internally in the software as follows):

Why are you restring the SYMBOL_TRADE_TICK_VALUE_LOSS calculation to BUY order ? and ...._PROFIT to SELL order ?

What for a BUY in profit and a SELL in loss ? You will end up with 2 different values for SYMBOL_TRADE_TICK_VALUE_LOSS and 2 values for SYMBOL_TRADE_TICK_VALUE_PROFIT ?

6. So, you can calculate profit using a simple calculation like:

Of course. When the trade is close. For symbols which need conversion SYMBOL_TRADE_TICK_VALUE_LOSS and SYMBOL_TRADE_TICK_VALUE_PROFIT are  changing with each new quotes for the symbol needed for the conversion.

Your function to get exchange (conversion) rate is incorrect (or rather very confusing).
 

A last time.

Your GetExchangeRate() is correct IF and only IF your using ORDER_TYPE_BUY for any loss (so if your trade is a BUY in loss AND if your trade is a SELL in loss). Because it's NOT related to the order type of the trade but to the LOSS.

And in the same way, your function is correct IF and only IF you are using ORDER_TYPE_SELL for any profit (so if your trade is a BUY in profit AND if your trade is a SELL in profit). Because it's NOT related to the trade order type but to the PROFIT.

So your function parameter is confusing, because your are mixing the original trade direction, and the direction to use considering if it was a profit or loss.

I will stop repeating things again and again, all is explained in my first post.

 
I have double checked the conversions myself, using trades made on a demo account, to calculate profits using the above methods at the exact moments of position closure. This is what the software is doing. (Either, you accept or do not accept this, it is your decision at the end). But, this is how things go on metatrader, and this is what is supposed to be.

If you have another point of view, please report it to the developers.

Compare profits (at position closure) using OrderCalcProfit(), my custom OrderCalcProfit2() and symbol's tick values or even the deal_profit field, to confirm how the calculations are made, then we can go further in discussion. I am not discussing my point of view here.

Edit:
I actually confirm it again, OrderCalcProfit() is correct, so, I would better have deleted the thread. The names of tick values should be TICK_VALUE_BUY and TICK_VALUE_SELL. It was a bad decision (as usual!) of the MT5 developers from the start. 
 
I hadn't considered some of the points made by Alain so I'll take a look at this again later this week when I have some free time and see if I can understand it better using his explanation. Thanks Amrali for letting me know about this thread!
 
Alain Verleyen #:

This is an old version of my function that I used to have, until I finally corrected it to match MT5 calculations , please check the updated one on the code base.

https://www.mql5.com/en/code/viewcode/28029/267359/functions.mqh

 
amrali #:
I have double checked the conversions myself, using trades made on a demo account, to calculate profits using the above methods at the exact moments of position closure. This is what the software is doing. (Either, you accept or do not accept this, it is your decision at the end). But, this is how things go on metatrader, and this is what is supposed to be.

If you have another point of view, please report it to the developers.

Compare profits (at position closure) using OrderCalcProfit(), my custom OrderCalcProfit2() and symbol's tick values or even the deal_profit field, to confirm how the calculations are made, then we can go further in discussion. I am not discussing my point of view here.

Edit:
I actually confirm it again, OrderCalcProfit() is correct, so, I would better have deleted the thread. The names of tick values should be TICK_VALUE_BUY and TICK_VALUE_SELL. It was a bad decision (as usual!) of the MT5 developers from the start. 

Ok, let's take a numerical example. For a trade I have on history.

Account EUR.

The EURAUD Bid/Ask at that time :

What would be your calculation ? If I follow your code, I am right to say it would be :

double profit = volume*contract*(close-open)*GetExchangeRate("AUD","EUR",BUY); /*Rate = 1/Bid */

                    = 0.07*100,000*(1.70407-1.75114)*(1/1.44725);

                    = -227.67 EUR

Is that correct from your point of view ?

 
 
amrali #:
@Alain Verleyen yes.

The problem is the profit/loss of this trade was -227.59 EUR.


So the real calculation was :

double profit = volume*contract*(close-open)*GetExchangeRate("AUD","EUR",BUY); /*Rate = 1/Ask*/

                    = 0.07*100,000*(1.70407-1.75114)*(1/1.44774);

                    = -227.59 EUR

This is a trade from a real account.

 

Ok, I see Ask price is used here. That's contrary to the tests I performed on OrderCalcProfit() and tick values.

Could you please check OrderCalcProfit() function and Tick values at the moment of position closure?

Edit:

I did not check the deal_profit field. I do not know if deal_profit == OrderCalcValue() == TICK_VALUE_xxx. I only checked the latter pair. If there is a mismatch, then both the function and tick_values are misleading.

Reason: