Get ticket immediately after opening position

 
Hello everyone,

I hope you're doing well!

I am currently working on developing an Expert Advisor (EA) and facing a challenge. I need to obtain the ticket number of the last position immediately after opening it.

I am using the following code for this purpose; however, I am encountering inconsistent behavior. Sometimes, the code works as expected, but on other occasions, it does not. The intriguing detail is that I am not receiving error messages; in other words, the program is not entering the "else" blocks.

//---
bool PlaceBuy(double lots)
  {
//---
   bool success = trade.Buy(lots, _Symbol, Ask, StopLoss, TakeProfit, Comments);

   if(success)
     {
      if(trade.ResultRetcode() == 10008 || trade.ResultRetcode() == 10009)
        {
         //---
         gblLastTicketBuy = trade.ResultOrder();
         //---
         return true;
        }
      else
        {
         Print("Unexpected return from server. Return code #", trade.ResultRetcode(), " (",  trade.ResultRetcodeDescription(), ").");
         //---
         return false;
        }
     }
   else
     {
      Print("Position failed (Buy). Return code #", trade.ResultRetcode(), " (",  trade.ResultRetcodeDescription(), ").");
      //---
      return false;
     }

   return false;
  }
Another detail to be considered is that I call the above function within another call named "OpenTrade," which, in turn, is invoked within the "OnTick" function.

I would appreciate guidance on how I can improve my code to resolve this issue. Any help or insights are highly appreciated.

Thank you in advance for your collaboration and understanding.
 

How do you know that is not working?

Where are you using the 

gblLastTicketBuy

?

If the problem is when you try to select a position you may need wait some ms after send the order to be able to select.

 
Samuel Manoel De Souza #:

How do you know that is not working?

Where are you using the 

?

If the problem is when you try to select a position you may need wait some ms after send the order to be able to select.

Hello,

I have a function called GetTicketLastPosition(type) (code below) that compares the value of the variable gblLastTicketBuy with the value it returns. If these values are not equal, then all other open positions in the same asset are closed.

//---
ulong GetTicketLastPosition(long type)
  {
   ulong index = -1;
   int total   = PositionsTotal();

   for(int i = total - 1; i >= 0; i--)
     {
      if(!PositionSelectByTicket(PositionGetTicket(i)))
         continue;

      if(PositionGetInteger(POSITION_MAGIC) != MagicNumber || (_Symbol != "" && PositionGetSymbol(i) != _Symbol))
         continue;

      if(PositionGetInteger(POSITION_TYPE) != type)
         continue;

      index = PositionGetTicket(i);
      break;
     }

   return index;
  }

In this way, occasionally, when opening a new position, if the ticket stored in the gblLastTicketBuy variable differs from the value returned by the GetTicketLastPosition(type) function, all positions, including the new one, are being closed immediately after the new position is opened.


In this context, would it be advisable to use the Sleep function before calling the ResultOrder() function? If so, how can I determine the ideal time interval?


Another detail to consider is that I have assigned the value false to the SetAsyncMode function of the CTrade class. Would it be advisable to assign the value true instead?


I appreciate your attention and willingness in advance.

 
immediately after get the ResultOrder you can try to select, if not select, do sleep and select until it be select, if after n trials it not be selected you have another issue in your code.

but if you only want to know if another position has been opened after that, you can compare the result of GetTicketLastPosition with the ResultOrder, like 
bool is_not_last = GetTicketLastPosition() > gblLastTicketBuy;
 
bool WaitForPositionOpen(ulong ticket, uint wait_msec = 1000)
  {
   bool result = false;
   uint tick = GetTickCount();
   do
     {
      result = PositionSelectByTicket(ticket);
     }
   while(!result && (GetTickCount() - tick < wait_msec) && !IsStopped());
   
   return(result);   
  }

Now, you can use to wait some time after OrderSend():

   ulong gblLastTicketBuy = -1;
   
   if(PlaceBuy(lots) && WaitForPositionOpen(gblLastTicketBuy, 1000))
     {
      ulong ticket = GetTicketLastPosition(type);
     }
 
