MA cross strategy issues

 

Hey,

I am quite new to coding in Meta Editor, but I have this code for a MA cross-over strategy, where it should generate orders every time the MA crosses and terminate the orders, when it crosses the opposite way. It does work somtimes, but if I backtest on real data it seems that it is only sometimes it executes and terminates the orders on the MA crossings. I don't understand why it just seems to ignore the crossings at times. I am currently testing it on the 1MIN timeframe for USDJPY back from 2020-01-01. On the photo is an example of one of the orders it creates and two crossings afterwards. The picture is attached.

#property version   "1.001"
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>  
#include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006

CPositionInfo  m_position;                   // trade position object
CTrade         m_trade;                      // trading object
CSymbolInfo    m_symbol;                     // symbol info object
CDealInfo      m_deal;  

input int            MA_1_Period    = 130;              // Ma period 1
input int            MA_2_Period    = 13;             // Ma period 2
input ENUM_MA_METHOD MA_1_Method    = MODE_SMA;       // Method МА1
input ENUM_MA_METHOD MA_2_Method    = MODE_SMA;      // Method МА2
input ENUM_APPLIED_PRICE MA_1_Price = PRICE_LOW;   // Applied price МА1
input ENUM_APPLIED_PRICE MA_2_Price = PRICE_LOW;   // Applied price МА2
input int            MA_1_Shift     = 0;              // shift МА1
input int            MA_2_Shift     = 1;              // Shift МА2
input double         Lot            = 5;            // Lot

input int   StopLoss                = 5000;  // Stop loss in points
input int   TakeProfit              = 5000;  // Take profit in points
input int   InpTrailingStopPoints   = 5000;  // Trailing stop loss in points
input bool  trailingStopLoss        = false; // Enable trailing stop loss

//---
int                  New_Bar;                         // 0/1 Formation of a new bar
datetime             Time_0;                          // Time of the start of a new bar
int                  PosOpen;                         // Direction of the crossover
int                  PosClose;                        // Direction of the crossover
int                  all_positions;                   // Total number of open positions
double               MA1_0;                           // Current value of the 1st MA
double               MA1_1;                           // Previous value of the 1st MA
double               MA2_0;                           // Current value of the 2nd MA
double               MA2_1;                           // Previous value of the 2nd MA
int                  PosBuy;                          // 1 = presence of Buy position
int                  PosSell;                         // 1 = presence of Sell position
//---
int    handle_iMA_1;                     // variable for storing the handle of the iMA indicator
int    handle_iMA_2;                     // variable for storing the handle of the iMA indicator
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   m_symbol.Name(Symbol());                  // sets symbol name
   //--- create handle of the iMA indicator
   handle_iMA_1=iMA(m_symbol.Name(),Period(),MA_1_Period,MA_1_Shift,MA_1_Method,MA_1_Price);
   //--- if the handle is not created
   if(handle_iMA_1==INVALID_HANDLE)
   {
      //--- report the failure and output the error code
      PrintFormat("Failed to create handle of the iMA indicator for the symbol %s/%s, error code %d",
                  m_symbol.Name(),
                  EnumToString(Period()),
                  GetLastError());
      //--- stop the indicator early
      return(INIT_FAILED);
   }
   //--- create handle of the iMA indicator
   handle_iMA_2=iMA(m_symbol.Name(),Period(),MA_2_Period,MA_2_Shift,MA_2_Method,MA_2_Price);
   //--- if the handle is not created
   if(handle_iMA_2==INVALID_HANDLE)
   {
      //--- report the failure and output the error code
      PrintFormat("Failed to create handle of the iMA indicator for the symbol %s/%s, error code %d",
                  m_symbol.Name(),
                  EnumToString(Period()),
                  GetLastError());
      //--- stop the indicator early
      return(INIT_FAILED);
   }
   //---
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   if (!RefreshRates())
      return;

   PosBuy = 0;
   PosSell = 0;
   int openOrders = 0;
   all_positions = PositionsTotal();                                  // Total number of positions
   for (int i = all_positions - 1; i >= 0; i--) // returns the number of open positions
   {
      if (m_position.SelectByIndex(i)) // Select the position
      {
         if (m_position.PositionType() == POSITION_TYPE_BUY)// If it's a BUY position
         {
            PosBuy = 1;
            if (CrossPositionClose() == 1) // Close the order if it satisfies the condition CrossPositionClose()=1
            {
               m_trade.PositionClose(m_position.Ticket());
            }
            else if (trailingStopLoss) // Apply trailing stop loss
            {
               double currentStopLoss = m_position.StopLoss();
               double newStopLoss = m_symbol.Ask() - InpTrailingStopPoints * m_symbol.Point();

               if (newStopLoss > currentStopLoss) {
                  double takeProfit = m_position.TakeProfit();
                  if (OrderSelect(m_position.Ticket(), SELECT_BY_TICKET)) {
                     OrderModify(OrderTicket(), OrderOpenPrice(), newStopLoss, takeProfit, 0);
                  }
               }
            }
         }
         if (m_position.PositionType() == POSITION_TYPE_SELL) // If it's a SELL position
         {
            PosSell = 1;
            if (CrossPositionClose() == 2) // Close the order if it satisfies the condition CrossPositionClose()=2
            {
               m_trade.PositionClose(m_position.Ticket());
            }
            else if (trailingStopLoss) // Apply trailing stop loss
            {
               double currentStopLoss = m_position.StopLoss();
               double newStopLoss = m_symbol.Bid() + InpTrailingStopPoints * m_symbol.Point();

               if (newStopLoss < currentStopLoss) {
                  double takeProfit = m_position.TakeProfit();
                  if (OrderSelect(m_position.Ticket(), SELECT_BY_TICKET)) {
                     OrderModify(OrderTicket(), OrderOpenPrice(), newStopLoss, takeProfit, 0);
                  }
               }
            }
         }
      }
   }
   
   New_Bar=0;                          // Reset
   if(Time_0!=iTime(m_symbol.Name(),Period(),0)) // If it's a new bar with a different start time
   {
      New_Bar=1;                      // It's a new bar
      Time_0=iTime(m_symbol.Name(),Period(),0);               // Remember the start time of the new bar
   }

   MA1_0=iMAGet(handle_iMA_1,0);       // Current value of the 1st MA
   MA1_1=iMAGet(handle_iMA_1, 1);      // Previous value of the 1st MA
   MA2_0=iMAGet(handle_iMA_2, 0);      // Current value of the 2nd MA
   MA2_1=iMAGet(handle_iMA_2, 1);      // Previous value of the 2nd MA

   if(CrossPositionOpen()==1 && New_Bar==1) // Downward to upward movement = open Buy
   {
      OpenBuy();
   }
   if(CrossPositionOpen()==2 && New_Bar==1) // Upward to downward movement = open Sell
   {
      OpenSell();
   }
   return;
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

int CrossPositionOpen()
{
   PosOpen=0;                                                 
   if((MA1_1 <= MA2_0 && MA1_0 > MA2_0) || (MA1_1 < MA2_0 && MA1_0 >= MA2_0)) // Crossover from below to above
   {
      PosOpen=1;
   }
   if((MA1_1 >= MA2_0 && MA1_0 < MA2_0) || (MA1_1 > MA2_0 && MA1_0 <= MA2_0)) // Crossover from above to below
   {
      PosOpen=2;
   }
   return(PosOpen);                                          // Return the direction of the crossover
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int CrossPositionClose()
{
   PosClose=0;                                                
   if((MA1_1 >= MA2_0 && MA1_0<MA2_0) || (MA1_1 > MA2_0 && MA1_0 <= MA2_0)) // Crossover from above to below
   {
      PosClose=1;
   }
   if((MA1_1 <= MA2_0 && MA1_0 > MA2_0) || (MA1_1 <MA2_0 && MA1_0 >= MA2_0)) // Crossover from below to above
   {
      PosClose=2;
   }
   return(PosClose);                                          // Return the direction of the crossover
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OpenBuy()
{
   if(all_positions==1)
   {
      for(int i=PositionsTotal()-1;i>=0;i--) // returns the number of open positions
         if(m_position.SelectByIndex(i))
            if(m_position.PositionType()==POSITION_TYPE_BUY)
               return; // If it's a Buy position, do not open
   }
   if(!RefreshRates())
      return;

   double stopLossPrice = m_symbol.Ask() - StopLoss * m_symbol.Point();
   double takeProfitPrice = m_symbol.Ask() + TakeProfit * m_symbol.Point();

   m_trade.Buy(Lot, m_symbol.Name(), m_symbol.Ask(), stopLossPrice, takeProfitPrice, "Buy: MA_cross_Method_PriceMode");
   return;
}

void OpenSell()
{
   if(all_positions==1)
   {
      for(int i=PositionsTotal()-1;i>=0;i--) // returns the number of open positions
         if(m_position.SelectByIndex(i))
            if(m_position.PositionType()==POSITION_TYPE_SELL)
               return; // If it's a Sell position, do not open
   }
   if(!RefreshRates())
      return;

   double stopLossPrice = m_symbol.Bid() + StopLoss * m_symbol.Point();
   double takeProfitPrice = m_symbol.Bid() - TakeProfit * m_symbol.Point();

   m_trade.Sell(Lot, m_symbol.Name(), m_symbol.Bid(), stopLossPrice, takeProfitPrice, "Sell: MA_cross_Method_PriceMode");
   return;
}
//+------------------------------------------------------------------+
//| Refreshes the symbol quotes data                                 |
//+------------------------------------------------------------------+
bool RefreshRates()
{
   // Refresh rates
   if(!m_symbol.RefreshRates())
      return(false);
   // Protection against zero return value
   if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
      return(false);
   return(true);
}
//+------------------------------------------------------------------+
//| Get value of buffers for the iMA                                 |
//+------------------------------------------------------------------+
double iMAGet(const int handle,const int index)
{
   double MA[];
   ArraySetAsSeries(MA,true);
   // Reset error code
   ResetLastError();
   // Fill a part of the iMABuffer array with values from the indicator buffer that has an index of 0
   if(CopyBuffer(handle,0,0,index+1,MA)<0)
   {
      // If the copying fails, output the error code
      PrintFormat("Failed to copy data from the iMA indicator, error code %d",GetLastError());
      // Return 0.0 to indicate that the indicator is not calculated
      return(0.0);
   }
   return(MA[index]);
}
Files:
USDJPY.png  205 kb
 
Your topic has been moved to the section: Expert Advisors and Automated Trading