MQL5 Wizard maakt het mogelijk om automatisch de code van Expert Advisors (EA's) te genereren. Voor meer details kun je kijken naar Het maken van kant-en-klare Expert Advisors in MQL5 Wizard.
De handelsignalen van deze strategie zijn gebaseerd op twee exponentieel gladgestreken voortschrijdende gemiddelden (EMA's), zoals beschreven in MQL5 Wizard - Handelsignalen op basis van crossover van twee EMA's. Deze EMA's zijn effectief bij het volgen van trends, maar kunnen in andere gevallen veel valse signalen geven. Een manier om de strategie te verbeteren, is door tijdfilters toe te passen (bijvoorbeeld, nieuwe posities openen tijdens de Europese sessie van de FOREX).
In dit artikel bespreken we de strategie die gebruik maakt van de crossover van twee EMA's (snelle EMA en trage EMA) met een intraday tijdfilter. Deze strategie wordt genoemd "Signalen op basis van crossover van twee EMA's met intraday tijdfilter" (wanneer je een EA automatisch aanmaakt in MQL5 Wizard).
Handelsignalen:
- Open een lange positie: de snelle EMA kruist omhoog over de trage EMA en de voorwaarden voor het intraday tijdfilter zijn niet voldaan.
- Open een korte positie: de snelle EMA kruist omlaag onder de trage EMA en de voorwaarden voor het intraday tijdfilter zijn niet voldaan.
Deze strategie is geïmplementeerd in de CSignal2EMA_ITF klasse.
Het handelssysteem is gebaseerd op pending orders, waarbij de prijsniveaus worden berekend op basis van de waarden van het voortschrijdend gemiddelde, en de ATR (Average True Range) eenheid wordt gebruikt.

Figuur 1. Handelsignalen, gebaseerd op crossover van twee EMA's met intraday tijdfilter
Handelsignalen
De handelsstrategie is geïmplementeerd in CSignal2EMA_ITF, en deze heeft enkele beschermde methoden om de toegang tot de indicatorwaarden te vereenvoudigen:
double FastEMA(int ind) // retourneert de waarde van de snelle EMA van de bar double SlowEMA(int ind) // retourneert de waarde van de trage EMA van de bar double StateFastEMA(int ind) // retourneert de positieve/negatieve waarde als de snelle EMA is gestegen/gedaald double StateSlowEMA(int ind) // retourneert de positieve/negatieve waarde als de trage EMA is gestegen/gedaald double StateEMA(int ind) // retourneert het verschil tussen snelle en trage EMA double ATR(int ind) // retourneert de waarde van de ATR van de bar
- Limit>0. Het zal instappen bij terugbeweging wanneer er een valse doorbraak van het voortschrijdend gemiddelde is op een betere prijs dan de marktprijs (Buy Limit en Sell Limit orders worden geplaatst afhankelijk van het handelssignaal)
- Limit<0. Het zal instappen in de richting van de prijsbeweging (Buy Stop en Sell Stop orders worden geplaatst afhankelijk van het handelssignaal).
- Limit=0. In dit geval zal het handelen met de marktprijzen.
1. Open lange positie
Het controleert de voorwaarden om een lange positie te openen: als het verschil tussen de snelle en trage EMA op de laatste voltooide bar van teken is veranderd van "-" naar "+" (StateEMA(1)>0 && StateEMA(2)<0).
Daarna controleert het de voorwaarden van het intraday tijdfilter door de CheckOpenLong() methode van de CSignalITF klasse aan te roepen. Als handelen is toegestaan, berekent het het basisprijsniveau (de waarde van het voortschrijdend gemiddelde) en de waarde van het ATR-bereik van de laatste voltooide bar.
Afhankelijk van het teken van de Limiet-invoervariabele zal het een pending buy order plaatsen. De orderprijs, Take Profit en Stop Loss niveaus worden berekend ten opzichte van het basisprijsniveau (in ATR-eenheden). De vervaltijd van de order wordt gedefinieerd (in bars) door de Expiration-invoervariabele.
//+------------------------------------------------------------------+ //| Controleert de voorwaarden om een lange positie (buy) te openen | //+------------------------------------------------------------------+ bool CSignal2EMA_ITF::CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration) { if(!(StateEMA(1)>0 && StateEMA(2)<0)) return(false); if(!m_time_filter.CheckOpenLong(price,sl,tp,expiration)) return(false); //--- double ema=SlowEMA(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. Sluit lange positie
In ons geval retourneert de functie die de voorwaarden controleert om een lange positie te sluiten altijd false, dat wil zeggen dat wordt aangenomen dat de lange positie zal worden gesloten door Take Profit of Stop Loss. Indien nodig kun je je eigen code schrijven voor de implementatie van deze methode.
//+------------------------------------------------------------------+ //| Controleert de voorwaarden om een lange positie te sluiten | //+------------------------------------------------------------------+ bool CSignal2EMA_ITF::CheckCloseLong(double& price) { return(false); }
3. Open korte positie
Het controleert de voorwaarden om een korte positie te openen: als het verschil tussen de snelle en trage EMA op de laatste voltooide bar van teken is veranderd van "+" naar "-" (StateEMA(1)<0 && StateEMA(2)>0).
Vervolgens controleert het de voorwaarden van het intraday tijdfilter door de CheckOpenLong() methode van de CSignalITF klasse aan te roepen. Als handelen is toegestaan, berekent het het basisprijsniveau (de waarde van het voortschrijdend gemiddelde) en de waarde van het ATR-bereik van de laatste voltooide bar.
Afhankelijk van het teken van de Limiet-invoervariabele zal het een pending sell order plaatsen. De orderprijs, Take Profit en Stop Loss niveaus worden berekend ten opzichte van het basisprijsniveau (in ATR-eenheden). De vervaltijd van de order wordt gedefinieerd (in bars) door de Expiration-invoervariabele.
//+------------------------------------------------------------------+ //| Controleert de voorwaarden om een korte positie (sell) te openen | //+------------------------------------------------------------------+ bool CSignal2EMA_ITF::CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration) { if(!(StateEMA(1)<0 && StateEMA(2)>0)) return(false); if(!m_time_filter.CheckOpenShort(price,sl,tp,expiration)) return(false); //--- double ema=SlowEMA(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. Sluit korte positie
In ons geval retourneert de functie die de voorwaarden controleert om een korte positie te sluiten altijd false, dat wil zeggen dat wordt aangenomen dat de positie zal worden gesloten door Take Profit of Stop Loss. Indien nodig kun je je eigen code schrijven voor de implementatie van deze methode.
//+------------------------------------------------------------------+ //| Controleert de voorwaarden om een korte positie te sluiten | //+------------------------------------------------------------------+ bool CSignal2EMA_ITF::CheckCloseShort(double& price) { return(false); }
5. Trailing Stop van Pending Buy Order
De Expert Advisor zal pending orders volgen afhankelijk van de huidige waarde van het voortschrijdend gemiddelde en ATR.
//+--------------------------------------------------------------------+ //| Controleert de voorwaarden om een pending buy order aan te passen | //+--------------------------------------------------------------------+ bool CSignal2EMA_ITF::CheckTrailingOrderLong(COrderInfo* order,double& price) { //--- controle if(order==NULL) return(false); //--- double ema=SlowEMA(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. Trailing Stop van Pending Sell Order
De Expert Advisor zal pending orders volgen afhankelijk van de huidige waarde van het voortschrijdend gemiddelde en ATR.
De order wordt uitgevoerd als de marktprijs de orderprijs bereikt.
//+--------------------------------------------------------------------+ //| Controleert de voorwaarden om een pending sell order aan te passen | //+--------------------------------------------------------------------+ bool CSignal2EMA_ITF::CheckTrailingOrderShort(COrderInfo* order,double& price) { //--- controle if(order==NULL) return(false); //--- double ema=SlowEMA(1); double atr=ATR(1); //--- price=m_symbol.NormalizePrice(ema+m_limit*atr); //--- return(true); }
Een Expert Advisor maken met MQL5 Wizard
Om een handelsrobot te creëren op basis van de strategie moet je de signaleigenschappen selecteren als "Signalen op basis van crossover van twee EMA's met intraday tijdfilter" in de optie "Kant-en-klare Expert Advisors maken" in MQL5 Wizard:

Figuur 2. Selecteer "Signalen op basis van crossover van twee EMA's met intraday tijdfilter" in MQL5 Wizard
Vervolgens moet je het benodigde trailing stop algoritme en geld- en risicobeheer systeem specificeren. De code van de Expert Advisor wordt automatisch aangemaakt, je kunt deze compileren en testen in de Strategy Tester van de MetaTrader 5 client.
Testresultaten
Laten we de backtesting van de Expert Advisor op historische data bekijken (EUenSD H1, testperiode: 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).
Bij het creëren van de Expert Advisor gebruikten we het vaste volume (Vast Lot Handelen, 0.1), en de Trailing Stop algoritme is niet gebruikt (Trailing niet gebruikt).

Figuur 3. Testresultaten van de Expert Advisor met handelsignalen, gebaseerd op crossover van twee EMA's zonder gebruik van ITF filter
Het intraday filter is niet gebruikt, dus er zijn veel valse signalen. De handelsignalen kunnen worden verbeterd door de analyse van de dealresultaten afhankelijk van de handelsuren uit te voeren.
In ons geval hebben we vastgesteld dat de crossover van twee EMA's veel valse signalen oplevert van 6:00 tot 23:59. We kunnen het intraday tijdfilter specificeren door de filterparameters in te stellen.
Bijvoorbeeld, we kunnen een tijdfilter specificeren dat het openen van posities alleen toelaat van 0:00 tot 5:59. Dit kan gedaan worden door de waarde van BadHoursOfDay=16777152=111111111111111111000000b in te stellen. Alle andere handelsuren zijn "slecht", dus het is beter om het openen van nieuwe posities van 6:00 tot het einde van de dag te verbieden.
Als we de waarde van BadHoursOfDay=16777152 instellen, zullen we veel valse signalen filteren:

Figuur 4. Testresultaten van de Expert Advisor met handelsignalen, gebaseerd op crossover van twee EMA's met tijdfilter (BadHoursofDay=16777152)
De CSignalITF biedt veel andere tijdfiltratiefuncties (geef gewoon de "goede" en "slechte" minuten binnen het uur, uren binnen de dag, dagen binnen de week op).
Bijlagen: De Signal2EMA-ITF.mqh met CSignal2EMA_ITF klasse moet worden geplaatst in terminal_data_folder\MQL5\Include\Expert\Signal map.
De expert_2ema_itf.mq5 bevat de code van de Expert Advisor, gemaakt met behulp van MQL5 Wizard.
Gerelateerde berichten
- MQL5 Wizard: Creëer Handelsstrategieën met Bullish en Bearish Engulfing Candlestick Patronen en Stochastic
- Efficiënt Trendvolgend Handelsysteem met Exp_X2MA_JFatl voor MetaTrader 5
- Close Cross MA: Efficiënt Orders Sluiten met MetaTrader 4
- Efficiënt Handelen met het ColorSchaffJCCXTrendCycle Systeem voor MetaTrader 5
- Efficiënt Handelen met de Ang_Zad_C Indicator voor MetaTrader 5