Samuel Manoel De Souza #:
immediately after get the ResultOrder you can try to select, if not select, do sleep and select until it be select, if after n trials it not be selected you have another issue in your code.

but if you only want to know if another position has been opened after that, you can compare the result of GetTicketLastPosition with the ResultOrder, like 

I understand, you've given me an idea. I will keep my function (PlaceBuy) as follows below. If this solves the problem, I'll come back here to provide feedback.


Thank you in advance.

//---
bool PlaceBuy(double lots)
  {
//---
   bool success = trade.Buy(lots, _Symbol, Ask, StopLoss, TakeProfit, Comments);

   if(success)
     {
      ulong lastTicket = GetTicketLastPosition(BUY);
      if(trade.ResultRetcode() == 10008 || trade.ResultRetcode() == 10009)
        {
         //---
         gblLastTicketBuy = trade.ResultOrder();

         while(lastTicket > gblLastTicketBuy)
           {
            gblLastTicketBuy = trade.ResultOrder();
            Sleep(2000);
           }

         //---
         return true;
        }
      else
        {
         Print("Unexpected return from server. Return code #", trade.ResultRetcode(), " (",  trade.ResultRetcodeDescription(), ").");
         //---
         return false;
        }
     }
   else
     {
      Print("Position failed (Buy). Return code #", trade.ResultRetcode(), " (",  trade.ResultRetcodeDescription(), ").");
      //---
      return false;
     }

   return false;
  }
 
amrali #:

Now, you can use to wait some time after OrderSend():

Hello,


Great idea. I will test this solution too. Thanks for the feedback.

 
According to the documentation, and I strongly suggest to go with it as it is adviced there, you should not expect a ticket number from order send.


It can happen (often it does) you get an order ticket or a deal ticket within the return code structure.

But it's not always the case. If you get a ticket number, you can search for positions, using the POSITION_ID, and try to find it in the current positions known to the terminal.

If this failed, you need to use OnTrade, OnTradeTransaction to find your position, or the state of your order, or whatever you are looking for.

This is the proper way to do it. All other are wasteful usage of resources, blocking your EA from further processing.

Your EA code around SendOrder should always be "reactive", not "anticipative".

 
Dominik Egert #:
According to the documentation, and I strongly suggest to go with it as it is adviced there, you should not expect a ticket number from order send.


It can happen (often it does) you get an order ticket or a deal ticket within the return code structure.

But it's not always the case. If you get a ticket number, you can search for positions, using the POSITION_ID, and try to find it in the current positions known to the terminal.

If this failed, you need to use OnTrade, OnTradeTransaction to find your position, or the state of your order, or whatever you are looking for.

This is the proper way to do it. All other are wasteful usage of resources, blocking your EA from further processing.

Your EA code around SendOrder should always be "reactive", not "anticipative".

Hello,


In this case, are you suggesting that I call the ResultOrder() function within the OnTrade or OnTradeTransaction function?


Thank you in advance for your help and availability.

 
Jeovane Reges #:

Hello,


In this case, are you suggesting that I call the ResultOrder() function within the OnTrade or OnTradeTransaction function?


Thank you in advance for your help and availability.

No. You can get ResultOrder immediately after send the order. But the fact that you get a success code and the order ticket, doesn't mean that the positions is already available to select. That is why i told to use Sleep.

What he is saying is that you have other ways to handle the opening of positions, like you get the order, then later in OnTradeTransaction you can check if the order was filled, partially filled, canceled, rejected, etc. in the same way you can know the position affected by an order execution handling trade transactions events, especially the TRADE_TRANSACTION_DEAL_ADD.
 
Samuel Manoel De Souza #: OnTradeTransaction

Hello Samuel,

Now I understand. I currently use only the OnTrade function, but I will study and learn how the OnTradeTransaction function works to optimize how I obtain the ticket.

Once again, thank you very much for your help and availability.