Getting unique identifier to refer to and manage open trade in MQL5 hedging - page 2

 
Vladimir Karputov:

I still do not understand what exactly you want.

In principle, it doesn’t matter: you opened three positions or you opened one hundred positions. If they need to be modified - move stop loss, then the universal function is used.


In general, explain (if you cannot explain in words - draw pictures) - what you want to do.

For example, say I open 3 positions using 3 PositionOpen() instructions. I will number them position #1, #2, and #3. At a later point in time, once a condition is met, I want to modify the SL for #1 by 100pts, for #2 by 150pts, and for #3 by 300pts. Then, once some other condition is met, I want to close #1, but leave #2 and #3 open. Later still, I want to change the TP for #3, but leave it unchanged for #2.

All I want is to be able to refer to these positions by a number, by some identifier, so I can manipulate them independently in unique ways in my program using functions such as PositionModify() or PositionClose(). So I can track exactly what happens to each position and be sure that I'm making the right changes to the right one.

The CTrade modification functions take the position ticket as an argument, so, once I have opened a position, I need to somehow get the position ticket and store it for later use. I believe I have figured this out by using the order ticket via ResultOrder(), which appears to be the same as the position ticket.

 
VoidSurf:

I can confirm that this does work. After placing the trade using a CTrade object, use ResultOrder() to get the order ticket, which appears to always be equal to the resulting position ticket. Store this ticket in a ulong variable, and then use it in PositionModify() or PositionClose() to manipulate.


Thanks to everyone for their help.

Good if it works for you. But I want to add a warning : this is not a generic approach and depending of the exact trading environment this can fail for two reasons :

  • 1. ResultOrder() doesn't always return the order ticket immediately after the OrderSend().
  • 2. An order ticket is not always the same as the position ticket.
 
Alain Verleyen:

Good if it works for you. But I want to add a warning : this is not a generic approach and depending of the exact trading environment this can fail for two reasons :

  • 1. ResultOrder() doesn't always return the order ticket immediately after the OrderSend().
  • 2. An order ticket is not always the same as the position ticket.

Hi Alain, thanks for joining the discussion.

1. If it does not return the ticket immediately, it must still return the ticket at some time if the order is successfully placed. Would looping to wait for the ticket be a possibility? Could a ticket simply never be returned on a successful order?

2. This is a point of enormous confusion for me. In the MQL5 documentation, specifically here, it states this:

position

Ticket of a position. Should be filled in when a position is modified or closed to identify the position. As a rule it is equal to the ticket of the order, based on which the position was opened.

It says, "as a rule", so presumably it is equal by the program logic. Under what conditions would the ticket of a position not be equal to the ticket of an order? I really don't understand how tickets are assigned and why it would assign to a position a different ticket to that of the order that opened it.

Finally, what would your recommendation be to do the job that I'm trying to do? If order ticket != position ticket, is there a function that allows me to get the position ticket right after a position has been opened? There is ResultOrder() and ResultDeal(), but no "ResultPosition()". Presumably, since functions such as PositionClose() take the position ticket as an argument, there must be a way to retrieve an individual position ticket?

Once I have opened multiple positions, I don't want to have to loop through them to make modifications, because that doesn't allow me to specifically identify and manipulate. I just want to get a position ticket immediately after a position has been opened and store it in a variable for later use.

Documentation on MQL5: Constants, Enumerations and Structures / Data Structures / Trade Request Structure
Documentation on MQL5: Constants, Enumerations and Structures / Data Structures / Trade Request Structure
  • www.mql5.com
Interaction between the client terminal and a trade server for executing the order placing operation is performed by using trade requests. The trade request is represented by the special predefined structure of MqlTradeRequest type, which contain all the fields necessary to perform trade deals. The request processing result is represented by...
 
VoidSurf:

Hi Alain, thanks for joining the discussion.

1. If it does not return the ticket immediately, it must still return the ticket at some time if the order is successfully placed. Would looping to wait for the ticket be a possibility? Could a ticket simply never be returned on a successful order?

You can loop if you want but it's not a good approach. The good one is to use OnTrade() or OnTradeTransaction() to catch the price once the order is executed.

2. This is a point of enormous confusion for me. In the MQL5 documentation, specifically here, it states this:

position

Ticket of a position. Should be filled in when a position is modified or closed to identify the position. As a rule it is equal to the ticket of the order, based on which the position was opened.

It says, "as a rule", so presumably it is equal by the program logic. Under what conditions would the ticket of a position not be equal to the ticket of an order? I really don't understand how tickets are assigned and why it would assign to a position a different ticket to that of the order that opened it.

I didn't say it will be different, but that it's possible to be different in some cases. For example partial closing, or adding to a position (netting account), maybe some others I didn't think about right now. If we talk about opening order only then all should be ok identifying a position ticket and the order ticket. (sorry if I confused you I had not read all the topic).

Finally, what would your recommendation be to do the job that I'm trying to do? If order ticket != position ticket, is there a function that allows me to get the position ticket right after a position has been opened? There is ResultOrder() and ResultDeal(), but no "ResultPosition()". Presumably, since functions such as PositionClose() take the position ticket as an argument, there must be a way to retrieve an individual position ticket?

Once I have opened multiple positions, I don't want to have to loop through them to make modifications, because that doesn't allow me to specifically identify and manipulate. I just want to get a position ticket immediately after a position has been opened and store it in a variable for later use.

If the simple approach you was using is working for you, then just keep it IF you know exactly when it can fail. If your EA never run in such situation, then all is fine.Otherwise use the already mentioned event handlers.

 
Alain Verleyen:
You can loop if you want but it's not a good approach. The good one is to use OnTrade() or OnTradeTransaction() to catch the price once the order is executed. I didn't say it will be different, but that it's possible to be different in some cases. For example partial closing, or adding to a position (netting account), maybe some others I didn't think about right now. If we talk about opening order only then all should be ok identifying a position ticket and the order ticket. (sorry if I confused you I had not read all the topic).

If the simple approach you was using is working for you, then just keep it IF you know exactly when it can fail. If your EA never run in such situation, then all is fine.Otherwise use the already mentioned event handlers.

I found more information here.

POSITION_TICKET

Position ticket. Unique number assigned to each newly opened position. It usually matches the ticket of an order used to open the position except when the ticket is changed as a result of service operations on the server, for example, when charging swaps with position re-opening. To find an order used to open a position, apply the POSITION_IDENTIFIER property.


So basically, a position ticket may differ from the order ticket if swaps are charged or the server refreshes, or something similar to this. I would not feel confident in my EA if it isn't prepared to deal with this eventuality. There is another way to identify a position, a POSITION_IDENTIFIER, which never changes:

POSITION_IDENTIFIER

Position identifier is a unique number assigned to each re-opened position. It does not change throughout its life cycle and corresponds to the ticket of an order used to open a position.

 

Position identifier is specified in each order (ORDER_POSITION_ID) and deal (DEAL_POSITION_ID) used to open, modify, or close it. Use this property to search for orders and deals related to the position.

 

When reversing a position in netting mode (using a single in/out trade), POSITION_IDENTIFIER does not change. However, POSITION_TICKET is replaced with the ticket of the order that led to the reversal. Position reversal is not provided in hedging mode.


However, the only way to use this identifier seems to be with HistorySelectByPosition, which I can't see the use of. If I have the POSITION_IDENTIFIER, is there some function I can use it in to retrieve the most recent position ticket assigned to that identifier? There is PositionSelectByTicket, I need something like, "PositionSelectByIdentifier".

Thank you for the tip on using OnTrade(). I will do more research into that.

Documentation on MQL5: Constants, Enumerations and Structures / Data Structures / Trade Request Structure
Documentation on MQL5: Constants, Enumerations and Structures / Data Structures / Trade Request Structure
  • www.mql5.com
Interaction between the client terminal and a trade server for executing the order placing operation is performed by using trade requests. The trade request is represented by the special predefined structure of MqlTradeRequest type, which contain all the fields necessary to perform trade deals. The request processing result is represented by...
 
I think I could write a function that loops through all open positions, gets their POSITION_IDENTIFIERs, uses HistorySelectByPosition to find the order that opened the position, get the order ticket, then compare the order ticket to the ticket stored in the variable to verify that the selected position is the right one.

