You're reading...
EA development, MQL5

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

Before we get data about a position, we need to ‘select’ it first.

‘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

There are 4 ways to ‘select’ a position.

1. bool   PositionSelect(string symbol)
2. bool   PositionSelectByTicket(ulong ticket)
3. string PositionGetSymbol(int index)
4. 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 index shifting here and the PositionSelect will select the lowest Ticket
      //By virtue of the following 'close logic', the Position with the lowest Ticket is removed and the loop works unintentionally, but this is still bad coding
         close order 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, and is marginally faster than below as we do not need to resolve PositionGetInteger(POSITION_MAGIC) if PositionGetSymbol(i)!=Symbol()
         close order 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 order logic;
      }
   }

Conversely, if the trigger to open a position occurs, we need to check that an existing position by the EA does not exist.

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 need to call PositionGetSymbol(i) or PositionGetTicket(i) first.

This is works:

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

This does not:

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

Discussion

No comments yet.

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 )

Google+ photo

You are commenting using your Google+ 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
Advertisements
%d bloggers like this: