MACD crossing 0 in MQL5

 

Hey guys,

I am trying to code an EA that takes positions every time the MACD (21, 48, 3) crosses 0.

However, this code takes positions when the EMA 21 and EMA 48 cross. I believe my issue is that I incorrectly coded the calculation: EMA 48 - EMA 21.

Can anyone please help me solve this issue?

I would really appreciate it.

Martin

//+------------------------------------------------------------------+
//| Long when MACD turns positive | Short when MACD turns negative 
//| H1 | 21 48 3
//| Only use the MACD line
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, Martin E"
#property version   "1.00"

// ****************************************************************************************************

#include <Trade\Trade.mqh> // Get code from other places

//--- Input Variables (Accessible from MetaTrader 5)

input double   lot = 1;
input int      shortemaPeriods = 21;
input int      longemaPeriods = 48;
input bool     useStopLoss = true;
input double   stopLossPips = 50;
input bool     useTakeProfit = true;
input double   takeProfitPips = 0;
input bool IsUseTrailingStop  = false;
input int TrailingStopDistance = 0;

//--- Service Variables (Only accessible from the MetaEditor)

CTrade myTradingControlPanel;
double shortemaData[], longemaData[], medemaData[]; // You can declare multiple variables of the same data type in the same line.
int numberOfShortemaData, numberOfLongemaData, numberofMedemaData; 
int shortemaControlPanel, longemaControlPanel, medemaControlPanel;
int P;
double currentBid, currentAsk;
double stopLossPipsFinal, takeProfitPipsFinal, stopLevelPips;
double stopLossLevel, takeProfitLevel;
double shortema1, shortema2, longema1, longema2, medema1, medema2;

double trailing_stop_value;
//ulong array_tickets[];

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   ArraySetAsSeries(medemaData,true);
      
   shortemaControlPanel = iMA(_Symbol, _Period, shortemaPeriods, 0, MODE_EMA, PRICE_CLOSE); // Getting the Control Panel/Handle for short SMA
   longemaControlPanel = iMA(_Symbol, _Period, longemaPeriods, 0, MODE_EMA, PRICE_CLOSE); // Getting the Control Panel/Handle for long SMA
//   medemaControlPanel = longemaControlPanel - shortemaControlPanel;
   
   if(_Digits == 5 || _Digits == 3 || _Digits == 1) P = 10;else P = 1; // To account for 5 digit brokers
   
//   ArrayResize(array_tickets,0,100000);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
//   IndicatorRelease(shortemaControlPanel);
//   IndicatorRelease(longemaControlPanel);
//   IndicatorRelease(medemaControlPanel);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   // -------------------- Collect most current data --------------------
   
   currentBid = SymbolInfoDouble(_Symbol,SYMBOL_BID); // Get latest Bid Price
   currentAsk = SymbolInfoDouble(_Symbol,SYMBOL_ASK); // Get latest Ask Price
   
   numberOfShortemaData = CopyBuffer(shortemaControlPanel, 0, 0, 3, shortemaData); // Collect most current SMA(10) Data and store it in the datatable/array shortSmaData[]
   numberOfLongemaData = CopyBuffer(longemaControlPanel, 0, 0, 3, longemaData); // Collect most current SMA(40) Data and store it in the datatable/array longSmaData[]
//   numberofMedemaData = CopyBuffer (medemaControlPanel, 0, 0, 3, medemaData);
   
//   shortema1 = shortemaData[1];
//   shortema2 = shortemaData[2]; 
//   longema1 = longemaData[1]; 
//   longema2 = longemaData[2]; 
//   medema1 = longemaData[1] - shortemaData[1];
   //medemaData[1];
   medema2 = longemaData[2] - shortemaData[2];
   //medemaData[2];
   
   // -------------------- Technical Requirements --------------------
   
   // Explanation: Stop Loss and Take Profit levels can't be too close to our order execution price. We will talk about this again in a later lecture.
   // Resources for learning more: https://book.mql4.com/trading/orders (ctrl-f search "stoplevel"); https://book.mql4.com/appendix/limits
   
   stopLevelPips = (double) (SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) + SymbolInfoInteger(_Symbol, SYMBOL_SPREAD)) / P; // Defining minimum StopLevel

   if (stopLossPips < stopLevelPips) 
      {
      stopLossPipsFinal = stopLevelPips;
      } 
   else
      {
      stopLossPipsFinal = stopLossPips;
      } 
      
   if (takeProfitPips < stopLevelPips) 
      {
      takeProfitPipsFinal = stopLevelPips;
      }
   else
      {
      takeProfitPipsFinal = takeProfitPips;
      }

   ModifyOrders(); //move trailing stop orders if it is necessary      
      
  // -------------------- EXITS --------------------
   
   if(PositionSelect(_Symbol) == true) // We have an open position
      { 
      
      // --- Exit Rules (Long Trades) ---
      
      /*
      Exits:
      - Exit the long trade when SMA(10) crosses SMA(40) from top
      - Exit the short trade when SMA(10) crosses SMA(40) from bottom
      */
      
      // TDL 3: Enter exit rule for long trades
      
      // --------------------------------------------------------- //
      
      if(medema2 > 0 && medema1 < 0) // Rule to exit long trades
         
      // --------------------------------------------------------- //
         
         {
         if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) // If it is Buy position
            { 
            
            myTradingControlPanel.PositionClose(_Symbol); // Closes position related to this symbol
            
            if(myTradingControlPanel.ResultRetcode()==10008 || myTradingControlPanel.ResultRetcode()==10009) //Request is completed or order placed
               {
               Print("Exit rules: A close order has been successfully placed with Ticket#: ",myTradingControlPanel.ResultOrder());
               }
            else
               {
               Print("Exit rules: The close order request could not be completed.Error: ",GetLastError());
               ResetLastError();
               return;
               }
               
            }
         }
      
      // TDL 4: Enter exit rule for short trades
      
      // --------------------------------------------------------- //
      
      if(medema2 < 0 && medema1 > 0) // Rule to exit short trades
         
      // --------------------------------------------------------- //  
       
         {
         if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) // If it is Sell position
            { 
            
            myTradingControlPanel.PositionClose(_Symbol); // Closes position related to this symbol
            
            if(myTradingControlPanel.ResultRetcode()==10008 || myTradingControlPanel.ResultRetcode()==10009) //Request is completed or order placed
               {
               Print("Exit rules: A close order has been successfully placed with Ticket#: ", myTradingControlPanel.ResultOrder());
               }
            else
               {
               Print("Exit rules: The close order request could not be completed. Error: ", GetLastError());
               ResetLastError();
               return;
               }
            }
         }
      
      }
   
   // -------------------- ENTRIES --------------------  
         
   if(PositionSelect(_Symbol) == false) // We have no open position
      { 
      
      // --- Entry Rules (Long Trades) ---
      
      /*
      Entries:
      - Enter a long trade when SMA(10) crosses SMA(40) from bottom
      - Enter a short trade when SMA(10) crosses SMA(40) from top
      */
      
      // TDL 1: Enter entry rule for long trades
      
      // --------------------------------------------------------- //
      
      if(medema2 < 0  && medema1 > 0) // Rule to enter long trades
      
      // --------------------------------------------------------- //
     
         {   
         
         if (useStopLoss) stopLossLevel = currentAsk - stopLossPipsFinal * _Point * P; else stopLossLevel = 0.0;
         if (useTakeProfit) takeProfitLevel = currentAsk + takeProfitPipsFinal * _Point * P; else takeProfitLevel = 0.0;
        
         myTradingControlPanel.PositionOpen(_Symbol, ORDER_TYPE_BUY, lot, currentAsk, stopLossLevel, takeProfitLevel, "Buy Trade. Magic Number #" + (string) myTradingControlPanel.RequestMagic()); // Open a Buy position
         
         if(myTradingControlPanel.ResultRetcode()==10008 || myTradingControlPanel.ResultRetcode()==10009) //Request is completed or order placed
            {
            Print("Entry rules: A Buy order has been successfully placed with Ticket#: ", myTradingControlPanel.ResultOrder());
            }
         else
            {
            Print("Entry rules: The Buy order request could not be completed. Error: ", GetLastError());
            ResetLastError();
            return;
            }
           
         }
         
      // --- Entry Rules (Short Trades) ---
      
      /*
      Exit:
      - Exit the long trade when SMA(10) crosses SMA(40) from top
      - Exit the short trade when SMA(10) crosses SMA(40) from bottom
      */
      
      // TDL 2: Enter entry rule for short trades
      
      // --------------------------------------------------------- //
      
      else if(medema2 > 0 && medema1 < 0) // Rule to enter short trades
      
      // --------------------------------------------------------- //

         {   
         
         if (useStopLoss) stopLossLevel = currentBid + stopLossPipsFinal * _Point * P; else stopLossLevel = 0.0;
         if (useTakeProfit) takeProfitLevel = currentBid - takeProfitPipsFinal * _Point * P; else takeProfitLevel = 0.0;

         myTradingControlPanel.PositionOpen(_Symbol, ORDER_TYPE_SELL, lot, currentBid, stopLossLevel, takeProfitLevel, "Sell Trade. Magic Number #" + (string) myTradingControlPanel.RequestMagic()); // Open a Sell position
         
         if(myTradingControlPanel.ResultRetcode()==10008 || myTradingControlPanel.ResultRetcode()==10009) //Request is completed or order placed
            {
            Print("Entry rules: A Sell order has been successfully placed with Ticket#: ", myTradingControlPanel.ResultOrder());
            }
         else
            {
            Print("Entry rules: The Sell order request could not be completed.Error: ", GetLastError());
            ResetLastError();
            return;
            }
         
         } 
      
      }
   
   } 
   
//+------------------------------------------------------------------+
//| Move trailing stop if it is necessary for all orders                                                 |
//+------------------------------------------------------------------+
/*void ModifyOrders()
{
   ModifyOrders(array_tickets);
  
}
*/
//+------------------------------------------------------------------+
//| Move trailing stop if it is necessary for all orders from array                                                |
//+------------------------------------------------------------------+
void ModifyOrders(/*ulong& arr_ticket[]*/)
{

   if(!IsUseTrailingStop || TrailingStopDistance==0)
      return;
/*   for(int i=0;i<ArraySize(arr_ticket);i++)
   {
       ulong ticket=arr_ticket[i];
       bool is_selected=PositionSelectByTicket(ticket);
       if(is_selected)
       {
  */       
          ENUM_POSITION_TYPE position_type=PositionGetInteger(POSITION_TYPE);
          double open_price=PositionGetDouble(POSITION_PRICE_OPEN);
//          double current_stop_loss=PositionGetDouble(POSITION_SL);
          double local_stop_loss;
          if(position_type==POSITION_TYPE_BUY)
          {
             if(currentBid-open_price>trailing_stop_value)
             {
               
                local_stop_loss=NormalizeDouble(currentBid-trailing_stop_value,Digits());
                if(stopLevelPips<local_stop_loss)
                {
                   bool is_modified=myTradingControlPanel.PositionModify(/*ticket*/0,local_stop_loss,0);
                   if(!is_modified)
                   {
                       uint result_ret_code=myTradingControlPanel.ResultRetcode();
                       Print("Terminal could not modify the position for",_Symbol," the error Code=",result_ret_code);
                   }
                   else
                   {
                       Print("Terminal modify the position for",_Symbol," successfully");
                   }
                }
             }
             else
             {
                 
             }
          }
          else if(position_type==POSITION_TYPE_SELL)
          {
             if(open_price-currentAsk>trailing_stop_value)
             {
                
                 local_stop_loss=NormalizeDouble(currentAsk+trailing_stop_value,Digits());
                 if(stopLevelPips>local_stop_loss)
                 {
                    bool is_modified=myTradingControlPanel.PositionModify(/*ticket*/0,local_stop_loss,0);
                    if(!is_modified)
                    {
                       uint result_ret_code=myTradingControlPanel.ResultRetcode();
                       Print("Terminal could not modify the position for",_Symbol," the error Code=",result_ret_code);
                    }
                    else
                    {
                        Print("Terminal modify the position for",_Symbol," successfully");
                    }
                 }
             
             }
             else
             {
                
             }
          }
          
   /*    }    */
/*   }    */
      
}

 
Martin_2017:

I am trying to code an EA that takes positions every time the MACD (21, 48, 3) crosses 0.

However, this code takes positions when the EMA 21 and EMA 48 cross. I believe my issue is that I incorrectly coded the calculation: EMA 48 - EMA 21.

   medema2 = longemaData[2] - shortemaData[2];
   if(medema2 > 0 && medema1 < 0) // Rule to exit long trades
What is the value of medema1?
 
whroeder1:
What is the value of medema1?

It is medema1 = longemaData[1] - shortemaData[1];

I don't understand why the EA isn't taking the difference between EMA48 and EMA 21...

 
Martin_2017: It is medema1 = longemaData[1] - shortemaData[1];

Exactly where is that line of code, in your original post?

 
whroeder1:

Exactly where is that line of code, in your original post?

Line 85 in the OnTick section - it is commented out but I believe it shouldn't be?

 
Yes it is comment out. Now answer #1
 
//+------------------------------------------------------------------+
//| Long when MACD turns positive | Short when MACD turns negative 
//| H1 | 21 48 3
//| Only use the MACD line
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, Martin E"
#property version   "1.00"

// ****************************************************************************************************

#include <Trade\Trade.mqh> // Get code from other places

//--- Input Variables (Accessible from MetaTrader 5)

input double   lot = 1;
input int      shortemaPeriods = 21;
input int      longemaPeriods = 48;
input bool     useStopLoss = true;
input double   stopLossPips = 50;
input bool     useTakeProfit = true;
input double   takeProfitPips = 0;
input bool IsUseTrailingStop  = false;
input int TrailingStopDistance = 0;

//--- Service Variables (Only accessible from the MetaEditor)

CTrade myTradingControlPanel;
double shortemaData[], longemaData[], medemaData[]; // You can declare multiple variables of the same data type in the same line.
int numberOfShortemaData, numberOfLongemaData, numberofMedemaData; 
int shortemaControlPanel, longemaControlPanel, medemaControlPanel;
int P;
double currentBid, currentAsk;
double stopLossPipsFinal, takeProfitPipsFinal, stopLevelPips;
double stopLossLevel, takeProfitLevel;
double shortema1, shortema2, longema1, longema2, medema1, medema2;

double trailing_stop_value;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   ArraySetAsSeries(medemaData,true);
      
   shortemaControlPanel = iMA(_Symbol, _Period, shortemaPeriods, 0, MODE_EMA, PRICE_CLOSE); // Getting the Control Panel/Handle for short SMA
   longemaControlPanel = iMA(_Symbol, _Period, longemaPeriods, 0, MODE_EMA, PRICE_CLOSE); // Getting the Control Panel/Handle for long SMA
   
   if(_Digits == 5 || _Digits == 3 || _Digits == 1) P = 10;else P = 1; // To account for 5 digit brokers
   
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   // -------------------- Collect most current data --------------------
   
   currentBid = SymbolInfoDouble(_Symbol,SYMBOL_BID); // Get latest Bid Price
   currentAsk = SymbolInfoDouble(_Symbol,SYMBOL_ASK); // Get latest Ask Price
   
   numberOfShortemaData = CopyBuffer(shortemaControlPanel, 0, 0, 3, shortemaData); // Collect most current SMA(10) Data and store it in the datatable/array shortSmaData[]
   numberOfLongemaData = CopyBuffer(longemaControlPanel, 0, 0, 3, longemaData); // Collect most current SMA(40) Data and store it in the datatable/array longSmaData[]

   medema1 = longemaData[1] - shortemaData[1];
   medema2 = longemaData[2] - shortemaData[2];
      
   stopLevelPips = (double) (SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) + SymbolInfoInteger(_Symbol, SYMBOL_SPREAD)) / P; // Defining minimum StopLevel

   if (stopLossPips < stopLevelPips) 
      {
      stopLossPipsFinal = stopLevelPips;
      } 
   else
      {
      stopLossPipsFinal = stopLossPips;
      } 
      
   if (takeProfitPips < stopLevelPips) 
      {
      takeProfitPipsFinal = stopLevelPips;
      }
   else
      {
      takeProfitPipsFinal = takeProfitPips;
      }

   ModifyOrders(); //move trailing stop orders if it is necessary      
      
  // -------------------- EXITS --------------------
   
   if(PositionSelect(_Symbol) == true) // We have an open position
      { 
      
      // TDL 3: Enter exit rule for long trades
      
      // --------------------------------------------------------- //
      
      if(medema2 > 0 && medema1 < 0) // Rule to exit long trades
         
      // --------------------------------------------------------- //
         
         {
         if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) // If it is Buy position
            { 
            
            myTradingControlPanel.PositionClose(_Symbol); // Closes position related to this symbol
            
            if(myTradingControlPanel.ResultRetcode()==10008 || myTradingControlPanel.ResultRetcode()==10009) //Request is completed or order placed
               {
               Print("Exit rules: A close order has been successfully placed with Ticket#: ",myTradingControlPanel.ResultOrder());
               }
            else
               {
               Print("Exit rules: The close order request could not be completed.Error: ",GetLastError());
               ResetLastError();
               return;
               }
               
            }
         }
      
      // TDL 4: Enter exit rule for short trades
      
      // --------------------------------------------------------- //
      
      if(medema2 < 0 && medema1 > 0) // Rule to exit short trades
         
      // --------------------------------------------------------- //  
       
         {
         if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) // If it is Sell position
            { 
            
            myTradingControlPanel.PositionClose(_Symbol); // Closes position related to this symbol
            
            if(myTradingControlPanel.ResultRetcode()==10008 || myTradingControlPanel.ResultRetcode()==10009) //Request is completed or order placed
               {
               Print("Exit rules: A close order has been successfully placed with Ticket#: ", myTradingControlPanel.ResultOrder());
               }
            else
               {
               Print("Exit rules: The close order request could not be completed. Error: ", GetLastError());
               ResetLastError();
               return;
               }
            }
         }
      
      }
   
   // -------------------- ENTRIES --------------------  
         
   if(PositionSelect(_Symbol) == false) // We have no open position
      { 
            
      // TDL 1: Enter entry rule for long trades
      
      // --------------------------------------------------------- //
      
      if(medema2 < 0  && medema1 > 0) // Rule to enter long trades
      
      // --------------------------------------------------------- //
     
         {   
         
         if (useStopLoss) stopLossLevel = currentAsk - stopLossPipsFinal * _Point * P; else stopLossLevel = 0.0;
         if (useTakeProfit) takeProfitLevel = currentAsk + takeProfitPipsFinal * _Point * P; else takeProfitLevel = 0.0;
        
         myTradingControlPanel.PositionOpen(_Symbol, ORDER_TYPE_BUY, lot, currentAsk, stopLossLevel, takeProfitLevel, "Buy Trade. Magic Number #" + (string) myTradingControlPanel.RequestMagic()); // Open a Buy position
         
         if(myTradingControlPanel.ResultRetcode()==10008 || myTradingControlPanel.ResultRetcode()==10009) //Request is completed or order placed
            {
            Print("Entry rules: A Buy order has been successfully placed with Ticket#: ", myTradingControlPanel.ResultOrder());
            }
         else
            {
            Print("Entry rules: The Buy order request could not be completed. Error: ", GetLastError());
            ResetLastError();
            return;
            }
           
         }
         
      // --- Entry Rules (Short Trades) ---
            
      // TDL 2: Enter entry rule for short trades
      
      // --------------------------------------------------------- //
      
      else if(medema2 > 0 && medema1 < 0) // Rule to enter short trades
      
      // --------------------------------------------------------- //

         {   
         
         if (useStopLoss) stopLossLevel = currentBid + stopLossPipsFinal * _Point * P; else stopLossLevel = 0.0;
         if (useTakeProfit) takeProfitLevel = currentBid - takeProfitPipsFinal * _Point * P; else takeProfitLevel = 0.0;

         myTradingControlPanel.PositionOpen(_Symbol, ORDER_TYPE_SELL, lot, currentBid, stopLossLevel, takeProfitLevel, "Sell Trade. Magic Number #" + (string) myTradingControlPanel.RequestMagic()); // Open a Sell position
         
         if(myTradingControlPanel.ResultRetcode()==10008 || myTradingControlPanel.ResultRetcode()==10009) //Request is completed or order placed
            {
            Print("Entry rules: A Sell order has been successfully placed with Ticket#: ", myTradingControlPanel.ResultOrder());
            }
         else
            {
            Print("Entry rules: The Sell order request could not be completed.Error: ", GetLastError());
            ResetLastError();
            return;
            }
         
         } 
      
      }
   
   } 
//+------------------------------------------------------------------+
//| Move trailing stop if it is necessary for all orders from array                                                |
//+------------------------------------------------------------------+
void ModifyOrders(/*ulong& arr_ticket[]*/)
{

   if(!IsUseTrailingStop || TrailingStopDistance==0)
      return;

          ENUM_POSITION_TYPE position_type=PositionGetInteger(POSITION_TYPE);
          double open_price=PositionGetDouble(POSITION_PRICE_OPEN);
//          double current_stop_loss=PositionGetDouble(POSITION_SL);
          double local_stop_loss;
          if(position_type==POSITION_TYPE_BUY)
          {
             if(currentBid-open_price>trailing_stop_value)
             {
               
                local_stop_loss=NormalizeDouble(currentBid-trailing_stop_value,Digits());
                if(stopLevelPips<local_stop_loss)
                {
                   bool is_modified=myTradingControlPanel.PositionModify(/*ticket*/0,local_stop_loss,0);
                   if(!is_modified)
                   {
                       uint result_ret_code=myTradingControlPanel.ResultRetcode();
                       Print("Terminal could not modify the position for",_Symbol," the error Code=",result_ret_code);
                   }
                   else
                   {
                       Print("Terminal modify the position for",_Symbol," successfully");
                   }
                }
             }
             else
             {
                 
             }
          }
          else if(position_type==POSITION_TYPE_SELL)
          {
             if(open_price-currentAsk>trailing_stop_value)
             {
                
                 local_stop_loss=NormalizeDouble(currentAsk+trailing_stop_value,Digits());
                 if(stopLevelPips>local_stop_loss)
                 {
                    bool is_modified=myTradingControlPanel.PositionModify(/*ticket*/0,local_stop_loss,0);
                    if(!is_modified)
                    {
                       uint result_ret_code=myTradingControlPanel.ResultRetcode();
                       Print("Terminal could not modify the position for",_Symbol," the error Code=",result_ret_code);
                    }
                    else
                    {
                        Print("Terminal modify the position for",_Symbol," successfully");
                    }
                 }
             
             }
             else
             {
                
             }
          }
          
   /*    }    */
/*   }    */
      
}

whroeder1


:

Yes it is comment out. Now answer #1

Here's the same version, without all the lines commented out. 

The answer to your question:

medema1 = longemaData[1] - shortemaData[1];

It's supposed to be the MACD line, so EMA 48 - EMA 21.

medema1 is the most recent value of the MACD line and medema2 is the one before. Therefore, the EA takes a long position when medema2 < 0 & medema1 > 0.