New to mql4, need help to stop EA trading on every tick

 

Hi forum,

 

First time poster here, please forgive me for any bad etiquette.  I'll do my best to keep this post polite and informative for other readers.

 

Using this and other forums, I have spliced together a very rough EA.  I plan to develop it as my skill set grows.  For now, I have managed to successfully open and close a trade.  My problem arises when my code needs to analyse whether or not it should open/close a trade.  As a result, it is trading on every tick!  What a relief we get "play money" to test with...

 

I've listed the code below.  Essentially, I am manually opening a trade (long or short), and when the open order reaches a profit, I want the order to close, and a trade to open in the opposite direction.  Doesn't matter if profit is only 1 pip, I just want that condition to be met, and the trade closed.  Probably seems simple to the guru's out there, so I'd really appreciate any input.  I know there are countless code snippets like this already in existence, but I'd like some advice on something I've written myself, so I can learn properly from it.  Copy/Paste can only get one so far...

 

Code compiles with no errors.  From what I gather, there must be something wrong with my syntax, as orders are being shot off in rapid fire - It seems as though my "if" statements governing conditions to open/close a trade are being bypassed. 

 

I've attached below one half of the code, the other half is exactly the same ("mirrored" so to speak, to trade in the opposite direction).  I've added comments to show what I understand the code to be doing.  Note, it is very likely my understanding is wrong, so please tell me if I am using things incorrectly.

 

I have moderate recreational experience in VB coding, but am finding it hard to transfer these skills to mql4.  I'm sure if you're reading this post you can understand why.

 

Once again, any advice to get me headed in the right direction (and even a lesson of my errors in layman's terms, if time permits) would be extremely useful.  Thanks in advance to those who contribute, particularly the forum regulars who make this place so useful for all of us.

 

 

// Buy Function

void SendBuy(double Lots)

{
   
int PositionIndex;                                                                                 //  <-- Declare variable used as the index in the loop.
int TotalNumberOfOrders;                                                                           //  <-- Declare variable for number of current orders.
int OrderTypeModifier;                                                                             //  <-- Declare variable for order type identification.
int Profit;                                                                                        //  <-- Declare variable for profit.

TotalNumberOfOrders = OrdersTotal();                                                               //  <-- Store the number of orders in the variable.

for(PositionIndex = TotalNumberOfOrders - 1; PositionIndex >= 0 ; PositionIndex --)                //  <-- Loop through all Orders (Count down, not up.)
   {
   if    (!OrderSelect(PositionIndex, SELECT_BY_POS, MODE_TRADES) ) continue;                      //  <-- If the OrderSelect fails, advance the loop to the next PositionIndex.
           
           OrderTypeModifier = ((OrderType() * 2) - 1) * -1;                                       //  <-- Returns value of 1 for a long order, -1 for a short order.
           Profit = ( OrderClosePrice() - OrderOpenPrice() ) * OrderTypeModifier * Point;          //  <-- Returns positive value for a gain, negative value for a loss.
   
   if    ( OrderType() == OP_SELL                                                                  //  <-- Check if order is a short order.
      && (  Profit >= 1 )                                                                          //  <-- Check for profit on short order.
      &&   OrderSymbol() == Symbol())                                                              //  <-- Check order symbol matches EA symbol.   
      {                                                               
      if (!OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(), 0 ) )                        //  <-- Try to close the order.
         Print("Order Close failed, order number: ", OrderTicket(), " Error: ", GetLastError() );  //  <-- If the order close fails, show information.
      }
   }
 

I should add, the code above and my other "SendSell" function are called on directly via the "Start" function. 

 
5T3L7H:

 

Hi forum,

 

First time poster here, please forgive me for any bad etiquette.  I'll do my best to keep this post polite and informative for other readers.

 

You could at least acknowledge the source for "your" code . . .
 
5T3L7H:

 

Using this and other forums, I have spliced together a very rough EA.  I plan to develop it as my skill set grows.  For now, I have managed to successfully open and close a trade.  My problem arises when my code needs to analyse whether or not it should open/close a trade.  As a result, it is trading on every tick!  What a relief we get "play money" to test with...

 

You don't show the code that places an order . . .  it might help if you show that code in relation to the code above.
 
5T3L7H: It seems as though my "if" statements governing conditions to open/close a trade are being bypassed. 
  1. Put print statements before and inside ifs so you find out why.
  2. Profit = ( OrderClosePrice() - OrderOpenPrice() ) * OrderTypeModifier * Point;      
             (   1.2347          -    1.2345        )                     * 0.0001
                              0.0002                                      * 0.0001
                                              0.00000002 (zero as an int)
    If you want profit to be profit in points divide by Point.
  3. OrderTypeModifier = ((OrderType() * 2) - 1) * -1; 
    Don't write unreadable code like that. It's also wrong:
    Op
    Result
    0 Buy
    +1
    1 Sell
    -1
    2 Buy Limit
    -3
    3 Sell Limit
    -5
    4 Buy Stop
    -7
    Separate and self-document.
    double   Direction(int op_xxx){ return( 1. - 2. * (op_xxx%2) );               }
    :
    OrderTypeModifier = Direction(OrderType());

 
RaptorUK:
You could at least acknowledge the source for "your" code . . .


Hi Raptor,

 

Obviously you recognize some of this code as your own work, which it is.  Please don't mistake me, I'm not trying to pass this off as my own masterpiece.  Reality is, it's a learning exercise, which is malfunctioning at best.  I fully acknowledge that it contains the work of others, and I am merely attempting to piece together bits of information as I gradually learn more.  I'm not going to list every page and author I've borrowed code from, or I would need a fully blown reference list.

5T3L7H 2014.06.24 15:46

Using this and other forums, I have spliced together a very rough EA.  I plan to develop it as my skill set grows.  For now, I have managed to successfully open and close a trade.

...

Once again, any advice to get me headed in the right direction (and even a lesson of my errors in layman's terms, if time permits) would be extremely useful.  Thanks in advance to those who contribute, particularly the forum regulars who make this place so useful for all of us.

 

As you say, I did not attach the code to open a trade.  This seems logical, and I don't know why I didn't do it in the first place.  See below:

 

// Buy Function

void SendBuy(double Lots)

{
   
int PositionIndex;                                                                                 //  <-- Declare variable used as the index in the loop.
int TotalNumberOfOrders;                                                                           //  <-- Declare variable for number of current orders.
int OrderTypeModifier;                                                                             //  <-- Declare variable for order type identification.
int Profit;                                                                                        //  <-- Declare variable for profit.

TotalNumberOfOrders = OrdersTotal();                                                               //  <-- Store the number of orders in the variable.

for(PositionIndex = TotalNumberOfOrders - 1; PositionIndex >= 0 ; PositionIndex --)                //  <-- Loop through all Orders (Count down, not up.)
   {
   if    (!OrderSelect(PositionIndex, SELECT_BY_POS, MODE_TRADES) ) continue;                      //  <-- If the OrderSelect fails, advance the loop to the next PositionIndex.
           
           OrderTypeModifier = ((OrderType() * 2) - 1) * -1;                                       //  <-- Returns value of 1 for a long order, -1 for a short order.
           Profit = ( OrderClosePrice() - OrderOpenPrice() ) * OrderTypeModifier * Point;          //  <-- Returns positive value for a gain, negative value for a loss.
   
   if    ( OrderType() == OP_SELL                                                                  //  <-- Check if order is a short order.
      && (  Profit >= 1 )                                                                          //  <-- Check for profit on short order.
      &&   OrderSymbol() == Symbol())                                                              //  <-- Check order symbol matches EA symbol.   
      {                                                               
      if (!OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(), 0 ) )                        //  <-- Try to close the order.
         Print("Order Close failed, order number: ", OrderTicket(), " Error: ", GetLastError() );  //  <-- If the order close fails, show information.
      }
   }
 
//-------------------------------------------------------------------------------------------------

   if (TotalNumberOfOrders < 1)                                                                    //  <-- Ensure only one order is open at any time.
   
      {
      int      Ticket_Value;
      int      Slippage_Value;
      double   Take_Profit_Value;
      double   Stop_Loss_Value;
      
      Take_Profit_Value = 0;
      Stop_Loss_Value = 0;
      Slippage_Value = 0;
      
      Ticket_Value = OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage_Value, Stop_Loss_Value, Take_Profit_Value, "", Magic_Number_Long, 0, Green);
     }
}

 

This SendBuy function, as well as the associated SendSell function is called directly every tick, through the Start function.

 

My expectation is that an open order will be closed once it is profitable, and subsequently, a new trade will be opened in the opposing direction.   This is not the case.

 

I am assuming therefore, that the code is ignoring the conditions set to close a trade.  This is because there is a limit of 1 open order, no new orders are to open if it will exceed this amount.  This is working.  Orders are being closed though before they reach a profit.  They close at a loss on every tick, and that follows with a trade being opened in the opposite direction every tick, which is then closed immediately at a loss on the next tick, etc...

 

For this reason, I'm inclined to think I've made a mistake somewhere in the vicinity  of the condition check to see if the trade is profitable? 

 
WHRoeder:
  1. Put print statements before and inside ifs so you find out why.
  2. If you want profit to be profit in points divide by Point.
  3. Don't write unreadable code like that.
  4. Separate and self-document.


Hi WHRoeder,

 

Thank you very much for the suggestions.  I'm working on putting some print statements in there now.  May seem simple to some, but to an amateur, it's a long process.

 

What do you refer to in your third suggestion, "Don't write unreadable code like that." ?  Will the negative values of other order types cause problems?  If so, why is it permissible to use the "-1" value for a sell order?

 

With suggestion four, would you mind explaining why this method is better?  To me, it looks like the same result will be returned, yet the method is only very slightly different.  What are the advantages?

 
5T3L7H:


 My expectation is that an open order will be closed once it is profitable, and subsequently, a new trade will be opened in the opposing direction.   This is not the case.


So if your trade is in your favour by 1 point (1/10th a pip) you want it to be closed ?  in the time it takes to send the order price may have moved back against you by more than one point . . .  you need to see what is happening,  Print()  Profit,  OrderClosePRice() and OrderOpenPrice() in the same block of code that calls OrderClose(),  then when an order is closed you will know what these values were at the time,  then you can determine what is going on.

 
RaptorUK:


So if your trade is in your favour by 1 point (1/10th a pip) you want it to be closed ?  in the time it takes to send the order price may have moved back against you by more than one point . . .  you need to see what is happening,  Print()  Profit,  OrderClosePRice() and OrderOpenPrice() in the same block of code that calls OrderClose(),  then when an order is closed you will know what these values were at the time,  then you can determine what is going on.


Brilliant, thanks Raptor.  I will implement that idea.

 

Obviously this code wouldn't make the greatest EA.  In fact, I never intend to use it as one on it's own.  It's more so an exercise for me, so I can see how individual functions work step by step.

 

After I understand this step, I'll work on something different, then may try to start combining things.  Slow and steady, right...?

 

Thanks very much for your help.  I see posts from yourself and WHRoeder in just about every thread I read - You guys certainly make this forum a great source of information.  Thanks to you both for donating your time to teach the less learned of us!

 

So...  This is the part where I admit complete and utter stupidity...

 

:-)

 

Turns out I forgot I had an old EA running at the same time as this one.  (Yup, that'll do it...!)

 

It happened to be a one liner I made to see the OrderClose function in action...  So it was the culprit closing my orders in rapid fire, then the code above was happily reopening one every time...

 

I was looking at the above code over and over, and just couldn't work out why it was missing the "if" conditions.  It all makes sense now...

 

All good though, the best lessons are learned from the stupidest mistakes, because you remember to never make the same one again!

 

Thanks again for your help Raptor and  WHRoeder.

Reason: