How can I cancel a trade when another is open and keep the open trade for a given duration?

 

I have written the code below that opens a buy and sell trade (a certain number of pips above and below the ask and bid price) at a specific time.

  1. How can I close/cancel one immediately when the other is opened?

  2. How can I close the opened trade if it's say X pips in profit or after a minute (depending on which condition is reached first)?

I'm a not too sure I've done the right thing in the code below and would really appreciate some help.


double spread = Ask-Bid;
extern datetime time;
extern int pipGap = 7;
extern int lotSize = 0.01;
extern int closeTimeInSeconds = 60;


int start() {
  if (TimeCurrent() >= StrToTime(time)){

    OrderSend(Symbol(),OP_BUYSTOP,lotSize, Ask + Point*pipGap, 0,0,0);
    OrderSend(Symbol(),OP_SELLSTOP,lotSize, Bid - Point*pipGap, 0,0,0);


    }


for(int pos = OrdersTotal()-1; pos >= 0 ; pos--) if (
    OrderSelect(pos, SELECT_BY_POS)           
){              
    int duration = TimeCurrent() - OrderOpenTime();
    if (duration >= closeTimeInSeconds)
         OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(),
                     3*Point);
}

   return(0);
}
 
HappyMeMe:

I have written the code below that opens a buy and sell trade (a certain number of pips above and below the ask and bid price) at a specific time.

  1. How can I close/cancel one immediately when the other is opened?

  2. How can I close the opened trade if it's say X pips in profit or after a minute (depending on which condition is reached first)?

I'm a not too sure I've done the right thing in the code below and would really appreciate some help.


The best way to learn programming is to try it out. This is especially easy on MetaTrader since we can use demo accounts.

I'll just give you some comments:

  if (TimeCurrent() >= StrToTime(time)){
    OrderSend(Symbol(),OP_BUYSTOP,lotSize, Ask + Point*pipGap, 0,0,0);
    OrderSend(Symbol(),OP_SELLSTOP,lotSize, Bid - Point*pipGap, 0,0,0);
  }

These lines have a couple of issues:

(1) StrToTime is not necessary since you've declared time as datetime type.

(2) The entire if condition will execute EVERY TICK AFTER time, so you'll be seeing tonnes of buystops and sellstops... LOL

(3) This is probably a good time to also include the TP price, since you've already decide that at X pips in profit you want the order closed.

So on top of checking time, you can set a bool flag to make sure that this chunk of code only gets executed once.

Next,

for(int pos = OrdersTotal()-1; pos >= 0 ; pos--) if (
    OrderSelect(pos, SELECT_BY_POS)           
){              
    int duration = TimeCurrent() - OrderOpenTime();
    if (duration >= closeTimeInSeconds)
         OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(),
                     3*Point);
}

Again, couple of issues:

(1) You need to check whether it's a buy, sell, buystop, or sellstop order right after orderselect to prevent closing the wrong order.

(2) You can't use OrderClosePrice() here since the order has not been closed. Instead, check whether this is a buy or sell order, and use Ask or Bid accordingly.

(3) This loop is also a good place to remove the opposite stop order (so if there is a buy, remove sellstop, and vice versa).

My suggestion is that you try running it, and attempt to reduce the number of obvious issues first, then get us to help out when you are stuck :). Learn to use Print() and GetLastError() functions - very good for figuring out what has gone wrong.

 
Seng Joo Thio:

The best way to learn programming is to try it out. This is especially easy on MetaTrader since we can use demo accounts.

I'll just give you some comments:

These lines have a couple of issues:

(1) StrToTime is not necessary since you've declared time as datetime type.

(2) The entire if condition will execute EVERY TICK AFTER time, so you'll be seeing tonnes of buystops and sellstops... LOL

(3) This is probably a good time to also include the TP price, since you've already decide that at X pips in profit you want the order closed.

So on top of checking time, you can set a bool flag to make sure that this chunk of code only gets executed once.

Next,

Again, couple of issues:

(1) You need to check whether it's a buy, sell, buystop, or sellstop order right after orderselect to prevent closing the wrong order.

(2) You can't use OrderClosePrice() here since the order has not been closed. Instead, check whether this is a buy or sell order, and use Ask or Bid accordingly.

(3) This loop is also a good place to remove the opposite stop order (so if there is a buy, remove sellstop, and vice versa).

My suggestion is that you try running it, and attempt to reduce the number of obvious issues first, then get us to help out when you are stuck :). Learn to use Print() and GetLastError() functions - very good for figuring out what has gone wrong.


Okay, I've been reading around and watching some examples and I've put my EA together based on the conditions I posted in the info you provided. But I'm still getting a number of errors and I'm not sure if my code would achieve what it's suppose to. I would be grateful if you'd please help me out. I attached what I've done so far. For some reason I couldn't paste the code in the comments.

Files:
LatestEA.mq4  3 kb
 
HappyMeMe:

I'm still getting a number of errors.

I'm assuming that you DO want to learn how to code your own EA, otherwise you would have gone to the freelance section to get someone to finish the job for you.

As such, I'll just guide you along, rather than solving all issues for you in one go.

