MQL5 Wizard - Trading signals based on two EMA crossovers and intraday time filter - MetaTrader 5 Expert






MQL5 Wizard allows automatic creation of Expert Advisor codes. See Creating a Ready-made Expert Advisor in MQL5 Wizard for details.
Here we will consider a strategy based on the intersection of two exponentially smoothed moving averages (fast EMA and slow EMA) with an intraday time filter. The strategy is called "Signal based on the intersection of two EMAs with intraday time filters" (when automatically creating an EA in the MQL5 Wizard).
This strategy is implemented in the CSignal2EMA_ITF class.
The trading system is based on pending orders, price levels are calculated based on the values of moving averages, using ATR units (Average True Range).

Figure 1. Trading signal based on intersection of two EMAs with intraday time filter
The implementation of the trading strategy is in CSignal2EMA_ITF , which has some protected methods to simplify access to indicator values:
Double fast EMA ( Integer Industrial) // Returns the fast EMA value of the bar Double Slow EMA ( Integer Industrial) // Returns the slow EMA value of the bar Double StateFastEMA( Integer Industrial) // Return positive/negative value if EMA increases/decreases rapidly Double status SlowEMA ( Integer Industrial) // Return positive/negative value if slow EMA increases/decreases DOUBLE STATUSEMA( INTEGER INDUSTRIAL) // Returns the difference between fast EMA and slow EMA Double ATR ( Integer Industrial) // Returns the ATR value of the bar
1. Open a long position
It checks the conditions for opening a long position: the difference between fast and slow EMA on the last completed bar has changed its sign from "-" to "+" (StateEMA(1)>0 && StateEMA(2)<0).
Next, it checks the time-of-day filter by calling the CheckOpenLong() method of the CSignalITF class. If the trade is allowed, it will calculate the base price level (the value of the moving average) and the ATR range value of the last completed bar.
Depending on the sign of the Limit input parameter, it will place a buy pending order. Order price, Take Profit and Stop Loss levels are calculated relative to the base price level (in ATR units). The order expiry time is defined by the Expiration input parameter (in bars).
//+------------------------------------------------------------------+ //|Check the conditions for opening a long position (Buy) | //+------------------------------------------------------------------+ Boolean CSignal2EMA_ITF::CheckOpenLong( double &price, double &SL, double &tp,DateTime&ExpiryDate) { if (!(status EMA( 1 ) > 0 && status EMA( 2 ) < 0 )) return ( false ); if (!m_time_filter.CheckOpenLong(price,sl,tp,expiry)) returns ( false ); //--- Double EMA = slow EMA( 1 ); double atr=ATR( 1 ); Double spread=m_symbol.Ask()-m_symbol.Bid(); //--- Price=m_symbol.NormalizePrice(ema-m_limit*atr+spread); sl =m_symbol.NormalizePrice(price+m_stop_loss*atr); tp =m_symbol.NormalizePrice(price-m_take_profit*atr); Expiration+=m_expiration*PeriodSeconds(m_period); //--- return ( true ); }
2. Long position closing
In our example, the function that checks the closing conditions always returns false, i.e. it is assumed that the long position will be closed via Take Profit or Stop Loss. If desired, you can write your own code to implement this method.
//+------------------------------------------------------------------+ //|Check closing conditions| //+-----------------------------------------------------------------+ boolean CSignal2EMA_ITF::CheckCloseLong( double &price) { return ( false ); }
3. Open a short position
It checks the conditions for opening a short position: the difference between fast and slow EMA on the last completed bar has changed its sign from "+" to "-" (StateEMA(1)<0 && StateEMA(2)>0).
Next, it checks the time-of-day filter by calling the CheckOpenLong() method of the CSignalITF class. If the trade is allowed, it will calculate the base price level (the value of the moving average) and the ATR range value of the last completed bar.
Depending on the sign of the Limit input parameter, it will place a sell pending order. Order price, Take Profit and Stop Loss levels are calculated relative to the base price level (in ATR units). The order expiry time is defined by the Expiration input parameter (in bars).
//+------------------------------------------------------------------+ //|Check the conditions for opening a short position (sell) | //+------------------------------------------------------------------+ Boolean CSignal2EMA_ITF::CheckOpenShort( double &price, double &SL, double &tp,datetime&expiryDate) { if (!(status EMA( 1 ) < 0 && status EMA( 2 ) > 0 )) return ( false ); if (!m_time_filter.CheckOpenShort(price,sl,tp,expiry)) returns ( false ); //--- Double EMA = slow EMA( 1 ); Double atr=ATR( 1 ); //--- price =m_symbol.NormalizePrice(ema+m_limit*atr); sl =m_symbol.NormalizePrice(price+m_stop_loss*atr); tp =m_symbol.NormalizePrice(price-m_take_profit*atr); Expiration+=m_expiration*PeriodSeconds(m_period); //--- return ( true ); }
4. Close position
In our example, the function that checks the short position closing conditions always returns false, i.e. it is assumed that the position will be closed via Take Profit or Stop Loss. If desired, you can write your own code to implement this method.
//+------------------------------------------------------------------+ //|Check short position closing conditions| //+----------------------------------------------------------------------------------+ boolean CSignal2EMA_ITF::CheckCloseShort( double &price) { return ( false ); }
5. Buy pending order with trailing stop loss
The Expert Advisor will track pending orders based on the moving average and the current value of ATR.
//+------------------------------------------------------------------------------------------------+ //|Check and modify the conditions for pending and buying orders| //+---------------------------------------------------------------------------------------------+ Boolean CSignal2EMA_ITF::CheckTrailingOrderLong(COrderInfo* order, double & price) { // - - Check if (order == NULL) returns ( false ); //--- Double EMA = Slow EMA( 1 ); double atr=ATR( 1 ); Double spread=m_symbol.Ask()-m_symbol.Bid(); //--- Price=m_symbol.NormalizePrice(ema-m_limit*atr+spread); //--- Return ( true ); }
6. Sell pending order with trailing stop loss
The Expert Advisor will track pending orders based on the moving average and the current value of ATR.
If the market price reaches the order price, the order will be executed.
//+------------------------------------------------------------------------------------------------+ //|Check and modify the conditions for pending and buying orders| //+------------------------------------------------------------------------------------------------+ boolean CSignal2EMA_ITF::CheckTrailingOrderShort(COrderInfo* order, double & price) { // - - Check if (order == NULL) returns ( false ); //--- Double EMA = Slow EMA( 1 ); Double atr=ATR( 1 ); //--- price=m_symbol.NormalizePrice(ema+m_limit*atr); //--- return ( true ); }
Create an Expert Advisor using the MQL5 Wizard
To create a trading robot based on a strategy, you need to select the signal property as " Signal based on the crossing of two EMAs with an intraday time filter " in the "Create ready-made Expert Advisor" option in the MQL5 Wizard :

Figure 2. Select "Signal based on intersection of two EMAs with intraday time filter" in the MQL5 Wizard
Next you must specify the required trailing stop algorithm and money and risk management system. The code of the Expert Advisor will be automatically created and you can compile and test it with the Strategy Tester MetaTrader 5 client terminal.
Test results
Let's consider the backtesting of Expert Advisors on historical data (EUenSD H1, test period: 1.1.2010-05.01.2011, PeriodFastEMA=5, PeriodSlowEMA=30, PeriodATR=7, Limit=1.2, StopLoss=5, TakeProfit=8, Expiration=4, GoodMinuteOfHour=-1, BadMinutesOfHour=0, GoodHourOfDay=-1, BadHoursOfDay=0, GoodDayOfWeek=-1, BadDaysOfWeek=0).
When creating the EA, we used a fixed trading volume ( fixed lot size for trading , 0.1) and did not use the trailing stop algorithm ( trailing was not used ).

In our case, we found that the crossover of two EMAs from 6:00 to 23:59 provided many false signals. We can specify an intraday time filter by setting the filter parameter.
For example, we can specify a time filter that only allows positions to be opened between 0:00 and 5:59. This can be done by setting the value of BadHoursOfDay=16777152=111111111111111111000000b. All other trading hours are "bad", so it is better to prohibit opening new positions from 6:00 to the end of the day.
If we set the value BadHoursOfDay=16777152, we will filter out many error signals:

CSignalITF provides many other time filtering functions (just specify "good" and "bad" minutes within an hour, hour of day, day of week).
Attachment: Signal2EMA-ITF.mqh with CSignal2EMA_ITF class must be placed in the terminal_data_folder\MQL5\Include\Expert\Signal folder.
Expert_2ema_itf.mq5 contains the code of the Expert Advisor created using the MQL5 Wizard.
Attachment download
📎 signal2ema-itf.mqh (16.53 KB)
📎 expert_2ema_itf.mq5 (7.29 KB)
Source: MQL5 #264
💡 Featured Recommendations
✍️ Latest by the author
- •
- •
- •
- •
- •
- •
📌 Popular topics
- •
- •
- •
- •
- •
- •
- •
- •
🔗 You May Be Interested In
- •
- •
- •
- •
- •
- •