MACD EA Issues

 

I wrote a macd EA. I need the EA trade on the close of the histogram (candle), but seems not be working. I have tried using:

Volume [1]


Open [1] < Close [1] and Open [1] > Close [1]


time.


And a combination of all three.

But its not working.

What other way can it be done?

On the image attached observe that on the test, the histogram bars closed below the signal line, but a buy trade was still initiated.

Test date: 7th June, 2023

Any ideas on what to do?

Also attached is the code.

 
  1. ecsentricjay:have tried using: Volume [1]

    For a new bar test, Bars is unreliable (a refresh/reconnect can change number of bars on chart), volume is unreliable (miss ticks), Price is unreliable (duplicate prices and The == operand. - MQL4 programming forum.) Always use time.
              MT4: New candle - MQL4 programming forum #3 (2014)
              MT5: Accessing variables - MQL4 programming forum #3 (2022)

    I disagree with making a new bar function, because it can only be called once per tick (second call returns false). A variable can be tested multiple times.
              Running EA once at the start of each bar - MQL4 programming forum (2011)

  2. ecsentricjay: Open [1] < Close [1] and Open [1] > Close [1]

    When can that ever be true? 10 <  20 and 10 > 20 will never be true at the same time.

    Look for a cross.

    double aPrev = …(i+1), aCurr = …(i),
           bPrev = …(i+1), bCurr = …(i);
    bool   wasUp = aPrev > bPrev,
            isUp = aCurr > bCurr,
         isCross = isUp != wasUp;
  3. Don't post pictures of code, they are generally too hard to read.

    Use the CODE button (or Alt+S)! (For large amounts of code, attach it.)
              General rules and best pratices of the Forum. - General - MQL5 programming forum #25 (2019)
              Forum rules and recommendations - General - MQL5 programming forum (2023)
              Messages Editor

 
William Roeder #:
  1. For a new bar test, Bars is unreliable (a refresh/reconnect can change number of bars on chart), volume is unreliable (miss ticks), Price is unreliable (duplicate prices and The == operand. - MQL4 programming forum.) Always use time.
              MT4: New candle - MQL4 programming forum #3 (2014)
              MT5: Accessing variables - MQL4 programming forum #3 (2022)

    I disagree with making a new bar function, because it can only be called once per tick (second call returns false). A variable can be tested multiple times.
              Running EA once at the start of each bar - MQL4 programming forum (2011)

  2. When can that ever be true? 10 <  20 and 10 > 20 will never be true at the same time.

    Look for a cross.

  3. Don't post pictures of code, they are generally too hard to read.

    Use the CODE button (or Alt+S)! (For large amounts of code, attach it.)
              General rules and best pratices of the Forum. - General - MQL5 programming forum #25 (2019)
              Forum rules and recommendations - General - MQL5 programming forum (2023)
              Messages Editor

Did this still having the same issues. Here is the full code for you perusal

//+------------------------------------------------------------------+
//|                                              Profit Maker V3.mq4 |
//|                                                 Ecsentric Trades |                                                                             
//+------------------------------------------------------------------+
#property strict



input string saperator_00 = " *\/*\/*\/*\/* Trade Managment *\/*\/*\/*\/* " ; // *\/*\/*\/*\/*
input int magic_number = 7460828 ; // Magic Number
input bool is_open_buy = true ; // Open BUY trades
input bool is_open_sel = true ; // Open SELL trades


input string saperator_01 = " *\/*\/*\/*\/* Lot Managment *\/*\/*\/*\/* " ; // *\/*\/*\/*\/*
input bool use_fix_lot = true; // Use Fix Lot Size
input double fix_lot_size = 0.01 ; // Fix Lot Size
input double risk_percent = 5 ; // % of Equity


input string saperator_02 = " *\/*\/*\/*\/* SL/TP *\/*\/*\/*\/* " ; // *\/*\/*\/*\/*
input double tp_points = 500 ; // TP in Points
input double sl_points = 500 ; // SL in Points
input bool is_trailing = true; // Use Trailing Stop
input double trailing_stop_points = 100 ; // Trailing Stop in Points
input int slippage_points = 100 ; // Slippage


input string saperator_03 = " *\/*\/*\/*\/* Stochi Settings *\/*\/*\/*\/* " ; // *\/*\/*\/*\/*
extern int FastEMA = 12;
extern int SlowEMA = 26;
extern int SignalSMA = 9;
input bool is_trade_on_candle_close = true ; // Trade on Candle Close
input bool is_close_opposit_signal = true ; // Close on Opposit Signal

extern string S1 = "||======== MA1 Indicator Setting ========||";
extern int MA1_Period = 200;
extern int MA1_Shift = 0;
extern ENUM_MA_METHOD MA1_Method = MODE_SMA;
extern ENUM_APPLIED_PRICE MA1_Apply = PRICE_CLOSE;

extern string S2 = "||======== MA2 Indicator Setting ========||";
extern int MA2_Period = 100;
extern int MA2_Shift = 0;
extern ENUM_MA_METHOD MA2_Method = MODE_SMA;
extern ENUM_APPLIED_PRICE MA2_Apply = PRICE_CLOSE;


input string saperator_04 = " *\/*\/*\/*\/* Trading Hours *\/*\/*\/*\/* " ; // *\/*\/*\/*\/*
input int start_hour = 0 ; // Start Hour
input int stop_hour = 23 ; // Stop Hour

extern string CommentsOrders    = "EA";



//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

   main_body();

  }
//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
//|                                                                  | Main Body of EA
//+------------------------------------------------------------------+
void main_body()
  {


//+------------------------------------------------------------------+
//|                                                                  |  Trailing Stop
//+------------------------------------------------------------------+
   if(is_trailing && OrdersTotal() != 0)
     {
      for(int i=0; i<OrdersTotal(); i++)
        {
         OrderSelect(i,SELECT_BY_POS,MODE_TRADES);

         if(OrderType() == OP_BUY) //************************************************ for BUY
           {
            if((Ask - OrderOpenPrice()) > (trailing_stop_points * Point()))
              {
               if((Ask - (trailing_stop_points * Point())) > OrderStopLoss())
                 {
                  OrderModify(OrderTicket(),OrderOpenPrice(),Ask - (trailing_stop_points * Point()),OrderTakeProfit(),0,clrAqua);
                 }
              }
           }


         if(OrderType() == OP_SELL) //************************************************* for SELL
           {
            if((OrderOpenPrice() - Bid) > (trailing_stop_points * Point()))
              {
               if((Bid + (trailing_stop_points * Point())) < OrderStopLoss())
                 {
                  OrderModify(OrderTicket(),OrderOpenPrice(),Bid + (trailing_stop_points * Point()),OrderTakeProfit(),0,clrAqua);
                 }
              }
           }
        }
     }


string comment_str = " Ecsentric Trades ";
  double MA1=0;
   double MA2=0;
   double macdCurrent, macdPrevious, signalCurrent, signalPrevious;
   
   MA1=iMA(NULL,0,MA1_Period,MA1_Shift,MA1_Method,MA1_Apply,1);
   MA2=iMA(NULL,0,MA2_Period,MA2_Shift,MA2_Method,MA2_Apply,1);
   
   macdCurrent = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, MODE_MAIN, 0);
   macdPrevious = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, MODE_MAIN, 1);
   signalCurrent = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, MODE_SIGNAL, 0);
   signalPrevious = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, MODE_SIGNAL, 1);
   
   static datetime timeCur; datetime timePre = timeCur; timeCur=Time [0];
   bool isNewBar = timeCur != timePre;
      
    if(is_trade_on_candle_close && Volume[1] && isNewBar)
     {
      if(MA2>MA1 && (macdCurrent > signalCurrent && macdPrevious < signalPrevious) && macdCurrent < 0 && signalCurrent < 0 && (Hour() >= start_hour && Hour() <= stop_hour))
        {
         if(is_close_opposit_signal)
           {
            do
              {
               closeSell();
              }
            while(checkIfalreadyHaveSell());
           }

         if(is_open_buy)
            openBuy();
        }

      if(MA2<MA1 && (macdCurrent < signalCurrent && macdPrevious > signalPrevious) && macdCurrent > 0 && signalCurrent > 0 && (Hour() >= start_hour && Hour() <= stop_hour))
        {
         if(is_close_opposit_signal)
           {
            do
              {
               closeBuy();
              }
            while(checkIfalreadyHaveBuy());
           }

         if(is_open_sel)
            openSell();
        }
     }
   else
     {
      if(MA2>MA1 && (macdCurrent > signalCurrent && macdPrevious < signalPrevious)&& macdCurrent < 0 && signalCurrent < 0 && (Hour() >= start_hour && Hour() <= stop_hour))
        {
         if(is_close_opposit_signal)
           {
            do
              {
               closeSell();
              }
            while(checkIfalreadyHaveSell());
           }

         if(is_open_buy)
            openBuy();
        }

      if(MA2<MA1 && (macdCurrent < signalCurrent && macdPrevious > signalPrevious) && macdCurrent > 0 && signalCurrent > 0 && (Hour() >= start_hour && Hour() <= stop_hour))
        {
         if(is_close_opposit_signal)
           {
            do
              {
               closeBuy();
              }
            while(checkIfalreadyHaveBuy());
           }


         if(is_open_sel)
            openSell();
        }
     }

   comment_str += "\n time = " + checkTime() + "\n current hour = " + Hour() + " ~Start hour = "+ start_hour + " ~Stop hour = " +stop_hour;

   Comment(comment_str);

   
   }
//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool checkTime()
  {
   datetime temp_datetime ;
   if(Hour() >= start_hour && Hour() <= stop_hour)
     {
      return true;
     }

   return false;
  }


//+------------------------------------------------------------------+
//|                                                                  |  Open BUY
//+------------------------------------------------------------------+
void openBuy()
  {
   if(checkIfalreadyHaveBuy())
     {
      return ;
     }

   double tempTP = Ask + (tp_points * Point());
   double tempSL = Ask - (sl_points * Point());
   double tempLotSize = lotCalculator(tempSL,Ask,11);
   
     
   int current_ticket = OrderSend(Symbol(),OP_BUY,tempLotSize,Ask,slippage_points,tempSL,tempTP,CommentsOrders,magic_number,0,clrGreen);
  }

//+------------------------------------------------------------------+
//|                                                                  |  Open SELL
//+------------------------------------------------------------------+
void openSell()
  {

   if(checkIfalreadyHaveSell())
     {
      return ;
     }

   double tempTP = Bid - (tp_points * Point());
   double tempSL = Bid + (sl_points * Point());
   double tempLotSize = lotCalculator(tempSL,Bid,22);
   
   

   int current_ticket = OrderSend(Symbol(),OP_SELL,tempLotSize,Bid,slippage_points,tempSL,tempTP,CommentsOrders,magic_number,0,clrRed);
  }



//+------------------------------------------------------------------+
//|                                                                  |  Lot Size Calculator
//+------------------------------------------------------------------+
double lotCalculator(double slPrice, double openPrice, int sellbuy)
  {

   if(use_fix_lot)
     {
      return fix_lot_size;
     }

   double current_sl_price = slPrice;
   double current_open_price = openPrice;
   int current_sellbuy = sellbuy;

   double current_risk_amount = (AccountInfoDouble(ACCOUNT_EQUITY) / 100) * risk_percent;

   double current_lot ;

   if(current_sellbuy == 11) // for BUY
     {
      current_lot = NormalizeDouble(current_risk_amount / ((current_open_price - current_sl_price)/Point()), 2);
      if(current_lot < 0.01)
        {
         return 0.01;
        }
     }
   if(current_sellbuy == 22) // for SELL
     {
      current_lot = NormalizeDouble(current_risk_amount / ((current_sl_price - current_open_price)/Point()), 2);
      if(current_lot < 0.01)
        {
         return 0.01;
        }
     }

   return current_lot;
  }
//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
//|                                                                  |  close BUY
//+------------------------------------------------------------------+
void closeBuy()
  {
   if(OrdersTotal() != 0)
     {
      for(int i=0; i<=OrdersTotal()+2; i++)
        {
         OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
         if(OrderType() == OP_BUY && OrderSymbol() == Symbol())
           {
            OrderClose(OrderTicket(),OrderLots(),Bid,10,clrWhite);
           }
        }
     }
  }


//+------------------------------------------------------------------+
//|                                                                  |  close SELL
//+------------------------------------------------------------------+
void closeSell()
  {
   if(OrdersTotal() != 0)
     {
      for(int i=0; i<=OrdersTotal()+1; i++)
        {
         OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
         if(OrderType() == OP_SELL && OrderSymbol() == Symbol())
           {
            OrderClose(OrderTicket(),OrderLots(),Ask,10,clrWhite);
           }
        }
     }
  }

//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
//|                                                                  |  check if already have trade on current pair
//+------------------------------------------------------------------+
bool checkIfalreadyHaveTrade()
  {
   if(OrdersTotal() != 0)
     {
      for(int i = 0; i <= OrdersTotal() ; i++)
        {
         OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
         if(OrderSymbol() == Symbol())
           {
            return true;
           }
        }
     }
   return false;
  }
//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
//|                                                                  |  check if already have buy trade on current pair
//+------------------------------------------------------------------+
bool checkIfalreadyHaveBuy()
  {
   if(OrdersTotal() != 0)
     {
      for(int i = 0; i <= OrdersTotal() ; i++)
        {
         OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
         if(OrderSymbol() == Symbol() && OrderType() == OP_BUY)
           {
            return true;

           }
        }
     }
   return false;
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|                                                                  |   check if already have sell trade on current pair
//+------------------------------------------------------------------+
bool checkIfalreadyHaveSell()
  {
   if(OrdersTotal() != 0)
     {
      for(int i = 0; i <= OrdersTotal() ; i++)
        {
         OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
         if(OrderSymbol() == Symbol() && OrderType() == OP_SELL)
           {
            return true;

           }
        }
     }
   return false;
  }
//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
 
ecsentricjay #: Did this still having the same issues. Here is the full code for you perusal
  1.          if(OrderType() == OP_BUY) //************************************************ for BUY
               {
                if((Ask - OrderOpenPrice()) > (trailing_stop_points * Point()))

    You buy at the Ask and sell at the Bid. Pending Buy Stop orders become market orders when hit by the Ask.

    1. Your buy order's TP/SL (or Sell Stop's/Sell Limit's entry) are triggered when the Bid / OrderClosePrice reaches it. Using Ask±n, makes your SL shorter and your TP longer, by the spread. Don't you want the specified amount used in either direction?

    2. Your sell order's TP/SL (or Buy Stop's/Buy Limit's entry) will be triggered when the Ask / OrderClosePrice reaches it. To trigger close at a specific Bid price, add the average spread.
                MODE_SPREAD (Paul) - MQL4 programming forum - Page 3 #25

    3. The charts show Bid prices only. Turn on the Ask line to see how big the spread is (Tools → Options (control+O) → charts → Show ask line.)

      Most brokers with variable spreads widen considerably at end of day (5 PM ET) ± 30 minutes.
      My GBPJPY shows average spread = 26 points, average maximum spread = 134.
      My EURCHF shows average spread = 18 points, average maximum spread = 106.
      (your broker will be similar).
                Is it reasonable to have such a huge spreads (20 PIP spreads) in EURCHF? - General - MQL5 programming forum (2022)

  2. Your code
                if((Ask - OrderOpenPrice()) > (trailing_stop_points * Point()))
                  {
                   if((Ask - (trailing_stop_points * Point())) > OrderStopLoss())
                     {
                      OrderModify(OrderTicket(),OrderOpenPrice(),Ask - (trailing_stop_points * Point()),OrderTakeProfit(),0,clrAqua);
    
    Simplified
                double TSL = Bid - trailing_stop_points * Point(), CSL=MathMax( OrderStopLoss(), OrderOpenPrice() );
                if(TSL > CSL)
                     {
                      OrderModify(OrderTicket(),OrderOpenPrice(),TSL,OrderTakeProfit(),0,clrAqua);
    
  3.     if(is_trade_on_candle_close && Volume[1] && isNewBar)

    What does “and int and” mean to you? What part of #1.1 was unclear? Or did you miss it? Or ignore it?

  4.    if(OrdersTotal() != 0)
         {
          for(int i=0; i<=OrdersTotal()+2; i++)
            {
             OrderSelect(i,SELECT_BY_POS,MODE_TRADES);

    If you have n orders their position indexes is [0 … total-1]. The equals and +2 are bogus. The If is unnecessary, no open orders your loop does nothing. You must check the select.

    In the presence of multiple orders (one EA multiple charts, multiple EAs, manual trading), while you are waiting for the current operation (closing, deleting, modifying) to complete, any number of other operations on other orders could have concurrently happened and changed the position indexing and order count:

    1. For non-FIFO (non-US brokers), (or the EA only opens one order per symbol), you can simply count down, in an index loop, and you won't miss orders. Get in the habit of always counting down.
                Loops and Closing or Deleting Orders - MQL4 programming forum

    2. For In First Out (FIFO rules — US brokers), and you (potentially) process multiple orders per symbol, you must find the earliest order (count up), close it, and on a successful operation, reprocess all positions (from zero).
                CloseOrders by FIFO Rules - Strategy Tester - MQL4 programming forum - Page 2 #16
                MetaTrader 5 platform beta build 2155: MQL5 scope, global Strategy Tester and built-in Virtual Hosting updates - Best Expert Advisors - General - MQL5 programming forum #1.11

    and check OrderSelect in case other positions were deleted.
              What are Function return values ? How do I use them ? - MQL4 programming forum
              Common Errors in MQL4 Programs and How to Avoid Them - MQL4 Articles

    and if you (potentially) process multiple orders, must call RefreshRates() after server calls if you want to use, on the next order / server call, the Predefined Variables (Bid/Ask.) Or instead, be direction independent and just use OrderClosePrice().

  5. ecsentricjay #: Did this still having the same issues.

    Use the debugger or print out your variables, including _LastError and prices and find out why. Do you really expect us to debug your code for you?
              Code debugging - Developing programs - MetaEditor Help
              Error Handling and Logging in MQL5 - MQL5 Articles (2015)
              Tracing, Debugging and Structural Analysis of Source Code - MQL5 Articles (2011)
              Introduction to MQL5: How to write simple Expert Advisor and Custom Indicator - MQL5 Articles (2010)