English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Réseaux de neurones de troisième génération : Réseaux profonds

Réseaux de neurones de troisième génération : Réseaux profonds

MetaTrader 5Indicateurs | 13 janvier 2022, 15:44
566 0
Vladimir Perervenko
Vladimir Perervenko

Contenu

  1. Réseaux de neurones de deuxième génération
  2. Apprentissage profond
  3. Expériences pratiques
  4. L’implémentation (Indicateur et Expert Advisor)

Introduction

Cet article va examiner les idées principales de ce sujet telles que l’apprentissage profond et le réseau profond sans calculs complexes en termes simples.

Les expériences avec des données réelles confirment (ou ne confirment pas) les avantages théoriques des réseaux de neurones profonds par rapport aux réseaux peu profonds par définition métrique et comparaison. La tâche en main est la classification. Nous allons créer un indicateur et un Expert Advisor basés sur un modèle de réseau de neurones profond et travailler en conjonction selon le schéma client/serveur, puis les tester.

Le lecteur est présumé avoir une idée juste des concepts de base utilisés dans les réseaux de neurones.


1. Réseaux de neurones de deuxième génération

Les réseaux de neurones sont conçus pour résoudre un large éventail de problèmes liés au traitement d’images.

Vous trouverez ci-dessous une liste des problèmes généralement résolus par les réseaux de neurones:

  • Approximation des fonctions par un ensemble de points (régression) ;
  • Classification des données par l’ensemble spécifié de classes ;
  • Regroupement de données avec identification de classes prototypes jusqu’alors inconnues ;
  • Compression de l’information ;
  • Restauration des données perdues ;
  • Mémoire associative ;
  • Optimisation, contrôle optimal, etc.

Parmi la liste ci-dessus, seule la « Classification » sera abordée dans cet article.


1.1. L’architecture des connexions

Le mode de traitement de l’information est grandement affecté par l’absence ou la présence de boucles de rétroaction dans le réseau. S’il n’y a pas de boucles de rétroaction entre les neurones (c’est-à-dire que le réseau a une structure de couches séquentielles où chaque neurone ne reçoit des informations que de la couche précédente), le traitement de l’information dans le réseau est unidirectionnel. Un signal d’entrée est traité par une séquence de couches et la réponse est reçue dans le nombre de tacts égal au nombre de couches.

La présence de boucles de rétroaction peut rendre la dynamique d’un réseau de neurones (dans ce cas appelé récurrent) imprévisible. En fait, un réseau peut « tourner en boucle pour toujours » et ne jamais produire de réponse. Dans le même temps, selon Turing, il n’y a pas d’algorithme pour un réseau récurrent arbitraire pour identifier si ses éléments vont entrer en équilibre (le problème de l’arrêt).

D’une manière générale, le fait que les neurones des réseaux récurrents participent au traitement de l’information plusieurs fois permet à ces réseaux de traiter l’information à un niveau plus profond de différentes manières. Dans ce cas, des mesures spéciales doivent être prises pour que le réseau ne tourne pas en boucle indéfiniment. Par exemple, utilisez des connexions symétriques, comme dans un réseau Hopfield ou limitez avec force le nombre d’itérations.


Type d’entraînement

Type de connexion
Avec un « superviseur »Sans « superviseur »
Sans boucles de rétroactionPerceptrons multicouches (approximation des fonctions, classification)

Réseau compétitif, cartes auto-organisées (compression de données, séparation des entités)
Avec boucles de rétroactionPerceptron récurrent (prédiction de séries chronologiques, entraînement en ligne)

Réseau Hopfield (mémoire associative, clustering de données, optimisation)

Table 1. Classification des réseaux de neurones par type de connexion et type d’entraînement


1.2. Principaux types de réseaux de neurones

Ayant commencé avec le perceptron, les réseaux de neurones ont parcouru un long chemin dans leur évolution. Aujourd’hui, un grand nombre de réseaux de neurones variant dans la structure et les méthodes d’entraînement sont utilisés.

Les plus célèbres sont :

1.2.1. Réseaux d’alimentation directe multicouches entièrement connectés MLP (Perceptron multicouche)

Fig. 1. Structure d’un réseau de neurones multicouche

Fig. 1. Structure d’un réseau de neurones multicouche

1.2.2. Les réseaux Jordan sont des réseaux partiellement récurrents et similaires aux réseaux Elman.

Il peut être traité comme un réseau d’alimentation directe avec des neurones de contexte supplémentaires dans la couche d’entrée.

Ces neurones de contexte sont alimentés par eux-mêmes (rétroaction directe) et à partir des neurones d’entrée. Les neurones contextuels préservent l’état actuel du réseau. Dans un réseau Jordan, le nombre de neurones de contexte et d’entrée doit être le même.

Fig. 2. Structure d’un réseau Jordan

Fig. 2. Structure d’un réseau Jordan

1.2.3. Les réseaux Elman sont des réseaux partiellement récurrents et similaires aux réseaux Jordan. La différence entre les réseaux Elman et Jordan est que dans un contexte de réseau Elman, les neurones ne sont pas alimentés par des neurones de sortie, mais par des neurones cachés. De plus, il n’y a pas de rétroaction directe dans les neurones de contexte.

Dans un réseau Elman, le nombre de neurones de contexte et de neurones cachés doit être le même. Le principal avantage des réseaux Elman est que le nombre de neurones de contexte n’est pas défini par le nombre de sorties comme dans le réseau Jordan mais par le nombre de neurones cachés, ce qui rend le réseau plus flexible. Les neurones cachés peuvent être facilement ajoutés ou retirés contrairement au nombre de sorties.


Fig. 3. Structure d’un réseau Elman

Fig. 3. Structure d’un réseau Elman

1.2.4. Radial Basis Function Network (RBF) - est un réseau de neurones d’alimentation directe qui contient une couche intermédiaire (cachée) de neurones à symétrie radiale. Un tel neurone convertit la distance d’un vecteur d’entrée spécifié à son centre correspondant par une loi non linéaire communément considérée comme gaussienne.

Les réseaux RBF présentent de nombreux avantages par rapport aux réseaux d’alimentation directe multicouches. Tout d’abord, ils émulent (pas sûr du mot) une fonction non linéaire arbitraire avec une seule couche intermédiaire, ce qui évite au développeur la nécessité de décider du nombre de couches. Ensuite, les paramètres de la combinaison linéaire dans la couche de sortie peuvent être optimisés à l’aide de méthodes d’optimisation linéaire largement connues. Ces derniers travaillent vite et n’ont pas de difficultés avec les minimums locaux qui interfèrent grandement dans la rétropropagation. C’est la raison pour laquelle le réseau RBF apprend beaucoup plus rapidement que lors de l’utilisation de la rétropropagation.

Inconvénients du FBR : ces réseaux ont de faibles caractéristiques d’extrapolation et s’avèrent encombrants lorsque le vecteur d’entrée est grand.

Fig. 4. Structure d’un FBR

Fig. 4. Structure d’un FBR

1.2.5. Quantification vectorielle d'apprentissage dynamique, Les réseaux DLVQ sont très similaires aux cartes auto-organisatrices (SOM). Contrairement aux SOM, les DLVO sont capables d’apprentissage supervisé et manquent d’une relation de voisinage entre les prototypes. La quantification vectorielle a une utilisation plus large que le clustering.

1.2.6. Le réseau Hopfield est un réseau entièrement connecté avec une matrice de connexion symétrique. Pendant le fonctionnement, la dynamique de ces réseaux converge vers l’un des états d’équilibre. Ces états d’équilibre sont des minima locaux de fonctionnalité connus sous le nom d’énergie du réseau. Un tel réseau peut être utilisé comme un système de mémoire associative adressable par contenu, comme filtre et pour relever certains défis d’optimisation.

Contrairement à de nombreux réseaux de neurones fonctionnant jusqu’à ce qu’ils reçoivent une réponse dans un certain nombre de tacts, les réseaux Hopfield fonctionnent jusqu’à ce qu’ils atteignent l’état d’équilibre qui est lorsque l’état suivant d’un réseau est exactement le même que le précédent. Dans ce cas, l’état initial est un modèle d’entrée et dans l’état d’équilibre, l’image de sortie est reçue. L’entraînement d’un réseau Hopfield nécessite qu’un modèle d’entraînement soit présenté simultanément aux couches d’entrée et de sortie.

Fig. 5. Structure d’un réseau Hopfield avec trois neurones

Fig. 5. Structure d’un réseau Hopfield avec trois neurones

Malgré des caractéristiques attrayantes, un réseau Hopfield classique est loin d’être idéal. Il a une mémoire limitée, environ 15 % du nombre de neurones dans le réseau N, tandis que les systèmes de mémoire adressée peuvent stocker jusqu’à 2N d’images différentes, en utilisant N bits.

En outre, les réseaux Hopfield ne sont pas capables de reconnaître si l’image est déplacée ou tournée par rapport à sa position stockée initiale. Ces inconvénients et d’autres définissent la perception d’un réseau Hopfield comme un modèle théorique pratique pour l’étude plutôt que comme un instrument pratique pour une utilisation quotidienne.

Beaucoup d’autres (le réseau récurrent de Hemming, le réseau de Grossberg, les réseaux de théorie de la résonance adaptative (ART-1, ART-2) etc.) n’ont pas été mentionnés dans cet article car ils sont en dehors de la portée de notre intérêt.


1.3. Méthodes d’entraînement

La capacité d’apprendre de nouvelles choses est la principale caractéristique d’un cerveau humain. Dans le cas des réseaux de neurones artificiels, l’apprentissage est un processus de configuration de l’architecture du réseau (la structure des connexions entre les neurones) et des poids des liaisons synaptiques (affectant les signaux de coefficient) pour obtenir une solution efficace pour la tâche à accomplir. Habituellement, l’entraînement d’un réseau de neurones est effectué sur un échantillon de données. Un processus d’entraînement suit un certain algorithme et au fur et à mesure, la réaction du réseau aux signaux d’entrée devrait s’améliorer.

Il existe trois grands paradigmes d’apprentissage : supervisé, non supervisé et combiné. Dans le premier cas, les bonnes réponses pour chaque exemple d’entrée sont connues et les poids tentent de minimiser l’erreur. L’apprentissage non supervisé permet de catégoriser les échantillons en expliquant la structure interne et la nature des données. Dans l’entraînement combiné, les deux approches ci-dessus sont utilisées.

1.3.1. Principales règles de l’apprentissage des réseaux de neurones

Il existe quatre règles d’apprentissage principales basées sur l’architecture de réseau qui leur est liée : la correction d’erreurs, la loi de Boltzmann, la règle de Hebb et l’apprentissage compétitif.

1.3.1.1. Correction d’erreur

Chaque exemple d’entrée a une valeur de sortie souhaitée spécifiée (valeur cible), qui peut ne pas correspondre à une valeur réelle (prévision). La règle d’apprentissage de la correction d’erreur utilise la différence entre la cible et les valeurs de prévision pour l’ajustement direct des poids afin de réduire l’erreur. L’entraînement n’est effectué qu’en cas de résultat erroné. Cette règle d’apprentissage comporte de nombreuses modifications.

1.3.1.2. Règle de Boltzmann

La règle de Boltzmann est une règle d’apprentissage stochastique par analogie avec les principes thermodynamiques. Il en résulte un ajustement des coefficients de poids des neurones en fonction de la distribution probabiliste souhaitée. L’apprentissage de la règle de Boltzmann peut être considéré comme un cas isolé de correction par une erreur où une erreur signifie un écart de corrélation des états dans deux modes.

1.3.1.3. Règle de Hebb

La règle de Hebb est l’algorithme le plus célèbre de l’apprentissage des réseaux de neurones. L’idée de cette méthode est que si les neurones des deux côtés d’une synapse s’activent simultanément et régulièrement, la force de la connexion synaptique augmente. Une particularité importante ici est que le changement de poids synaptique ne dépend que de l’activité des neurones connectés à cette synapse. Il existe de nombreuses variantes de cette règle qui diffèrent par des particularités dans la modification du poids synaptique.

1.3.1.4. Apprentissage compétitif

Contrairement à la règle d’apprentissage de Hebb, où un certain nombre de neurones de sortie peuvent s’activer simultanément, ici les neurones de sortie sont en concurrence les uns avec les autres. Un neurone de sortie avec une valeur maximale de somme pesée est le « gagnant » et « le gagnant prend tout ». Les sorties des autres neurones de sortie sont rendues inactives. Lors de l’apprentissage, seuls les poids du « gagnant » sont modifiés en ciblant une proximité croissante avec l’instance d’entrée actuelle.

Il existe de nombreux algorithmes d’apprentissage qui traitent différents problèmes. La rétropropagation, l’un des algorithmes modernes les plus efficaces, est l’un d’entre eux. Le principe appuyant cela est que le changement de poids synaptique a lieu en tenant compte du gradient local de la fonction d’erreur.

La différence entre les réponses réelles et correctes d’un réseau de neurones évalué à la couche de sortie est rétropropagée - vers le flux de signaux (Fig.5). De cette façon, chaque neurone peut définir la contribution de son poids à l’erreur cumulative du réseau. La règle d’apprentissage la plus simple est la méthode de descente la plus raide, c’est-à-dire le changement de poids synaptique proportionnellement à leur contribution à l’erreur cumulative.

Fig. 6. Le modèle de diffusion des données et des erreurs dans un réseau lors de l’apprentissage par rétropropagation

Fig. 6. Le modèle de diffusion des données et des erreurs dans un réseau lors de l’apprentissage par rétropropagation

Certes, ce type d’apprentissage en réseau de neurones n’assure pas le meilleur résultat d’apprentissage car il est toujours possible que l’algorithme soit entré dans un minimum local. Il existe des techniques spéciales permettant d’éliminer la solution trouvée à partir d’un point extrême local. Si, après quelques applications de cette technique, le réseau de neurones a la même décision, on peut conclure que la solution trouvée est la plus susceptible d’être optimale.

1.4. Inconvénients

  • La principale difficulté d’utilisation des réseaux de neurones est la soi-disant « malédiction de la dimensionnalité ». Lorsque les dimensions d’entrée et le nombre de couches sont augmentés, la complexité d’un réseau et le temps d’apprentissage augmentent de manière exponentielle et le résultat reçu n’est pas toujours optimal.
  • Une autre difficulté de l’utilisation des réseaux de neurones est que les réseaux de neurones traditionnels sont incapables d’expliquer comment ils résolvent les tâches. Dans certains domaines d’application comme la médecine, cette explication est plus importante que le résultat lui-même. La représentation interne des résultats est souvent si complexe qu’il est impossible de l’analyser, sauf dans les cas les plus simples qui ne sont généralement pas intéressants.

2. Apprentissage profond

Aujourd’hui, la théorie et la pratique de l’apprentissage automatique traversent une « révolution profonde », causée par la mise en œuvre réussie des méthodes d’apprentissage profond, représentant les réseaux de neurones de troisième génération. Contrairement aux réseaux classiques de deuxième génération utilisés dans les années 80-90 du siècle dernier, les nouveaux paradigmes d’apprentissage résolvent un certain nombre de problèmes qui ont limité l’expansion et la mise en œuvre réussie des réseaux de neurones traditionnels.

Les réseaux formés avec des algorithmes d’apprentissage profond n’ont pas simplement excellé dans les meilleures méthodes alternatives en termes de précision, mais dans certains cas, ont révélé des rudiments de compréhension du sens de l’information d’entrée. La reconnaissance d’images et l’analyse d’informations textuelles en sont les exemples les plus brillants.

Aujourd’hui, les méthodes industrielles les plus avancées de vision par ordinateur et de reconnaissance vocale sont basées sur des réseaux profonds. Des géants de l’industrie informatique comme Apple, Google, Facebook emploient des chercheurs développant des réseaux de neurones profonds.


2.1. Arrière-plan

Une équipe d’étudiants diplômés qui étudient à l’Université de Toronto, dirigée par le professeur Geoffrey E. Hinton, a remporté le premier prix d’un concours parrainé par Merck. En utilisant un ensemble de données limité, décrivant la structure chimique de 15 molécules, le groupe de G. Hinton a réussi à créer et à appliquer un système de programme spécial qui définissait laquelle de ces molécules était la plus susceptible d’être un médicament efficace.

La particularité de ce travail était que les développeurs utilisaient un réseau de neurones artificiels basé sur l’apprentissage profond. En conséquence, ce système a réussi à effectuer des calculs et des recherches basés sur un ensemble très limité de données sources alors que l’entraînement d’un réseau de neurones nécessite normalement une quantité importante d’informations mises dans le système.

La réussite de l’équipe de Hinton a été particulièrement impressionnante parce que l’équipe a décidé de participer au concours à la dernière minute. Ajouté à cela, le système d’apprentissage profond a été développé sans connaissances spécifiques sur la façon dont les molécules se lient à leurs cibles. La mise en œuvre réussie de l’apprentissage profond a été une autre réalisation dans le développement de l’intelligence artificielle de l’année 2012 mouvementée.

Ainsi, pendant l’été 2012, Jeff Dean et Andrew Y. Ng de Google ont présenté un nouveau système de reconnaissance d’images avec un taux de précision de 15,8 %, où pour former un système de cluster de 16 000 nœuds, ils ont utilisé le réseau ImageNet contenant une bibliothèque de 14 millions d’images de 20 000 objets différents. L’année dernière, un programme créé par des scientifiques suisses a surpassé un humain dans la reconnaissance des images de panneaux de signalisation. Le programme gagnant a identifié avec précision 99,46 % des images sur un ensemble de 50 000 ; le score le plus élevé dans un groupe de 32 participants humains était de 99,22 %, et la moyenne pour les humains était de 98,84 %. En octobre 2012, Richard F. Rashid, coordinateur des programmes scientifiques de Microsoft, a présenté lors d’une conférence à Tianjin, en Chine, une technologie de traduction simultanée de l’anglais vers le mandarin accompagnée d’une simulation de sa propre voix.

Toutes ces technologies démontrant une percée dans le domaine de l’intelligence artificielle sont basées sur la méthode d’apprentissage profond dans une certaine mesure. La principale contribution à la théorie de l’apprentissage profond est faite par le professeur Hinton, un arrière-arrière-petit-fils de George Boole, un scientifique anglais, fondateur de l’algèbre de Boole sous-jacente aux ordinateurs contemporains.

La théorie de l’apprentissage profond complète les méthodes ordinaires d’apprentissage automatique avec des algorithmes spéciaux pour l’analyse des informations d’entrée à plusieurs niveaux de présentation. La particularité de la nouvelle approche est que l’apprentissage profond étudie le sujet jusqu’à ce qu’il trouve suffisamment de niveaux de présentation informatifs pour tenir compte de tous les facteurs qui peuvent influencer les paramètres de l’objet en question.

De cette façon, un réseau de neurones basé sur une telle approche nécessite moins d’informations d’entrée pour l’apprentissage et un réseau formé est capable d’analyser les informations avec un niveau de précision plus élevé que les réseaux neuronaux habituels. Le professeur Hinton et ses collègues affirment que leur technologie est particulièrement utile pour rechercher des particularités dans des tableaux d’informations multidimensionnels et bien structurés.

Les technologies d’intelligence artificielle (IA), en particulier l’apprentissage profond, sont largement utilisées dans différents systèmes, y compris l’assistant personnel intelligent Apple Siri basé sur les technologies Nuance Communications et la reconnaissance des adresses dans Google Street View. Néanmoins, les scientifiques estiment très soigneusement le succès dans ce domaine, car l’histoire de la création d’une intelligence artificielle est pleine de promesses optimistes et de déceptions.

Dans les années 1960, les scientifiques pensaient qu’il ne faudrait que 10 ans pour créer une intelligence artificielle complète. Puis dans les années 1980, il y a eu une vague de jeunes entreprises proposant une « intelligence artificielle prête à l’emploi » suivie de « la période glaciaire » dans ce domaine, qui a duré jusqu’à récemment. Aujourd’hui, les vastes capacités de calcul disponibles dans les services cloud fournissent un nouveau niveau de mise en œuvre puissante de réseaux de neurones en utilisant une nouvelle base théorique et algorithmique.

Il convient de noter que les réseaux de neurones, même ceux de la troisième génération comme les réseaux de neurones convolutifs, les autoassociateurs, les machines de Boltzmann, n’ont rien en commun avec les neurones biologiques, sauf le nom.

Le nouveau paradigme d’apprentissage met en œuvre l’idée d’apprentissage en deux étapes. À la première étape, les informations sur la structure interne des données d’entrée sont extraites d’un large éventail de données non formatées avec autoassociateur par le biais d’un entraînement non supervisé couche par couche. Ensuite, en utilisant ces informations dans un réseau de neurones multicouche, cela passe par un entraînement supervisé par des méthodes connues utilisant des données formatées. Dans le même temps, la quantité de données non formatées doit être aussi importante que possible. Les données formatées peuvent être beaucoup plus petites. Dans notre cas, ce n’est pas d’une importance immédiate.


2.2. Autoencodeurs. Autoencodeur et machine Boltzmann restreinte. Différences et particularités

2.2.1. Encodeur automatique

Le premier autoassociateur (АА) était un néocognitron de Fukushima.

Sa structure est présentée à la Fig.7.

Fig. 7. Un néocognitron de Fukushima

Fig. 7. Un néocognitron de Fukushima

Le but d’un autoassociateur (АА) est de recevoir à la sortie une image aussi précise que possible de l’entrée.

Il existe deux types d’АА : la génération et la synthèse. Une machine de Boltzmann restreinte appartient au premier type et un autoencodeur représente le second type.

Un autoencodeur est un réseau de neurones avec une couche ouverte. En utilisant un algorithme d’apprentissage non supervisé et la rétropropagation, il définit une valeur cible égale au vecteur d’entrée, c’est-à-dire y = x.

Un exemple d’autoencodeur est présenté sur la Fig.8.

Fig. 8. Une structure d’autoencodeur

Fig. 8. Une structure d’autoencodeur

L’autoencodeur tente de construire la fonction h(x)=x. En d’autres termes, il essaie de trouver une approximation d’une fonction garantissant qu’une rétroaction de réseau de neurones est approximativement égale aux valeurs des paramètres d’entrée. Pour que la solution du problème soit non triviale, le nombre de neurones dans la couche ouverte doit être inférieur à la dimension des données d’entrée (comme sur l’image).

Cela permet de compresser les données lorsque le signal d’entrée est transmis à la sortie réseau. Par exemple, si le vecteur d’entrée est un ensemble de niveaux de luminosité d’une image de 10х10 pixels (100 caractéristiques), le nombre de neurones de la couche cachée est de 50, le réseau est obligé d’apprendre à compresser l’image. L’exigence h(x)=x signifie que sur la base des niveaux d’activation de cinquante neurones de la couche cachée, la couche de sortie doit restaurer 100 pixels de l’image initiale. Une telle compression est possible s’il existe des interconnexions cachées, une corrélation caractéristique ou toute structure quelconque. De cette façon, une opération d’autoencodeur rappelle la méthode d’analyse en composantes principales (PCA) dans le sens où les données d’entrée sont réduites.

Étonnamment, les expériences menées par Bengio et al. (2007), ont montré que lors de l’entraînement avec la descente du gradient stochastique, les réseaux d’autocodage non linéaires avec le nombre de neurones cachés supérieur au nombre d’entrées (également appelé « surabondant ») avaient une présentation utile à la lumière de l’erreur de conformité du réseau qui a pris cette présentation de l’entrée.

Plus tard, lorsque l’idée de parcimonie est apparue, un autoencodeur clairsemé a été largement utilisé.

Un autoencodeur clairsemé est un autoencodeur qui a un nombre de neurones cachés significativement supérieur à la dimension d’entrée, mais ils ont une activation clairsemée. Une activation clairsemée se produit lorsque le nombre de neurones inactifs dans la couche cachée est significativement supérieur au nombre de neurones actifs. Si nous décrivons la rareté de manière informelle, alors un neurone peut être considéré comme actif si la valeur de sa fonction est proche de 1. Si une fonction sigmoïde est utilisée, alors pour le neurone inactif, sa valeur doit être proche de 0 (pour la fonction de tangente hyperbolique, la valeur doit être proche de -1).

Il existe une variante d’un autoencodeur appelé autoencodeur de débruisation (Vincent et al., 2008). C’est le même autoencodeur mais son entraînement a quelques particularités. Lors de l’entraînement de ce réseau, des données « corrompues » sont entrées (certaines valeurs sont remplacées par 0). Dans le même temps, il existe des données « correctes » à comparer avec les données de sortie. De cette façon, un autoencodeur peut restaurer les données endommagées.


2.2.2. Machine Boltzmann restreinte, RBM.

Nous n’allons pas nous concentrer sur l’histoire d’une machine Boltzmann restreinte (RBM). Tout ce que nous devons savoir, c’est que cela a commencé avec des réseaux de neurones récurrents avec des commentaires très difficiles à entraîner. En raison de cette difficulté d’apprentissage, des modèles récurrents plus restreints sont apparus afin que des algorithmes d’apprentissage plus simples puissent être appliqués. Un réseau de neurones Hopfield était l’un de ces modèles. John Hopfield est la personne qui a introduit le concept de l’énergie du réseau après avoir comparé la dynamique du réseau de neurones avec la thermodynamique.

L’étape suivante sur le chemin d’un RBM était les machines Boltzmann ordinaires. Elles diffèrent d’un réseau de Hopfield par leur nature stochastique et ses neurones sont divisés en deux groupes décrivant des états visibles et cachés (similaires à un modèle de Markov caché). Une machine de Boltzmann restreinte est différente d’une machine ordinaire en l’absence de connexions entre les neurones d’une couche.

La Fig. 9 représente une structure RBM.

Fig. 9. Une structure de RBM

Fig. 9. Une structure de RBM

La particularité de ce modèle est que dans les états actuels des neurones d’un groupe, les états des neurones d’un autre groupe vont être indépendants les uns des autres. Maintenant, nous pouvons passer à une théorie où cette propriété a le rôle clé.

Interprétation et objectif

Une RBM est interprété de la même manière qu’un modèle de Markov caché. Nous avons un certain nombre d’états que nous pouvons observer (neurones visibles) et un certain nombre d’états cachés que nous ne pouvons pas voir directement (neurones cachés). Nous pouvons arriver à une conclusion basée sur les probabilités concernant les états cachés en nous appuyant sur les états que nous pouvons observer. Une fois qu’un tel modèle a été formé, nous avons l’occasion de tirer des conclusions concernant les états visibles en sachant que les états cachés suivent le théorème de Bayes. Cela permet de générer des données à partir de la distribution de probabilité utilisée pour l’entraînement du modèle.

De cette façon, nous pouvons formuler l’objectif de l’entraînement d’un modèle : les paramètres du modèle doivent être ajustés de manière à ce qu’un vecteur restauré de l’état initial soit le plus proche de l’original. Un vecteur restauré est un vecteur reçu par une inférence probabiliste à partir d’états cachés, qui à leur tour, ont été reçus par une inférence probabiliste à partir d’états visibles, c’est-à-dire du vecteur d’origine.

L’algorithme d’entraînement est la divergence contrastive CD-k

Cet algorithme a été inventé par le professeur Hinton en 2002 et est remarquablement simple. L’idée principale est que les valeurs d’attente mathématiques sont remplacées par des valeurs définies. L’idée de l’échantillonnage de Gibbs est introduite.

Le CD-k ressemble à :

  1. L’état des neurones visibles est égal au modèle d’entrée ;
  2. Les probabilités des états de couche cachés sont dessinées ;
  3. Chaque neurone de la couche cachée se voit attribuer l’état « 1 » avec une probabilité égale à son état actuel ;
  4. Les probabilités des états de couche visibles sont dessinées en fonction de la couche cachée ;
  5. Si l’itération actuelle est inférieure à k, revenez à l’étape 2 ;
  6. Les probabilités des états de couche cachés sont dessinées ;

Dans les conférences de Hinton, cela ressemble à :

Fig.10. Algorithme de l’apprentissage CD-k

Fig.10. Algorithme de l’apprentissage CD-k

En d’autres termes, plus nous faisons de l’échantillonnage, plus le gradient est précis. Le professeur affirme que le résultat reçu pour le CD-1, c’est-à-dire une seule itération d’échantillonnage, est déjà bon.


2.3. Réseaux d’autoassociateurs empilés. Encodeur automatique empilé SAE, machine Boltzmann restreinte empilée (RBM empilé)

Pour extraire des abstractions de haut niveau de l’ensemble de données d’entrée, les autoassociateurs sont combinés dans un réseau.

La Fig. 11 représente une structure d’autoencodeur empilé et un réseau de neurones, qui représentent ensemble un réseau de neurones profond avec des poids initialisés par un autoencodeur empilé

Fig. 11. Structure d’un DN SAE

Fig. 11. Structure d’un DN SAE

Sur la Fig.12, il y a un modèle d’un RBM empilé (SRBM) et d’un réseau de neurones, qui représentent ensemble un réseau de neurones profond avec des poids initialisés par SRBM.

Ces illustrations de structures de réseau profond soulignent le fait que l’information est extraite de bas en haut.

Fig. 12. Structure d’une SRBM DN

Fig. 12. Structure d’une SRBM DN

2.4. Entraînement des réseaux profonds (DN). Étapes. Particularités

L’entraînement des réseaux profonds comprend deux étapes. Lors de la première étape, un réseau autoassociateur (SAE ou SRBM, selon le type de DN) reçoit un entraînement non supervisé sur un tableau de données non formaté. Après cela, les neurones de couche cachée de MLP ordinaire sont initialisés par les poids de couche cachés reçus après l’entraînement. Les figures 11 et 12 représentent un modèle des processus d’apprentissage et de transfert. Après l’entraînement du premier АЕ/RBM, les poids des neurones de la couche cachée deviennent des entrées de la seconde, etc. De cette façon, la généralisation des informations sur la structure (ligne, contour, modèle, etc.) est extraite des données.

La deuxième étape est le moment de peaufiner le MLP (entraînement supervisé) sur un ensemble de données formatées à l’aide de méthodes bien connues. La pratique a prouvé qu’une telle initialisation fixe les poids des neurones des couches cachées du MLP au minimum global et que le réglage fin suivant prend très peu de temps.

De plus, pour les réseaux profonds dont le nombre de couches est supérieur à trois, D. Hinton a suggéré que le réglage fin devrait être effectué en deux étapes. À la première étape, seules deux couches supérieures doivent être formées et à la seconde, le reste du réseau.

Il convient de mentionner qu’une SRBM a des résultats moins stables d’entraînement non supervisé qu’un SAE.

Remarque.: Très souvent, ces termes sont confondus. Une SRBM est identifié à un réseau de croyances profondes DBN. Malgré le fait qu’une RBM dérive d’un DBN, ce sont des structures totalement différentes. Un DBN est un réseau de neurones multicouche, avec des poids neuronaux de couches cachées initialisées aléatoirement par des modèles binaires.


3. Expériences pratiques

Les réseaux profonds seront effectués dans R.

3.1. Le langage R

Historique. R est un langage de programmation et un environnement pour les calculs statistiques et la cartographie, développé en 1996 par les scientifiques néo-zélandais Ross Ihaka et Robert Gentleman à l’Université d’Aokland.

R est un projet GNU qui est un logiciel libre et sa philosophie se résume aux principes suivants :

  • la liberté de lancer des programmes à quelque fin que ce soit (liberté 0) ;
  • la liberté d’apprendre le fonctionnement d’un programme et de l’adapter à ses propres besoins (liberté 1) ;
  • la liberté de distribuer des copies pour aider les autres (liberté 2) ;
  • la liberté d’améliorer le programme et de permettre à la société de bénéficier des améliorations.

Dans la perspective historique, R est une alternative pour la mise en œuvre de S. Ce dernier a été développé par John Chambers et ses collègues de la société Bell Labs en 1976. Aujourd’hui, R est toujours en cours d’amélioration par l’équipe de base de développement R, y compris John Chambers.

Pour répéter les expériences, vous devrez installer R et Rstudio. Des informations sur où télécharger et comment ils peuvent être trouvés sur Internet. S’il y a des questions, nous pouvons en discuter dans les commentaires de l’article.

Avantages de R:

  • Aujourd’hui, R est la norme dans les calculs statistiques.
  • Il est développé et soutenu par la communauté scientifique mondiale des universités.
  • Large gamme de packages pour tous les domaines avancés de l’exploration de données. Le temps entre la publication de l’idée et sa mise en œuvre dans le package R n’est généralement plus de 2 semaines.
  • Et enfin, c’est absolument gratuit. Un célèbre développeur d’un système d’exploitation gratuit a dit une fois : « Les programmes sont comme le sexe - c’est mieux quand c’est gratuit ».


3.2. Variations de mise en œuvre et problèmes abordés

Il y a deux façons possibles de mettre en œuvre.

La première consiste à utiliser des programmes uniques de John Hinton pour Matlab. Pour cela, le « R.matlab » est nécessaire. Ce package possède les méthodes writeMat() et readMat() pour lire et écrire les fichiers MAT. Il permet la communication (implémentation de code, envoi et réception d’objets, etc.) à partir de Matlab v6 et plus lancé localement ou sur l’hôte distant dans la liaison client-serveur. Les détails peuvent être trouvés dans la description du package. C’est le moyen pour ceux qui sont à l’aise avec Matlab. Je n’ai pas essayé d’utiliser cette méthode mais il est possible de lier Matlab et MQL de cette façon.

La deuxième façon d’implémentation consiste à utiliser les packages R sur ce sujet. Nous allons l’explorer.

Il y a trois packages que je connais, qui sont liés au sujet de cet article :

  1. «deepnet» est un package simple implémentant les modèles DN SAE et SRBM DN. La longueur de l’ensemble de données d’entrée lors de l’apprentissage supervisé et non supervisé est la même. Ne donne pas l’occasion d’effectuer un réglage fin du système en deux étapes. Utilisé pour l’exploration et le test des modèles au début.

  2. «darh» est un package avancé et varié pour la modélisation de SRBM DN. Il existe un modèle pour DN SAE mais je n’ai pas réussi à le lancer. Ce package est destiné aux utilisateurs expérimentés, il permet de créer et de régler un modèle de n’importe quel niveau de complexité. Il est basé sur les programmes uniques de Hinton dans le langage m pour MatLab.

  3. «H2O» est un package complet pour l’entraînement de réseaux profonds (pas seulement eux) sur de grands ensembles de données (>1 Гб) écrits dans des fichiers csv.

Dans les expériences ci-dessous, nous allons utiliser le package « deepnet ».


3.3. Préparation des données d’entrée et cibles pour l’expérience

Aujourd’hui, l’exploration de données a un certain ordre de travail :

  1. Sélection des données d’entrée (étude, analyse, préparation préliminaire, évaluation). Ventilation des données dans les ensembles entraînement, validation et test (échantillons) ;
  2. Former un modèle sur l’ensemble de données d’entraînement et sélectionner un ou plusieurs modèles sur celui de la validation ;
  3. Évaluation de la qualité du ou des modèles sur l’échantillon d’essai et définition des paramètres optimaux du modèle ou du meilleur modèle hors de l’ensemble par certaines mesures ;
  4. Laisser le ou les modèles commencer le travail.

La première étape est la plus longue et la plus importante pour le résultat final. Pour être juste, cette étape n’est pas formalisée et, d’une manière générale, c’est presque une forme d’art. Beaucoup dépend de l’expérience d’un chercheur. Toutefois ! Il est très important d’obtenir des évaluations quantitatives de l’ensemble de données d’entrée pour sélectionner les plus importantes. La sélection automatique des meilleures variables pour un certain modèle est encore meilleure dans ce cas. R fournit des fonctionnalités étendues pour relever les défis à toutes les étapes.

Les données sources sont non seulement très importantes, mais elles ont également de nombreux aspects à prendre en compte. Cela mérite un article séparé. Puisque le but de cet article est de raconter une chose complexe avec des mots très simples, nous discuterons des points importants mais n’entrerons pas dans les détails.


3.3.1. Données sources

Pour notre classification, nous avons besoin d’un ensemble de variables indépendantes (d’entrée) et d’une variable cible. Étant donné que le principal avantage prononcé des réseaux profonds est leur capacité à apprendre rapidement sur de grands échantillons d’entrée, créons un ensemble de données d’entrée comprenant 17 prédicteurs (11 indicateurs). ZigZag a un rôle de variable cible. Télécharger dans l’environnement R des vecteurs Ouverts, Hauts, Bas, Proches de 4000 bars de profondeur. La façon de le faire est débattue ci-dessous dans la description de la rédaction d’un indicateur. À ce stade, ce n’est pas important. Tous les autres calculs seront effectués dans R.

Construisez une matrice à partir de 4 vecteurs, du prix moyen et de la taille du corps de bar. Transformez-la en fonction :

pr.OHLC <- function (o, h, l, c) 
{
  #Unite quote vectors into a matrix having previously expanded them
  #Indexing of time series of vectors in R starts with 1. 
  #Direction of indexing is from old to new ones.   
  price <- cbind(Open = rev(o), High = rev(h), Low = rev(l), Close = rev(c))
  Med <- (price[, 2] + price[, 3])/2
  CO <- price[, 4] - price[, 1]
  #add Med and CO to the matrix
  price <- cbind(price, Med, CO)
}

Voir le résultat (état à 08.10. 14 12:00)

> head(price)
        Open    High     Low   Close      Med     CO
[1,] 1.33848 1.33851 1.33824 1.33844 1.338375 -4e-05
[2,] 1.33843 1.33868 1.33842 1.33851 1.338550  8e-05
[3,] 1.33849 1.33862 1.33846 1.33859 1.338540  1e-04
[4,] 1.33858 1.33861 1.33856 1.33859 1.338585  1e-05
[5,] 1.33862 1.33868 1.33855 1.33855 1.338615 -7e-05
[6,] 1.33853 1.33856 1.33846 1.33855 1.338510  2e-05


3.3.2. Données d’entrée (prédicteurs)

Dressez la liste des indicateurs. Les indicateurs ont été sélectionnés au hasard, sans préférence pour obtenir une différence maximale de tailles d’entrée.

Le calcul de tous les indicateurs est effectué à l’aide du package « TTR » contenant de nombreux indicateurs.


3.3.2.1. Index du mouvement directionnel de Welles Wilder - ADX(HLC, n) - 4 out (Dip, Din, DX, ADX)

Calculez et voyez à quoi cela ressemble sur les 200 premiers bars :

> library(TTR)
> adx<-ADX(price, n = 16)
> plot.ts(head(adx, 200))

Fig. 13. Index indicateur du mouvement directionnel de Welles Wilder - ADX(HLC, n)

Fig. 13. Index indicateur du mouvement directionnel de Welles Wilder - ADX(HLC, n)

> summary(adx)
      DIp             DIn                DX                 ADX    
 Min.   :15.90   Min.   :  5.468   Min.   : 0.00831      Min.   : 5.482   
 1st Qu.:41.21   1st Qu.: 33.599   1st Qu.: 8.05849      1st Qu.:14.046 
 Median :47.36   Median : 43.216   Median :16.95423      Median :18.099
 Mean   :47.14   Mean   : 46.170   Mean   :19.73032      Mean   :19.609 
 3rd Qu.:53.31   3rd Qu.: 55.315   3rd Qu.:27.97471      3rd Qu.:23.961     
 Max.   :80.12   Max.   :199.251   Max.   :81.08751      Max.   :52.413
 NA's   :16      NA's   :16        NA's   :16            NA's   :31 

Au début de la matrice, il y a 31 valeurs non définies (NA). Effectuez ensuite les mêmes calculs pour tous les indicateurs sans explications détaillées.


3.3.2.2. aroon(HL, n) - 1 sortie (oscillateur)

Calculez et voyez les 200 premiers bars d’un seul « oscillateur » variable

> ar<-aroon(price[ , c('High', 'Low')], n = 16)[ ,'oscillator']
> plot(head(ar, 200), t = "l")
> abline(h = 0)

Fig. 14. Indicateur aroon(HL, n)

Fig. 14. Indicateur aroon(HL, n)

> summary(ar)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
-100.00  -56.25  -18.75   -7.67   43.75  100.00      16 


3.3.2.3. Index des canaux de commodité - CCI(HLC, n) - 1 sortie

> cci<-CCI(price[ ,2:4], n = 16)
> plot.ts(head(cci, 200))
> abline(h = 0)

Fig. 15. Indicateur index des canaux de commodité - CCI(HLC, n)

Fig. 15. Indicateur index des canaux de commodité - CCI(HLC, n)

> summary(cci)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
-469.10  -90.95  -18.74  -14.03   66.91  388.20      15 


3.3.2.4. Volatilité de Chaikin - chaikinVolatility (HLC, n) - 1 sortie

> chv<-chaikinVolatility(price[ , 2:4], n = 16)
> summary(chv)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max.     NA's 
-0.67570 -0.29940  0.02085  0.12890  0.41580  5.15700       31 
> plot(head(chv, 200), t = "l")
> abline(h = 0)

Fig. 16. Indicateur chaikinVolatility (HLC,n)

Fig. 16. Indicateur chaikinVolatility (HLC, n)

3.3.2.5. Oscillateur Chande Momentum - CMO(Med, n) - 1 sortie

> cmo<-CMO(price[ ,'Med'], n = 16)
> plot(head(cmo, 200), t = "l")
> abline(h = 0)

Fig. 17. Indicateur Oscillateur Chande Momentum - CMO(Med, n)

Fig. 17. Indicateur Oscillateur Chande Momentum - CMO(Med, n)

> summary(cmo)
   Min.    1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
-97.670 -32.650  -5.400  -6.075  19.530  93.080      16 


3.3.2.6. Oscillateur MACD - MACD(Med, nFast, nSlow, nSig) 1 sortie est utilisée (macd)

> macd<-MACD(price[ ,'Med'], 12, 26, 9)[ ,'macd']
> plot(head(macd, 200), t = "l")
> abline(h = 0)

Fig. 18. Indicateur oscillateur MACD

Fig. 18. Indicateur oscillateur MACD

> summary(macd)
     Min.   1st Qu.    Median      Mean   3rd Qu.      Max.      NA's
-0.346900 -0.025150 -0.005716 -0.011370  0.013790  0.088880      25       


3.3.2.7. OsMA(Med,nFast, nSlow, nSig) – 1 sortie

> osma<-macd - MACD(price[ ,'Med'],12, 26, 9)[ ,'signal']
> plot(head(osma, 200), t = "l")
> abline(h = 0)

Fig. 19. Indicateur OsMA(Med,nFast, nSlow, nSig)

Fig. 19. Indicateur OsMA(Med,nFast, nSlow, nSig)

> summary(osma)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max.     NA's 
-0.10560 -0.00526  0.00034  0.00007  0.00646  0.05922       33 


3.3.2.8. Index de force relative - RSI(Med,n) – 1 sortie

> rsi<-RSI(price[ ,'Med'], n = 16)
> plot(head(rsi, 200), t = "l")
> abline(h = 50)

Fig. 20. Index de force relative de l’indicateur - RSI(Med,n)

Fig. 20. Index de force relative de l’indicateur - RSI(Med,n)

> summary(rsi)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
   5.32   37.33   47.15   46.53   55.71   84.82      16 


3.3.2.9. Oscillateur stochastique - stoch(HLC, nFastK=14, nFastD=3, nSlowD=3) - 3 sortie

> stoh<-stoch(price[ ,2:4], 14, 3, 3)
> plot.ts(head(stoh, 200))

Fig. 21. Indicateur oscillateur stochastique - stoch(HLC, nFastK=14, nFastD=3, nSlowD=3)

Fig. 21. Indicateur oscillateur stochastique - stoch(HLC, nFastK=14, nFastD=3, nSlowD=3)

> summary(stoh)
     fastK            fastD             slowD        
 Min.   :0.0000   Min.   :0.01782   Min.   :0.02388  
 1st Qu.:0.2250   1st Qu.:0.23948   1st Qu.:0.24873  
 Median :0.4450   Median :0.44205   Median :0.44113  
 Mean   :0.4622   Mean   :0.46212   Mean   :0.46207  
 3rd Qu.:0.6842   3rd Qu.:0.67088   3rd Qu.:0.66709  
 Max.   :1.0000   Max.   :0.99074   Max.   :0.97626  
 NA's   :13       NA's   :15        NA's   :17     


3.3.2.10. Index de quantité de mouvement stochastique - SMI(HLC, n = 13, nFast = 2, nSlow = 25, nSig = 9) — 2 sortie

> smi<-SMI(price[ ,2:4],n = 13, nFast = 2, nSlow = 25, nSig = 9)
> plot.ts(head(smi, 200))

Fig. 22. Index indicateur de quantité de mouvement stochastique - SMI(HLC, n = 13, nFast = 2, nSlow = 25, nSig = 9)

Fig. 22. Index indicateur de quantité de mouvement stochastique - SMI(HLC, n = 13, nFast = 2, nSlow = 25, nSig = 9)

> summary(smi)
      SMI              signal       
 Min.   :-82.185   Min.   :-78.470  
 1st Qu.:-33.392   1st Qu.:-31.307  
 Median : -9.320   Median : -8.839  
 Mean   : -8.942   Mean   : -8.985  
 3rd Qu.: 15.664   3rd Qu.: 14.069  
 Max.   : 71.878   Max.   : 63.865  
 NA's   :25        NA's   :33  


3.3.2.11. Volatilité (Yang et Zhang) - volatilité (OHLC, n, calc=« yang.zhang », N=96)- 1 sortie

> vol<-volatility(price[ ,1:4],n = 16,calc = "yang.zhang", N =96)
> plot.ts(head(vol, 200))

Fig. 23. Volatilité des indicateurs (Yang et Zhang) - volatilité(OHLC, n, calc="yang.zhang", N=96)

Fig. 23. Volatilité des indicateurs (Yang et Zhang) - volatilité(OHLC, n, calc="yang.zhang", N=96)

> summary(vol)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max.      NA's
0.000599 0.001858 0.002638 0.003127 0.004015 0.012840      16      

Nous avons donc 17 variables à partir de 11 indicateurs pour EURUSD sur la période М15 pour l’échantillon OHLC de 4000 bars de profondeur.

Utilisez-les pour former une matrice et écrire les paramètres ci-dessus dans une fonction avec un paramètre formel р, qui sera nécessaire pour l’optimisation.

Calculez la matrice des paramètres d’entrée à l’aide de la formule suivante :

In<-function(p = 16){
  adx<-ADX(price, n = p);
  ar<-aroon(price[ ,c('High', 'Low')], n=p)[ ,'oscillator'];
  cci<-CCI(price[ ,2:4], n = p);
  chv<-chaikinVolatility(price[ ,2:4], n = p);
  cmo<-CMO(price[ ,'Med'], n = p);
  macd<-MACD(price[ ,'Med'], 12, 26, 9)[ ,'macd'];
  osma<-macd - MACD(price[ ,'Med'],12, 26, 9)[ ,'signal'];
  rsi<-RSI(price[ ,'Med'], n = p);
  stoh<-stoch(price[ ,2:4],14, 3, 3);
  smi<-SMI(price[ ,2:4],n = p, nFast = 2, nSlow = 25, nSig = 9);
  vol<-volatility(price[ ,1:4],n = p,calc="yang.zhang", N=96);
  In<-cbind(adx, ar, cci, chv, cmo, macd, osma, rsi, stoh, smi, vol);
  return(In)
}
> X<-In()
> tail(X)
             DIp      DIn       DX      ADX   ar      cci       chv
[3995,] 46.49620 36.32411 12.28212 18.17544 25.0 168.0407 0.1835102
[3996,] 52.99009 31.61164 25.26952 18.61882 37.5 227.7030 0.3189822
[3997,] 58.11948 28.16241 34.72000 19.62515 37.5 145.2337 0.3448520
[3998,] 56.00323 30.48687 29.50206 20.24245 37.5 118.5831 0.3068059
[3999,] 55.96197 28.78737 32.06467 20.98134 37.5 116.5376 0.3517668
[4000,] 54.97777 26.85440 34.36713 21.81795 62.5 160.0767 0.6169701
             cmo         macd       osma      rsi     fastK
[3995,] 29.71342 -0.020870825 0.01666593 52.91932 0.8832685
[3996,] 41.89526 -0.009654368 0.02230591 61.49793 0.8833819
[3997,] 30.98237 -0.002051532 0.02392699 58.94513 0.7259475
[3998,] 33.84813  0.003454534 0.02354645 58.00549 0.7930029
[3999,] 38.84892  0.009590136 0.02374564 60.63806 0.8367347
[4000,] 54.71698  0.019303110 0.02676689 66.64815 0.9354120
            fastD     slowD        SMI    signal         vol
[3995,] 0.7773581 0.7735064 -35.095406 -47.27712 0.003643196
[3996,] 0.7691688 0.7761507 -26.482951 -43.11828 0.003858942
[3997,] 0.8308660 0.7924643 -19.699762 -38.43458 0.003920541
[3998,] 0.8007775 0.8002707 -13.141932 -33.37605 0.003916109
[3999,] 0.7852284 0.8056239  -6.569699 -28.01478 0.003999789
[4000,] 0.8550499 0.8136852   2.197810 -21.97226 0.004293766

Les données d’entrée brutes sont préparées.


3.3.3. Données de sortie (Cible)

Maintenant, nous allons former la sortie (données cibles). Comme nous l’avons mentionné précédemment, nous allons utiliser ZigZag.

Nous allons utiliser ZigZag avec la largeur de canal de 37 grands points. ZigZag va être calculé par le prix moyen. L’indicateur peut être calculé par les prix HL, mais le prix moyen est préférable car l’indicateur est plus stable dans ce cas. Après avoir extrait le signal (0 - Acheter, 1 - Vendre), convertissez-le en une matrice d’entrée, qui suppose le modèle de réseau.

Écrivez une fonction :

