Trader’s Tech – Writing Your Own EA Part 18 – Functions

Forex RobotHere we go again. Hopefully we can get through this article without finding any more programming errors. Remember when you do your own programming, errors like I’ve made are considerably less public, so therefore less painful. ;)

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

In Part 17 we started the OpenTrade() function. Mostly we discussed the quirks of MT4. I want to help you through as many of those quirks as possible so you won’t have to waste time discovering them on your own. In this part, we’ll continue with the OpenTrade() function.

If you recall, we will be calling the OpenTrade() function with a single parameter – the direction of our trade – and we will be returning nothing to the caller. So this is how we will open the function:

 

void OpenTrade(int TradeDir)
    {
    }

We will want to find the prices for the Stop Loss (SL) and Take Profit (TP) before calling the OrderSend() function. We will also need to know our trade size, allowed slippage (the amount of pips the price can slip and still enter the order), trade comments and trade arrow color we would like to use.

There are other minutiae that needs handling (minimum distance of SL & TP, minimum/maximum trade size, etc.), but in keeping with the keep it simple maxim, we’re going to hold those explanations for a future article.

Let’s fill out our function just a little bit (or a lot):

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(TradeContextIsBusy())  //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(TradeContextIsBusy())
                sleep(100);
            RefreshRates();
            OrderSelect(Ticket,SELECT_BY_TICKET);
            ModifyResult = OrderModify(Ticket,OrderPrice(),
                                       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(TradeContextIsBusy())  //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(TradeContextIsBusy())
                sleep(100);
            RefreshRates();
            OrderSelect(Ticket,SELECT_BY_TICKET);
            ModifyResult = OrderModify(Ticket,OrderPrice(),
                                       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)

I apologize. That was a lot of code to just blow right out there, but it must be viewed as a big group. I’ll step through each line and explain it.

For starters, I used a new double variable TradeSize to hold the trade size. At first blush that may seem redundant, since we have the external variable LotSize, but this is for future expansion. Most programs don’t use a fixed trade size and you will actually be calculating a trade size in this function. In this case, you could have just used the external variable LotSize.

You’ll notice that I separated the function into two groups, trade direction long (TradeDir == 1) and short (TradeDir == -1). This is because several calculations require us to know the direction of the trade (SL & TP) and as I mentioned earlier, when calling a market order trade, it’s best to use the Ask and Bid to be sure we’ve got the latest price. The code in each of these sections is essentially identical – with the exception of using Bid/Ask or +/- when calculating the SL & TP. I’ll discuss the long trade section, know that the explanations are the same for the short trade section.

In the long trade section, I’ve used the Bid to calculate the TP and SL. The long (buy) trade is opened at the Ask and closed at the Bid, so using the Bid to calculate the TP and SL should allow for the spread. Since we designated the SL & TP in points in the external variables, we use the built-in constant Digits to convert that number to price. In a later article we’ll discuss using actual pips instead of points which is broker-specific.

Next you’ll see the code I mentioned in Part 17, testing to see if the trade context is busy. These two lines will save you much grief:

while(IsTradeContextBusy())
    sleep(100);
RefreshRates();

This just sets up a while loop that continues looping and sleeping while the trade context is busy, then refreshes the built-in variables when it stops looping. I always use these lines ahead of executing any type of trade opening/modifying/closing activity.

Well, we’re out of space again today. We’ll pick it up from right here tomorrow. Thanks for your attention. Please don’t hesitate to ask question and comment on these articles. And please follow me on Twitter.

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!

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