You're reading...
EA development, MQL5

MQL5: Getting your EA to manage its own orders with others around

‘Selecting’ a Position “copies data about a position into the program environment, and further calls of PositionGetDouble(), PositionGetInteger() and PositionGetString() return the earlier copied data. This means that the position itself may no longer exist (or its volume, direction, etc. has changed), but data of this position still can be obtained. To ensure receipt of fresh data about a position, it is recommended to call PositionSelect() right before referring to them.”

https://www.mql5.com/en/docs/trading/positionselect

It basically populates a custom struct with information about the Position you ‘selected’, and that the data in this struct persists until you update it with a fresh ‘selection’.

There are 4 ways to ‘select’ a Position.

bool   PositionSelect(string symbol)
bool   PositionSelectByTicket(ulong ticket)
string PositionGetSymbol(int index)
ulong  PositionGetTicket(int index)

If there are multiple Positions present, for an EA to close only the Positions opened by it, we need to search through all of them and check which are tagged with that EA’s Magic Number.

To do this, we need a loop to check through each.

input MagicNumber = 123;

void OnStart(){

    //WRONG
    for(int i = PositionsTotal() - 1; i >= 0; i--){
       if(PositionSelect(_Symbol) && PositionGetInteger(POSITION_MAGIC) == MagicNumber){
       //There is no Position index shifting here and the PositionSelect will, by default, select the lowest Ticket
       //By virtue of the following 'close Position logic', the Position with the lowest Ticket is removed and the loop works unintentionally, but this is still horrible coding
          close Position logic;
       }
    }

   //CORRECT
   for(int i = PositionsTotal() - 1; i >= 0; i--){
      if(PositionGetSymbol(i) == Symbol() && PositionGetInteger(POSITION_MAGIC) == MagicNumber){
      //This works great if the EA only opens Positions on one Symbol. It is marginally faster than below as we do not need to resolve PositionGetInteger(POSITION_MAGIC) if PositionGetSymbol(i) != Symbol()
         close Position logic;
      }
   }
 
   //CORRECT
   for(int i = PositionsTotal() - 1; i >= 0; i--){
      if(PositionGetTicket(i) > 0 && PositionGetInteger(POSITION_MAGIC) == MagicNumber){
      //this works for a multi-Symbol EA
         close Position logic;
      }
   }

Conversely, if the trigger to open a Position occurs, we need to check that an existing Position by the EA does not exist. (as we may not want to have more than one Position open at any point in time)

bool PositionExists = false;
  
//for one Symbol EA
for(int i = PositionsTotal() - 1; i >= 0; i--){
   if(PositionGetSymbol(i) != Symbol())continue; //we go to the next Position
   else{ //if(PositionGetSymbol(i) == Symbol())
      if(PositionGetInteger(POSITION_MAGIC) == MagicNumber){
         PositionExists = true;
         break; //we exit the loop once an existing EA Position is found (this saves unnecessary searching)
      }
   }
}
 
//for multi-Symbol EA
for(int i = PositionsTotal() - 1; i >= 0; i--){
   if(PositionGetTicket(i) > 0 && PositionGetInteger(POSITION_MAGIC) == MagicNumber){
      PositionExists = true;
      break; //we exit the loop once the existing EA Position is found (this saves unnecessary searching)
   }
}
 
if(PositionExists == false){
   order entry logic;
}

An important point, before we call PositionGetInteger(POSITION_MAGIC), we must call PositionGetSymbol(i) or PositionGetTicket(i) first.

This works:

if(PositionGetTicket(i) > 0 && PositionGetInteger(POSITION_MAGIC) == MagicNumber)

This does not:

if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetTicket(i) > 0)

Discussion

2 thoughts on “MQL5: Getting your EA to manage its own orders with others around

  1. Thank you for the help! Much appreciated and good info!

    Posted by Pete | 2020-03-28, 4:32 AM

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Archives

Visitors

Flag Counter
%d bloggers like this: