English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Plusieurs modes de recherche de tendance dans MQL5

Plusieurs modes de recherche de tendance dans MQL5

MetaTrader 5Trading | 22 décembre 2021, 16:41
663 0
Dmitriy Skub
Dmitriy Skub

Introduction

Tout trader connaît la règle qui dit que « La tendance est votre amie, suivez-la », malheureusement presque chacun a sa propre idée de ce qu'est une tendance. Presque tous les traders ont entendu ou lu des histoires horribles, qui racontent comment les traders, qui ont tradé à contre-courant, se sont ruinés.

Tout trader ferait tout ce qui est en son pouvoir pour réussir à détecter avec précision une tendance à un moment donné. C’est peut-être sans doute cela le Saint-Graal que tout le monde recherche. Dans cet article, nous examinerons plusieurs modes de détection de tendance. Pour être plus précis - comment programmer plusieurs modes classiques pour détecter une tendance au moyen de MQL5.


1. Qu'est-ce qu'une tendance et pourquoi le savoir

Tout d'abord, formulons le concept général de tendance.

Trend - est une tendance à long terme (direction) de changement de prix sur le marché. De cette définition générale de la tendance découlent les conséquences :

  • La direction du changement de prix est fonction de délai, sur lequel les séries temporelles de prix sont prises en compte.
  • La direction du changement de prix est fonction du point de référence, à partir duquel commence l'analyse des séries temporelles pour identifier une tendance.

Illustrons ce concept :

Figure 1. Analyse des tendances

Figure 1. Analyse des tendances

En considérant la figure, vous pouvez voir que la tendance globale depuis fin 2005 jusqu'en mai 2006 est à la hausse (flèche verte sur le graphique). Mais si nous considérons le graphique des prix dans ses moindres détails, vous constaterez qu'en février 2006, la tendance était clairement à la baisse (flèche rouge sur le graphique), et presque tout le mois de janvier, le prix évoluait de façon aléatoire (flèche jaune).

Ainsi, avant d'identifier une tendance, vous devez déterminer la période qui vous intéresse. Dans le contexte du trading, le délai détermine tout d'abord le temps de détention de la position sur le marché, de son ouverture à sa clôture. En outre, les niveaux d'arrêts de protection et de fermetures prévues, ainsi que la fréquence des opérations de trading, en dépendent.

Le but de cet article est d'aider les nouveaux traders à utiliser avec compétence les outils de détection de tendance, fournis par la plateforme MetaTrader 5. Cet article vise également à donner des connaissances de base sur l'écriture d'indicateurs simples, qui automatisent ce processus. Le but ultime est d'écrire des Experts simples, qui utilisent ces indicateurs pour le trading automatisé.  

  Pour plus de précision, nous considérerons le graphique des cours au quotidien (période D1 dans le terminal) de l'instrument le plus liquide du marché des changes - EURUSD. Le temps de détention de la position sur une telle période peut varier de plusieurs jours à plusieurs mois. En conséquence, l'objectif - est de prendre des centaines, voire des milliers de points, et les stop loss de protection sont situés à une distance de plusieurs centaines de points.

En général, tout ce qui est décrit ci-dessous peut être utilisé sur n'importe quel délai. Cependant, gardez à l'esprit que plus le délai de temps du graphique est petit, plus le trade fera écho, en raison des news, des spéculations du marché des principaux participants et d'autres facteurs, affectant la volatilité du marché.

Si nous tenons compte du fait que plus la tendance est longue, moins elle est susceptible de changer, alors, lorsque vous tradez avec la tendance, il est plus probable de gagner que de perdre de l'argent. Maintenant, vous devez comprendre comment détecter une tendance sur le graphique des prix. Cela sera discuté dans cet article.


2. Comment détecter une tendance

Voici quelques modes connus de la détection de tendance :

  1. Via la Moyenne Mobile
  2. Via les pics de zigzag
  3. Via les indications ADX
  4. Via NRTR
  5. Via les couleurs des chandeliers d’Heiken Ashi

Nous considérerons systématiquement tous ces modes, leurs avantages et leurs inconvénients. Ensuite, nous les comparerons sur la même période de l'histoire.

2.1. Détection de tendance via la moyenne mobile

Peut-être, le mode le plus simple de détecter une tendance et sa direction - moyennes mobiles. L'un des premiers outils d'analyse technique - la moyenne mobile - est encore utilisé dans différentes variantes et constitue la base de la plupart des indicateurs. Les traders utilisent à la fois une moyenne mobile et un ensemble complet d'entre elles, parfois appelées « fan ». 

Formulons une règle simple pour une moyenne mobile :
  • La tendance monte si, à un moment donné, le cours de clôture de la barre est supérieur à la moyenne mobile.
  • La tendance baisse si, à un moment donné, le cours de clôture de la barre est inférieur à la moyenne mobile.

Dans ce cas, nous utiliserons le cours de clôture de la barre pour réduire le nombre de « faux » changements de tendance, lorsque le cours fluctue de haut en bas près de la moyenne mobile (le soi-disant "rebond").  

Illustrons cette méthode :

Figure 2. Identification d’une tendance via la moyenne mobile

Figure 2. Identification d’une tendance via la moyenne mobile

Ici, nous utilisons le graphique EURUSD D1 et une moyenne mobile simple avec une période de 200, construite sur les cours de clôture (ligne rouge sur le graphique). Au bas de la figure, vous pouvez voir un indicateur de tendance spécialement développé - MATrendDetector. La direction de la tendance est indiquée par la position de l'histogramme de l'indicateur, par rapport à l'axe zéro. +1 correspond à la tendance haussière. -1 - tendance baissière. De plus, nous discuterons de cet indicateur et d'autres, utilisés dans cet article.

Vous pouvez voir que lorsque la barre se ferme au-dessus/en dessous de la moyenne mobile, le prix se transforme alors souvent en direction opposée. C'est-à-dire que cette méthode donne beaucoup de faux signaux. C'est pourquoi son utilisation dans les Experts et les Indicateurs est très limitée, sauf exceptionnellement comme filtre de tendance très « approximative ».

2.2. Détection de tendance à l'aide de trois moyennes mobiles

Que peut-on faire pour améliorer la qualité de la détection des tendances à l'aide de moyennes mobiles ? Par exemple, vous pouvez utiliser deux ou plusieurs moyennes mobiles avec des périodes différentes. Ensuite, la règle de détection de tendance pour n'importe quel nombre (plus d'un) de moyennes mobiles avec différentes périodes se présentera comme suit :

  • Il y a tendance haussière si, à un moment donné, toutes les moyennes mobiles sont tracées dans l'ordre croissant correct à la fermeture de la barre.
  • Il y a tendance baissière si, à un moment donné, toutes les moyennes mobiles sont tracées dans l'ordre décroissant correct à la fermeture de la barre.

Ici, nous utilisons les termes suivants :

  • Ordre croissant correct - chaque moyenne mobile doit être supérieure à toutes les autres moyennes mobiles avec une période plus élevée.
  • Ordre décroissant correct - chaque moyenne mobile doit être inférieure à toutes les autres moyennes mobiles avec une période plus élevée.

Un tel « ordre correct des moyennes » est également appelé ouverture up/down fan des moyennes, en raison de la ressemblance visuelle.

Illustrons cette méthode :

Figure 3. Détection de tendance via des moyennes mobiles diverses

Figure 3. Détection de tendance via des moyennes mobiles diverses

Ici, nous utilisons le graphique EURUSD D1 et des moyennes mobiles simples avec des périodes de 200 (ligne rouge épaisse), 50 (ligne jaune d'épaisseur moyenne) et 21 (ligne violette fine), construites sur les cours de clôture.

Au bas de la figure, vous pouvez voir un indicateur de tendance spécialement développé - FanTrendDetector. La direction de la tendance est indiquée par la position de l'histogramme de l'indicateur, par rapport à l'axe zéro. +1 correspond à la tendance haussière. -1 - tendance baissière. Si la valeur de l'histogramme est égale à zéro, cela signifie que la tendance ne peut pas être détectée. Il existe également l'indicateur MATrendDetector à titre de comparaison.

Il est évident que le nombre de fausses alarmes de changement de tendance a diminué. Mais le délai de détection de tendance a été augmenté. Cela a du sens - jusqu'à ce que toutes les moyennes mobiles s'alignent dans le « bon » ordre, cela peut prendre un certain temps. Ce qui est mieux et ce qui ne l'est pas - dépend du système de trading qui utilise ces méthodes.

Dans ce cas, les valeurs de période des moyennes ne sont pas sélectionnées de toute façon, mais elles sont le plus largement utilisées par les traders et par l'auteur de l'article. En sélectionnant un ensemble de moyennes et leur nombre, vous pouvez essayer d'améliorer les caractéristiques de cette méthode de détection de tendance pour une paire de devises particulière.

2.3. Détection de tendance via des maximums et des minimums de l'indicateur ZigZag

Abordons maintenant la détection des tendances du point de vue des classiques de l'analyse technique. À savoir, nous utiliserons la règle suivante de Charles Dow :

  • La tendance monte si chaque prochain maximum local du tableau des prix est supérieur au précédent maximum local et que chaque minimum local suivant du tableau des prix est également supérieur au précédent minimum local.
  • La tendance baisse si chaque minimum local suivant du tableau des prix est inférieur au minimum local précédent, et chaque maximum local suivant du tableau des prix est également inférieur au précédent maximum local.

Nous trouverons des maxima/minima locaux par les sommets de l'indicateur Zigzag.

Illustrons cette méthode :

Figure 4. Détection de tendance via l’Indicateur ZigZag

Figure 4. Détection de tendance via l'Indicateur ZigZag

Ici, nous utilisons le graphique EURUSD D1 et Zigzag avec les paramètres suivants : ExtDepth = 5, ExtDeviation = 5, ExtBackstep = 3.

Au bas de la figure, vous pouvez voir un indicateur de tendance spécialement développé - ZigZagTrendDetector.

Le principal inconvénient de cette méthode de détection de tendance - en temps réel, il est impossible de comprendre si l'extremum est déjà formé ou non. Sur l'historique, les extrema se voient très bien, et vous pouvez comprendre où ils se sont formés. Cependant, lorsque le prix change en temps réel, l'extremum formé peut soudainement disparaître ou réapparaître. Pour le voir, il suffit de regarder les lignes en zigzag tracées en mode de test visuel dans chaque Expert.

Cet inconvénient rend cette méthode sans valeur pour une utilisation pratique dans le trading. Mais il est très utile pour l'analyse technique des données historiques afin de trouver des modèles et d'évaluer la qualité de divers systèmes de trading.

2.4. Détection de tendance via l'indicateur ADX

Le mode considéré ci-après - est la détection de tendance via l'indicateur ADX (indice de mouvement directionnel moyen). Cet indicateur est utilisé non seulement pour détecter la direction de la tendance, mais aussi pour évaluer sa force. C'est une caractéristique très précieuse de l'indicateur ADX. La force de la tendance est déterminée par la ligne ADX principale - si la valeur est supérieure à 20 (le niveau généralement accepté, mais pas nécessairement le meilleur pour le moment), alors la tendance est suffisamment forte.

La direction de la tendance est déterminée par les lignes +DI et -DI entre elles. Cet indicateur utilise le lissage des trois lignes avec une moyenne exponentielle, et a donc un délai de réponse au changement de tendance.

Formulons la règle de détection de tendance :

  • La tendance monte si la ligne +DI est supérieure à la ligne -DI.
  • La tendance baisse si la ligne +DI est inférieure à la ligne -DI.

Dans ce cas, la ligne de tendance ADX n'est pas utilisée pour détecter une tendance. Il est nécessaire de réduire le nombre de faux signaux de cet indicateur. Si la tendance est faible (ADX est inférieur à 20), il est préférable d'attendre qu'elle devienne plus forte et ensuite seulement de commencer à trader avec la tendance.

Illustrons cette méthode :

Figure 5. Identification d’une tendance via Indicateur ADX

Figure 5. Identification d’une tendance via l'indicateur ADX

Ici, nous utilisons le graphique EURUSD D1 et l'indicateur ADX avec les paramètres suivants : PeriodADX = 21 (ligne bleue épaisse - valeur de la force de la tendance ADX, ligne verte fine - valeur de +DI, ligne rouge fine - valeur de -DI).

Au bas de la figure, vous pouvez voir un indicateur de tendance spécialement développé - ADXTrendDetector. À titre de comparaison, dans le graphique supérieur (cramoisi) de l'indicateur ADXTrendDetector, le filtre de force de tendance a été désactivé (ADXTrendLevel = 0), et dans le graphique inférieur (bleu) - il a été activé (ADXTrendLevel = 20).

Notez que nous avions laisser tomber cette partie du soi-disant « rebond » dans la détection de la direction de la tendance lorsque nous avons activé le filtre de force de la tendance. Il est souhaitable d'utiliser ce filtre dans un travail réel. Une amélioration supplémentaire de la qualité des indicateurs peut être obtenue par la sélection habile de paramètres externes en fonction de la situation actuelle du marché (flat/range/trend) et en fonction de la nature du mouvement de la paire de devises.

En général, cet indicateur offre une bonne opportunité de créer des systèmes de trading de suivi des tendances comme filtre d'entrée.

2.5. Détection de tendance via l'indicateur NRTR

La méthode suivante pour détecter une tendance - en utilisant l'indicateur NRTR (Nick Rypock Trailing Reverse). Cet indicateur est toujours situé à une distance constante des extrema de prix atteints - des prix plus bas sur les tendances haussières et des prix plus élevés sur les tendances baissières. L'idée principale de cet indicateur - de petits mouvements correctifs contre la tendance principale doit être ignorés, et un mouvement contre la tendance principale, dépassant un certain niveau, signale un changement de direction de la tendance.

De cette affirmation découle la règle de détection de la direction de la tendance :

  • La tendance monte - si la ligne indicatrice correspond à la tendance haussière à la fermeture de la barre.
  • La tendance baisse - si la ligne indicatrice correspond à la tendance baissière à la fermeture de la barre.

Pour réduire l'influence des faux renversements de tendance sur les fluctuations de prix, nous utiliserons les prix de clôture pour vérifier la position de la ligne NRTR.

Illustrons cette méthode :

Figure 6. Identification d’une tendance via l’indicateur NRTR

Figure 6. Identification d'une tendance via l'indicateur NRTR

Ces gros points bleus correspondent à la tendance haussière, tandis que les gros points rouges - à la tendance baissière. Au bas du graphique s'affiche notre indicateur de tendance NRTRTrendDetector, décrit ci-dessous.

2.6. Détection de tendance via trois chandeliers d’Heiken Ashi

Un autre moyen populaire de détecter une tendance est d'utiliser les chandeliers Heiken Ashi. Les graphiques Heiken Ashi sont des graphiques de chandeliers japonais. Leurs valeurs sont en partie une moyenne de la bougie précédente.

Illustrons cette méthode :

Figure 7. Detection de tendance via la couleur des chandeliers Heiken Ashi

Figure 7. Détection de tendance par couleur des chandeliers Heiken Ashi

Comme vous pouvez le voir, cette méthode n'est pas non plus exempte de « faux » signaux, lorsque le cours fluctue de façon aléatoire. Mais le pire est que cet indicateur peut redessiner non seulement la dernière barre, mais aussi l'avant-dernière. C'est-à-dire que le signal sur lequel nous sommes entrés, peut être inversé sur la barre suivante. Cela est dû au fait que lorsque la couleur des chandeliers est déterminée, deux barres sont analysées, il est donc recommandé d'utiliser cette méthode en conjonction avec d'autres signaux de support.


3. Indicateurs de Tendance

Créons maintenant des indicateurs de tendance.

3.1. Indicateur de tendance basé sur la moyenne mobile

L'indicateur le plus simple, comme mode le plus simple de déterminer une tendance, sur la base de la moyenne mobile. Considérons, de quelles parties il se compose. Le code source complet de l'indicateur se trouve dans le fichier MATrendDetector.MQ5, joint à l'article.

Au début du programme indicateur vient la ligne, qui relie la bibliothèque pour calculer les différentes moyennes mobiles. Cette bibliothèque est livrée avec Client Terminal et est prête à être utilisée immédiatement après l'installation. Voici cette ligne :

#include <MovingAverages.mqh>

Nous en utiliserons une fonction, qui calcule une moyenne mobile simple :

double SimpleMA(const int position, const int period, const double &price[])

Ici, vous définissez les paramètres d'entrée :

  • position - indice initial dans le tableau price[], à partir duquel commence le calcul.
  • period - période de moyenne mobile, doit être supérieure à zéro.
  • price[] - tableau, qui contient la plage de prix spécifiée lors du placement de l'indicateur sur le graphique. Par défaut, le travail s’effectue avec les cours de clôture de la barre Close[].

La fonction renvoie la valeur calculée de la moyenne mobile.

La partie suivante du texte contient les paramètres initiaux pour afficher l'indicateur à l'écran :

//---------------------------------------------------------------------
#property indicator_separate_window
//---------------------------------------------------------------------
#property indicator_applied_price       PRICE_CLOSE
#property indicator_minimum             -1.4
#property indicator_maximum             +1.4
//---------------------------------------------------------------------
#property indicator_buffers             1
#property indicator_plots               1
//---------------------------------------------------------------------
#property indicator_type1               DRAW_HISTOGRAM
#property indicator_color1              Black
#property indicator_width1              2
//---------------------------------------------------------------------

Les paramètres suivants sont disponibles :

  • #property indicator_separate_window indique au terminal MetaTrader 5 d'afficher le graphique de l’indicateur dans une fenêtre séparée.
  • #property indicator_applied_price    PRICE_CLOSE - type de prix utilisé par défaut.
  • #property indicator_minimum   -1.4 - valeur minimale de l'axe vertical, affichée dans la fenêtre d'indicateur.
  • #property indicator_maximum  +1.4 - valeur maximale de l'axe vertical, affichée dans la fenêtre d'indicateur.

Les deux derniers paramètres vous permettent de définir une échelle fixe pour afficher le graphique des indicateurs. Cela est possible car nous connaissons les valeurs minimales et maximales de notre indicateur - de -1 à +1 inclus. Cela est fait pour donner au graphique une apparence esthétique, pour ne pas chevaucher les bordures de la fenêtre ainsi que le titre de l'indicateur dans la fenêtre.

  • #property indicator_buffers   1 - nombre de tampons pour le calcul de l'indicateur. Nous n'utilisons qu'un seul tampon.
  • #property indicator_plots       1 - nombre de séries graphiques dans l’indicateur. Nous affichons un seul graphique à l'écran.
  • #property indicator_type1     DRAW_HISTOGRAM - affiche le graphique des indicateurs sous forme d'histogramme.
  • #property indicator_color1     Black - couleur par défaut du tableau des indicateurs.
  • #property indicator_width1    2 - largeur de ligne du graphique des indicateurs, dans ce cas, il s'agit de la largeur des colonnes de l'histogramme.

Vient ensuite la partie pour entrer les paramètres externes de l'indicateur, qui peuvent être modifiés lors du placement de l'indicateur sur le graphique et plus tard, lorsqu'il fonctionne :

input int   MAPeriod = 200;

Il n'y a qu'un seul paramètre - la valeur de la période de moyenne mobile.

La prochaine partie essentielle de l'indicateur - les fonctions, qui traitent divers événements, qui se produisent lorsque l'indicateur fonctionne sur le graphique.

En premier vient la fonction d'initialisation - OnInit(). Elle est appelée immédiatement après le chargement de l'indicateur. Dans notre indicateur, cela se présente comme suit :

void OnInit()
{
  SetIndexBuffer( 0, TrendBuffer, INDICATOR_DATA );
  PlotIndexSetInteger( 0, PLOT_DRAW_BEGIN, MAPeriod );
}

La fonction SetIndexBuffer() lie le tableau précédemment déclaré, dans lequel nous stockerons les valeurs de tendance TrendBuffer[], avec l'un des tampons d'indicateur. Nous n'avons qu'un seul indicateur tampon et son indice est égal à zéro.

La fonction PlotIndexSetInteger() configure le nombre de barres initiales sans les dessiner dans la fenêtre d'indicateur.

Puisqu’ il est mathématiquement impossible de calculer une moyenne mobile simple sur le nombre de barres inférieures à sa période, spécifions le nombre de barres, égal à la période de la moyenne mobile.

Vient ensuite la fonction, qui traite les événements concernant la nécessité de recalculer un indicateur - OnCalculate() :

int OnCalculate(const int _rates_total, 
                const int _prev_calculated,
                const int _begin, 
                const double& _price[ ] )
{
  int  start, i;

//   If number of bars on the screen is less than averaging period, calculations can't be made:
  if( _rates_total < MAPeriod )
  {
    return( 0 );
  }

//  Determine the initial bar for indicator buffer calculation:
  if( _prev_calculated == 0 )
  {
    start = MAPeriod;
  }
  else
  {
    start = _prev_calculated - 1;
  }

//      Loop of calculating the indicator buffer values:
  for( i = start; i < _rates_total; i++ )
  {
    TrendBuffer[ i ] = TrendDetector( i, _price );
  }

  return( _rates_total );
}

Cette fonction est appelée pour la première fois après l'initialisation de l'indicateur et à chaque fois que les données de prix changent. Par exemple, quand vient une nouvelle cotation sur le symbole pour lequel l'indicateur est calculé. Considérons-le en détail.

Tout d'abord, vérifiez s'il y a assez de nombres de barres sur un graphique - s'il est inférieur à la période de moyenne mobile, alors il n'y a rien à calculer et cette fonction se termine par l'opérateur de retour. Si le nombre de barres est suffisant pour les calculs, déterminez la barre initiale à partir de laquelle l'indicateur sera calculé. Cela est fait afin de ne pas recalculer toutes les valeurs des indicateurs à chaque trait de prix.

Ici, nous utilisons le mécanisme, fourni par le terminal. Chaque fois que vous appelez une fonction de gestionnaire, vérifiez la valeur de l'argument de fonction _prev_calculated - il s'agit du nombre de barres, traitées lors de l'appel précédent de la fonction OnCalculate(). S'il est égal à zéro, recalculez toutes les valeurs de l'indicateur. Sinon recalculez uniquement la dernière barre avec l'indice _prev_calculated - 1.

La boucle de calcul des valeurs de tampon d'indicateur est effectuée par l'opérateur for - dans son corps, nous appelons la fonction de détection de tendance TrendDetector pour chaque valeur de tampon d'indicateur recalculé. Ainsi, en remplaçant uniquement cette fonction, nous pouvons appliquer différents algorithmes pour calculer la direction de la tendance. Dans ce cas, le reste des parties de l'indicateur ne varient pas (il est possible que des paramètres externes changent).

Considérons maintenant la fonction de détection de tendance elle-même - TrendDetector.

int TrendDetector(int _shift, const double& _price[])
{
  double  current_ma;
  int     trend_direction = 0;

  current_ma = SimpleMA(_shift, MAPeriod, _price);

  if(_price[_shift] > current_ma)
  {
    trend_direction = 1;
  }
  else if(_price[_shift] < current_ma)
  {
    trend_direction = -1;
  }

  return(trend_direction);
}

La fonction effectue les tâches suivantes :

  • Calcule la moyenne mobile simple, à partir de la barre, définie par l'argument _shift. On se sert de la fonction de bibliothèque SimpleMA.
  • Compare les valeurs de prix sur cette barre avec la valeur moyenne mobile.
  • Si la valeur du prix est supérieure à la valeur moyenne mobile, elle renvoie 1, sinon si la valeur du prix est inférieure à la valeur moyenne mobile, elle renvoie -1, sinon elle renvoie zéro.

Si la fonction a renvoyé zéro, cela signifie que la tendance n'a pas pu être détectée.

Le résultat du travail sur les indicateurs est visible sur les figures Figure 2 et Figure 3.

3.2. Indicateur de tendance en base « fan » des moyennes mobiles

Voyons maintenant comment, sur la base de cet indicateur, vous pouvez créer un indicateur un peu plus complexe, qui utilise le « ventilateur » des moyennes mobiles pour détecter une tendance.

Le code source complet de l'indicateur se trouve dans le fichier FanTrendDetector.MQ5, joint à l'article.

Les différences de cet indicateur par rapport au précédent sont les suivantes :

  • Des périodes de trois moyennes mobiles sont définies dans les paramètres externes :
input int MA1Period = 200; // period value of senior moving average
input int MA2Period = 50;  // period value of medium moving average
input int MA3Period = 21;  // period value of junior moving average
  • Une autre fonction TrendDetector :
int TrendDetector(int _shift, const double& _price[])
{
  double  current_ma1, current_ma2, current_ma3;
  int     trend_direction = 0;

  current_ma1 = SimpleMA(_shift, MA1Period, _price);
  current_ma2 = SimpleMA(_shift, MA2Period, _price);
  current_ma3 = SimpleMA(_shift, MA3Period, _price);

  if(current_ma3 > current_ma2 && current_ma2 > current_ma1)
  {
    trend_direction = 1;
  }
  else if(current_ma3 < current_ma2 && current_ma2 < current_ma1)
  {
    trend_direction = -1;
  }

  return(trend_direction);
}

La fonction vérifie si les moyennes mobiles sont situées dans le bon ordre, en les comparant les unes aux autres à l'aide des opérateurs if...else et de leur ordre. Si les moyennes sont classées par ordre croissant, cela renvoie 1 - tendance haussière. Si les moyennes sont classées par ordre décroissant, alors il renvoie -1 - tendance baissière. Si les deux conditions, vérifiées sous le bloc if, sont fausses, elle renvoie zéro (la tendance n'a pas pu être détectée). La fonction a deux arguments d'entrée - le décalage dans le tampon de la barre analysée et le tampon lui-même avec une série de prix.

Les autres parties de l'indicateur sont les mêmes que dans la précédente.

3.3. Indicateur de tendance en base de l'indicateur ZigZag

Considérons maintenant l'indicateur, qui utilise des fractures de Zigzag pour déterminer les extrema et détecter la direction de la tendance selon Charles Dow. Le code source complet de l'indicateur se trouve dans le fichier ZigZagTrendDetector.MQ5, joint à l'article.

Les variables externes sont affectées avec des valeurs de paramètres de l'indicateur externe ZigZag :

//---------------------------------------------------------------------
//  External parameters:
//---------------------------------------------------------------------
input int   ExtDepth = 5;
input int   ExtDeviation = 5;
input int   ExtBackstep = 3;
//---------------------------------------------------------------------

Une différence importante de cet indicateur - le nombre de tampons indicateurs. Ici, outre le tampon d'affichage, nous utilisons deux autres tampons de calcul. Par conséquent, nous avons modifié le paramètre approprié dans le code indicateur :

#property indicator_buffers  3

Ajoutez deux tampons supplémentaires. Ils stockeront les extrema, obtenus à partir de l'indicateur externe ZigZag :

double ZigZagHighs[];  // zigzag's upper turnarounds
double ZigZagLows[];   // zigzag's lower turnarounds

Il est également nécessaire d'apporter des modifications au gestionnaire d'événements d'initialisation de l'indicateur - configurez ces deux tampons supplémentaires comme tampons de calcul :

//  Buffers to store zigzag's turnarounds
SetIndexBuffer(1, ZigZagHighs, INDICATOR_CALCULATIONS);
SetIndexBuffer(2, ZigZagLows, INDICATOR_CALCULATIONS);

Dans le code de calcul de la fonction OnCalculate, nous devons également fournir la lecture des fractures en zigzag dans nos tampons. Cela se fait comme suit:

//  Copy upper and lower zigzag's turnarounds to buffers:
  CopyBuffer(indicator_handle, 1, 0, _rates_total - _prev_calculated, ZigZagHighs);
  CopyBuffer(indicator_handle, 2, 0, _rates_total - _prev_calculated, ZigZagLows);

//  Loop of calculating the indicator buffer values:
  for(i = start; i < _rates_total; i++)
  {
    TrendBuffer[i] = TrendDetector(i);
  }

La fonction TrendDetector ressemble à ceci :

//---------------------------------------------------------------------
//  Determine the current trend direction:
//---------------------------------------------------------------------
//  Returns:
//    -1 - Down trend
//    +1 - Up trend
//     0 - trend is not defined
//---------------------------------------------------------------------
double    ZigZagExtHigh[2];
double    ZigZagExtLow[2];
//---------------------------------------------------------------------
int TrendDetector(int _shift)
{
  int    trend_direction = 0;

//  Find last four zigzag's turnarounds:
  int    ext_high_count = 0;
  int    ext_low_count = 0;
  for(int i = _shift; i >= 0; i--)
  {
    if(ZigZagHighs[i] > 0.1)
    {
      if(ext_high_count < 2)
      {
        ZigZagExtHigh[ext_high_count] = ZigZagHighs[i];
        ext_high_count++;
      }
    }
    else if(ZigZagLows[i] > 0.1)
    {
      if(ext_low_count < 2)
      {
        ZigZagExtLow[ext_low_count] = ZigZagLows[i];
        ext_low_count++;
      }
    }

//  If two pairs of extrema are found, break the loop:
    if(ext_low_count == 2 && ext_high_count == 2)
    {
      break;
    }
  }

//  If required number of extrema is not found, the trend can't be determined:
  if(ext_low_count != 2 || ext_high_count != 2)
  {
    return(trend_direction);
  }

//  Check Dow's condition fulfillment:
  if(ZigZagExtHigh[0] > ZigZagExtHigh[1] && ZigZagExtLow[0] > ZigZagExtLow[1])
  {
    trend_direction = 1;
  }
  else if(ZigZagExtHigh[0] < ZigZagExtHigh[1] && ZigZagExtLow[0] < ZigZagExtLow[1])
  {
    trend_direction = -1;
  }

  return(trend_direction);
}

Ici, nous recherchons les quatre derniers extrema de zigzag. Notez que la recherche remonte à l'historique. C'est pourquoi, l'index dans la boucle for diminue à chaque itération de recherche jusqu'à zéro. Si les extrema sont trouvés, ils sont comparés les uns aux autres pour assurer la cohérence de la définition de la tendance selon Dow. Il existe deux extrêmes positions possibles - pour la tendance haussière et pour la tendance baissière. Ces variantes sont vérifiées par les opérateurs if...else.

3.4. Indicateur de tendance en base de l'indicateur ADX

Considérez l'indicateur de tendance ADXTrendDetector, qui utilise l'indicateur ADX. Le code source complet de l'indicateur se trouve dans le fichier ADXTrendDetector.MQ5, joint à l'article. Les paramètres externes sont assignés avec les valeurs de l'indicateur externe ADX :

//---------------------------------------------------------------------
//      External parameters
//---------------------------------------------------------------------
input int  PeriodADX     = 14;
input int  ADXTrendLevel = 20;

La fonction TrendDetector ressemble à ceci :

//---------------------------------------------------------------------
//  Determine the current trend direction:
//---------------------------------------------------------------------
//  Returns:
//    -1 - Down trend
//    +1 - Up trend
//     0 - trend is not defined
//---------------------------------------------------------------------
int TrendDetector(int _shift)
{
  int     trend_direction = 0;
  double  ADXBuffer[ 1 ];
  double  PlusDIBuffer[ 1 ];
  double  MinusDIBuffer[ 1 ];

//  Copy ADX indicator values to buffers:
  CopyBuffer(indicator_handle, 0, _shift, 1, ADXBuffer);
  CopyBuffer(indicator_handle, 1, _shift, 1, PlusDIBuffer);
  CopyBuffer(indicator_handle, 2, _shift, 1, MinusDIBuffer);

//  If ADX value is considered (trend strength):
  if(ADXTrendLevel > 0)
  {
    if(ADXBuffer[0] < ADXTrendLevel)
    {
      return(trend_direction);
    }
  }

//  Check +DI and -DI positions relative to each other:
  if(PlusDIBuffer[0] > MinusDIBuffer[0])
  {
    trend_direction = 1;
  }
  else if(PlusDIBuffer[0] < MinusDIBuffer[0])
  {
    trend_direction = -1;
  }

  return( trend_direction );
}

Grâce à CopyBuffer(), obtenez les valeurs nécessaires des tampons d'indicateur de l'indicateur externe ADX pour le nombre de barres, donné par l'argument _shift. Ensuite, analysez les positions des lignes +DI et -DI l'une par rapport à l'autre. Si nécessaire, tenez compte de la force de la tendance - si elle est inférieure à ce qui est défini, alors la tendance n'est pas détectée.

3.5. Indicateur de tendance en base de l'indicateur NTRT

La structure de l'indicateur de tendance NRTRTrendDetector, en base de NRTR, est similaire à la précédente. Le code source complet de l'indicateur se trouve dans le fichier NRTRTrendDetector.MQ5, joint à l'article.

La première différence - dans le bloc de paramètres externes :

//---------------------------------------------------------------------
//      External parameters:
//---------------------------------------------------------------------
input int     ATRPeriod =  40;    // ATR period, in bars
input double  Koeff     = 2.0;    // Coefficient of ATR value change   
//---------------------------------------------------------------------

La deuxième différence - dans la fonction TrendDetector de détection de la direction de la tendance :

//---------------------------------------------------------------------
//      Determine the current trend direction:
//---------------------------------------------------------------------
//  Returns:
//    -1 - Down trend
//    +1 - Up trend
//     0 - trend is not defined
//---------------------------------------------------------------------
int TrendDetector(int _shift)
{
  int     trend_direction = 0;
  double  Support[1];
  double  Resistance[1];

//      Copy NRTR indicator values to buffers::
  CopyBuffer(indicator_handle, 0, _shift, 1, Support);
  CopyBuffer(indicator_handle, 1, _shift, 1, Resistance);

//  Check values of indicator lines:
  if(Support[0] > 0.0 && Resistance[0] == 0.0)
  {
    trend_direction = 1;
  }
  else if(Resistance[0] > 0.0 && Support[0] == 0.0)
  {
    trend_direction = -1;
  }

  return( trend_direction );
}

Ici, nous lisons les valeurs de deux tampons de l'indicateur externe NRTR avec les indices 0 et 1. Les valeurs du tampon Support sont différentes de zéro en cas de tendance haussière, tandis que les valeurs du tampon Resistance sont différentes de zéro en cas de tendance baissière.

3.6. Indicateur de tendance en base des chandeliers Heiken Ashi

Considérons maintenant l'indicateur de tendance, qui utilise les chandeliers Heiken Ashi.

Dans ce cas, nous n'appellerons pas l'indicateur externe, mais calculerons nous-mêmes les bougies. Cela améliorera les performances de l'indicateur et libérera le processeur pour les tâches plus importantes. Le code source complet de l'indicateur se trouve dans le fichier HeikenAshiTrendDetector.MQ5, joint à l'article.

Puisque l'indicateur Heiken Ashi ne nécessite pas le réglage de paramètres externes, nous pouvons supprimer le bloc avec les opérateurs d’entrée. Des changements majeurs nous attendent dans le gestionnaire d'événement de recalcul de l'indicateur. Ici, nous utiliserons une variante alternative du gestionnaire, qui donne accès à tous les tableaux de prix du graphique actuel.

La fonction OnCalculate() ressemble maintenant à ceci :

int OnCalculate(const int _rates_total, 
                const int _prev_calculated,
              const datetime& Time[],
              const double& Open[],
              const double& High[],
              const double& Low[],
              const double& Close[],
              const long& TickVolume[],
              const long& Volume[], 
              const int& Spread[])
{
  int     start, i;
  double  open, close, ha_open, ha_close;

//  Determine the initial bar for indicator buffer calculation:
  if(_prev_calculated == 0)
  {
    open = Open[0];
    close = Close[0];
    start = 1;
  }
  else
  {
    start = _prev_calculated - 1;
  }

//  Loop of calculating the indicator buffer values:
  for(i = start; i < _rates_total; i++)
  {
//  Heiken Ashi candlestick open price:
    ha_open = (open + close) / 2.0;

//  Heiken Ashi candlestick close price:
    ha_close = (Open[i] + High[i] + Low[i] + Close[i]) / 4.0;

    TrendBuffer[i] = TrendDetector(ha_open, ha_close);

    open = ha_open;
    close = ha_close;
  }

  return(_rates_total);
}

En ce qui concerne la détermination de la couleur des bougies Heiken Ashi, nous n'avons besoin que de deux prix - l'ouverture et la clôture, il ne faudrait donc prendre en compte que ces derniers. 

Après avoir détecté la direction de la tendance via l'appel de fonction TrendDetector, enregistrez les valeurs de prix actuelles des chandeliers Heiken Ashi dans les variables intermédiaires d'ouverture et clôture. La fonction TrendDetector semble très simple. Vous pouvez l'insérer dans OnCalculate, mais pour une plus grande polyvalence en cas de développement et de complexité de l'algorithme, nous laissons cette fonction. Voici cette fonction :

int TrendDetector(double _open, double _close)
{
  int    trend_direction = 0;

  if(_close > _open)         // if candlestick is growing, then it is the up trend
  {
    trend_direction = 1;
  }
  else if(_close < _open)     // if candlestick is falling, then it is the down trend
  {
    trend_direction = -1;
  }

  return(trend_direction);
}

Les arguments de la fonction sont deux prix pour le chandelier Heiken Ashi - ouverture et clôture, par lesquels sa direction est déterminée.


4. Exemple d'utilisation de l'indicateur de détection de tendance dans Expert

Créons un Expert Advisor, qui utilise différents indicateurs. Il sera intéressant de comparer les résultats d'Experts, qui utilisent différentes méthodes de détection de tendance. Vérifiez d'abord les résultats avec les paramètres par défaut, puis essayez de les ajuster pour trouver les meilleurs.

Dans ce cas, le but de la création d'Expert Advisors - est de comparer les méthodes de détection de tendance par la précision et la vitesse. Formulons donc les principes généraux de création de tous les Expert Advisors :

  • La position Buy s’ouvre lorsque la tendance passe de la baisse à la hausse ou de l'indéfini à la hausse.
  • La position Sell s’ouvre lorsque la tendance passe de la hausse à la baisse ou de l'indéfini à la baisse.
  • La position clôture lorsque la tendance change de direction pour devenir inversée ou indéfinie.
  • Expert Advisor doit ouvrir/clôturer une position lorsqu'une nouvelle barre s'ouvre (lorsqu'il y a un signal correspondant).

Tous les indicateurs de tendance que nous avons créés contiennent un tampon d’indicateur avec un indice zéro, qui stocke les données requises sur la direction de la tendance. Nous l'utiliserons dans les Expert Advisors pour obtenir un signal d'ouverture/clôture de la position.

Parce que nous avons besoin de fonctions de trading, nous avons inclus la bibliothèque correspondante, qui est installée avec MetaTrader 5. Cette bibliothèque contient la classe CTrade et plusieurs méthodes de travail avec positions et ordres. Cela simplifie le travail de routine avec les fonctions de trading. La bibliothèque est incluse dans la ligne suivante :

#include <Trade\Trade.mqh>

Nous en utiliserons deux méthodes : position ouverture et clôture. La première méthode permet d'ouvrir une position de direction donnée et de volume :

PositionOpen(const string symbol, 
             ENUM_ORDER_TYPE order_type,
             double volume, double price,
             double sl, double tp, const string comment )

Les arguments d'entrée sont les suivants :

  • symbole - nom de l'instrument pour le commerce, par exemple, « EURUSD ».
  • order_type - sens d'ouverture de la position, short ou long.
  • volume - volume de la position ouverte en lots, par exemple 0,10.
  • prix - prix d'ouverture.
  • sl - prix Stop Loss.
  • tp - prix Take Profit.
  • commentaire - commentaire, affiché lorsque la position est affichée dans le terminal de trading.

La deuxième méthode vous permet de clôturer une position :

PositionClose( const string symbol, ulong deviation )

Les arguments d'entrée sont les suivants :

  •  symbole - nom de l'instrument pour le commerce, par exemple, « EURUSD ».
  •  écart - écart maximal autorisé par rapport au prix actuel (en points) lors de la clôture d'une position.

Considérons en détail la structure d'Expert Advisor, qui utilise l'indicateur MATrendDetector. Le code source complet d'Expert Advisor se trouve dans le fichier MATrendExpert.MQ5, joint à l'article. Le premier bloc majeur de l'expert - est le bloc de réglage des paramètres externes.

input double Lots = 0.1;
input int    MAPeriod = 200;

Le paramètre Lots d'Expert Advisor - est la taille du lot, utilisé lorsque la position est ouverte. Pour obtenir des résultats comparatifs de différentes méthodes de détection de tendance, nous utilisons le lot permanent sans gestion monétaire. Tous les autres paramètres externes sont utilisés par les indicateurs de tendance, discutés ci-dessus. La liste et le but sont exactement les mêmes que l'indicateur correspondant.

Le deuxième bloc important d'Expert Advisor - gestionnaire d'événements d'initialisation d'Expert Advisor.

//---------------------------------------------------------------------
//      Initialization event handler:
//---------------------------------------------------------------------
int OnInit()
{
//  Create external indicator handle for future reference to it:
  ResetLastError();
  indicator_handle = iCustom(Symbol(), PERIOD_CURRENT, "Examples\\MATrendDetector", MAPeriod);

// If initialization was unsuccessful, return nonzero code:
  if(indicator_handle == INVALID_HANDLE)
  {
    Print("MATrendDetector initialization error, Code = ", GetLastError());
    return(-1);
  }
  return(0);
}

Ici, créez un descripteur pour faire référence à l'indicateur de tendance et, si la création a réussi, renvoyez le code zéro. En cas d'échec de la création du descripteur d'indicateur (par exemple, l'indicateur n'a pas été compilé au format EX5), nous imprimons le message à ce sujet et renvoyons un code différent de zéro. Dans ce cas, Expert Advisor arrête son travail ultérieur et il est déchargé du terminal, avec le message correspondant dans le Journal.

Le prochain bloc d'Expert Advisor - gestionnaire d'événements de la désinitialisation d'Expert Advisor.

//---------------------------------------------------------------------
//      Indicator deinitialization event handler:
//---------------------------------------------------------------------
void OnDeinit(const int _reason)
{
//  Delete indicator handle:
  if(indicator_handle != INVALID_HANDLE)
  {
    IndicatorRelease(indicator_handle);
  }
}

Ici, le descripteur de l'indicateur est supprimé et sa mémoire allouée est libérée.

Vous n'avez pas besoin d'effectuer d'autres actions pour désinitialiser Expert Advisor.

Vient ensuite le bloc principal d'Expert Advisor - gestionnaire d'événements concernant le new teak par le symbole actuel.

//---------------------------------------------------------------------
//  Handler of event about new tick by the current symbol:
//---------------------------------------------------------------------
int    current_signal = 0;
int    prev_signal = 0;
bool   is_first_signal = true;
//---------------------------------------------------------------------
void OnTick()
{
//  Wait for beginning of a new bar:
  if(CheckNewBar() != 1)
  {
    return;
  }

//  Get signal to open/close position:
  current_signal = GetSignal();
  if(is_first_signal == true)
  {
    prev_signal = current_signal;
    is_first_signal = false;
  }

//  Select position by current symbol:
  if(PositionSelect(Symbol()) == true)
  {
//  Check if we need to close a reverse position:
    if(CheckPositionClose(current_signal) == 1)
    {
      return;
    }
  }

//  Check if there is the BUY signal:
  if(CheckBuySignal(current_signal, prev_signal) == 1)
  {
    CTrade  trade;
    trade.PositionOpen(Symbol(), ORDER_TYPE_BUY, Lots, SymbolInfoDouble(Symbol(), SYMBOL_ASK ), 0, 0);
  }

//  Check if there is the SELL signal:
  if(CheckSellSignal(current_signal, prev_signal) == 1)
  {
    CTrade  trade;
    trade.PositionOpen(Symbol(), ORDER_TYPE_SELL, Lots, SymbolInfoDouble(Symbol(), SYMBOL_BID ), 0, 0);
  }

//  Save current signal:
  prev_signal = current_signal;
}

Considérons les fonctions auxiliaires, qui sont utilisées par Expert Advisor.

Tout d'abord, notre Expert Advisor doit vérifier le signal pour ouvrir une autre nouvelle barre sur le graphique. La fonction CheckNewBar est utilisée à cette fin :

//---------------------------------------------------------------------
//  Returns flag of a new bar:
//---------------------------------------------------------------------
//  - if it returns 1, there is a new bar
//---------------------------------------------------------------------
int CheckNewBar()
{
  MqlRates  current_rates[1];

  ResetLastError();
  if(CopyRates(Symbol(), Period(), 0, 1, current_rates)!= 1)
  {
    Print("CopyRates copy error, Code = ", GetLastError());
    return(0);
  }

  if(current_rates[0].tick_volume>1)
  {
    return(0);
  }

  return(1);
}

La présence d'une nouvelle barre est déterminée par la valeur du volume de trait. Lors de l'ouverture d'une nouvelle barre, son volume est initialement égal à zéro (puisqu'il n'y avait pas de cotations). Avec l'arrivée d'un nouveau trait, la taille devient égale à 1.

Dans cette fonction, nous allons créer le tableau current_rates[] de structures MqlRates, composé d'un élément, y copier les informations sur les prix et les volumes actuels, puis vérifier la valeur du volume de trait. 

Dans notre gestionnaire d'événements sur le nouveau trait au travers le symbole actuel, nous utiliserons cette fonction de la manière suivante :

//  Wait for beginning of a new bar:
if(CheckNewBar()!= 1)
{
  return;
}

Ainsi, une nouvelle barre s'ouvre et vous pouvez obtenir un signal sur la direction de la tendance actuelle. Cela se fait comme suit:

//  Get signal to open/close position:
  current_signal = GetSignal();
  if(is_first_signal == true)
  {
    prev_signal = current_signal;
    is_first_signal = false;
  }

Puisque nous devons suivre les changements dans la tendance, il est nécessaire de se souvenir de la valeur de tendance sur la barre précédente. Dans l’élément de code ci-dessus, nous utilisons pour cela la variable prev_signal. De plus, vous devez utiliser le drapeau, signalant qu'il s'agit du premier signal (il n'y en a pas encore de précédent). Il s'agit de la variable is_first_signal. Si le drapeau a une valeur true, nous initialisons la variable prev_signal avec la valeur initiale.

Ici, nous utilisons la fonction GetSignal, qui renvoie la direction de la tendance actuelle, obtenue à partir de notre indicateur. Cela ressemble à ceci :  

//---------------------------------------------------------------------
//      Get signal to open/close position:
//---------------------------------------------------------------------
int GetSignal()
{
  double    trend_direction[1];

//  Get signal from trend indicator:
  ResetLastError();
  if(CopyBuffer(indicator_handle, 0, 0, 1, trend_direction) != 1)
  {
    Print("CopyBuffer copy error, Code = ", GetLastError());
    return(0);
  }

  return((int)trend_direction[0]);
}

Les données de l'indicateur de tendance sont copiées du tampon zéro vers notre tableau trend_direction, composé d'un élément. Et la valeur de l'élément du tableau est renvoyée par la fonction. De plus, le type double est converti en type int pour éviter l'avertissement du compilateur.

Avant d'ouvrir une nouvelle position, vous devez vérifier s'il est nécessaire de fermer la position opposée, ouverte plus tôt. Vous devez également vérifier s'il existe déjà une position ouverte dans la même direction. Tout cela est fait par l’élément de code suivant :

//  Select position by current symbol:
  if(PositionSelect(Symbol()) == true)
  {
//  Check if we need to close a reverse position:
    if(CheckPositionClose(current_signal) == 1)
    {
      return;
    }
  }

Pour accéder à la position, il faut d'abord la sélectionner - cela se fait en utilisant la fonction PositionSelect() pour le symbole actuel. Si la fonction renvoie true, alors la position existe et elle a été sélectionnée avec succès, vous pouvez donc la manipuler.

Pour fermer la position opposée, la fonction CheckPositionClose est utilisée :

//---------------------------------------------------------------------
//  Check if we need to close position:
//---------------------------------------------------------------------
//  Returns:
//    0 - no open position
//    1 - position already opened in signal's direction
//---------------------------------------------------------------------
int CheckPositionClose(int _signal)
{
  long    position_type = PositionGetInteger(POSITION_TYPE);

  if(_signal == 1)
  {
//  If there is the BUY position already opened, then return:
    if(position_type == (long)POSITION_TYPE_BUY)
    {
      return(1);
    }
  }

  if(_signal==-1)
  {
//  If there is the SELL position already opened, then return:
    if( position_type == ( long )POSITION_TYPE_SELL )
    {
      return(1);
    }
  }

//  Close position:
  CTrade  trade;
  trade.PositionClose(Symbol(), 10);

  return(0);
}

Tout d'abord, vérifiez si la position est ouverte dans le sens de la tendance. Si c'est le cas, la fonction renvoie 1 et la position actuelle n'est pas fermée. Si la position est ouverte dans le sens inverse de la tendance, vous devez la fermer. Cela se fait par la méthode PositionClose décrite ci-dessus. Puisque la position ouverte n'est plus, il s’effectue un renvoi à zéro.

Une fois toutes les vérifications et actions nécessaires pour les positions existantes effectuées, vous devez vérifier la présence d'un nouveau signal. Cela se fait par l’élément de code suivant :

//  Check if there is the BUY signal:
if(CheckBuySignal(current_signal, prev_signal)==1)
{
  CTrade  trade;
  trade.PositionOpen(Symbol(), ORDER_TYPE_BUY, Lots, SymbolInfoDouble(Symbol(), SYMBOL_ASK), 0, 0);
}

S'il y a le signal Buy, ouvrez une position long avec un volume donné par le prix actuel SYMBOL_ASK. Étant donné que toutes les positions sont fermées par le signal opposé, le Take Profit et le Stop Loss ne sont pas utilisés. L'Expert Advisor est « toujours présent sur le marché ». 

En réel trade, il est recommandé d'utiliser un Stop Loss protecteur en cas de circonstances imprévues, telles que la perte de connexion avec le serveur DC et d'autres conditions de force majeure.

Pour les signaux Sell, tout est similaire :

//  Check if there is the SELL signal:
if(CheckSellSignal(current_signal, prev_signal) == 1)
{
  CTrade  trade;
  trade.PositionOpen(Symbol(), ORDER_TYPE_SELL, Lots, SymbolInfoDouble(Symbol(), SYMBOL_BID), 0, 0);
}

La seule différence réside dans le prix de vente - SYMBOL_BID.

La présence d'un signal est vérifiée par la fonction CheckBuySignal - pour acheter et par la fonction CheckSellSignal - pour vendre. Ces fonctions sont très simples et claires :

//---------------------------------------------------------------------
//  Check if signal has changed to BUY:
//---------------------------------------------------------------------
//  Returns:
//    0 - no signal
//    1 - there is the BUY signal
//---------------------------------------------------------------------
int CheckBuySignal(int _curr_signal, int _prev_signal)
{
//  Check if signal has changed to BUY:
  if((_curr_signal==1 && _prev_signal==0) || (_curr_signal==1 && _prev_signal==-1))
  {
    return(1);
  }

  return(0);
}

//---------------------------------------------------------------------
//  Check if there is the SELL signal:
//---------------------------------------------------------------------
//  Returns:
//    0 - no signal
//    1 - there is the SELL signal
//---------------------------------------------------------------------
int CheckSellSignal(int _curr_signal, int _prev_signal)
{
//  Check if signal has changed to SELL:
  if((_curr_signal==-1 && _prev_signal==0) || (_curr_signal==-1 && _prev_signal==1))
  {
    return(1);
  }

  return(0);
}

Ici, nous vérifions si la tendance a changé dans la direction opposée ou si la direction de la tendance est apparue. Si l'une de ces conditions est satisfaite, la fonction renvoie la présence du signal.

En général, un tel schéma d'Expert Advisor donne une structure assez universelle, qui peut être facilement mise à niveau et étendue pour s'adapter à des algorithmes plus complexes.

Les autres Expert Advisor sont construits exactement de la même manière. Il n'y a de différences significatives que dans le bloc de paramètres externes - ils doivent correspondre à l'indicateur de tendance utilisé et doivent être passés en tant qu'arguments lors de la création d’un descripteur d'indicateur.

Considérons les résultats de notre premier Expert Advisor sur les données historiques. Nous utiliserons l'historique EURUSD, dans la plage du 01.04.2004 au 06.08.2010 sur les barres journalières. Après avoir exécuté Expert Advisor dans Strategy Tester avec les paramètres par défaut, nous obtenons les résultats suivants :

Figure 8. Résultats des tests d'Expert Advisor à l'aide de l'indicateur MATrendDetector

Figure 8. Résultats des tests d'Expert Advisor à l'aide de l'indicateur MATrendDetector

Rapport du testeur de stratégie
MetaQuotes-Demo (Build 302)

Paramètres
Expert : MATrendExpert
Symbole : EURUSD
Période : Quotidien (2004.04.01 - 2010.08.06)
Entrées : Lots=0.100000

MAPeriod=200
Courtier : MetaQuotes Software Corp.
Devise : USD
Dépôt initial : 10 000,00

Résultats
Barres : 1649 Traits : 8462551
Bénéfice net total : 3 624,59 Bénéfice brut : 7 029,16 Perte brute : -3 404,57
Facteur de profit : 2,06 Gain attendu : 92,94
Facteur de récupération : 1,21 Ratio de Sharpe : 0,14

Encaissement Solde :
Encaissement de solde absolu : 2 822,83 Encaissement de solde maximal : 2 822,83 (28,23 %) Encaissement de solde relatif : 28,23% (2 822,83)
Encaissement sur capitaux propres :
Encaissement sur capitaux propres absolus : 2 903,68 Encaissement sur capitaux propres maximaux : 2 989,93 (29,64 %) Encaissement sur capitaux propres relatifs : 29,64 % (2 989,93)

Total de trades : 39 Trades short (% acquis) : 20 (20,00 %) Trades long (% acquis) : 19 (15,79 %)
Total de transactions : 78 Trades bénéficiaires (% du total) : 7 (17,95 %) Trades à perte (% du total) : 32 (82,05 %)

Trades les plus lucratifs : 3 184,14 Trades à pertes massives (% du total) : -226,65

Trades à bénéfice moyen : 1 004,17 Trades à perte moyenne (% du total) : -106,39

Gains consécutifs maximaux ($) : 4 (5 892,18) Pertes consécutives maximales ($) : 27 (-2 822,83)

Bénéfice consécutif maximum (décompte) : 5 892,18 (4) Pertes consécutives maximales (décompte) : -2 822,83 (27)

Gains consécutifs moyens : 2 Pertes consécutives maximales : 8


En général, ça a l'air bien, à l'exception de la section du début des tests jusqu'au 22.09.2004. Rien ne garantit que cette section ne sera pas répétée à l'avenir. Si vous regardez sur le graphique de cette période, vous pouvez voir qu'il y avait une tendance aléatoire prédominante sur une plage limitée. Dans ces conditions, notre Expert de tendance simple n'était pas si bon. Voici l’image de cette période avec l’ensemble de transactions qui ont été placées :

Figure 9. Section avec tendances aléatoires

Figure 9. Section avec tendances aléatoires

Il y a aussi la moyenne mobile SMA200 sur le graphique.

Voyons maintenant ce que montrera l'Expert Advisor plus « avancé » utilisant un indicateur avec plusieurs moyennes mobiles - sur le même intervalle et avec des paramètres par défaut :

Figure 10. Résultats des tests d'Expert Advisor utilisant l'indicateur

Figure 10. Résultats des tests d'Expert Advisor à l'aide de l'indicateur FanTrendDetector

Rapport du testeur de stratégie
MetaQuotes-Demo (Build 302)

Paramètres
Expert : FanTrendExpert
Symbole : EURUSD
Période : Quotidien (2004.04.01 - 2010.08.06)
Entrées : Lots=0.100000

MA1Period=200

MA2Period=50

MA3Period=21
Courtier : MetaQuotes Software Corp.
Devise : USD
Dépôt initial : 10 000,00

Résultats
Barres : 1649 Traits : 8462551
Bénéfice net total : 2 839,63 Bénéfice brut : 5 242,93 Perte brute : -2 403,30
Facteur de profit : 2,18 Gain attendu : 149,45
Facteur de récupération : 1,06 Ratio de Sharpe : 0,32

Encaissement Solde :
Encaissement de solde absolu : 105,20 Encaissement de solde maximal : 1 473,65 (11,73 %) Encaissement de solde relatif : 11,73 % (1 473,65)
Encaissement sur capitaux propres :
Encaissement sur capitaux propres absolus : 207,05 Encaissement sur capitaux propres maximaux : 2 671,98 (19,78 %) Encaissement sur capitaux propres relatifs : 19,78 % (2 671,98)

Total de trades : 19 Trades short (% acquis) : 8 (50,00 %) Trades long (% acquis) : 11 (63,64 %)
Total de transactions : 38 Trades bénéficiaires (% du total) : 11 (57,89 %) Trades à perte (% du total) : 8 (42,11 %)

Trades les plus lucratifs : 1 128,30 Trades à pertes massives (% du total) : -830,20

Trades à bénéfice moyen : 476,63 Trades à perte moyenne (% du total) : -300,41

Gains consécutifs maximaux ($) : 2 (1 747,78) Pertes consécutives maximales ($) : 2 (-105,20)

Bénéfice consécutif maximum (décompte) : 1 747,78 (2) Pertes consécutives maximales (décompte) : -830,20 (1)

Gains consécutifs moyens : 2 Pertes consécutives maximales : 1

De loin meilleur ! Si vous regardez notre section « problème », l’Expert précédent a failli en beaucoup de choses. Voici l’image :

Figure 11. Résultats FanTrendExpert sur Section avec tendances aléatoires

Figure 11. Résultats FanTrendExpert sur la section avec tendances aléatoires

Comparez-le avec la Figure 9 - il est évident que le nombre de fausses alarmes de changement de tendance a diminué. Mais le nombre de transactions a été réduit de moitié, ce qui est assez logique. Lors de l'analyse de la courbe de solde/valeurs des deux Expert Advisors, vous pouvez voir que de nombreuses transactions ont été conclues de manière moins qu'optimale en termes d'obtention de bénéfice maximum. Par conséquent, la prochaine mise à niveau d'Expert Advisor est l'amélioration de l'algorithme de clôture des transactions. Mais cela dépasse le cadre de cet article. Les lecteurs peuvent le faire eux-mêmes.


5. Résultats des tests des Expert Advisors

Testons tous nos experts. Les résultats sur l’ensemble de la plage historique disponible depuis 1993 à 2010 sur la paire EURUSD et le délai D1 sont présentés ci-dessous.

Figure 12. Test de MATrendExpert

Figure 12. Tests MATrendExpert

Figure 13. Tests de FanTrendExpert

Figure 13. Tests FanTrendExpert

Figure 14. Test d'ADXTrendExpert (ADXTrendLevel = 0)

Figure 14. Tests ADXTrendExpert (ADXTrendLevel = 0)

Figure 15. Tests d'ADXTrendExpert (ADXTrendLevel = 20)

Figure 15. Tests ADXTrendExpert (ADXTrendLevel = 20)

Figure 16. Tests NRTRTrendExpert

Figure 16. Tests NRTRTrendExpert

Figure 17. Test de Heiken Ashi

Figure 17. Test Heiken Ashi

Considérons les résultats des tests.

Comme leaders, il existe deux Expert Advisors les plus courants - sur une moyenne mobile et le « fan » des moyennes mobiles. En effet, ces experts sont les plus proches de la règle de suivi des tendances (and, hence, and price), simplement en utilisant une série affinée de prix pour la dernière période de temps. Parce que nous utilisons une moyenne mobile plutôt « pesante » avec une période de 200, l'impact de la volatilité du marché semble diminuer.

Le faible nombre de transactions de ces Expert Advisor n'est pas un inconvénient, car le temps de rétention de la position peut durer jusqu'à plusieurs mois - suivant la tendance des 200 jours. Fait intéressant, comment MATrendExpert alterne les zones de tendance, où il y a solde ascendant, flat (dans le contexte de l'expert), où sont enregistrées des pertes d'argent.

La méthode de détection de tendance sur l'indicateur ADX a également donné de bons résultats. Là, le PeriodADX a été légèrement modifié à la valeur de 17, ce qui donne des résultats plus uniformes tout au long de l'historique. L'effet de filtre par force de tendance n'est pas significatif. Vous devrez peut-être ajuster le paramètre ADXTrendLevel, ou même le définir dynamiquement en fonction de la volatilité actuelle du marché. Il y a plusieurs périodes d’encaissement, et donc des mesures supplémentaires pour équilibrer la courbe de solde sont nécessaires.

L'indicateur NRTR a montré une rentabilité pratiquement nulle en utilisant les paramètres par défaut, à la fois sur l'ensemble de la plage de tests et sur un intervalle long choisi au hasard. C'est dans une certaine mesure un signe de stabilité de cette méthode de détection de tendance. Peut-être que l'ajustement des paramètres rendra cet Expert Advisor rentable, c'est-à-dire qu'une optimisation est requise.

L'Expert Advisor en base de Heiken Ashi n'était évidemment pas rentable. Bien qu'il ait un air agréable du point de vue de l'historique, probablement en raison des retouches en temps réelrésultats des tests sont loin d'être l’idéal. Peut-être que de meilleurs résultats seront obtenus en utilisant une version affinée de cet indicateur - Smoothed Heiken Ashi, qui n'est pas si encline aux retouches.

Certainement, tous les Expert Advisor bénéficieront du système d’exécution d'une position ouverte avec dynamisme tout étirant le niveau stop et en créant un niveau cible. Il serait également intéressant d'avoir un système de gestion du capital, permettant de minimiser l’encaissement et peut-être d'augmenter le bénéfice sur un long terme.


Conclusion

Ainsi, il n'est pas si difficile d'écrire du code qui détecte une tendance. L'essentiel ici - travailler et une idée réfléchie, tout en veillant à exploiter certaines lois du marché. Et plus ces lois seront fondamentales, plus vous serez confiant dans le système de trading construit sur ces lois - il ne pourra pas si vite faillir.

Traduit du russe par MetaQuotes Ltd.
Article original : https://www.mql5.com/ru/articles/136

Fichiers joints |
experts.zip (9.35 KB)
indicators.zip (7.82 KB)
Évaluation des systèmes de trading - l’efficacité d’ouverture, de clôture et de trades en général Évaluation des systèmes de trading - l’efficacité d’ouverture, de clôture et de trades en général
Il existe de nombreuses mesures qui permettent de déterminer l’efficacité et la rentabilité d’un système de trading. Cependant, les traders sont toujours prêts à soumettre n’importe quel système à un nouveau crash test. L’article explique comment les statistiques basées sur des mesures d’efficacité peuvent être utilisées pour la plateforme MetaTrader 5. Il contient la classe pour la transformation de l’interprétation des statistiques par les transactions à celle qui ne contredit pas la description donnée dans le livre de S.V. « Statistika dlya traderov » (« Statistiques destinées aux traders »). Bulashev. Il contient également un exemple de fonction personnalisée pour optimisation.
Création d'indicateurs multicolores dans MQL5 Création d'indicateurs multicolores dans MQL5
Dans cet article, nous verrons comment créer des indicateurs multicolores ou convertir les indicateurs existants en multicolores. MQL5 permet de représenter les informations sous une forme pratique. Désormais, il n'est plus nécessaire de regarder une douzaine de graphiques avec des indicateurs et d'effectuer des analyses du RSI ou des niveaux stochastiques, il est mieux simplement de peindre les bougies avec des couleurs différentes selon les valeurs des indicateurs.
Expert Advisor basé sur les « Nouvelles dimensions en trading » livre écrit par Bill Williams Expert Advisor basé sur les « Nouvelles dimensions en trading » livre écrit par Bill Williams
Dans cet article, je vais discuter du développement de l'Expert Advisor, basé sur le livre intitulé « Nouvelles dimensions en trading : Comment tirer profit du chaos dans les changes, les actions et les matières premières » par Bill Williams. La stratégie elle-même est bien connue et son utilisation est encore controversée parmi les traders. L'article examine les signaux système en trading, les spécificités de sa mise en œuvre et les résultats des tests sur les données historiques.
Comment créer votre propre Trailing Stop Comment créer votre propre Trailing Stop
La règle de base du trader : Laisse que le bénéfice croisse et que les pertes tombent ! Cet article considère l'une des techniques de base, permettant de suivre cette règle - déplacer le niveau d’arrêt protecteur (niveau de stop loss) après avoir augmenté le bénéfice de la position, c'est-à-dire - le niveau Trailing Stop. Vous trouverez la procédure étape par étape pour créer une classe pour le trailing stop sur les indicateurs SAR et NRTR. Chacun pourra insérer ce trailing stop dans ses experts ou l'utiliser de manière autonome pour contrôler les positions dans leurs comptes.