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") } } } } }
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.
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.
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
For Starters
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 StructureTRADE_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.
- www.mql5.com
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.
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
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....