OnTradeTransaction consitently getting called invoked with incorrect values in

 
/// Following code always line with message "Filled Long " even when order sell is filled. 

void OnTradeTransaction(const MqlTradeTransaction &trans,
        const MqlTradeRequest &request,
        const MqlTradeResult &result)
{

   double postn_price, postn_volume;
   long postn_magic;
   CDealInfo dealInfo;
   if ((trans.type == TRADE_TRANSACTION_DEAL_ADD) &&
       (trans.position == trans.order) &&
       (trans.position != 0)) {
       if (PositionSelectByTicket(trans.position))
       {
          postn_price = PositionGetDouble (POSITION_PRICE_OPEN);
          postn_volume = PositionGetDouble (POSITION_VOLUME); // trans.volume 
          long postn_magic = PositionGetInteger(POSITION_MAGIC);
          dealInfo.Ticket(trans.deal);
       }

       if ((trans.symbol == m_symbol.Name()) && (postn_magic == paramMagic) && (dealInfo.Entry() == DEAL_ENTRY_IN))
       {
          if (trans.order_type == ORDER_TYPE_BUY )
          {
              


///BUG: Code always prints this line even when sell order gets filled
              Print(__FUNCTION__, " ", __LINE__, " Filled Long @ ", DoubleToString(trans.price));
          }
          if (trans.order_type == ORDER_TYPE_SELL)
          {
              


///BUG: This line of code never gets executed.
              Print(__FUNCTION__, " ", __LINE__, " Filled Short ", DoubleToString(trans.price));
          } 
       } 
   }
}

Following code always prints Filled Long regardless of whether a Sell order gets filled or buy order gets filled. I am unable to figure out what is wrong here. dealinfo was added later on to weed out DEAL_ENTRY_OUT messages but that does not resolve problem.... 
Documentation on MQL5: Constants, Enumerations and Structures / Trade Constants / Deal Properties
Documentation on MQL5: Constants, Enumerations and Structures / Trade Constants / Deal Properties
  • www.mql5.com
Deal Properties - Trade Constants - Constants, Enumerations and Structures - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
{
    CDealInfo dealInfo;
    if ((trans.type == TRADE_TRANSACTION_DEAL_ADD) &&
        (trans.position == trans.order) &&
        (trans.position != 0))
    {
        if (PositionSelectByTicket(trans.position))
        {
            double postn_price = PositionGetDouble(POSITION_PRICE_OPEN);
            double postn_volume = PositionGetDouble(POSITION_VOLUME);  // trans.volume
            long postn_magic = PositionGetInteger(POSITION_MAGIC);
            dealInfo.Ticket(trans.deal);
            if (HistoryDealSelect(trans.deal))
            {
                if ((trans.symbol == m_symbol.Name()) && (postn_magic == paramMagic) && (dealInfo.Entry() == DEAL_ENTRY_IN))
                {
                    if (dealInfo.DealType() == DEAL_TYPE_BUY)
                    {
                        Print(__FUNCTION__, " ", __LINE__, " Filled Long @ ", DoubleToString(trans.price));
                    }
                    if (dealInfo.DealType() == DEAL_TYPE_SELL)
                    {
                        Print(__FUNCTION__, " ", __LINE__, " Filled Short ", DoubleToString(trans.price));
                    }
                }
            }
        }
    }
}
 

Proper work with OnTradeTransaction includes the following steps:

1. Determine the type of transaction. If the transaction is of type 'TRADE_TRANSACTION_DEAL_ADD' - go to the algorithm

2. We turn to the trading history and look for the DEAL that generated this transaction - if this transaction was found, then go to the algorithm

3. Determine the type of transaction

//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//--- get transaction type as enumeration value
   ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
//--- if transaction is result of addition of the transaction in history
   if(type==TRADE_TRANSACTION_DEAL_ADD)
     {
      ResetLastError();
      if(HistoryDealSelect(trans.deal))
         m_deal.Ticket(trans.deal);
      else
        {
         Print(__FILE__," ",__FUNCTION__,", ERROR: ","HistoryDealSelect(",trans.deal,") error: ",GetLastError());
         return;
        }
      if(m_deal.Symbol()==m_symbol.Name() && m_deal.Magic()==InpMagic)
        {
         ENUM_DEAL_TYPE deal_type   = m_deal.DealType();
         ENUM_DEAL_ENTRY deal_entry = m_deal.Entry();
         if(deal_type==DEAL_TYPE_BUY || deal_type==DEAL_TYPE_SELL)
           {
            if(deal_entry==DEAL_ENTRY_IN)
              {
               if(deal_type==DEAL_TYPE_BUY)
                  Print("BUY");
               else
                  Print("SELL")
              }
           }
        }
     }
  }
 

Thanks you  amrali and  Vladimir Karputov


Most important bit was call to HistoryDealSelect which was missing. 

If you know of a link to a comprehensive source of OnTradeTransaction that handles all trans.type messages , please do share 


I hereby confirm that OnTradeTransaction callback from MT5 infrastructure has a bug that it returns ORDER_TYPE_BUY even when underlying order is ORDER_TYPE_SELL*

Actually quite a lot of enums have incorrect values. 

I guess the source of the bug is the definition of enumerators such as ENUM_ORDER_TYPE. Most internal code uses ZeroMemory* function to initialise all structure memories to zero

and numeric value of zero equates to enum value of ORDER_TYPE_BUY. 

If the Seniors in MT5 developer team are reading this message and it is feasible for them to do, all of the enum definition must be expanded to include *_INVALID that equates to zero.

e.g. ORDER_TYPE_INVALID.

I undersrand that code logic to fix is very simple, this kind of error fix will have sweeping effect and many other enums also and changing it can resolve many

outstanding errors and may trap lot of work-arounds into redundancy.

 
cdjindia #:
Thanks you  amrali and  Vladimir Karputov


Most important bit was call to HistoryDealSelect which was missing. 

If you know of a link to a comprehensive source of OnTradeTransaction that handles all trans.type messages , please do share 


I hereby confirm that OnTradeTransaction callback from MT5 infrastructure has a bug that it returns ORDER_TYPE_BUY even when underlying order is ORDER_TYPE_SELL*

Actually quite a lot of enums have incorrect values. 

I guess the source of the bug is the definition of enumerators such as ENUM_ORDER_TYPE. Most internal code uses ZeroMemory* function to initialise all structure memories to zero

and numeric value of zero equates to enum value of ORDER_TYPE_BUY. 

If the Seniors in MT5 developer team are reading this message and it is feasible for them to do, all of the enum definition must be expanded to include *_INVALID that equates to zero.

e.g. ORDER_TYPE_INVALID.

I undersrand that code logic to fix is very simple, this kind of error fix will have sweeping effect and many other enums also and changing it can resolve many

outstanding errors and may trap lot of work-arounds into redundancy.

The bug is in your code, there is no problem with ENUMs. At least i do not experience them in any way and my logic depends on them.

 
cdjindia #:
Thanks you  amrali and  Vladimir Karputov


Most important bit was call to HistoryDealSelect which was missing. 

If you know of a link to a comprehensive source of OnTradeTransaction that handles all trans.type messages , please do share 

https://www.mql5.com/en/code/24901

https://www.mql5.com/en/articles/1111
TradeTransaction Class
TradeTransaction Class
  • www.mql5.com
A base class to simplify analyzing trade transactions in MQL5.
 
 

Can confirm the original post bug.

ORDER_TYPE_BUY is returned for the trans.order_type regardless of whether the original order type was  a buy or sell.

I agree you can get around this with the proposed code using the deal information, but the fact is it is still a bug.

 

There is no bug.

Yes, trans.order_type is always ORDER_TYPE_BUY when the transaction is TRADE_TRANSACTION_DEAL_ADD, because this field is NOT UPDATED for such transaction, so it's always 0 ( ORDER_TYPE_BUY ).

Please read the documentation carefully :

Trade Transaction Structure

TRADE_TRANSACTION_DEAL_*

The following fields in MqlTradeTransaction structure are filled for trade transactions related to deals handling (TRADE_TRANSACTION_DEAL_ADD, TRADE_TRANSACTION_DEAL_UPDATE and TRADE_TRANSACTION_DEAL_DELETE):

  • deal - deal ticket;
  • order - order ticket, based on which a deal has been performed;
  • symbol - deal symbol name;
  • type - trade transaction type;
  • deal_type - deal type;
  • price - deal price;
  • price_sl - Stop Loss price (filled, if specified in the order, based on which a deal has been performed);
  • price_tp - Take Profit price (filled, if specified in the order, based on which a deal has been performed);
  • volume - deal volume in lots.
  • position - the ticket of the position that was opened, modified or closed as a result of deal execution.
  • position_by - the ticket of the opposite position. It is only filled for the out by deals (closing a position by an opposite one).

You can see that order_type field is not used.

Documentation on MQL5: Constants, Enumerations and Structures / Data Structures / Trade Transaction Structure
Documentation on MQL5: Constants, Enumerations and Structures / Data Structures / Trade Transaction Structure
  • www.mql5.com
Trade Transaction Structure - Data Structures - Constants, Enumerations and Structures - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 

I concede then that this is not a bug but an unintuitive feature.

If I released an API today to a client with that feature it would be rejected. Exploring calls and then having to validate it by checking documentation seems less than optimal. I continue my journey with MQL5...

 
Mix Ascii #:

I concede then that this is not a bug but an unintuitive feature.

If I released an API today to a client with that feature it would be rejected. Exploring calls and then having to validate it by checking documentation seems less than optimal. I continue my journey with MQL5...

Maybe but it's irrelevant. You have to deal with the API as it is, not as you think it should be.

Always check the documentation and never assume. You will save a lot of time believe me.