Based on your file, I've done some reformatting (yes, formatting of code is important - makes it easier to debug), and added comments on what you need to change/add in order to move on to the testing stage - you just need to search for 'SJT' to see where I've changed/commented. Basically the file can compile now, but it won't do much since I've commented out lines that are improperly coded, for you to work on.


HappyMeMe:

I'm not sure if my code would achieve what it's suppose to.

Need not worry about that now. Focus on solving all the compilation errors first, then test run the EA part by part to see how each part behaves.

Files:
HappyMeMe.mq4  4 kb
 
Seng Joo Thio:

I'm assuming that you DO want to learn how to code your own EA, otherwise you would have gone to the freelance section to get someone to finish the job for you.

As such, I'll just guide you along, rather than solving all issues for you in one go.

Based on your file, I've done some reformatting (yes, formatting of code is important - makes it easier to debug), and added comments on what you need to change/add in order to move on to the testing stage - you just need to search for 'SJT' to see where I've changed/commented. Basically the file can compile now, but it won't do much since I've commented out lines that are improperly coded, for you to work on.


Need not worry about that now. Focus on solving all the compilation errors first, then test run the EA part by part to see how each part behaves.


Thanks. I've made a little progress by solving all the errors, but when I run it nothing happens. It doesn't set the buy and sell trade at the specified time. Also I've read the definition for OrderClose but I'm not sure I am using them correctly to solve my problem. Also not certain about the  "if (!elem.check()) {} " block is right. Here's my updated code below:

Files:
 
HappyMeMe:


Thanks. I've made a little progress by solving all the errors, but when I run it nothing happens. It doesn't set the buy and sell trade at the specified time. Also I've read the definition for OrderClose but I'm not sure I am using them correctly to solve my problem. Also not certain about the  "if (!elem.check()) {} " block is right. Here's my updated code below:

Here's the error:

int ticket1=OrderSend(Symbol(),OP_BUYSTOP,lotSize, Ask + Point*pipGap, 0,0,0), ticket2=OrderSend(Symbol(),OP_SELLSTOP,lotSize, Bid - Point*pipGap, 0,0,0);

You can combine ticket1 and ticket2 this way in one line, but it's ugly (LOL). Should split into two lines.

Next, check the return values of OrderSend, which will be assigned to ticket1 and ticket2 (*hint* use Print())... they're -1.

Then I added 'Print(GetLastError())' right after, and get error 130 - Invalid Stop. So Ask+Point*pipGap and Bid-Point*pipGap are not good.

Then, if you search for the documentation of OrderSend, you'll get to this page, which tells you that "At placing of a pending order, the open price cannot be too close to the market. The minimal distance of the pending price from the current market one in points can be obtained using the MarketInfo() function with the MODE_STOPLEVEL parameter. In case of false open price of a pending order, the error 130 (ERR_INVALID_STOPS) will be generated.

So orders get opened after I make these changes:

      if (canSetPendingOrders)
      {
         double StopLevel = MarketInfo(NULL,MODE_STOPLEVEL);
         int ticket1=OrderSend(Symbol(),OP_BUYSTOP,lotSize,Ask+Point*MathMax(pipGap,StopLevel),0,0,0);
         int ticket2=OrderSend(Symbol(),OP_SELLSTOP,lotSize,Bid-Point*MathMax(pipGap,StopLevel),0,0,0);
         listC2Orders.Add(new C2Orders(ticket1,ticket2));
         canSetPendingOrders = false;
      }

Learn to make use of Print() for debugging, to print out variables, or GetLastError(), or just a dummy string just so that you know that certain parts are executed, etc.

Few points to note:

- remember to initialise your time variable.

- whether 'if (!elem.check()) ' is right really depends on what kind of logic you are implementing - I won't know. but looking at the check() function, 'OrderType()<=OP_BUY' and 'OrderType()<=OP_SELL' condition checks are not useful (see this - OP_BUY and OP_SELL takes on integer values)... consider using == instead of <=. But of course, I won't know your logic, so you'll have to decide yourself.

- using the global 'bool canSetPendingOrders' will be problematic when you recompile and/or reload your code... because it'll reset back to default, and your OrderSends will get triggered again, and you'll end up having many buystops and sellstops. A more robust way is to check whether you already have buystops and sellstops around.

OrderSend - Trade Functions - MQL4 Reference
OrderSend - Trade Functions - MQL4 Reference
  • docs.mql4.com
Returns number of the ticket assigned to the order by the trade server or -1 if it fails. To get additional error information, one has to call the GetLastError() function. At opening of a market order (OP_SELL or OP_BUY), only the latest prices of Bid (for selling) or Ask (for buying) can be used as open price. If operation is performed with a...
 
HappyMeMeHow can I close/cancel one immediately when the other is opened?
for(int pos = OrdersTotal()-1; pos >= 0 ; pos--) if (
    OrderSelect(pos, SELECT_BY_POS)           
){              
    int duration = TimeCurrent() - OrderOpenTime();
    if (duration >= closeTimeInSeconds)
         OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(),
                     3*Point);
}

Go through the list and find out whether you have an open order (OrderType() <= OP_SELL). If you do, go through the list and delete pending order (OrderType() > OP_SELL).

Reason: