Transitioning from Manual trading to EA – Need help finalizing

 

 Hello All, 

 A friend of mine, who has a lot of experience coding in PHP and other languages, and I have been working together to a code an EA for a few weeks. This particular system that we are trying to code is one that my partner and I have manually back tested and traded for a few years now. we developed this trading strategy to be completely objective, so to take all of our emotions out of the market, and because it is objective it is programmable.  I have made some money off of it, but because of my crazy school and work schedule I haven’t realized the trade’s true potential. For the last 4 years my strategy would have doubled my account about 5 times a year, with the greatest drawdown of about 25 percent…  Recently I came to the realization that an EA would greatly enhance my chances for success, making every trade, and without emotion.  For these reasons I have begun the process of coding my first EA.

I have the basic code now finished and the logic in place, but it seems like the MT4 back tester has a mind of its own. My friend and I are stumped and have been trying to trouble shoot the code, and are left with unanswered questions. I thought I would reach out to you and lay my cards on the table. I was wondering if I showed you my trade and what I’m trying to do, maybe you can take a look at it and give me your opinion on what is going wrong.

 

This is my trade:

I trade the EUR/USD and the EJ

Time Frame: 4h

3 EMAS: 5, 20, 62

 For a buy:

If the 5 and 20 cross up and the 62 as underneath the cross it is a buy (however, if the 62 is above the cross up but the price closes about the 62, then we still take the buy)

Our take profit is when the price closes below the 5 EMA

Our stop is a trailing stop of 60 pips, trailing in 10 pip increments. However, if the price reaches positive 50 pips we move stops to 0.

The next part of the trade that isn’t included in my code that is figured into my manual trading strategy is a reentry if there is a engulfing candle. We only take these engulfing candles if the price pulls back to at least the 20EMA but not so far as to cross the 20EMA through the 62.    

Thanks so much,

Adam King              - Attached are a couple of pictures to clarify what my strategy....

// Override trading times (useful during testing)
extern bool   overrideTradingTimes = true;
// Define allowed trading times (by hour)
extern string tradingHoursOverride;
// Default values for fast, slow and trend eMAs
extern int    slowMA = 5;
extern int    slowMAShift = 0;
extern int    slowMAMethod = MODE_EMA;
extern int    slowMAAppliedTo = PRICE_CLOSE;
extern int    fastMA = 20;
extern int    fastMAShift = 0;
extern int    fastMAMethod = MODE_EMA;
extern int    fastMAAppliedTo = PRICE_CLOSE;
extern int    trendMA = 62;
extern int    trendMAShift = 0;
extern int    trendMAMethod = MODE_EMA;
extern int    trendMAAppliedTo = PRICE_CLOSE;
extern int    slippage = 3;
// Initial Take Profit about (used during OrderSend function
// NOTE: This is purposely set high, to ensure that orders are only closed when,
//       based on market conditions, the closeTrade function closes the trade)
extern int    initTakeProfit = 1000;
// Initial Stop Loss value, the order maybe modified by modifyStopLos function
extern int    initStopLoss = 50;
// Initial lot size
extern double lotSize = 0.1;

extern int    brokerSpread = 3;

int           tradingHoursArray[] = {0,1,5,6,7,8,23};
double        pips;
double        previousFastMA;
double        previousSlowMA;
double        previousTrendMA;
double        currentFastMA;
double        currentSlowMA;
double        currentTrendMA;
string        conditionMet;
string        arrowType;

static datetime lastBarOpenAt;
static double buyEntry;
static int stopLoss = NULL;

static int ticket;

void init()
{

}

int start()
{
    // Check if trading is allowed based on time
    if( checkIfTradingIsAllowed2() == false)
    {
        Print("Trade is not allowed at this time");
        return (-1);
    }
    RefreshRates();
    if( check_for_new_bar() )
    {
        get_MAs();

        // Clear variables for trade
        conditionMet = "";
        arrowType    = "";

        if( check_to_place_trade() == true )
        {
            Print( "Init Trade" );
            initiateTrade( conditionMet, arrowType );
        }

        if( OrdersTotal() > 0 )
        {
            check_modify_stoploss();
        }
    }

    // Close trade process
    if( check_to_close() == true )
    {
        closeTrade();
    }

    return(0);
}

bool checkIfTradingIsAllowed2()
{
    if( overrideTradingTimes == true ) return (true);
    if( ArrayBsearch( tradingHoursArray, TimeHour( TimeCurrent() ) ) == TimeHour( TimeCurrent() ) ) return (true);

    return (false);
}

//bool checkIfTradingIsAllowed()
//{
//    if( overrideTradingTimes == true ) return (true);
//    // If the current time is between the allowed trading times
//    if( (beginAllowTrading1 < TimeHour(TimeCurrent()) && TimeHour(TimeCurrent()) < endAllowTrading1) &&
//        (beginAllowTrading2 < TimeHour(TimeCurrent()) && TimeHour(TimeCurrent()) < endAllowTrading2) &&
//        (beginAllowTrading3 < TimeHour(TimeCurrent()) && TimeHour(TimeCurrent()) < endAllowTrading3) )
//    {
//        return (true);
//    }
//    else
//    {
//        return (false);
//    }
//}

void get_MAs()
{
    // Set Slow MA based on given params
    previousSlowMA = iMA(NULL, 0, slowMA, slowMAShift, slowMAMethod, slowMAAppliedTo, 2);
    currentSlowMA  = iMA(NULL, 0, slowMA, slowMAShift, slowMAMethod, slowMAAppliedTo, 1);
    // Set Fast MA based on given params
    previousFastMA = iMA(NULL, 0, fastMA, fastMAShift, fastMAMethod, fastMAAppliedTo, 2);
    currentFastMA  = iMA(NULL, 0, fastMA, fastMAShift, fastMAMethod, fastMAAppliedTo, 1);
    // Set Trend MA based on given params
    previousTrendMA = iMA(NULL, 0, trendMA, trendMAShift, trendMAMethod, trendMAAppliedTo, 2);
    currentTrendMA  = iMA(NULL, 0, trendMA, trendMAShift, trendMAMethod, trendMAAppliedTo, 1);
}

bool check_to_place_trade()
{
    //BUY CONDITIONS
    // normal buy condition
    if( currentFastMA > currentSlowMA &&
        previousSlowMA > previousFastMA &&
        currentSlowMA > currentTrendMA &&
        currentFastMA > currentTrendMA
       )
    {
        conditionMet = "Simple Cross";
Print("simple cross buy");
        arrowType    = Red;
        return (true);
    }
    // crossing 62 buy condition
    if( currentTrendMA > currentSlowMA &&
             currentTrendMA > currentFastMA &&
             previousFastMA < previousSlowMA &&
             previousSlowMA < previousTrendMA &&
             currentFastMA  > currentSlowMA &&
             Close[0]       > currentTrendMA )
   {
        conditionMet = "Cross through trend";
        arrowType    = Red;
Print("Cross through trend buy");
        return (true);
    }
    // SELL CONDITIONS
    // normal sell
    if( currentFastMA  < currentSlowMA &&
             previousSlowMA < previousFastMA &&
             currentSlowMA  < currentTrendMA &&
             currentFastMA  < currentTrendMA )
    {
        conditionMet = "Simple Cross";
        arrowType    = Green;
Comment( "simple cross sell" );
        return (true);
    }
    // crossing 62 sell condition
    if( currentTrendMA < currentSlowMA &&
             currentTrendMA < currentFastMA &&
             previousFastMA > previousSlowMA &&
             previousSlowMA > previousTrendMA &&
             currentFastMA  < currentSlowMA &&
             Close[0]       < currentTrendMA )
   {
        conditionMet = "Cross through trend";
        arrowType    = Green;
Comment( "cross through trend sell" );
        return (true);
    }
    return (false);
}

double adjustForDigits( int value )
{
    double adjusted;

    if( Digits == 5 || Digits == 3 )
    {
        adjusted = value * 10;
    }
    else
    {
        adjusted = value;
    }
    return (adjusted);
}

bool check_for_new_bar()
{
    if( lastBarOpenAt == Time[0] ) // This tick is not in new bar
    {
        return (false);
    }
    else
    {
          lastBarOpenAt = Time[0];
          return (true);
    }
}

int initiateTrade(string conditionMet, int arrowType)
{
    if( OrdersTotal() == 0 )
    {
        int ticket = OrderSend(Symbol(),OP_BUY,lotSize,Ask,adjustForDigits(slippage),0,0,conditionMet,0,0,arrowType);
        Comment("OrderSend("+Symbol()+",OP_BUY,"+lotSize+","+Ask+","+adjustForDigits(slippage)+",0,0,"+conditionMet+",0,0,"+arrowType+")");
        Alert("OrderSend("+Symbol()+",OP_BUY,"+lotSize+","+Ask+","+adjustForDigits(slippage)+",0,0,"+conditionMet+",0,0,"+arrowType+")");
        if( ticket >= 0 )
        {
            Print("ticket #: " + ticket);

            OrderSelect(ticket,SELECT_BY_TICKET);
            //OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*10,0,0,Blue);
            OrderModify(OrderTicket(), OrderOpenPrice(), Bid-Point*adjustForDigits(initStopLoss), 0, 0, Blue);

        }
    }
    else
    {
        //Print("Stoploss: " +OrderStopLoss());
    }
}

void check_modify_stoploss()
{
    if( stopLoss == NULL )
    {
        stopLoss = initStopLoss;
    }
    if( Close[0] > OrderOpenPrice() && stopLoss > 0 )
    {
        double difference = Close[0] - OrderOpenPrice();

        double stopLossJump = MathFloor(difference / 10);

        double increaseStopLossBy = 10 * stopLossJump;

        stopLoss = stopLoss - increaseStopLossBy;

        if( OrderSelect(ticket, SELECT_BY_TICKET) )
        {
            OrderModify(OrderTicket(), OrderOpenPrice(), adjustForDigits(stopLoss), adjustForDigits(initTakeProfit), 0);
        }
    }
}

// TODO
// Engulfing Pattern Condition

int check_to_close()
{
    int order_type;

    if( OrdersTotal() < 1 )
    {
        return (0);
    }

    if( OrderSelect(ticket, SELECT_BY_TICKET) == true )
    {
        order_type = OrderType();
    }
    else
    {
        //Print("OrderSelect() returned error - ",GetLastError());
    }

    if( order_type == OP_BUY )
    {
        if( Close[0] < currentFastMA )
        {
            OrderSelect(0,SELECT_BY_POS);

            OrderClose(OrderTicket(),lotSize,Bid,slippage,Red);
            if( closeTrade() == false)
            {
                //Print("OrderClose failed with error #",GetLastError());
                return(-1);
            }

        }
    }
    else if (order_type == OP_SELL)
    {
        Print("should not print");
        if( Close[0] > currentFastMA )
        {
            OrderSelect(0,SELECT_BY_POS);

            OrderClose(OrderTicket(),lotSize,Bid,slippage,Red);
            if( closeTrade() == false)
            {
                //Print("OrderClose failed with error #",GetLastError());
                return(-1);
            }
        }
    }
    return (0);
}

int closeTrade()
{
    if( ticket != 0 )
    {
        OrderClose(ticket,lotSize,Ask,3,Yellow);
        return(0);
    }
}

void take_screen_shot(string tradetype)
{
    if(!WindowScreenShot(TimeYear( TimeCurrent() ) + "-" + TimeMonth( TimeCurrent() ) + "-" + TimeDay( TimeCurrent() ) + "_" + TimeHour( TimeCurrent() ) + "-" + 
             TimeMinute( TimeCurrent() ) + "-" + TimeSeconds( TimeCurrent() ) + "__" +  tradetype + ".gif",640,480))
        Alert(GetLastError());
}
Files:
5-20w_1_.mq4  10 kb
 

Hi Adam

Would love to help but your description is a bit vague.

1.  What do you mean by about the 62? "If the 5 and 20 cross up and the 62 as underneath the cross it is a buy (however, if the 62 is above the cross up but the price closes "about the 62", then we still take the buy)"

2. How do you enter the engulfing candles? What is the re-entry criteria? Do you place a market order or a pending order? Also, if a re-entry occurs what will be your stoploss?

3. I noticed that you don't place any sell orders? Is there a specific reason for this? 

4. I could not see any attachments? 

Thank you,
DTK-Forex

 
pianoking87:

 Hello All, 

I have the basic code now finished and the logic in place, but it seems like the MT4 back tester has a mind of its own. My friend and I are stumped and have been trying to trouble shoot the code, and are left with unanswered questions. I thought I would reach out to you and lay my cards on the table. I was wondering if I showed you my trade and what I’m trying to do, maybe you can take a look at it and give me your opinion on what is going wrong.

There are no pictures attached . . .

 

 

You haven't actually said what your problem is ?  what is your code doing that it shouldn't or not doing what it should be doing ?

I can see you aren't checking return values fro your trade functions,  don't you want to know if they fail ?  and if they fail what the error was ?  and if there was an error what the values of Bid, Ask, trade entry, SL, TP, etc were at the time ?

Read this:   What are Function return values ? How do I use them ?

If you have an open order and MT4 crashes when you restart it and your EA finds the open trade where does it get the correct value of  ticket  from ?  your EA needs to be able to pick up from where it left of in the case of a unexpected termination . . . this will help a little:   Loops and Closing or Deleting Orders