Trader’s Tech – Writing Your Own EA Part 24 – Bench Check

Forex RobotWe had some pretty major storms in the Midwest last night. It was sort of a non-event here on the farm in Northeastern Indiana, but it looked like it might have been bad in some places.I hope everyone is all right.

If you’re new to this series and want to check it out from the beginning, you can find that here.

In Part 23 we discussed the framework created by the MetaEditor wizard. Today we’re going to add our code to the editor and bench check it. Bench check is programmer-speak for reading through the code and making sure there are no typos or obvious logic issues. The MetaEditor is a pretty decent code editor, so I usually write the code right into the editor. Since this whole series is about writing EAs for MT4, I’ll stick to that.  But I just want to say that sometimes the editors with which you must work are not very good and you’ll want to use a third-party editor. And in some rare cases (not so much now as twenty years ago), there is no programming environment at all and you must use third-party editors and command-line compilers. So if you plan to be a programmer, keep those things in mind. The MT4 programming environment is pretty good but lacks one thing that has been included in most environments for years – an inline debugger. But I’ll save that rant for another day. ;)

During the course of preparing all the code, I discovered an error in our IsThereAnOpenTrade() function from Part 13. In the if() statement, I used:

if(OrderPair() == Symbol()....

Rather than:

if(OrderSymbol() == Symbol()...

And another one in the IsThereACrossOver() function in Part 14:

int IsThereACrossover()

Should be:

int IsThereACrossOver()

Do you see the difference? The computer will see it.  And one more:

start()

Should be:

int start()

You must declare the return value of your functions. There are also several typos in the OpenTrade() function in Part 18. They are mostly uppercasing issues and the others are misspellings of the IsTradeContextBusy() and OrderOpenPrice() functions. They’ve been corrected in the code below. As I mentioned, I usually type write into the MetaEditor and it picks up on many of these errors when you type them (it uses color coding to identify built-in functions, if the color doesn’t change to lavender, you know you’ve misspelled the function name.) If you have any questions about changes I’ve made to the code, please don’t hesitate to ask.

Let’s look at our completed code:

 

//+------------------------------------------------------------------+
//|                                                     SMACross.mq4 |
//|                                  Copyright 2013, T Black & Assoc |
//|                                    http://www.winnersedgetrading.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2013, T Black & Assoc"
#property link      "http://www.winnersedgetrading.com"

//--- input parameters
extern double    LotSize=0.01;
extern int       MA1=3;
extern int       MA2=30;
extern int       SLPoints=15;
extern int       TPPoints=25;
extern int       MagicNumber=1234567;

static datetime LastTradeTime = 0;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----

//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----

//----
   return(0);
  }

bool NewBar()
   {
   datetime CurrBarTime = iTime(NULL,0,0);
   bool NewBar = false;
   if(CurrBarTime > LastTradeTime)
      {
      NewBar = true;
      }

   return(NewBar);
   }

bool IsThereAnOpenTrade()
   {
   bool OpenTrade = false;
   int i;
   for (i = 0; i < OrdersTotal(); i++)
      {
      OrderSelect(i,SELECT_BY_POS);
      if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
         {
         OpenTrade = true;
         break;
         }
      }
   return(OpenTrade);
   }
    
    
int IsThereACrossOver()
    {
    int CrossOver = 0;
    double currMA1, currMA2;
    double priorMA1, priorMA2;
    int currLoc, priorLoc;

    //Assign the prices for the moving averages
    currMA1 = iMA(NULL, 0, MA1, 0, MODE_SMA, PRICE_CLOSE, 1);
    currMA2 = iMA(NULL, 0, MA2, 0, MODE_SMA, PRICE_CLOSE, 1);
    priorMA1 = iMA(NULL, 0, MA1, 0, MODE_SMA, PRICE_CLOSE, 2);
    priorMA2 = iMA(NULL, 0, MA2, 0, MODE_SMA, PRICE_CLOSE, 2);

    //Determine relative locations of the prior closed candle moving averages
    if (priorMA1 > priorMA2)
        priorLoc = 1;
    if(priorMA1 < priorMA2)
        priorLoc = -1;
    if(priorMA1 == priorMA2)
        priorLoc = 0;

    //Determine relative locations of the current closed candle moving averages
    if(currMA1 > currMA2)
        currLoc = 1;
    if(currMA1 < currMA2)
        currLoc = -1;
    if(currMA1 == currMA2)
        currLoc = 0;

    //Determine if a crossover has taken place
    if(priorLoc == -1 && currLoc == 1)
        CrossOver = 1;
    if(priorLoc == 1 && currLoc == -1)
        CrossOver = -1;

    return(CrossOver);
    }


void OpenTrade(int TradeDir)
   {
   double TP,SL,TradeSize;
   int Ticket;
   bool ModifyResult;

   TradeSize = LotSize;  //We don't have to calculate the TradeSize 
                    //since it's in the external variables

   if(TradeDir == 1)  //Long Trade
      {
      TP = Bid + (TPPoints / Digits);
      SL = Bid  - (SLPoints / Digits);
      while(IsTradeContextBusy())  //our loop for the busy trade context
         Sleep(100);  //sleep for 100 ms and test the trade context again
      RefreshRates();  //refreshing all the variables when the 
                      //trade context is no longer busy
      Ticket = OrderSend(Symbol(),OP_BUY,NormalizeDouble(TradeSize,2),
                        NormalizeDouble(Ask,Digits),2.0,0.0,0.0,"Trade Comment",
                        MagicNumber,Blue);
      if(Ticket >= 0)
         {
         while(IsTradeContextBusy())
            Sleep(100);
         RefreshRates();
         OrderSelect(Ticket,SELECT_BY_TICKET);
         ModifyResult = OrderModify(Ticket,OrderOpenPrice(),
                                    NormalizeDouble(SL,Digits),
                                    NormalizeDouble(TP,Digits),0,Blue);
         if(!ModifyResult)
            Alert("Stop Loss and Take Profit not set on order ",Ticket);
         }  //if(Ticket >= 0)
      else
         {
         Alert("Trade Not Entered");
         }  //else
      }  //if(TradeDir == 1)
   if(TradeDir == -1)
      {
      TP = Ask - (TPPoints / Digits);
      SL = Ask + (SLPoints / Digits);
      while(IsTradeContextBusy())  //our loop for the busy trade context
         Sleep(100);  //sleep for 100 ms and test the trade context again
      RefreshRates();  //refreshing all the variables when the 
                      //trade context is no longer busy
      Ticket = OrderSend(Symbol(),OP_SELL,NormalizeDouble(TradeSize,2),
                        NormalizeDouble(Bid,Digits),2.0,0.0,0.0,"Trade Comment",
                        MagicNumber,Blue);
      if(Ticket >= 0)
         {
         while(IsTradeContextBusy())
            Sleep(100);
         RefreshRates();
         OrderSelect(Ticket,SELECT_BY_TICKET);
         ModifyResult = OrderModify(Ticket,OrderOpenPrice(),
                                    NormalizeDouble(SL,Digits),
                                    NormalizeDouble(TP,Digits),0,Blue);
         if(!ModifyResult)
            Alert("Stop Loss and Take Profit not set on order ",Ticket);
         }  //if(Ticket >= 0)
      else
         {
         Alert("Trade Not Entered");
         }  //else
      }  //if(TradeDir == -1)
   }  //void OpenTrade()  


//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
   {
   int CrossOver;
   if(!IsThereAnOpenTrade())
      {
      //Enter code that executes if there is no open trade here.
      CrossOver = IsThereACrossOver();
      if(CrossOver != 0)
         {
         //Enter code that executes if there is a crossover
         if(NewBar())
           {
           //Set LastTradeTime to iTime(NULL,0,0)
           LastTradeTime = iTime(NULL,0,0);
           //Enter code to trigger a trade
           OpenTrade(CrossOver);
           }
         }
      }
   }
//+------------------------------------------------------------------+

Tomorrow we’ll actually copy and paste this into the MetaEditor and run the compiler on it. Thanks for your attention and please follow me on Twitter and LinkedIn.

Tim

 

here_for_you_001

1359774937_facebook 1359774984_linkedin 1359774949_twitter 1359774960_google 1359774973_rss 1360027635_youtube
Connect_With_Winners_Edge

Get trade set ups everyday!

The following two tabs change content below.

Latest posts by Tim Black (see all)

Follow our social media:
1359774937_facebook 1359774984_linkedin 1359774949_twitter 1359774960_google 1359774973_rss 1360027635_youtube

Winner’s Edge Trading, as seen on:

Winner's Edge Trading in the news

  • http://twitter.com/IsItCoffeeYet Tim Black

    Hi Buck,
    I’m terribly sorry for not responding sooner. I’m still hard at work on the series. I may have missed a day due to some family issues. You can find the list of the articles here. Thanks for your interest.

    Tim

  • Buck

    You stopped at part 36 and it looks like you’re not finished with these superb tutorials. Where can we find the remaining ones? Thanks in advance for all your help, Tim.