Chapter 2

Calc Digits / work with ECN Broker

In this chapter we will fix the Digits Problem and we will make the EA work for ever ECN Broker.

Open 3 black crows

But First the solution from the first tutorial. This is how to open a sell order when the last 3 candles are bearish:
   if(TotalOpenOrders() == 0 && IsNewBar() == true)
   { 
      // Buy Logic
      if(Close[1] > Open[1] && Close[2] > Open[2] && Close[3] > Open[3])
      {
         //Open Buy Order
         OrderSend(_Symbol,OP_BUY,LotSize,Ask,Slippage,Ask-StopLoss*_Point,Ask+TakeProfit*_Point,"BUY",MagicNumber);
      }      
      
      // Sell Logic
      if(Close[1] < Open[1] && Close[2] < Open[2] && Close[3] < Open[3])
      {
         //Open Buy Order
         OrderSend(_Symbol,OP_SELL,LotSize,Bid,Slippage,Bid+StopLoss*_Point,Bid-TakeProfit*_Point,"SELL",MagicNumber);
      }
   }

4/5 Digits or 2/3 Digits

So we begin with the Digits problem. For now we use the predefined variable _Point to convert the TakeProfit and StopLoss. But we do want to create a function which gives us the same point value for 4 and 5 respectively 2 and 3 digits symbols. We first create the global variables MyPoint and MySlippage. We put this right below our input parameters:
//--- global variable
double MyPoint;
int    MySlippage;
Now we create the function which stores the correct value in these 2 variable (MyPoint and MySlippage) and put them below to our custom functions:
// Get My Points   
double MyPoint()
{
   double CalcPoint = 0;
   
   if(_Digits == 2 || _Digits == 3) CalcPoint = 0.01;
   else if(_Digits == 4 || _Digits == 5) CalcPoint = 0.0001;
   
   return(CalcPoint);
}


// Get My Slippage
double MySlippage()
{
   double CalcSlippage = 0;
   
   if(_Digits == 2 || _Digits == 4) CalcSlippage = Slippage;
   else if(_Digits == 3 || _Digits == 5) CalcSlippage = Slippage * 10;
   
   return(CalcSlippage);
}
We only have to calculate these values one time. Only when we attach the EA to the chart. So we call these function in the OnInit() section. Like this:
int OnInit()
  {
//---
   MyPoint = MyPoint();
   MySlippage = MySlippage();
   
//---
   return(INIT_SUCCEEDED);
  }
Now we normalize our TakeProfit, StopLoss and Slippage:
//--- input parameters
input int      TakeProfit=50;
input int      StopLoss=50;
input double   LotSize=0.1;
input int      Slippage=3;
input int      MagicNumber=5555;
And we replace all the Slippage and _Point in the OnTick functions with our 2 new global variables MyPoint and MySlippage. So the 2 OrderSend functions would look like this:
//Open Buy Order
OrderSend(_Symbol,OP_BUY,LotSize,Ask,MySlippage,Ask-StopLoss*MyPoint,Ask+TakeProfit*MyPoint,"BUY",MagicNumber);
and
//Open Buy Order
OrderSend(_Symbol,OP_SELL,LotSize,Bid,MySlippage,Bid+StopLoss*MyPoint,Bid-TakeProfit*MyPoint,"SELL",MagicNumber);
Here is the file we have created until now (my-first-ea-2): Download the source code

Open Order on ECN Brokers and Error handling

On ECN Broker you can not send an order with a TakeProfit or StopLoss. You first have to send an order without TP/SL and later to modify the order. I also show you how to handle errors if for example the order could not be placed or modified successfully. What we do: First we save the ticket number from the just opened Order in the int ticket. Then we check if we received a ticket from the broker. Either we receive a ticket (example 652474285) or in case that the order could not be opened we receive a -1. So in the if(ticket<0) part we check if the order is less than one (-1) or not. Then we want to modify our order. For this we call the OrderModify function. We give it the ticket we received from above, the OrderOpenPrice from that order we just sent and the StopLoss and Takeprofit. The OrderModify function returns either a true or false which we store in the bool res. We check the result with if(!res) (the same as if(res == false) ) and print the corresponding message.
   if(TotalOpenOrders() == 0 && IsNewBar() == true)
   { 
      // Buy Logic
      if(Close[1] > Open[1] && Close[2] > Open[2] && Close[3] > Open[3])
      {
         //Open Buy Order
         int ticket = OrderSend(_Symbol,OP_BUY,LotSize,Ask,MySlippage,0,0,"BUY",MagicNumber);
            if(ticket<0)
            {
               Print("OrderSend failed with error #",GetLastError());
            }
            else
            {
               Print("OrderSend placed successfully");
            }
                       
         // Modify Buy Order
         bool res = OrderModify(ticket,OrderOpenPrice(),Ask-StopLoss*MyPoint,Ask+TakeProfit*MyPoint,0,Blue);
            if(!res)
            {
               Print("Error in OrderModify. Error code=",GetLastError());
            }
            else
            {
               Print("Order modified successfully.");
            }
      }              
      
      // Sell Logic
      if(Close[1] < Open[1] && Close[2] < Open[2] && Close[3] < Open[3])
      {
         //Open Buy Order
         int ticket = OrderSend(_Symbol,OP_SELL,LotSize,Bid,MySlippage,0,0,"SELL",MagicNumber);
            if(ticket<0)
            {
               Print("OrderSend failed with error #",GetLastError());
            }
            else
            {
               Print("OrderSend placed successfully");
            }
                       
         // Modify Buy Order
         bool res = OrderModify(ticket,OrderOpenPrice(),Bid+StopLoss*MyPoint,Bid-TakeProfit*MyPoint,0,Blue);
            if(!res)
            {
               Print("Error in OrderModify. Error code=",GetLastError());
            }
            else
            {         //Open Buy Order
         OrderSend(_Symbol,OP_BUY,LotSize,Ask,MySlippage,Ask-StopLoss*MyPoint,Ask+TakeProfit*MyPoint,"BUY",MagicNumber);
               Print("Order modified successfully.");
            }  
      }
   }
Now this works on all ECN and non-ECN brokers. And it prints us out if there was an error or if the EA could place the trade.

Clean up our source code

Our source code looks now really complex. I do not like to have it like this so I put the trade logic and the OpenOrder/ModifyOrder in a custom function and call it in the OnTick() section. You can download the EA below. You will see the EA is very easy to read. The OnTick() section is very small and all our custom functions are below. The OnTick() Section should look simple and clean, it should be like an index for all the function you have written below in the custom functions section and should look clean and clear like this:
   if(TotalOpenOrders() == 0 && IsNewBar() == true)
   { 
      // Check Buy Enty
      if(BuySignal() == true)
         {
            OpenBuy();
         }
      
      // Check Sell Enty
      else if(SellSignal() == true)
         {
            OpenSell();
         }  
   }
Please download the file to see the whole source code. In the next tutorial, I show you how to add indicators like Moving Average and RSI. Have questions about this mql4 tutorial? Write a comment or open a topic in the forum (if there is not already an answer for it) If you see an error please contact me. This MQL4 tutorial was created on July 23 2015. Next Chapter Download the source code
4.7/513 ratings

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.