Out<-function(ch=0.0037){
  # ZigZag has values on each bar and not only in the points 
  zz<-ZigZag(price[ ,'Med'], change = ch, percent = F, retrace = F, lastExtreme = T);
  n<-1:length(zz);
  # On the last bars substitute the undefined values for the last known ones
  for(i in n) { if(is.na(zz[i])) zz[i] = zz[i-1];}
  #Define the speed of ZigZag changes and move one bar forward
  dz<-c(diff(zz), NA);
  #If the speed >0 - signal = 0(Buy), if <0, signal = 1 (Sell) otherwise NA
  sig<-ifelse(dz>0, 0, if else(dz<0, 1, NA));
  return(sig);
}

Calculez les signaux.

> Y<-Out()
> table(Y)
Y
   0    1 
1567 2423 

Le ratio de classe est déséquilibré. Le nombre d’exemples d’une classe est supérieur à l’autre. Tous les modèles de la classification sont hostiles à de tels ensembles.

Lors de la séparation des données en échantillons d’entraînement et de test, nous rectifierons cette situation.


3.3.4. Suppression des données

Supprimez nos ensembles de données à partir de données non définies. Dans ce cas, la suppression implique un ensemble plus large de tâches. Cela inclut la suppression des « variables pratiquement nulles » et des variables fortement corrélées, ainsi que d’autres tâches dont nous n’allons pas discuter ici.

Écrire une fonction et supprimer les données

Clearing<-function(x, y){
  dt<-cbind(x,y);
  n<-ncol(dt)
  dt<-na.omit(dt)
  return(dt);  
}
> dt<-Clearing(X,Y); nrow(dt)
[1] 3957

La matrice est devenue plus courte de 43 bars.


3.3.5. Entraînement et test de formation d’échantillons

Il existe plusieurs façons de ventiler les données sources dans les échantillons d’entraînement et de test. Nous allons utiliser une division aléatoire régulière des données sources dans le train et en tester une dans la proportion 8/10. Il est important que les échantillons soient stratifiés, ce qui signifie que le rapport des instances de classe en train et des échantillons de test doit correspondre au rapport de classe dans l’ensemble de données source. Il serait également avantageux de rectifier l’inégalité de classe dans l’ensemble de données sources. Il y a deux façons de le faire - soit le nivellement par la plus grande ou par la plus petite classe. Comme nous avons besoin de plus d’exemples, nous allons niveler par la plus grande classe « 1 ». Dans ce cas, nous allons utiliser le package « caret ».

Formons un nouvel ensemble équilibré où le nombre d’instances des deux classes est le même et est égal à la plus grande.


3.3.6. Équilibrage de classe

Ci-dessous se trouve la fonction qui nivèle le nombre de classes par le plus grand côté (si la divergence est supérieure à 15 %) et renvoie une matrice équilibrée

Balancing<-function(DT){
  #Calculate a table with a number of classes
  cl<-table(DT[ ,ncol(DT)]);
  #If the divergence is less than 15%, return the initial matrix
  if(max(cl)/min(cl)<= 1.15) return(DT)
  #Otherwise level by the greater side
  DT<-if(max(cl)/min(cl)> 1.15){ 
         upSample(x = DT[ ,-ncol(DT)],y = as.factor(DT[ , ncol(DT)]), yname = "Y")
        }
  #Convert у (factor) into a number
  DT$Y<-as.numeric(DT$Y)
  #Recode у from 1,2 into 0,1
  DT$Y<-ifelse(DT$Y == 1, 0, 1)
  #Convert dataframe to matrix
  DT<-as.matrix(DT)
  return(DT);
}

Explication. Dans la première chaîne, calculez le nombre d’instances de chaque classe (vecteur, avec une dimension égale au nombre de classes).

Trouvez le rapport entre le plus grand vecteur et le plus petit et s’il est inférieur au ratio du seuil défini, quittez. Si le rapport est plus grand, calculez la fonction, après avoir mis х et y séparément. Y doit être préalablement converti en facteur.

Il s’agit de l’exigence des paramètres formels de la fonction upSample().. Comme nous n’avons pas besoin de la variable cible comme facteur, nous la reconvertissons en une variable numérique avec les valeurs 0 et 1. Veuillez noter que lorsque nous convertissons une variable numérique (0,1) en facteur, nous recevons les variables de texte « 0 » et « 1 ». Lors de la conversion inversée en variables numériques, nous obtenons 1 et 2 (!). Nous les remplaçons par 0 et 1. Notre ensemble de données est converti de la « trame de données » à la classe « matrice ». Calculez-la :

dt.b<-Balancing(dt)
x<-dt.b[ ,-ncol(dt.b)]
y<-dt.b[ , ncol(dt.b)]

De cette façon, nous avons l’ensemble de données dt source (entrée et sortie) et l’ensemble équilibré dt.b.

Divisez cela dans en échantillons de train et de test

Obtenez les indices des échantillons de train et de test à partir du package "rminer" à l’aide de la fonction holdout()..

> library('rminer')
> t<-holdout(y, ratio = 8/10, mode = "random")

L’objet t est une liste contenant des indices de l’ensemble de données d’entraînement (t$tr) et de test (t$ts). Les ensembles reçus sont stratifiés.


3.3.7. Prétraitement

Notre source de données d’entrée contient des variables avec différentes plages de valeurs. Essentiellement, les réseaux profonds sont des réseaux réguliers avec une façon particulière d’initialiser les poids.

Les réseaux de neurones peuvent recevoir les variables d’entrée dans la plage (-1; 1) ou (0, 1). Normalisez les variables d’entrée dans la plage de [-1, 1].

Pour cela, utilisez la fonction preProcess() du package « caret ».. Veuillez noter que les paramètres de prétraitement doivent être calculés sur l’ensemble de données d’entraînement et les enregistrer pour un prétraitement ultérieur de l’ensemble de données de test et des données nouvellement saisies.

> spSign<-preProcess(x[t$tr, ], method = "spatialSign")
> x.tr<-predict(spSign, x[t$tr, ])
> x.ts<-predict(spSign, x[t$ts, ])

Maintenant, nous avons tout pour construire, entraîner et tester un réseau de neurones profond.


3.4. Création, entraînement et test de modèles

Nous allons construire et former le modèle DN SAE. La formule du modèle et la description des variables :

sae.dnn.train(x, y, hidden = c(10), activationfun = "sigm", learningrate = 0.8, momentum = 0.5, learningrate_scale = 1, output = "sigm", sae_output = "linear",
  numepochs = 3, batchsize = 100, hidden_dropout = 0, visible_dropout = 0)

Où :

  • х est une matrice de données d’entrée ;
  • y est un vecteur ou une matrice de variables cibles ;
  • hidden est un vecteur avec un certain nombre de neurones dans chaque couche cachée. Par défaut с(10) ;
  • activationfun est une fonction d’activation des neurones cachés. Peut être « sigm », « linéaire », « tanh ». Par défaut « sigm » ;
  • learningrate est un niveau d’entraînement pour la descente de gradient. Par défaut = 0,8 ;
  • momentum est un élan pour la descente de gradient. Par défaut = 0,5 ;
  • learningrate_scale le niveau d’entraînement peut être multiplié par cette valeur après chaque itération. Par défaut = 1,0 ;
  • numepochs est un certain nombre d’itérations pour l’entraînement. Par défaut = 3 ;
  • batchsize est la taille d’une petite quantité de données en cours d’entraînement. Par défaut = 100 ;
  • output est la fonction d’activation pour les neurones de sortie et peut être « sigm », « linéaire », « softmax ». Par défaut « sigm » ;
  • sae_output est la fonction d’activation des neurones de sortie de SAE et peut être « sigm », « linéaire », « softmax ». Par défaut « linéaire » ;
  • hidden_dropout est une partie supprimable pour les calques cachés. Par défaut = 0 ;
  • visible_dropout est une partie supprimable de la couche (d’entrée) visible. Par défaut = 0.

Nous allons créer un modèle avec les dimensions suivantes (17, 100, 100, 100, 1), l’entraîner, noter le temps d’apprentissage et observer la prévision.

> system.time(SAE<-sae.dnn.train(x= x.tr, y= y[t$tr], hidden=c(100,100,100), activationfun = "tanh", learningrate = 0.6, momentum = 0.5, learningrate_scale = 1.0, output = "sigm", sae_output = "linear", numepochs = 10, batchsize = 100, hidden_dropout = 0, visible_dropout = 0))
begin to train sae ......
training layer 1 autoencoder ...
training layer 2 autoencoder ...
training layer 3 autoencoder ...
sae has been trained.
begin to train deep nn ......
deep nn has been trained.
   user  system elapsed 
  12.92    0.00   13.09 

Comme nous pouvons le voir, cela se passe en deux étapes. Au début, l’autoencodeur est entraîné couche par couche, puis le réseau de neurones.

Le petit nombre de temps d’entraînement et l’immense nombre de neurones cachés dans les trois couches ont été définis exprès. L’ensemble du processus a pris 13 secondes !

Évaluons les prévisions sur l’ensemble de prédicteurs de test.

> pr.sae<-nn.predict(SAE, x.ts);
> summary(pr.sae)
       V1        
 Min.   :0.2649  
 1st Qu.:0.2649  
 Median :0.5881  
 Mean   :0.5116  
 3rd Qu.:0.7410  
 Max.   :0.7410 

Convertir en niveaux 0,1 et calculer les mesures

> pr<-ifelse(pr.sae>mean(pr.sae), 1, 0)
> confusionMatrix(y[t$ts], pr)
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 316 128
         1 134 378
                                         
               Accuracy : 0.7259         
                 95% CI : (0.6965, 0.754)
    No Information Rate : 0.5293         
    P-Value [Acc > NIR] : <2e-16         
                                         
                  Kappa : 0.4496         
 Mcnemar's Test P-Value : 0.7574         
                                         
            Sensitivity : 0.7022         
            Specificity : 0.7470         
         Pos Pred Value : 0.7117         
         Neg Pred Value : 0.7383         
             Prevalence : 0.4707         
         Detection Rate : 0.3305         
   Detection Prevalence : 0.4644         
      Balanced Accuracy : 0.7246         
                                         
       'Positive' Class : 0 

Ce n’est pas un coefficient exceptionnel. Nous sommes plus intéressés par le profit que nous allons faire en utilisant ces signaux, pas par le coefficient. Vérifiez cela sur les 500 derniers bars (environ une semaine). Nous allons recevoir des signaux sur les 500 derniers bars séquentiels de notre réseau formé.

Normalisez les 500 derniers bars de données d’entrée, recevez les prévisions du réseau de neurones entraîné et convertissez-les en signaux -1= (Vendre) et 1 = (Acheter)

> new.x<-predict(spSign,tail(dt[ ,-ncol(dt)], 500))
> pr.sae1<-nn.predict(SAE, new.x)
> pr.sig<-ifelse(pr.sae1>mean(pr.sae1), -1, 1)
> table(pr.sig)
pr.sig
 -1   1 
235 265 
> new.y<-ifelse(tail(dt[  , ncol(dt)], 500) == 0, 1, -1)
> table(new.y)
new.y
 -1   1 
201 299 
> cm1<-confusionMatrix(new.y, pr.sig)
> cm1
Confusion Matrix and Statistics

          Reference
Prediction  -1   1
        -1 160  41
        1   75 224
                                          
               Accuracy : 0.768           
                 95% CI : (0.7285, 0.8043)
    No Information Rate : 0.53            
    P-Value [Acc > NIR] : < 2.2e-16       
                                          
                  Kappa : 0.5305          
 Mcnemar's Test P-Value : 0.002184        
                                          
            Sensitivity : 0.6809          
            Specificity : 0.8453          
         Pos Pred Value : 0.7960          
         Neg Pred Value : 0.7492          
             Prevalence : 0.4700          
         Detection Rate : 0.3200          
   Detection Prevalence : 0.4020          
      Balanced Accuracy : 0.7631          
                                          
       'Positive' Class : -1   

Le coefficient de précision n’est pas mauvais, bien que nous soyons plus intéressés par le profit, pas par le coefficient.

Testez le bénéfice des 500 derniers bars à l’aide de nos signaux prévus et obtenez la courbe de la balance :

> bal<-cumsum(tail(price[ , 'CO'], 500) * pr.sig)
> plot(bal, t = "l")
> abline(h = 0)

Fig. 24. Balance sur les 500 dernières barres par les signaux du réseau de neurones

Fig. 24. Balance sur les 500 dernières barres par les signaux du réseau de neurones

La balance a été calculée sans tenir compte de l’écart, du dérapage et d’autres réalités d’un marché réel.

Maintenant, comparez avec la balance qui aurait été obtenue à partir des signaux idéaux de ZZ. La ligne rouge est la balance par les signaux du réseau de neurones :

> bal.zz<-cumsum(tail(price[ , 'CO'], 500) * new.y)
> plot(bal.zz,  t = "l")
> lines(bal,  col = 2)

Fig. 25. Balance sur les 500 derniers bars par les signaux du réseau de neurones et les signaux ZigZag

Fig. 25. Équilibrer sur les 500 dernières barres par les signaux du réseau de neurones et les signaux ZigZag

Il y a un potentiel d’amélioration.

Écrivez deux fonctions pour faciliter deux fonctions d’assistance pour Estimation() et Test(). La première générera des coefficients Précision/Err et la seconde équilibrera Bal/BalZZ.

Cela permet d’obtenir un résultat en changeant immédiatement certains paramètres du réseau et de voir quels paramètres influencent la qualité du réseau.

Après avoir écrit une fonction de pertinence, les paramètres de réseau optimaux peuvent être trouvés en utilisant un algorithme évolutif (génétique) sans aucune perturbation du processus de trading. Nous n’allons pas y consacrer du temps dans cet article et nous l’examinerons en détail une autre fois.

Vous trouverez ci-dessous la fonction Estimation() calculant les coefficients Err/Précision :

Estimation<-function(X, Y, r = 8/10, m = "random", norm = "spatialSign",
                     h = c(10), act = "tanh", LR = 0.8, Mom = 0.5, 
                     out = "sigm", sae = "linear", Ep = 10, Bs = 50, 
                     CM=F){
  #Indices of the training and test data set
  t<-holdout(Y, ratio = r, mode = m)
  #Parameters of preprocessing
  prepr<-preProcess(X[t$tr,  ], method = norm)
  #Divide into train and test data sets with preprocessing 
  x.tr<-predict(prepr, X[t$tr,  ])
  x.ts<-predict(prepr, X[t$ts,  ])
  y.tr<- Y[t$tr]; y.ts<- Y[t$ts]
  #Train the model
  SAE<-sae.dnn.train(x = x.tr , y = y.tr , hidden = h, 
                     activationfun = act,
                     learningrate = LR, momentum = Mom, 
                      output = out, sae_output = sae, 
                     numepochs = Ep, batchsize = Bs)
  #Obtain a forecast on the test data set
  pr.sae<-nn.predict(SAE, x.ts)
  #Recode it into signals 1,0
  pr<-ifelse(pr.sae>mean(pr.sae), 1, 0)
  #Calculate the Accuracy coefficient or classification error
  if(CM) err<-unname(confusionMatrix(y.ts, pr)$overall[1])
  if(!CM) err<-nn.test(SAE, x.ts, y.ts, mean(pr.sae))
  return(err)
}

Paramètres formels :

  • X – matrice des prédicteurs bruts d’entrée ;
  • Y – vecteur de la variable cible ;
  • r – rapport train/essai ;
  • m – mode d’entraînement de l’échantillon (aléatoire ou conséquent) ;
  • norm – mode de normalisation des paramètres d’entrée ([ -1, 1]= « spatialSign »;[ 0, 1]="plage ») ;
  • h – vecteur avec un certain nombre de neurones dans les couches cachées ;
  • agir – fonction d’activation des neurones cachés ;
  • LR – niveau d’entraînement ;
  • Мом — momentum ;
  • out – fonction d’activation de la couche de sortie ;
  • sae – fonction d’activation de l’autoencodeur ;
  • Ep – nombre d’époques d’entraînement ;
  • B – taille du petit échantillon ;
  • СM– Variable booléenne , si VRAI imprimez la Précision. Sinon Err.

À titre d’exemple, nous allons calculer l’erreur de classification sur l’ensemble de données dt déséquilibré par le réseau avec trois couches cachées contenant chacune 30 neurones :

> Err<-Estimation(X = dt[ ,-ncol(dt)], Y = dt[ ,ncol(dt)], h=c(30, 30, 30), LR= 0.7)
begin to train sae ......
training layer 1 autoencoder ...
training layer 2 autoencoder ...
training layer 3 autoencoder ...
sae has been trained.
begin to train deep nn ......
deep nn has been trained.
> Err
[1] 0.1376263

La fonction Test() calcule la balance par les signaux de prévision ou par les signaux idéaux (ZigZag) :

Testing<-function(dt1, dt2, r=8/10, m = "random", norm = "spatialSign",
                     h = c(10), act = "tanh", LR = 0.8, Mom = 0.5, 
                     out = "sigm", sae = "linear", Ep = 10, Bs=50, 
                     pr = T, bar = 500){
  X<-dt1[  ,-ncol(dt1)]
  Y<-dt1[  ,ncol(dt1)]
  t<-holdout(Y,  ratio = r,  mode = m)
  prepr<-preProcess(X[t$tr,  ], method = norm)
  x.tr<-predict(prepr, X[t$tr,  ])
  y.tr<- Y[t$tr]; 
  SAE<-sae.dnn.train(x = x.tr , y = y.tr , hidden = h, 
                     activationfun = act,
                     learningrate = LR, momentum = Mom, 
                     output = out, sae_output = sae, 
                     numepochs = Ep, batchsize = Bs)
  X<-dt2[ ,-ncol(dt2)]
  Y<-dt2[ ,ncol(dt2)]
  x.ts<-predict(prepr, tail(X, bar))
  y.ts<-tail(Y, bar)
  pr.sae<-nn.predict(SAE, x.ts)
  sig<-ifelse(pr.sae>mean(pr.sae), -1, 1)
  sig.zz<-ifelse(y.ts == 0, 1,-1 )
  bal<-cumsum(tail(price[  ,'CO'], bar) * sig)
  bal.zz<-cumsum(tail(price[  ,'CO'], bar) * sig.zz)
  if(pr) return(bal)
  if(!pr) return(bal.zz)
}

Paramètres formels :

  • dt1 – matrice de la variable d’entrée et cible utilisée pour l’entraînement du réseau ;
  • dt2 - matrice des variables d’entrée et cible utilisées pour tester le réseau ;
  • pr – Variable booléenne, si VRAI imprimez la balance par les signaux de prévision, sinon par ZigZag ;
  • bar - le nombre des derniers bars à utiliser pour calculer la balance.

Calculer l’équilibre sur les 500 dernières barres de notre ensemble de données dt lors de l’entraînement sur l’ensemble de données équilibré dt.b par le réseau de neurones avec les mêmes paramètres que ceux ci-dessus :

> Bal<-Testing(dt.b, dt, h=c(30, 30, 30), LR= 0.7)
begin to train sae ......
training layer 1 autoencoder ...
training layer 2 autoencoder ...
training layer 3 autoencoder ...
sae has been trained.
begin to train deep nn ......
deep nn has been trained.
> plot(Bal, t = "l")
> abline(h = 0)

Fig. 26. Équilibre sur les 500 dernières barres par les signaux du réseau de neurones h(30,30,30)

Fig. 26. Équilibre sur les 500 dernières barres par les signaux du réseau de neurones h(30,30,30)

Si nous comparons le résultat avec la balance obtenue précédemment, nous pouvons voir une amélioration significative. Ce n’est pas le point le plus intéressant ici.

Si nous jetons un coup d’œil au graphique des prix sur les 500 derniers bars, nous pouvons voir quelles parties de celui-ci ont été les mieux acceptées par notre réseau (150-350 bars).

> plot(tail(price[  ,'Close'], 500), t = "l")
> abline(v = c(150,350), col=2)

Fig. 27. Parcelle du prix de fermeture sur les 500 derniers bars

Fig. 27. Parcelle du prix de fermeture sur les 500 derniers bars

Remarque: Lors du décodage des résultats de prévision, nous avons utilisé une version simplifiée supérieure/inférieure à la moyenne, bien que d’autres versions puissent être utilisées.

Si les valeurs sont supérieures à 0,6 ou inférieures à 0,4, le segment instable de 0,4-0,6 est coupé. Des limites de classe plus précises peuvent être obtenues lors de l’étalonnage. Nous en discuterons plus tard.

Notre fonction Test() va être légèrement modifiée si un paramètre supplémentaire dec est sur le point d’être introduit. Cela nous permettra de sélectionner un moyen de décoder (« moyenne » ou « 60/40 ») et de vérifier sur les valeurs prévues l’impact que cela aura sur la balance.

Testing.1<-function(dt1, dt2, r = 8/10, m = "random", norm = "spatialSign",
                     h = c(10), act = "tanh", LR = 0.8, Mom = 0.5, 
                     out = "sigm", sae = "linear", Ep = 10, Bs = 50, 
                     pr = T, bar = 500, dec=1){
  X<-dt1[ ,-ncol(dt1)]
  Y<-dt1[ ,ncol(dt1)]
  t<-holdout(Y, ratio = r, mode = m)
  prepr<-preProcess(X[t$tr, ], method = norm)
  x.tr<-predict(prepr, X[t$tr, ])
  y.tr<- Y[t$tr]; 
  SAE<-sae.dnn.train(x = x.tr , y = y.tr , hidden = h, 
                     activationfun = act,
                     learningrate = LR, momentum = Mom, 
                     output = out, sae_output = sae, 
                     numepochs = Ep, batchsize = Bs)
  X<-dt2[ ,-ncol(dt2)]
  Y<-dt2[ ,ncol(dt2)]
  x.ts<-predict(prepr, tail(X, bar))
  y.ts<-tail(Y, bar)
  pr.sae<-nn.predict(SAE, x.ts)
  #Variant +/- mean
  if(dec == 1) sig<-ifelse(pr.sae>mean(pr.sae), -1, 1)
  #Variant 60/40
  if(dec == 2) sig<-ifelse(pr.sae>0.6, -1, ifelse(pr.sae<0.4, 1, 0))
  sig.zz<-ifelse(y.ts == 0, 1,-1 )
  bal<-cumsum(tail(price[  ,'CO'], bar) * sig)
  bal.zz<-cumsum(tail(price[  ,'CO'], bar) * sig.zz)
  if(pr) return(bal)
  if(!pr) return(bal.zz)
}

Calculez et évaluez la balance avec la première et la deuxième façon de décoder.

Pour que les résultats se répètent, placez le générateur de nombres pseudo-aléatoires dans la même position.

> set.seed<-1245
> Bal1<-Testing.1(dt.b, dt, h = c(30, 30, 30), LR = 0.7, dec = 1)
begin to train sae ......
training layer 1 autoencoder ...
training layer 2 autoencoder ...
training layer 3 autoencoder ...
sae has been trained.
begin to train deep nn ......
deep nn has been trained.
> set.seed<-1245
> Bal2<-Testing.1(dt.b, dt, h = c(30, 30, 30), LR = 0.7, dec = 2)
begin to train sae ......
training layer 1 autoencoder ...
training layer 2 autoencoder ...
training layer 3 autoencoder ...
sae has been trained.
begin to train deep nn ......
deep nn has been trained.
> plot(Bal2, t = "l")
> lines(Bal1, col = 2)

Fig. 28. Équilibre pour les 500 dernières barres par les signaux du réseau de neurones avec différentes façons de décoder les prévisions

Fig. 28. Équilibre pour les 500 dernières barres par les signaux du réseau de neurones avec différentes façons de décoder les prévisions

Clairement, la balance par la deuxième façon 60/40 semble mieux. Il y a également place à l’amélioration dans ce domaine.

Voici la dernière chose à vérifier. En théorie, un ensemble de plusieurs réseaux de neurones donne un résultat meilleur et plus stable. Nous allons tester un ensemble composé de plusieurs réseaux, qui sont formés sur les mêmes échantillons bien qu’ils puissent être formés sur des échantillons indépendants. Le résultat de la prévision de l’ensemble est une moyenne simple des prévisions de tous les réseaux. Il existe d’autres moyens plus complexes de faire la moyenne.

Nous allons améliorer notre fonction Test() en ajoutant un paramètre supplémentaire — ans=1 spécifiant le nombre de réseaux dans l’ensemble.


3.4.1. Calculs parallèles

Étant donné que les calculs effectués par plusieurs modèles indépendants peuvent facilement être mis en parallèle, nous allons utiliser l’opportunité offerte par le langage R et créer un cluster composé de plusieurs cœurs de processeur ou ordinateurs d’un réseau local, quels que soient les systèmes d’exploitation de ces ordinateurs.

Pour cela, nous avons besoin des packages « foreach » et « doParallel ».. Vous trouverez ci-dessous une fonction très simple qui lancera un cluster pour tous les cœurs de notre processeur.

library(doParallel)
library(foreach)
puskCluster<-function(){
  cores<-detectCores()
  cl<-makePSOCKcluster(cores)
  registerDoParallel(cl)
  clusterSetRNGStream(cl)
 return(cl)
}

Plusieurs points sont clarifiés ci-dessous. Dans les deux premières chaînes, nous chargeons les bibliothèques nécessaires. Elles doivent être préalablement installées sur votre ordinateur. Ensuite, nous définissons le nombre de cœurs qu’il y a dans le processeur, créons un cluster, enregistrons un package pour des calculs parallèles, installons un générateur de nombres pseudo-aléatoires indépendant dans chaque flux de calculs et renvoyons la gestion du cluster. La qualité du générateur de nombres pseudo-aléatoires pour les calculs de chaque modèle est extrêmement importante, bien qu’il s’agit d’un sujet distinct.

Une fois que le cluster a été lancé et que tous les calculs requis ont été effectués, nous devons nous rappeler de l’arrêter :

cl<-puskCluster()
stopCluster(cl) 

Les calculs parallèles vont être effectués par la formule suivante du "foreach" package:

SAE<-foreach(times(ans), .packages = "deepnet") %dopar%  
                sae.dnn.train(x = x.tr , y = y.tr , hidden = h, 
                        activationfun = act,
                        learningrate = LR, momentum = Mom, 
                        output = out, sae_output = sae, 
                        numepochs = Ep, batchsize = Bs)

times(an) est un nombre de réseaux que nous voulons obtenir et .packages pointe vers le package pour prendre la fonction calculée.

Le résultat a une forme de liste et contient le nombre de réseaux formés dont nous avons besoin.

Ensuite, nous avons besoin des prévisions de chaque réseau et calculons la moyenne.

pr.sae<-(foreach(i = 1:ans, .combine = "+") %do%  nn.predict(SAE[[i]], x.ts))/ans

Ici i est un vecteur des indices de réseau entraînés,.combine="+ » spécifie sous quelle forme les prédictions renvoyées dans tous les réseaux de neurones sont censées être renvoyées. Dans ce cas, nous devions renvoyer une somme et effectuer ces calculs séquentiellement, et non de manière parallèle (opérateur %do%). La somme obtenue va être divisée par le nombre de réseaux de neurones et ce sera le résultat final. C’est agréable et simple.

Calculer l’équilibre obtenu à partir d’ensembles constitués de 3 et 4 réseaux de neurones avec les mêmes paramètres que ceux ci-dessus et en utilisant la méthode de décodage 60/40. Comparez avec les résultats sur un réseau de neurones. Pour évaluer l’efficacité des calculs parallèles, augmentez le nombre d’époques à 300 et chronométrez le processus d’obtention de la prévision.

1. Un réseau de neurones :

> system.time(Bal21<-Testing.1(dt.b, dt, h = c(30, 30, 30), LR = 0.7, dec = 2, Ep=300))
begin to train sae ......
training layer 1 autoencoder ...
####loss on step 10000 is : 0.000057
####loss on step 20000 is : 0.000043
training layer 2 autoencoder ...
####loss on step 10000 is : 0.000081
####loss on step 20000 is : 0.000086
training layer 3 autoencoder ...
####loss on step 10000 is : 0.000072
####loss on step 20000 is : 0.000066
sae has been trained.
begin to train deep nn ......
####loss on step 10000 is : 0.069451
####loss on step 20000 is : 0.079629
deep nn has been trained.
   user  system elapsed 
 115.78    0.00  116.96 
> plot(Bal21, t = "l")
> abline(h = 0)

2. Ensemble de 3 réseaux de neurones :

> system.time(Bal41<-Testing.2(dt.b, dt, h = c(30, 30, 30), LR = 0.7, Ep=300, dec = 2, ans=3))
   user  system elapsed 
   0.22    0.06  233.64 
> lines(Bal41, col=4)

3. Ensemble de 4 réseaux de neurones :

> system.time(Bal44<-Testing.2(dt.b, dt, h = c(30, 30, 30), LR = 0.7, Ep=300, dec = 2, ans=4))
   user  system elapsed 
   0.13    0.03  247.86 
> lines(Bal44, col=2)

Le temps d’exécution au calcul parallèle est optimal si le nombre de flux est multiple au nombre de cœurs. J’ai utilisé 2 cœurs.

Cela dit, il n’y a pas d’avantages significatifs dans la balance. Sur le graphique ci-dessous, le graphique bleu désigne 3 réseaux, le rouge - 4 réseaux et le noir - un réseau.

Fig. 29. Balance sur les 500 derniers bars par les signaux des ensembles constitués de 3 et 4 réseaux de neurones et d’un réseau

Fig. 29. Balance sur les 500 derniers bars par les signaux des ensembles constitués de 3 et 4 réseaux de neurones et d’un réseau

En général, le résultat dépend de nombreux paramètres, à commencer par les données d’entrée et de sortie, la façon de les normaliser, le nombre de couches cachées et le nombre de neurones dans ces couches, le niveau d’entraînement, le nombre d’époques d’entraînement et bien d’autres.

Trois derniers exemples. Calculez la balance sur les 1000 derniers bars avec trois réseaux de neurones avec différents nombres de neurones cachés dans trois couches cachées.

> system.time(Bal0<-Testing.1(dt.b, dt, h = c(30, 30, 30), LR = 0.7, dec = 2, Ep=300, bar=1000))
begin to train sae ......
training layer 1 autoencoder ...
####loss on step 10000 is : 0.000054
####loss on step 20000 is : 0.000044
training layer 2 autoencoder ...
####loss on step 10000 is : 0.000078
####loss on step 20000 is : 0.000079
training layer 3 autoencoder ...
####loss on step 10000 is : 0.000090
####loss on step 20000 is : 0.000072
sae has been trained.
begin to train deep nn ......
####loss on step 10000 is : 0.072633
####loss on step 20000 is : 0.057917
deep nn has been trained.
   user  system elapsed 
 116.09    0.02  116.26 
> max(Bal0)
[1] 0.04725
> plot(Bal0, t="l")
> tail(Bal0,1)
[1] 0.03514

Le profit maximum est de 472 points, sur le dernier bar de 351 points. Sur le graphique, il est dessiné en noir.

> system.time(Bal0<-Testing.1(dt.b, dt, h = c(13, 8, 5), LR = 0.7, dec = 2, Ep=300, bar=1000))
begin to train sae ......
training layer 1 autoencoder ...
####loss on step 10000 is : 0.005217
####loss on step 20000 is : 0.004846
training layer 2 autoencoder ...
####loss on step 10000 is : 0.051324
####loss on step 20000 is : 0.046230
training layer 3 autoencoder ...
####loss on step 10000 is : 0.023292
####loss on step 20000 is : 0.026113
sae has been trained.
begin to train deep nn ......
####loss on step 10000 is : 0.057788
####loss on step 20000 is : 0.056932
deep nn has been trained.
   user  system elapsed 
  64.04    0.01   64.24 
Warning message:
In sae$encoder[[i - 1]]$W[[1]] %*% t(train_x) + sae$encoder[[i -  :
  longer object length is not a multiple of shorter object length
> lines(Bal0, col="blue")

Il s’agit clairement d’une variation inefficace.

La troisième variante :

> system.time(Bal0<-Testing.1(dt.b, dt, h = c(50, 50, 50), LR = 0.7, dec = 2, Ep=300, bar=1000))
begin to train sae ......
training layer 1 autoencoder ...
####loss on step 10000 is : 0.000018
####loss on step 20000 is : 0.000013
training layer 2 autoencoder ...
####loss on step 10000 is : 0.000062
####loss on step 20000 is : 0.000048
training layer 3 autoencoder ...
####loss on step 10000 is : 0.000053
####loss on step 20000 is : 0.000055
sae has been trained.
begin to train deep nn ......
####loss on step 10000 is : 0.096490
####loss on step 20000 is : 0.084860
deep nn has been trained.
   user  system elapsed 
 186.18    0.00  186.39 
> lines(Bal0, col="red")
> max(Bal0)
[1] 0.0543

Fig. 30. Balance sur les 1000 derniers bars par les signaux de trois réseaux de neurones avec différents nombres de neurones cachés

Fig. 30. Balance sur les 1000 derniers bars par les signaux de trois réseaux de neurones avec différents nombres de neurones cachés

Les résultats montrent que la troisième variante est la meilleure des trois avec un bénéfice maximum de 543 points. Nous avons seulement changé le nombre de neurones cachés et cela a conduit à une amélioration significative. La recherche des paramètres optimaux doit être effectuée à l’intermédiaire d’algorithmes évolutifs. Il appartient au lecteur d’explorer. 

Il convient de garder à l’esprit que l’algorithme de l’auteur n’a pas été entièrement implémenté dans ce package.


4. L’implémentation (Indicateur et Expert Advisor)

Maintenant, nous allons écrire un programme pour l’indicateur et l’Expert Advisor en utilisant un réseau profond pour recevoir des signaux de trading.

Il y a deux façons pour une telle mise en œuvre :

  • La première. L’entraînement du réseau de neurones est effectué dans Rstudio de façon manuelle. Après avoir obtenu des résultats acceptables, enregistrez le réseau dans le catalogue approprié. Ensuite, lancez l’EA et l’indicateur sur le graphique. L’EA chargera le réseau formé. L’indicateur prépare un vecteur de nouvelles données d’entrée sur chaque nouveau bar et le transmet à l’EA. L’EA présente les données du réseau, reçoit un signal et agit ensuite dessus. L’EA poursuit ses activités habituelles telles que les ordres d’ouverture et de fermeture, le suivi, etc. L’objectif de l’indicateur est de préparer et de transmettre à l’EA de nouvelles données d’entrée sur chaque nouveau bar et, surtout, de présenter les signaux prévus par le réseau sur un graphique. La pratique montre que le contrôle visuel est le moyen le plus efficace d’évaluer un réseau de neurones.
  • Deuxièmefaçon. Lancez l’EA et l’indicateur sur le graphique. Au premier lancement, l’indicateur transmet à l’EA un vaste ensemble préparé de données d’entrée et de sortie. L’EA lance l’entraînement, le test et la sélection du meilleur réseau de neurones. Après cela, le travail continue comme dans la première façon.

Nous allons écrire la liaison indicateur-EA en suivant le premier algorithme. EA avec un minimum d’arcs et de fioritures.

Pourquoi est-ce si difficile ? Cette méthode de mise en œuvre permet de connecter plusieurs indicateurs placés sur différents symboles/délais à un EA et de travailler avec eux en conséquence. Pour cela, l’EA doit passer par une petite modernisation. Nous en reparlerons plus tard.

Voici la structure de l’interaction entre l’indicateur et l’EA :

Fig. 31. Structure de l’interaction entre l’indicateur et l’EA

Fig. 31. Structure de l’interaction entre l’indicateur et l’EA

4.1. Entraînement et sauvegarde du modèle

En utilisant l’indicateur placé sur le graphique de notre intérêt, obtenez les données sources nécessaires. Pour cela, placez l’indicateur sur le graphique, après avoir défini une variable d’entrée send=false, c’est-à-dire que la représentation visuelle n’est pas censée être envoyée au serveur. Au premier lancement sur ce symbole ou cette période, l’indicateur consiste à créer les répertoires suivants /Symbol/TF/Test_Data/ dans le fichier de données du terminal (/MQL4/Files).

Une telle organisation des répertoires donne l’occasion de ne pas rassembler les résultats des expériences lors de l’entraînement préliminaire des modèles et de ne pas écraser les anciennes données par de nouvelles. Les résultats intermédiaires seront stockés dans le répertoire /Symbol/TF/Test_Data/ et le modèle que l’EA va utiliser pour le travail sera situé dans /Symbol/TF/ (il devra y être placé manuellement). Le même résultat sera au premier lancement sur un nouveau symbole ou sur le délai de l’EA.

Donc, pour EURUSD, М30, il y a 4000 bars le 14.10.2014. Nous avons besoin de la trame de données dt[].

Classes de balance :

> dt.b<-Balancing(dt)
> table(dt.b[ ,ncol(dt.b)])
   0    1 
2288 2288

Maintenant, avec la fonction précédemment écrite Testing.1(),, entraînez le réseau de neurones profond avec 500 et 300 époques et évaluez l’équilibre obtenu sur les 500 dernières barres par les signaux prévus par réseau de neurones.

> system.time(bal<-Testing.1(dt.b, dt, h = c(50, 50, 50), LR = 0.7, dec = 2, Ep=500, bar=500))
begin to train sae ......
training layer 1 autoencoder ...
####loss on step 10000 is : 0.000017
####loss on step 20000 is : 0.000015
####loss on step 30000 is : 0.000015
training layer 2 autoencoder ...
####loss on step 10000 is : 0.000044
####loss on step 20000 is : 0.000041
####loss on step 30000 is : 0.000039
training layer 3 autoencoder ...
####loss on step 10000 is : 0.000042
####loss on step 20000 is : 0.000042
####loss on step 30000 is : 0.000036
sae has been trained.
begin to train deep nn ......
####loss on step 10000 is : 0.089417
####loss on step 20000 is : 0.043276
####loss on step 30000 is : 0.069399
deep nn has been trained.
   user  system elapsed 
 267.59    0.08  269.37 
> plot(bal, t="l")

Enregistrez le réseau de neurones sous un autre nom et entraînez-en un autre

> SAE1<-SAE
> system.time(bal<-Testing.1(dt.b, dt, h = c(50, 50, 50), LR = 0.7, dec = 2, Ep=300, bar=500))
begin to train sae ......
training layer 1 autoencoder ...
####loss on step 10000 is : 0.000020
####loss on step 20000 is : 0.000016
training layer 2 autoencoder ...
####loss on step 10000 is : 0.000050
####loss on step 20000 is : 0.000050
training layer 3 autoencoder ...
####loss on step 10000 is : 0.000051
####loss on step 20000 is : 0.000043
sae has been trained.
begin to train deep nn ......
####loss on step 10000 is : 0.083888
####loss on step 20000 is : 0.083941
deep nn has been trained.
   user  system elapsed 
 155.32    0.02  156.25 
> lines(bal, col=2)

Jetez un coup d’œil aux graphiques de balance (le dernier résultat surligné en rouge).

Fig. 32. Balance sur les 500 derniers bars par les signaux de réseaux de neurones entraînés en 500 et 300 époques

Fig. 32. Balance sur les 500 derniers bars par les signaux de réseaux de neurones entraînés en 500 et 300 époques

Comme nous pouvons le constater, le réseau de neurones formé à 300 époques, a montré un meilleur résultat que le réseau formé à 500 époques.

Le temps d’entraînement de ces dernières est adapté à un recyclage rapide lors d’une session de trading sur cette période.

Pour poursuivre le travail sur un graphique réel, nous avons besoin de deux objets: le modèle entraîné "SAE" et les paramètres de normalisation "prepr" pour les données d’entrée. Enregistrez-les dans le répertoire correspondant, dans mon cas il s’agit de « D:/Alpari Limited MT4/MQL4/Files/EURUSD/M30/Test_2014-10-14 ». Ceci est défini et fonctionne comme un travail, si vous avez ouvert dans Rstudio la zone de travail « i_SAE_EURUSD_30.Rdata » enregistrée par l’indicateur.

save(SAE, prepr, file="SAE.model")

Dans le fichier"SAE.model", nous avons enregistré le modèle lui-même et les paramètres de normalisation. Utiliser le modèle sans ceux-ci n’a pas de sens. Vous pouvez expérimenter et enregistrer les modèles que vous aimez tous les jours. Ils seront enregistrés dans les dossiers « /File/Symbol/TF/Test_Data ». Pour que l’EA utilise le modèle, placez manuellement le fichier « SAE.model » dans le dossier « File/Symbol/TF/ ». Ce dossier ne peut contenir qu’un seul modèle et l’EA l’utilisera pour le travail.

Après avoir chargé le fichier « SAE.model », l’EA charge ces objets dans la zone de travail pour les utiliser pendant le travail. À ce stade, la partie manuelle du travail est terminée, vous pouvez placer l’indicateur-EA sur le graphique et le tester en temps réel.

Pour évaluer l’efficacité des travaux de l’EA, des critères quantitatifs sont requis. Le coefficient de précision n’est pas tout à fait adapté à cet effet.

La moyenne du ratio de prévision de la balance reçu par ZigZag et le rapport de la balance sur le dernier bar au nombre de bars. Dans notre cas, voici la balance par ZigZag :

sig.zz<-ifelse(tail(dt[  , ncol(dt)], 500) == 0, 1, -1)
bal.zz<-cumsum(tail(price[  , 'CO'], 500) * sig.zz)
Kzz<-mean(bal.zz / bal)
> Kzz
[1] 0.9173312

C’est un score très élevé mais il est relatif.

Si nous voyons à quoi cela ressemble au fil du temps, nous pouvons voir que pour les 50 à 100 premiers bars, il s’agit d’un index instable, bien que plus tard, il devienne presque constant. Les statistiques sont ci-dessous :

> plot(bal/bal.zz, t="l")
> summary(bal/bal.zz)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
-15.2500   0.7341   0.7844   0.9173   0.8833  55.0000

Fig. 33. Rapport entre la balance prévisionnelle et la balance obtenue par ZigZag

Fig. 33. Rapport entre la balance prévisionnelle et la balance obtenue par ZigZag

Le second est plus précis car il montre combien de points de profit il y a pour une barre sur un tronçon N bars de long.

Par exemple, pour l’équilibre par réseau de neurones prévu sur l’étendue de 500 barres :

> Kb<-tail(bal,1)/length(bal)*10^Dig
> Kb
[1] 11.508

par signaux ZigZag :

> Kbz<-tail(bal.zz,1)/length(bal)*10^Dig
> Kbz
[1] 13.784

Lorsque la limite inférieure d’efficacité sur l’un des paramètres est définie, nous connaissons le moment où nous pouvons entraîner à nouveau le réseau de neurones ou optimiser ses paramètres.

L’EA affichera les paramètres suivants sur le graphique : OP – opération exécutée, Acc – Précision, K – est Kb défini précédemment, Kmax – le même paramètre que Kb mais défini sur la balance haute et donne une idée de combien ce paramètre diffère sur le dernier bar du maximum.


4.2. Ordre d’installation et de lancement

Dans l’archive ci-jointe SAE.zip vous pouvez trouver :

  1. L’indicateur i_SAE.mq4, placé dans le dossier ~/MQL4/Indicators/
  2. Le e_SAE.mq4 EA, placé dans le dossier ~/MQL4/Experts/
  3. La bibliothèque mt4Rb7.dll, placée dans le dossier ~/MQL4/Libraries/.
  4. Le fichier d’en-tête mt4Rb7.mqh, placé dans le dossier ~/MQL4/Include/. La bibliothèque et le fichier d’en-tête ont été développés et aimablement fournis par Bernd Kreuss. Le nom inclut l’index de la dernière modification (b7). Quand il y a beaucoup de versions avec les mêmes noms, il y a des confusions qui prennent beaucoup de temps à corriger.
  5. Scripts sur R : i_SAE.r (script d’indicateur principal), i_SAE_fun.r (fonctions du script indicateur), e_SAE.r (script EA), e_SAE_init.r (script d’initialisation de l’EA), SAE_SetDir.r (script de validation et de création des répertoires nécessaires). Comme les scripts ne dépendent ni du symbole, ni d’un délai, ils peuvent être situés dans un répertoire séparé. Dans mon cas, il s’agit de « C:Rdata/SAE/ ». Le répertoire « C:Rdata/ » contient différents scripts qui ne sont attachés à aucun projet en question. Si vous placez des scripts dans un dossier différent du mien, apportez les corrections appropriées dans l’indicateur et EA qui sont corrects vers le chemin des scripts.
  6. SAE.model est un fichier avec le modèle « SAE » et les paramètres de normalisation « prepr ». Le modèle a été formé sur EURUSD (M30), dernière date 14.10.14. Le processus d’entraînement a été décrit ci-dessus.

N’oubliez pas non plus le chemin vers le répertoire où la langue R a été stockée sur votre ordinateur.

Il est préférable de suivre l’ordre suivant pour commencer à travailler. Placez l’EA sur le graphique. Si vous décidez de placer un EA sur un autre symbole, un port différent des serveurs précédemment lancés doit être spécifié. Par exemple, le port 8886 (par défaut le port 8888).

Remarque.: C’est un moyen absolument inefficace. Chaque serveur a une taille de 120-130 Mo. C’est ce que sont les choses aujourd’hui.

Après l’initialisation normale de l’EA, l’alerte « Aucun résultat de calcul ! Symbole » apparaîtra. Installez ensuite l’indicateur avec le paramètre externe send = true et le port de serveur spécifié auquel l’indicateur doit se connecter (voir ci-dessus). Si tout fonctionne correctement, les données réelles « opération », Précision, K et Kmax apparaîtront dans la chaîne de sortie et le trading commencera.

Un contrôle efficace du processus peut être mieux facilité à partir du Gestionnaire des tâches Windows. Si Rterm n’apparaît pas dans la liste après le lancement de l’EA ou de l’indicateur, le processus R a été interrompu. La principale raison de ces perturbations est une erreur de syntaxe dans les scripts, une incompatibilité de la longueur du vecteur MQL récepteur et du vecteur extrait de Rterm.

Les scripts peuvent être débogués dans Rstudio en lançant les scripts ligne par ligne du début à la fin.

Malheureusement, je n’ai pas pu lancer l’EA dans le testeur, il doit donc être testé sur un compte démo.


4.3. Moyens et méthodes d’amélioration des caractéristiques qualitatives

  1. Modifier l’ensemble des indicateurs utilisés à l’entrée.
  2. Modifier le mode de normalisation des données d’entrée.
  3. Optimiser les paramètres du « superviseur » et les indicateurs à l’entrée.
  4. Modifier le codage de la variable d’entrée de la matrice avec deux colonnes. Calibrer le signal de prévision.
  5. Optimiser les paramètres du réseau (nombre de neurones dans les couches cachées, nombre de couches, niveau d’apprentissage, nombre d’époques).

Conclusion

Nous avons créé, entraîné et testé des modèles de réseau profond avec initialisation des poids des neurones dans les couches cachées de SAE. Les réseaux se recyclent très rapidement et cela permet de les recycler sans perturber le processus de trading.

Les résultats obtenus par les réseaux de neurones sont moyens en termes de métriques. Le résultat idéal n’était pas l’objectif initial.

En utilisant un tel modèle et une évaluation permanente du coefficient d’efficacité, le modèle peut être réformé et optimisé sans perturber le processus de trading.

Pièce jointe:

  1. SAE.zip - indicateur, EA et fichiers d’accompagnement.
  2. R_intro.zip - documentation sur R et Rstudio en russe.
  3. DeepLearning.zip - documentation sur le Deep Learning (apprentissage profond).

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

Fichiers joints |
DeepLearning.zip (6542.81 KB)
R-intro.zip (15278.8 KB)
sae.zip (394.31 KB)
Le MQL5 Cookbook : Traitement de l'événement de TradeTransaction Le MQL5 Cookbook : Traitement de l'événement de TradeTransaction
Cet article considère les capacités du langage MQL5 du point de vue de la programmation par évènement. Le plus grand avantage de cette approche est que le programme peut recevoir des informations sur la mise en œuvre progressive d'une opération de trade. L'article contient également un exemple de réception et de traitement d'informations sur les opérations de trade en cours à l'aide du gestionnaire d'événements TradeTransaction. À mon avis, une telle approche peut être utilisée pour copier des transactions d'un terminal à un autre.
Comment nous avons développé le service MetaTrader Signals et le trading social Comment nous avons développé le service MetaTrader Signals et le trading social
Nous continuons d’améliorer le service des Signaux, d’améliorer les mécanismes, d’ajouter de nouvelles fonctions et de corriger les défauts. Le service de signaux MetaTrader de 2012 et le service de signaux MetaTrader actuel sont comme deux services complètement différents. Actuellement, nous mettons en œuvre un service Cloud d’hébergement virtuel qui consiste en un réseau de serveurs pour prendre en charge des versions spécifiques du terminal client MetaTrader.
Le MQL5 Cookbook : Gestion des événements du graphique personnalisés Le MQL5 Cookbook : Gestion des événements du graphique personnalisés
Cet article examine les aspects de la conception et du développement d'un système d'événements de graphique personnalisé dans l'environnement MQL5. Un exemple d'approche de la classification des événements peut également être trouvé ici, ainsi qu'un code de programme pour une classe d'événements et une classe de gestionnaire d'événements personnalisés.
Analyse de régression de l'influence des données macroéconomiques sur la fluctuation des prix des devises Analyse de régression de l'influence des données macroéconomiques sur la fluctuation des prix des devises
Cet article examine l'application de l'analyse de régression multiple aux statistiques macroéconomiques. Il donne également un aperçu de l'évaluation de l'impact des statistiques sur la fluctuation du taux de change sur la base de l'exemple de la paire de devises EURUSD. Une telle évaluation permet d'automatiser l'analyse fondamentale qui devient accessible même aux traders débutants.