Or, simply, since POSITION_IDENTIFIER is specified to be the same as the ticket of the order that opened the position, compare each one to the order ticket stored in variable until the right one is selected.

This is giving me a headache... 
 

I wrote this function to make sure I am always using the position ticket that matches the ticket of the order that created it:

ulong UpdatePositionTicket(ulong order_ticket)
     {
      ulong position_ticket = 0;
      for (int i=PositionsTotal()-1; i>=0; i--)
         {  PositionGetTicket(i);
            long positionID = PositionGetInteger(POSITION_IDENTIFIER);
            if((positionID == order_ticket) && (PositionGetString(POSITION_SYMBOL) == _Symbol)){
               position_ticket = PositionGetTicket(i);}
         }
      if(position_ticket == 0){Print("Error updating position ticket for order ticket #",order_ticket);}
      return position_ticket;
      }

It seems to work. What do you think? Documentation states that the POSITION_IDENTIFIER does not change throughout a position's life cycle and corresponds to the ticket of the order used to open the position. This function passes the stored ticket of the order and compares it to the POSITION_IDENTIFIER of each position. It should always return the corresponding position ticket even if that has changed. So this function can be used to link order tickets to position tickets.

Hope this helps someone.

 
VoidSurf :

For example, say I open 3 positions using 3 PositionOpen() instructions. I will number them position #1, #2, and #3. At a later point in time, once a condition is met, I want to modify the SL for #1 by 100pts, for #2 by 150pts, and for #3 by 300pts. Then, once some other condition is met, I want to close #1, but leave #2 and #3 open. Later still, I want to change the TP for #3, but leave it unchanged for #2.

All I want is to be able to refer to these positions by a number, by some identifier, so I can manipulate them independently in unique ways in my program using functions such as PositionModify() or PositionClose(). So I can track exactly what happens to each position and be sure that I'm making the right changes to the right one.

The CTrade modification functions take the position ticket as an argument, so, once I have opened a position, I need to somehow get the position ticket and store it for later use. I believe I have figured this out by using the order ticket via ResultOrder(), which appears to be the same as the position ticket.

Listen carefully to what Alain Verleyen tells you and do not be confused to remember the ticket! This is dangerous!

I offer a very simple and elegant way: you have opened three positions, which means they will have different opening times. You just have to go around the entire list of positions and sort them by age: the oldest Stop loss is 100, the younger - 150 and the youngest 300 points.

 
Vladimir Karputov:

Listen carefully to what Alain Verleyen tells you and do not be confused to remember the ticket! This is dangerous!

I offer a very simple and elegant way: you have opened three positions, which means they will have different opening times. You just have to go around the entire list of positions and sort them by age: the oldest Stop loss is 100, the younger - 150 and the youngest 300 points.


Thanks for the suggestion. I will test this out, I just need to understand the mechanism first. To sort positions by age, I assume I would start by using a for loop to go through all open positions and get their opening times using PositionGetInteger(POSITION_TIME). But then what? How would I sort them by date, and then refer to them using PositionModify()? I still have to pass it the position ticket.

Apologies for not being quick to understand, I am not an experienced programmer at all. I just started learning from scratch the elementary C++ syntax 2 months ago.
 
VoidSurf :

Thanks for the suggestion. I will test this out, I just need to understand the mechanism first. To sort positions by age, I assume I would start by using a for loop to go through all open positions and get their opening times using PositionGetInteger(POSITION_TIME). But then what? How would I sort them by date, and then refer to them using PositionModify()? I still have to pass it the position ticket.

Apologies for not being quick to understand, I am not an experienced programmer at all. I just started learning from scratch the elementary C++ syntax 2 months ago.

Position Crawl Cycle

   for(int i=PositionsTotal()-1; i>=0; i--)
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==InpMagic)
           {
            if(m_position.PositionType()==POSITION_TYPE_BUY)
              {
               ***
              }
            else
               if(m_position.PositionType()==POSITION_TYPE_SELL)
                 {
                  ***
                 }
           }
Reason: