MQL4 - Unrealized Order profit calculation with conversion

 

I am trying to produce the same result as OrderProfit() method by calculating the trade profit manually, but the result is inconsistent (25.73  vs. 25.74) . Looking at the numbers it doesn't seem to be rounding issue (unless mt4 is somehow internaly using MathFloor() on the profit rounding or smth?).

This is really puzzling me, can anybody please observe and verify if i'm doing anything wrong?

 

    if(OrderSelect(96982038, SELECT_BY_TICKET)==true)
    {
     OrderPrint(); // #96982038 2021.08.04 14:22:17 buy 0.05 EURPLN 4.54456 0.00000 0.00000 4.56454 0.00 -2.41 25.73  0

     Print("order 96982038 open price is ", OrderOpenPrice());  // 4.54456
     Print("order 96982038 close price is ", OrderClosePrice()); // 4.56454  
     Print("order 96982038 profit is ", OrderProfit());  // 25.73
     Print("order 96982038 volume is ", NormalizeDouble(OrderLots(),2));  // =======> Outputs 25.73
      
     
     double symbolBid = MarketInfo("USDPLN",MODE_BID); // 3.88174
     //double symbolAsk = MarketInfo("USDPLN",MODE_ASK); // 3.89056
     //double spread = MarketInfo("USDPLN", MODE_SPREAD); // 882
     
     // USING BID FOR CONVERSION AS PER DOCS
     // "If the pair is found, conversion is performed by Bid price for Buy positions or Ask price - for Sell ones."
     double convRate = symbolBid;
     
     double contractSize = MarketInfo(Symbol(), MODE_LOTSIZE); // 100000
     double lotSize = OrderLots();  // 0.05
     double open = NormalizeDouble( (OrderOpenPrice()*lotSize*contractSize) ,5);
     double close = NormalizeDouble( (OrderClosePrice() * lotSize * contractSize) ,5);
     
     double rawProfit = close - open; 
 
     Print("MANUAL CALC === raw profit ", rawProfit);  //     99.90000000000146
     Print("MANUAL CALC === original conv rate ", convRate); // 3.88174
     Print("MANUAL CALC === inverted conv rate ",  1/convRate  ); // 0.2576164297454234
 
      /*
      === to get desired 25.73 result (25.725 - 25.73499999) as max available for rounding by 2 digits)
      === inverted rate has to be in range:
      === 0.25760761 <- 0.25750751  which translates to raw rate 3.88187294 -> 3.88338192  
      */

     Print("MANUAL CALC === converted profit ",  rawProfit * 1/convRate ); //  ===> Outputs 25.73588133156818
     Print("MANUAL CALC === converted profit ", NormalizeDouble(rawProfit * 1/convRate,2)); // =======> Outputs 25.74
     Print("MANUAL CALC === converted profit ", MathRound((rawProfit * 1/convRate)*100)/100); // =======> Outputs 25.74
     Print("MANUAL CALC === converted profit ", DoubleToStr(rawProfit * 1/convRate,2)); // =======> Outputs 25.74
    }
 
Why using the bid price ? It should be the ask.
 
Alain Verleyen:
Why using the bid price ? It should be the ask.

I'm pretty sure it's the BID price for conversion (it's a Buy position)

By using

MarketInfo("USDPLN",MODE_ASK);

the calculation yields profit value of  25.68


As per my notes from previous research:

- If the pair is found, conversion is performed by Bid price for Buy positions or Ask price - for Sell ones.
 

You buy at the Ask and sell at the Bid. Pending Buy Stop orders become market orders when hit and open at the Ask.

  1. Your buy order's TP/SL (or Sell Stop's/Sell Limit's entry) are triggered when the Bid / OrderClosePrice reaches it. Using Ask±n, makes your SL shorter and your TP longer, by the spread. Don't you want the specified amount used in either direction?

  2. Your sell order's TP/SL (or Buy Stop's/Buy Limit's entry) will be triggered when the Ask / OrderClosePrice reaches it. To trigger close to a specific Bid price, add the average spread.
              MODE_SPREAD (Paul) - MQL4 programming forum - Page 3 #25

  3. The charts show Bid prices only. Turn on the Ask line to see how big the spread is (Tools → Options (control+O) → charts → Show ask line.)
    Most brokers with variable spreads widen considerably at end of day (5 PM ET) ± 30 minutes. My GBPJPY (OANDA) shows average spread = 26 points, but average maximum spread = 134 (your broker will be similar).

 
William Roeder:

You buy at the Ask and sell at the Bid. Pending Buy Stop orders become market orders when hit and open at the Ask.

  1. Your buy order's TP/SL (or Sell Stop's/Sell Limit's entry) are triggered when the Bid / OrderClosePrice reaches it. Using Ask±n, makes your SL shorter and your TP longer, by the spread. Don't you want the specified amount used in either direction?

  2. Your sell order's TP/SL (or Buy Stop's/Buy Limit's entry) will be triggered when the Ask / OrderClosePrice reaches it. To trigger close to a specific Bid price, add the average spread.
              MODE_SPREAD (Paul) - MQL4 programming forum - Page 3 #25

  3. The charts show Bid prices only. Turn on the Ask line to see how big the spread is (Tools → Options (control+O) → charts → Show ask line.)
    Most brokers with variable spreads widen considerably at end of day (5 PM ET) ± 30 minutes. My GBPJPY (OANDA) shows average spread = 26 points, but average maximum spread = 134 (your broker will be similar).

Hi William, thanks for your answer but i'm not sure how this is relevant to the issue i'm encountering - please elaborate if i missed anything..

- I am trying to reproduce the underline calculation of OrderProfit() and my manual calculation effort is very slightly off (by 0.01) , i'm not trying to do any SL/TP calculations (there is no SL or TP on this order anyway)

- I have both bid/ask lines on in my chart, i'm working with correct last tick values from the end of session friday night (and yes, the spread widened , but that's irrelevant at this point i believe)

 
mikeTh:

I'm pretty sure it's the BID price for conversion (it's a Buy position)

By using

the calculation yields profit value of  25.68


MT4 documentaiton states:

Interesting, where in the documentation ? Can't seem to find it.
 
Alain Verleyen:
Interesting, where in the documentation ? Can't seem to find it.

That was misleading, i'm sorry, copied it from my internal research notes (found it doing my initial research before somewhere on the web) , thought i got it from the official docs. Still, using the ASK price in my calculation produces profit that is even more off from the one provided by OrderProfit() method.

Reason: