EA not placing correct orders all the time.

 

Hey Everyone.

I am having a few problems with my code. There are many problems, and as I hope you can appreciate, I am new to coding and am doing it in my spare time - I am slowly working through them.
The problem I am currently trying to overcome is that occasionally the EA is only placing an order one way. For example, only a sell, or only a buy. This is only sometimes. It should place a buy and sell at the same time.
Before anyone says "this is not a sound trading strategy", I am not worried, the point here is for me to learn how to code, rather than the strategy. I know my code may not be the most efficient, but I am just trying to get it to work before I refine it.

So could anyone tell me why this may be happening? As I said, I am new to coding, so rather than one or two word answers, if you could briefly explain it, it may help me learn what I am doing wrong.

Thanks.

#include <stdlib.mqh>

// External Variables
extern double StopLoss = 0.00300;
extern double TakeProfit = 0.00400;
extern double LotSize = 1;
extern int MagicNumber = 123;

// Global Variables
int SellLimit;
int BuyStop;
int BuyLimit;
int SellStop;

// Start Function
int start()
        {
                double DayHigh = iHigh(NULL, PERIOD_D1, 1);  // Yesterday's High
                double DayLow = iLow(NULL, PERIOD_D1, 1);  // Yesterday's Low
                double Spread = Ask - Bid;
                double Price = Bid;
                
                // Calculate SL & TP For Sell Limit
                RefreshRates();
                     double SellLimitSL = Price + StopLoss;
                                    double SellLimitTP = Price - TakeProfit;
                                   
                                    // Calculate SL & TP For Buy Stop                   
                RefreshRates(); 
                                    double BuyStopSL = Price - StopLoss;
                                    double BuyStopTP = Price + TakeProfit;
                                    
                                    // Calculate SL & TP For Buy Limit                  
                RefreshRates(); 
                                    double BuyLimitSL = Price - StopLoss;
                                    double BuyLimitTP = Price + TakeProfit;
                                    
                     // Calculate SL & TP For Sell Stop                 
                RefreshRates(); 
                                    double SellStopSL = Price + StopLoss;
                                    double SellStopTP = Price - TakeProfit;
                                    
                                    // Generating Comments
                                    string DH1 = DoubleToStr(DayHigh,5);
                                    string DL1 = DoubleToStr(DayLow,5);
                                    string BD1 = DoubleToStr(Bid,5);
                                    string AK1 = DoubleToStr(Ask,5);
                                    string SPRD = DoubleToStr(Spread,5);
                                    Comment("Previous Day High: " + DH1+"\nPrevious Day Low: " + DL1+"\nCurrent Bid Price: " + BD1+"\nCurrent Ask Price: " 
                                        + AK1+"\nCurrent Spread: " + SPRD);
                                                    
                                                                
                // Previous Day High // 
                if(Price > DayHigh && SellLimit == 0 && BuyStop == 0)
         {              
                                // Open Sell Limit
                                SellLimit = OrderSend(Symbol(),OP_SELLLIMIT,LotSize,Bid,5,SellLimitSL,SellLimitTP,"SellLimit Order",MagicNumber,0,Green);

                        // Open Buy Stop
                                BuyStop = OrderSend(Symbol(),OP_BUYSTOP,LotSize,Ask,5,BuyStopSL,BuyStopTP,"BuyStop Order",MagicNumber,0,Green);
         }
         
                           
        // Previous Day Low //
                if(Price < DayLow && SellStop == 0 && BuyLimit == 0)
         {
                    // Open Buy Limit
                                BuyLimit = OrderSend(Symbol(),OP_BUYLIMIT,LotSize,Ask,5,BuyLimitSL,BuyLimitTP,"BuyLimit Order",MagicNumber,0,Green);

                                // Open Sell Stop
                                SellStop = OrderSend(Symbol(),OP_SELLSTOP,LotSize,Bid,5,SellStopSL,SellStopTP,"SellStop Order",MagicNumber,0,Green);
         }    
             
                return(0);
        }
 
NewCoder47:

Hey Everyone.

I am having a few problems with my code. There are many problems, and as I hope you can appreciate, I am new to coding and am doing it in my spare time - I am slowly working through them.
The problem I am currently trying to overcome is that occasionally the EA is only placing an order one way. For example, only a sell, or only a buy. This is only sometimes. It should place a buy and sell at the same time.
Before anyone says "this is not a sound trading strategy", I am not worried, the point here is for me to learn how to code, rather than the strategy. I know my code may not be the most efficient, but I am just trying to get it to work before I refine it.

So could anyone tell me why this may be happening? As I said, I am new to coding, so rather than one or two word answers, if you could briefly explain it, it may help me learn what I am doing wrong.

Thanks.

Some general comments:

  • the code in your start() function is minimal so will execute very quickly, you do not need RefreshRates() at all, and certainly not four calls. In between your RefreshRates() calls you don't even use Ask or Bid . . .
  • if your OrderSend() fails you need to know why, you capture the return values from your OrderSend() calls . . . why aren't you using them ? Read this: What are Function return values ? How do I use them ?
  • why are you using pending orders to place trades at the current price ?
  • you are using Bid to calculate your SL & TP for both your Buy and Sell orders . . . this does not allow for spread at all. Do your orders comply with this : Requirements and Limitations in Making Trades


The first thing you need to do if find out why one of your Orders fails . . . you need to use the return value and report an error when it occurs . . . read the thread I have linked to above, it will help you do exactly that. When you know why the Order fails you will be in a better position to be able to fix it.

 

Because OrderSend takes TIME, your bid/ask are out of date after the first. If they are out of date by more than 5 points, (1/2 pip on a 5 digit broker) the second will fail.

  1. What are Function return values ? How do I use them ? - MQL4 forum You would have found out why.
  2. Adjusting for 4/5 digit brokers, adjusting for ECN brokers
  3. RefreshRates() AFTER orderSend. Not the three that don't ever refer to Bid/Ask
 
Thanks Guys.
I have Adjusted the Pending Orders, to just normal market orders. I have moved the refresh rates so they are between the market orders. I have also modified the SL & TP for the orders, so they use Ask & Bid, rather than just Bid. Hopefuly these will help fix the problem.

I understand the reporting of the error, however I am confused as to where I put it in the code, how does it differentiate between the four OrderSend's? Do I put it after each one? Or at the end of the two tests?
Help with where to place the OrderSend function return would be helpful.

Thanks so far guys.
 
NewCoder47:

I understand the reporting of the error, however I am confused as to where I put it in the code, how does it differentiate between the four OrderSend's? Do I put it after each one? Or at the end of the two tests?
Help with where to place the OrderSend function return would be helpful.

Each OrderSend can fail, so you need to report the error for each one . . .
 

Ok, so I have put the function return checks in after each order send. Is this correct?? Can someone let me know that this would report correctly if there was a problem???

 

    		// Previous Day High // 
		if(Price > DayHigh && SellLimit == 0 && BuyStop == 0)
         	{		 
         	RefreshRates(); 
			      	// Open Sell Limit
			        SellLimit = OrderSend(Symbol(),OP_SELLLIMIT,LotSize,Bid,5,SellLimitSL,SellLimitTP,"SellLimit Order",MagicNumber,0,Green);
    
                  if( OrderSend(Symbol(),OP_SELLLIMIT,LotSize,Bid,5,SellLimitSL,SellLimitTP,"SellLimit Order",MagicNumber,0,Green) < 0 )  //  OrderSend has failed and has returned a value of  -1
                  {
                  Print("Order Send failed, error # ", GetLastError() );
                  }
       
         	
                 		// Open Buy Stop
			        BuyStop = OrderSend(Symbol(),OP_BUYSTOP,LotSize,Ask,5,BuyStopSL,BuyStopTP,"BuyStop Order",MagicNumber,0,Green);
         
                 if( OrderSend(Symbol(),OP_BUYSTOP,LotSize,Ask,5,BuyStopSL,BuyStopTP,"BuyStop Order",MagicNumber,0,Green) < 0 )  //  OrderSend has failed and has returned a value of  -1
                  {
                  Print("Order Send failed, error # ", GetLastError() );
                  }
         
       	       }
 
OK, so I have found that this code effectively places another order, rather than reporting on the previous order. How do I arrange this so it reports the errors of the previous OrderSend, rather than placing another order?
 

I have now tried this approach. Will this report the error correctly???

                // Previous Day High // 
                if(Price > DayHigh && SellLimit == 0 && BuyStop == 0)
         {               
         RefreshRates(); 
                                // Open Sell Limit
                                SellLimit = OrderSend(Symbol(),OP_SELLLIMIT,LotSize,Price,5,SellLimitSL,SellLimitTP,"SellLimit Order",MagicNumber,0,Green);
    
                  if(SellLimit < 0 )  //  OrderSend has failed and has returned a value of  -1
                  {
                  Print("Order Send failed, error # ", GetLastError() );
                  }
       
                        // Open Buy Stop
                                BuyStop = OrderSend(Symbol(),OP_BUYSTOP,LotSize,Price1,5,BuyStopSL,BuyStopTP,"BuyStop Order",MagicNumber,0,Green);
         
                 if(BuyStop < 0 )  //  OrderSend has failed and has returned a value of  -1
                  {
                  Print("Order Send failed, error # ", GetLastError() );
                  }
         
         }
 
NewCoder47:

Ok, so I have put the function return checks in after each order send. Is this correct?? Can someone let me know that this would report correctly if there was a problem???

You need to take some time to understand what return values are . . .  in this code you are performing 2 OrderSends,  the first one on it's own and the 2nd  as part of the if command.  You only need the 2nd . . .
 
NewCoder47:

I have now tried this approach. Will this report the error correctly???

That looks OK.  You might want to edit the printed message so yo can tell what Order has failed . . .  if you use  

"Order Send failed, error # ", GetLastError()

 for all the OrderSend messages you won't know which is which.  Then you may also want to ininclude more information so that when an OrderSend has failed you are able to determine why . . . for example you might want to add . . .

Print("BuyStop failed, error # ", GetLastError(), " Price: ", Price1, " Bid: ", Bid, " Ask: ", Ask );

 Then you will find that you only get 4 digits output and you want all 5 . . .    so . . .

Print("BuyStop failed, error # ", GetLastError(), " Price: ", DoubleToStr(Price1, 5), " Bid: ", DoubleToStr(Bid, 5), " Ask: ", DoubleToStr(Ask, 5) );
 

Thanks for that. Ill have a go tomorrow night to refine it further.

Reason: