OnTradeTransaction processing

 

Good evening.

Guys, please help me out. The problem is probably not new, but I haven't found a single solution (neither in practice nor on the forums).

I am running 2 different robots in the terminal on 2 different instruments. The magics are different everywhere. The robot places pending limits and the procedure OnTradeTransaction allows me to detect a transaction and place pending stop orders using this transaction.

Below is the code for the trade transaction

case TRADE_TRANSACTION_DEAL_ADD:
        {
         drop_info2("TRADE_TRANSACTION_DEAL_ADD\r\n"+TransactionDescription(trans));
         if((trans.deal_type==DEAL_TYPE_BUY || trans.deal_type==DEAL_TYPE_SELL) && trans.order!=0)
           {
            if(getIsDealOfExpert(trans.deal)) //функция проверки принадлежности сделки к роботу
              {
               drop_info2("Сделка наша");
               analyzeFilledOrder(trans.order,trans.volume); //процедура по выставлению отложенных стоп ордеров
              }
           }
        }
      break;

This is the code of the function that checks whether the deal belongs to a robot

bool getIsDealOfExpert(ulong dealTicket)
     {
      if(HistoryDealSelect(dealTicket) && HistoryDealGetInteger(dealTicket,DEAL_MAGIC)==magic_number && HistoryDealGetString(dealTicket,DEAL_SYMBOL)==symbol)
         return true;
      else
         return false;
     }

This is the code of the procedure for pending stop orders

void analyzeFilledOrder(ulong orderTicket,double volume)
  {
   bool isFindOrder=false;
   string fullComment;
   ENUM_ORDER_TYPE orderType;
   if(getIsOrderOfExpert(orderTicket,true)) //Если ордер из сделки уже в истории
     {
      fullComment=HistoryOrderGetString(orderTicket,ORDER_COMMENT);
      orderType=ENUM_ORDER_TYPE(HistoryOrderGetInteger(orderTicket,ORDER_TYPE));
      isFindOrder=true; //локальная переменная, если нашли в истории
     }
   if(!isFindOrder && getIsOrderOfExpert(orderTicket,false)) //Если не нашли ордер в истории и ордер есть не в истории
     {
      fullComment=OrderGetString(ORDER_COMMENT); 
      orderType=ENUM_ORDER_TYPE(OrderGetInteger(ORDER_TYPE));
      isFindOrder=true; //локальная переменная, если нашли не в истории
     }
   if(isFindOrder) //если хоть где-то нашли, то выставляем отложенные стоп ордера
     {
     //выставляем стоп ордера

This is the code of the function for searching for an order in the history and out of the history

bool getIsOrderOfExpert(ulong OrderTicket,bool isHistory)
     {
      bool is_expert=false;
      //если ордер находится в истории
      if(isHistory)
        {
         if(HistoryOrderSelect(OrderTicket) && HistoryOrderGetInteger(OrderTicket,ORDER_MAGIC)==magic_number && HistoryOrderGetString(OrderTicket,ORDER_SYMBOL)==symbol)
            is_expert=true;
        }
      else
        {
         if(OrderSelect(OrderTicket) && OrderGetInteger(ORDER_MAGIC)==magic_number && OrderGetString(ORDER_SYMBOL)==symbol)
            is_expert=true;
        }
      return is_expert;
     }

I would output the information about the incoming transactions in the log files in the order they are received in the terminal. Now I have a problem that I have faced when trading on a demo account:

Sometimes transactions come in the following order TRADE_TRANSACTION_ORDER_DELETE, then TRADE_TRANSACTION_DEAL_ADD, then TRADE_TRANSACTION_HISTORY_ADD. In this case stop orders are often not placed after a trade has been executed. I suppose this happens because the order has already been deleted but has not yet been added to the history. It means that we cannot find the order from the deal either in the history or in the terminal. Although it is doubtful, the fact is that no stop order is placed because the robot does not find it after searching for the order in all dimensions(isFindOrder=false). The order of transactions may be correct, but the order is still nowhere to be found. In all cases, the robot detects the transaction correctly, but does not get to placing orders.However, it also occasionally works correctly and orders are placed.

I have tried different approaches, nothing works. I am now thinking of adding a 1-second interval at the beginning of pending order placing procedure. I do not know where else to dig.

Please share your experiences and ideas.

 
Илья Ребенок:

Good evening.

Guys, please help me understand. The problem is probably not new, but I haven't found a single solution (neither in practice nor on the forums).

I am running 2 different robots in the terminal on 2 different instruments. The magics are different everywhere. The robot places pending limits and the procedure OnTradeTransaction allows me to detect a transaction and place pending stop orders using this transaction.

Below is the code for the trade transaction

This is the code of the function that checks whether the deal belongs to a robot

This is the code of the procedure for pending stop orders

This is the code of the function for searching for an order in the history and out of the history

I would output the information about the incoming transactions in the log in the order they are received in the terminal. Now I have a problem that I have faced when trading on a demo account:

Sometimes transactions come in the following order TRADE_TRANSACTION_ORDER_DELETE, then TRADE_TRANSACTION_DEAL_ADD, then TRADE_TRANSACTION_HISTORY_ADD. In this case stop orders are often not placed after a trade has been executed. I suppose this happens because the order has already been deleted but has not yet been added to the history. It means that we cannot find the order from the deal either in the history or in the terminal. Although it is doubtful, the fact is that no stop order is placed because the robot does not find it after searching for the order in all dimensions(isFindOrder=false). The transaction order may be correct, but the order is still nowhere to be found.

Tried different approaches, nothing helps. I am now thinking of adding a 1 second sleep at the beginning of a procedure to place pending orders, maybe the time is not enough. I do not even know where else to dig.

Please share your experiences and ideas.

I haven't started to look through all the code. I don't think this approach is correct at all.

At the moment of transaction type TRADE_TRANSACTION_DEAL_ADD we must choose the trans.position and check its magic.

if(PositionSelectByTicket(trans.position) && PositionGetInteger(POSITION_MAGIC) == mag)

You can also check trans.symbol == _Symbol and make a decision based on the results of these checks.

 
Alexey Viktorov:

I didn't look into all the code. In my opinion, the approach is not correct at all.

At the moment of TRADE_TRANSACTION_DEAL_ADD transaction type one should choose trans.position and check its magik.

You can also check trans.symbol == _Symbol and make a decision based on the results of these checks.

I forgot to add that the mode is netting. The position is the same for all robots. That is, one robot bought a position, the second one bought it, the TRADE_TRANSACTION_DEAL_ADD events came in reverse order and the first robot did not see it as a result.

And I logically need to get the order comment from the trade, the position isn't of much help here.
 
Илья Ребенок:

Share your experiences and ideas please.

One situation

Forum on trading, automated trading systems & strategy testing

Bugs, bugs, questions

fxsaber, 2018.06.20 23:18

Decided to check how long these phantom order situations last, when an order is in the system but not in the Terminal.

// Советник отслеживает длительность ситуаций, когда ордер отсутствует среди текущих и исторических

#define  TOSTRING(A)  #A + " = " + (string)(A) + "\n"
#define  TOSTRING2(A) #A + " = " + EnumToString(A) + " (" + (string)(A) + ")\n"

bool OrderIsExist( const ulong &OrderTicket )
{
  return(OrderTicket ? OrderSelect(OrderTicket) || HistoryOrderSelect(OrderTicket) : true);
}

void OnTradeTransaction ( const MqlTradeTransaction &Trans, const MqlTradeRequest&, const MqlTradeResult& )
{
  static bool PrevIsExist = true;
  static ulong StartTime = 0;
  static ulong MaxInterval = 0;
  
  const ulong NowTime = GetMicrosecondCount();
  const bool IsExist = OrderIsExist(Trans.order);
    
  if (!IsExist)
  {
    Print(TOSTRING2(Trans.type) + TOSTRING(Trans.order) +
          TOSTRING(OrderSelect(Trans.order)) + TOSTRING(HistoryOrderSelect(Trans.order)));       
  
    if (PrevIsExist) 
      StartTime = NowTime;
  }
  else if (!PrevIsExist)
  {
    const ulong Interval = NowTime - StartTime;
    
    Print(TOSTRING(Interval) + TOSTRING2(Trans.type) + TOSTRING(Trans.order) +
          TOSTRING(OrderSelect(Trans.order)) + TOSTRING(HistoryOrderSelect(Trans.order)));       
    
    if (Interval > MaxInterval)
    {
      MaxInterval = Interval;
      
      Comment(TOSTRING(MaxInterval) + TOSTRING(Trans.order)); // mcs.
    }
  }
          
  PrevIsExist = IsExist;
}


Result

2018.06.21 00:10:31.047 Trans.type = TRADE_TRANSACTION_ORDER_DELETE (2)
2018.06.21 00:10:31.047 Trans.order = 2210967406
2018.06.21 00:10:31.047 OrderSelect(Trans.order) = false
2018.06.21 00:10:31.047 HistoryOrderSelect(Trans.order) = false
2018.06.21 00:10:31.047 
2018.06.21 00:10:31.080 Interval = 32643
2018.06.21 00:10:31.080 Trans.type = TRADE_TRANSACTION_HISTORY_ADD (3)
2018.06.21 00:10:31.080 Trans.order = 2210967406
2018.06.21 00:10:31.080 OrderSelect(Trans.order) = false
2018.06.21 00:10:31.080 HistoryOrderSelect(Trans.order) = true


32 milliseconds an order is there but not in the Terminal! Just imagine the consequences if the trading logic was executed in this interval ...


It is interesting that phantom orders are most often present only atTRADE_TRANSACTION_ORDER_DELETE and at TRADE_TRANSACTION_DEAL_ADD (much rarer) transaction types.


Very bad platform nuance.


ZZY questionable speed of trade transactions on five, unfortunately.


Second

opening a position and OrdersTotal has increased by one.

  • It was executed and OrdersTotal decreased by one, but PositionsTotal did not increase by one. In other words, there is a position, but the terminal doesn't know about it.
  • For example, there are no positions or orders - PositionsTotal = 0, OrdersTotal = 0.

    You set a market order. PositionsTotal = 0, OrdersTotal = 1.

    The market order is executed - OrdersTotal = 0. But PositionsTotal = 0!

     
    Илья Ребенок:

    I forgot to add that the mode is netting. The position is the same for all robots.

    Doesn't matter. The position always has a ticket, but it can also be selected by symbol. You might have to add a check on deal volume or something else. For example, select orders and deals of a position and shake them to find the right one. But a deal is a deal... And no one guarantees the consistency of transactions. Not so long ago there was a warning about possible loss of transactions.


    Given the addendum in your post, it's all wrong. In that case, you need to look into it more carefully.

     
    Илья Ребенок:

    Tried different approaches, nothing works.

    Write a simple action that needs to be implemented.

     
    fxsaber:

    One situation


    Second

    Thanks, I'll read it, but at first glance it confirms my assumption.

    Alexey Viktorov:

    It doesn't matter. The position always has a ticket, but you can also select by symbol. You may have to add a check on transaction volume or something else. For example, select orders and deals of a position and shake them to find the right one. But a deal is a deal... And no one guarantees the consistency of transactions. Not so long ago there was a warning about possible loss of transactions.


    Considering the addendum in your post, it doesn't all fit. In that case, you need to look into it more carefully.

    Saw a post about transaction loss, but the moderators there said it was a relic of the past and forgot to remove it from the documentation.

    fxsaber:

    Write a simple action to be implemented.

    I don't quite understand writing a simple action) Please explain.

     
    Илья Ребенок:


    Saw a post about losing transactions, but the moderators there said it was a relic of the past and forgot to remove it from the documentation.

    They did, but it wasn't that long ago.

     
    Илья Ребенок:

    I don't quite understand about writing a simple action) Explain please.

    What is the trade objective?

     
    fxsaber:

    What is your trading objective?

    We place limit orders, and when they trigger, we place a stop order and a take profit order. When a stop order triggers, we remove the take profit and vice versa. The initial limit ticket, on the basis of which we set the stop order and take profit, is written in the comment of the stop order and take profit. This is why it is important to get order comments so that when a stop order triggers, you can find the take profit with the same comment and delete it.

    Since our robot allows us to refill positions, we should also place a stop order and a take profit and leave a comment with the entry of a refill ticket.

    Can 1 second sleep be a good idea? To have time for all transactionsTRADE_TRANSACTION_ORDER_DELETE andTRADE_TRANSACTION_HISTORY_ADD

    Общие принципы - Торговые операции - MetaTrader 5
    Общие принципы - Торговые операции - MetaTrader 5
    • www.metatrader5.com
    Перед тем как приступить к изучению торговых функций платформы, необходимо создать четкое представление об основных терминах: ордер, сделка и позиция. — это распоряжение брокерской компании купить или продать финансовый инструмент. Различают два основных типа ордеров: рыночный и отложенный. Помимо них существуют специальные ордера Тейк Профит...
     

    Илья Ребенок:

    The robot allows for scaling in, so when we buy more, we also place a stop order and a take profit, and record the scaling in the ticket comment

    Can we have >=2 take and stop orders at the same time?