
Utilisation des Indicateurs MetaTrader 5 avec le Cadre d'Apprentissage Automatique ENCOG pour la Prédiction de Séries Chronologiques
Introduction
Cet article présentera MetaTrader 5 vers ENCOG - Réseau avancé neuronal et cadre d’apprentissage automatique élaboré par Heaton Research. Il existe des méthodes décrites précédemment que je connais qui permettent à MetaTrader d'utiliser des techniques d'apprentissage automatique : FANN, NeuroSolutions, Matlab et NeuroShell. J'espère qu ENCOG sera une solution complémentaire puisqu'il s'agit d'un code robuste et bien conçu.
Pourquoi j'ai choisi ENCOG ? Il y a quelques motifs.
- ENCOG est utilisé dans deux autres progiciels de trading commerciaux. L'un est basé sur C#, le second sur JAVA. Cela indique qu'il a déjà été testé pour prédire les données de séries chronologiques financières.
- ENCOG est un logiciel gratuit et de source publique Si vous souhaitez voir ce qui se passe à l'intérieur d'un réseau de neurones, vous pouvez parcourir le code source. C'est ce que j'ai fait pour comprendre certaines parties du problème de prédiction des séries chronologiques. C# est un langage de programmation propre et facile à comprendre.
- ENCOG est très bien documenté. M. Heaton, fondateur de Heaton Research, propose un cours en ligne gratuit sur les réseaux neuronaux, l'apprentissage automatique et l'utilisation d' ENCOG pour prédire les données futures. J'ai parcouru plusieurs de ses cours avant d'écrire cet article. Ils m'ont beaucoup aidé à comprendre les réseaux de neurones artificiels. De plus, il existe des livres électroniques sur la programmation d' ENCOG en JAVA et C# sur le site Web de Heaton Research. Documentation entière d’ ENCOG est disponible en ligne.
- ENCOG n'est pas un projet mort. Au moment de la rédaction de cet article, ENCOG 2.6 est toujours en cours d’élaboration. La feuille de route ENCOG 3.0 a été récemment publiée.
- ENCOG est robuste. Il est bien conçu, peut utiliser plusieurs noyaux de processeur et le multithreading pour accélérer les calculs du réseau neuronal. Des parties du code commencent à être transférées pour les calculs compatibles OpenCL - GPU.
- Fonctionnalités actuellement prises en charge par ECNOG :
Types d'Apprentissage Automatique
- Réaction Anticipative et Simple Recurrent (Elman/Jordan)
- Genetic Algorithms
- NEAT
- Probablistic Neural Network/ General Regression Neural Network (PNN/GRNN)
- Self Organizing Map (SOM/Kohonen)
- Simulated Annealing
- Support Vector Machine
Architectures de Réseaux de Neurones
Techniques de Formation
- ADALINE Neural Network
- Théorie de la résonance adaptative 1 (ART1)
- Mémoire associative bidirectionnelle (BAM)
- Boltzmann Machine
- Counterpropagation Neural Network (CPN)
- Elman Réseau de neurones récurrents
- Feedforward Neural Network (Perceptron)
- Hopfield Neural Network
- Jordan Recurrent Neural Network
- Neuroevolution of Augmenting Topologies (NEAT)
- Radial Basis Function Network
- Carte d'auto-organisation récurrente (RSOM)
- Self Organizing Map (Kohonen)
Fonctions d'Activation
- Backpropagation
- Resilient Propagation (RPROP)
- Gradient conjugué mis à l'échelle (SCG)
- Propagation de la règle de mise à jour Manhattan
- Competitive Learning
- Hopfield Learning
- Levenberg-Marquardt Algorithm (LMA)
- Genetic Algorithm Training
- Formation Instar
- Formation Outstar
- ADALINE Training
- Modèles de Formation en Données
- Supervised
- Unsupervised
- Temporel (Prédiction)
- Financier (téléchargements depuisYahoo Finance
- SQL
- XML
- CSV
- Sous-échantillonnage d'images
Techniques de Randomisation
- Compétitif
- Sigmoid
- Hyperbolic Tangent
- Linéaire
- SoftMax
- Tangentiel
- Sin Wave
- Etape
- Bipolaire
- Gaussian
- Randomisation de la plage
- Nombres aléatoires gaussiens
- Fan-In
- Nguyen-Widrow
Fonctionnalités prévues :
- HyperNEAT
- Restrictive Boltzmann Machine (RBN/Deep Belief)
- Réseaux Neuronaux Spiking
Comme vous pouvez le constater, la liste des fonctionnalités est assez longue.
Cet article préliminaire se concentre sur l'architecture de réseau neuronal à réaction anticipative avec la formation Propagation Résiliente (RPROP) . Il couvre également les bases de la préparation des données - le timeboxing et la normalisation pour la prévision des séries chronologiques.
Les connaissances qui m'ont permis d'écrire cet article sont axées sur des tutoriels disponibles sur le site de Heaton Research et des articles très récents sur la prédiction de séries chronologiques financières dans NinjaTrader. Veuillez noter qu 'ENCOG est basé sur JAVA et C#. Sans mon précédent travail, l’écriture de cet article ne serait pas possible Exposer le code C# à MQL5 à l'aide d'exportations non gérées. Cette solution a permis d'utiliser la DLL C# comme pont entre l'indicateur Metatrader 5 et le prédicteur de séries chronologiques ENCOG.
1. Utilisation de valeurs d'indicateurs techniques comme entrées pour un réseau de neurones
Le Réseau de Neurones Artificiels est un algorithme conçu par l'homme qui tente d'émuler le réseau de neurones du cerveau.
Il existe différents types d'algorithmes neuronaux disponibles ainsi qu’une variété d'architectures de réseaux neuronaux. Le domaine de recherche est si vaste qu'il existe des livres entiers consacrés à un seul type de réseau de neurones. Vu que de tels détails sortent du cadre de cet article, je ne peux que recommander de parcourir les didacticiels de Heaton Research ou de lire un livre sur le sujet. Je me concentrerai sur les entrées et les sorties du réseau de neurones à action directe et j'essaierai de décrire l'exemple pratique de prédiction de séries chronologiques financières.
Afin de commencer à prévoir des séries chronologiques financières, nous devons réfléchir à ce que nous devrions fournir au réseau de neurones et à ce que nous pourrions attendre en retour. Dans la plupart des pensées abstraites de la boîte noire, nous réalisons un bénéfice ou une perte en prenant des positions longues ou courtes sur le contrat d'un titre donné et en concluant le deal après un certain temps.
Par l'observation des prix passés d'un titre et des valeurs des indicateurs techniques, nous essayons de prédire le sentiment futur ou la direction des prix afin d'acheter ou de vendre un contrat et de nous assurer que notre décision n'est pas prise en lançant une pièce. La situation ressemble plus moins à la figure ci-dessous :
Figure 1. Prévision de séries chronologiques financières à l'aide d'indicateurs techniques
Nous allons tenter d'obtenir la même chose avec l'intelligence artificielle. Le réseau neuronal tentera de reconnaître les valeurs des indicateurs et décidera s'il y a une chance que le prix monte ou baisse. Comment y parvenir ? Étant donné que nous prévoyons des séries chronologiques financières en utilisant l'architecture de réseau de neurones feed forward,je pense que nous devons faire une introduction à son architecture.
Le réseau de neurones à réaction anticipée est constitué de neurones regroupés en couches. Il doit y avoir au minimum 2 couches : une couche d'entrée qui comporte les neurones d'entrée et une couche de sortie qui comporte les neurones de sortie. Il peut également y avoir des couches cachées entre les couches d'entrée et de sortie. La couche d'entrée peut être simplement considérée comme un tableau de valeurs doubles et la couche de sortie peut être constituée d'un ou plusieurs neurones qui forment également un tableau de valeurs doubles. Veuillez consulter la figure ci-dessous :
Figure 2. Couches de réseau de neurones à réaction anticipative
Les connexions entre les neurones n'ont pas été dessinées afin de simplifier le dessin. Chaque neurone de la couche d'entrée est connecté à un neurone de la couche cachée. Chaque neurone de la couche cachée est connecté à un neurone de la couche de sortie.
Chaque connexion a son poids, qui est aussi une double valeur et une fonction d'activation avec un seuil, qui est responsable de l'activation d'un neurone et de la transmission de l'information au neurone suivant. C'est pourquoi on l'appelle un réseau « Réaction anticipative » - les informations axées sur les sorties de neurones activés sont transmises d'une couche à une autre couche de neurones. Pour des vidéos d'introduction détaillées sur les réseaux de neurones à réaction anticipative, vous pouvez visiter les liens suivants :
- Neural Network Calculation (Part 1): Structure d'anticipation
- Neural Network Calculation (Part 2): Fonctions d'Activation et Calcul de Base
- Calcul de réseau neuronal (partie 3) : Calcul de Réseau de Neurones à Réaction Anticipative
Une fois que vous aurez appris davantage sur l'architecture des réseaux neuronaux et ses mécanismes, vous serez peut-être encore perplexe.
Les principaux problèmes sont :
- Quelles données devons-nous fournir à un réseau de neurones ?
- Comment le nourrir ?
- Comment préparer les données d'entrée pour un réseau de neurones ?
- Comment choisir l'architecture de réseau de neurones ? De combien de neurones d'entrée, de neurones cachés et de neurones de sortie avons-nous besoin ?
- Comment former le réseau ?
- Qu'attendez-vous du résultat ?
2. Avec quelles données alimenter le réseau de neurones
Puisque nous avons affaire à des prévisions financières basées sur les sorties d'indicateurs, nous devons alimenter le réseau avec des valeurs de sortie d'indicateurs. Pour cet article j'ai choisi Stochastic %K, Stochastic Slow %D, and Williams %Rcomme entrées.
Figure 3. Indicateurs techniques utilisés pour la prédiction
Afin d'extraire les valeurs des indicateurs, nous pouvons utiliser les fonctionsiStochastic et iWPR MQL5:
double StochKArr[], StochDArr[], WilliamsRArr[]; ArraySetAsSeries(StochKArr, true); ArraySetAsSeries(StochDArr, true); ArraySetAsSeries(WilliamsRArr, true); int hStochastic = iStochastic(Symbol(), Period(), 8, 5, 5, MODE_EMA, STO_LOWHIGH); int hWilliamsR = iWPR(Symbol(), Period(), 21); CopyBuffer(hStochastic, 0, 0, bufSize, StochKArr); CopyBuffer(hStochastic, 1, 0, bufSize, StochDArr); CopyBuffer(hWilliamsR, 0, 0, bufSize, WilliamsRArr);
Une fois ce code exécuté, trois tableaux StochKArr, StochDArr et WilliamsRArr doivent être remplis avec les valeurs de sortie des indicateurs. En fonction de la taille de l'échantillon d'apprentissage, cela peut aller jusqu'à quelques milliers de valeurs. Veuillez garder à l'esprit que ces deux indicateurs ont été choisis uniquement à des fins éducatives.
Nous vous encourageons à expérimenter avec tous les indicateurs que vous jugez appropriés pour la prédiction. Vous voudrez peut-être alimenter le réseau avec les prix de l'or et du pétrole pour prédire les indices boursiers ou vous pouvez utiliser des paires de devises forex corrélées pour prédire une autre paire de devises.
3. Données d'entrée de timeboxing
Après avoir collecté les données d'entrée de plusieurs indicateurs, nous devons appliquer «timeboxing» l'entrée avant de l'alimenter dans le réseau de neurones. Le timeboxing est une technique qui permet de présenter les entrées pour le réseau sous forme de tranches de données mobiles. Vous pouvez imaginer une boîte en mouvement de données d'entrée avançant sur l'axe du temps. Il y a essentiellement deux étapes impliquées dans cette procédure:
1. Rassembler les données d'entrée de chaque tampon d'indicateur. Nous devons copier le nombre d'éléments INPUT_WINDOW de la position de départ vers le futur. La fenêtre d'entrée est le nombre de barres utilisées pour la prédiction.
Figure 4. Collecte des données de la fenêtre d'entrée à partir du tampon indicateur
Comme vous pouvez le constater dans l'exemple ci-dessus, INPUT_WINDOW équivaut à 4 barres et nous avons copié des éléments dans le tableau I1. I1[0] est le premier élément I1[3] est le dernier. De même, les données doivent être copiées à partir d'autres indicateurs dans des tableaux de taille INPUT_WINDOW. Ce chiffre est valable pour séries chronologiques tableaux avec AS_SERIES flag fixés à vrai.
2. Combinaison de tableaux INPUT_WINDOW en un seul tableau qui alimente la couche d'entrée du réseau neuronal.
Figure 5. Tableaux de fenêtres d'entrée ayant fait l’objet de timeboxing
Il y a 3 indicateurs, d'abord nous prenons la première valeur de chaque indicateur, puis la deuxième valeur de chaque indicateur, et nous continuons jusqu'à ce que la fenêtre de saisie soit remplie comme sur la figure ci-dessus. Un tel tableau combiné à partir de sorties d'indicateurs peut être transmis à la couche d'entrée de notre réseau de neurones. Lorsqu'une nouvelle barre arrive, les données sont découpées par un élément et toute la procédure est répétée. Si vous souhaitez obtenir plus de détails sur la préparation des données pour la prédiction, vous pouvez également voir une vidéosur le thème.
4. Normalisation des données d'entrée
Afin de rendre le réseau de neurones efficace, nous devons normaliser les données. Ceci est nécessaire pour un bon calcul des fonctions d'activation. La normalisation est un processus mathématique qui convertit les données dans la plage 0..1 ou -1..1. Les données normalisées peuvent faire l’objet de dénormalisation, c'est-à-dire reconverties dans la plage d'origine.
La dénormalisation est nécessaire pour décoder la sortie du réseau neuronal sous une forme lisible par l'homme. Heureusement, ENCOG s'occupe de la normalisation et de la dénormalisation, il n'est donc pas nécessaire de l'implémenter. Si vous êtes curieux de savoir comment cela fonctionne, vous pouvez analyser le code suivant :
/** * Normalize the specified value. * @param value The value to normalize. * @return The normalized value. */ public static double normalize(final int value) { return ((value - INPUT_LOW) / (INPUT_HIGH - INPUT_LOW)) * (OUTPUT_HIGH - OUTPUT_LOW) + OUTPUT_LOW; } /** * De-normalize the specified value. * @param value The value to denormalize. * @return The denormalized value. */ public static double deNormalize(final double data) { double result = ((INPUT_LOW - INPUT_HIGH) * data - OUTPUT_HIGH * INPUT_LOW + INPUT_HIGH * OUTPUT_LOW) / (OUTPUT_LOW - OUTPUT_HIGH); return result; }
et lire un article sur la normalisationpour plus de détails.
5. Choix de l'architecture du réseau et du nombre de neurones
Pour un débutant sur le sujet, choisir une architecture de réseau correcte est une partie difficile. Dans cet article, je limite l'architecture du réseau de neurones à réaction anticipative à trois couches : une couche d'entrée, une couche cachée et une couche de sortie. Vous êtes libre d'expérimenter avec un plus grand nombre de couches.
Pour les couches d'entrée et de sortie, nous pourrons compter avec précision le nombre de neurones nécessaires. Pour une couche cachée, nous tenterons de minimiser les erreurs de réseau neuronal en utilisant un algorithme de sélection directe. Vous êtes encouragé à utiliser d'autres méthodes ; il peut y avoir des algorithmes génétiques pour calculer le nombre de neurones.
Une autre méthode utilisée par ENCOG est appelée algorithme de sélection en arrière ou élagage. Il s'agit essentiellement d'évaluer les connexions entre les couches et de supprimer les neurones cachés avec des connexions à pondération nulle. Vous pouvez également l'essayer.
5.1. Couche de neurones d'entrée
En raison du timeboxing, le nombre de neurones dans la couche d'entrée devra être égal au nombre d'indicateurs multiplié par le nombre de barres utilisées pour prédire la barre suivante. Si nous utilisons 3 indicateurs comme entrées et que la taille de la fenêtre d'entrée est égale à 6 barres, la couche d'entrée sera constituée de 18 neurones. La couche d'entrée est alimentée en données préparées par timeboxing.
5.2. Couche de neurones cachés
Le nombre de réseaux cachés doit être estimé en fonction des performances du réseau neuronal entraîné. Il n'y a pas d'équation mathématique simple pour un certain nombre de neurones cachés. Avant d'écrire l'article, j'ai utilisé plusieurs approches d'essais et d'erreurs et j'ai trouvé un algorithme sur le site Web de Heaton Research qui aide à comprendre l'algorithme de sélection directe :
Figure 6. Algorithme de sélection directe pour le nombre de neurones cachés
5.3. Couche de neurones de sortie
Pour nos besoins, le nombre de neurones de sortie est le nombre de barres que nous essayons de prédire. N'oubliez pas que plus le nombre de neurones cachés et de sortie est plus élevé, plus le réseau prend du temps à se former. Dans cet article, je tente de prédire une barre dans le futur, donc la couche de sortie se compose d'un neurone.
6. Exportation des données d'entraînement de MetaTrader 5 vers ENCOG
Encog accepte les fichiers CSV pour la formation sur les réseaux neuronaux.
J'ai examiné le format de fichier exporté d'un autre logiciel de trading vers ENCOG et implémenté le script MQL5 qui prépare le même format de fichier pour la formation. Je présenterai d'abord l'exportation d'un indicateur et poursuivrai plus tard avec plusieurs indicateurs.
La première ligne de données est un en-tête séparé par des virgules :
DATE,TIME,CLOSE,Indicator_Name1,Indicator_Name2,Indicator_Name3
Les trois premières colonnes comportent les valeurs de date, d'heure et de fermeture, les colonnes suivantes comportent les noms des indicateurs. Les prochaines lignes du fichier de formation doivent comprendre des données séparées par des virgules, les valeurs des indicateurs doivent être écrites au format scientifique :
20110103,0000,0.93377000,-7.8970208860e-002
Veuillez observer le script prêt à l'emploi pour un indicateur ci-dessous.
//+------------------------------------------------------------------+ //| ExportToEncog.mq5 | //| Copyright 2011, Investeo.pl | //| http:/Investeo.pl | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, Investeo.pl" #property link "http:/Investeo.pl" #property version "1.00" //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ // Export Indicator values for NN training by ENCOG extern string IndExportFileName = "mt5export.csv"; extern int trainSize = 400; extern int maPeriod = 210; MqlRates srcArr[]; double expBullsArr[]; void OnStart() { //--- ArraySetAsSeries(srcArr, true); ArraySetAsSeries(expBullsArr, true); int copied = CopyRates(Symbol(), Period(), 0, trainSize, srcArr); if (copied!=trainSize) { Print("Not enough data for " + Symbol()); return; } int hBullsPower = iBullsPower(Symbol(), Period(), maPeriod); CopyBuffer(hBullsPower, 0, 0, trainSize, expBullsArr); int hFile = FileOpen(IndExportFileName, FILE_CSV | FILE_ANSI | FILE_WRITE | FILE_REWRITE, ",", CP_ACP); FileWriteString(hFile, "DATE,TIME,CLOSE,BullsPower\n"); Print("Exporting indicator data to " + IndExportFileName); for (int i=trainSize-1; i>=0; i--) { string candleDate = TimeToString(srcArr[i].time, TIME_DATE); StringReplace(candleDate,".",""); string candleTime = TimeToString(srcArr[i].time, TIME_MINUTES); StringReplace(candleTime,":",""); FileWrite(hFile, candleDate, candleTime, DoubleToString(srcArr[i].close), DoubleToString(expBullsArr[i], -10)); } FileClose(hFile); Print("Indicator data exported."); } //+------------------------------------------------------------------+
Le fichier de résultats pouvant être utilisé pour la formation doit ressembler à la sortie suivante :
DATE,TIME,CLOSE,BullsPower 20110103,0000,0.93377000,-7.8970208860e-002 20110104,0000,0.94780000,-6.4962292188e-002 20110105,0000,0.96571000,-4.7640374727e-002 20110106,0000,0.96527000,-4.4878854587e-002 20110107,0000,0.96697000,-4.6178012364e-002 20110110,0000,0.96772000,-4.2078647318e-002 20110111,0000,0.97359000,-3.6029181466e-002 20110112,0000,0.96645000,-3.8335729509e-002 20110113,0000,0.96416000,-3.7054869514e-002 20110114,0000,0.96320000,-4.4259373120e-002 20110117,0000,0.96503000,-4.4835729773e-002 20110118,0000,0.96340000,-4.6420936126e-002 20110119,0000,0.95585000,-4.6868984125e-002 20110120,0000,0.96723000,-4.2709941621e-002 20110121,0000,0.95810000,-4.1918330800e-002 20110124,0000,0.94873000,-4.7722659418e-002 20110125,0000,0.94230000,-5.7111591557e-002 20110126,0000,0.94282000,-6.2231529077e-002 20110127,0000,0.94603000,-5.9997865295e-002 20110128,0000,0.94165000,-6.0378312069e-002 20110131,0000,0.94414000,-6.2038328069e-002 20110201,0000,0.93531000,-6.0710334438e-002 20110202,0000,0.94034000,-6.1446445012e-002 20110203,0000,0.94586000,-5.2580791504e-002 20110204,0000,0.95496000,-4.5246755566e-002 20110207,0000,0.95730000,-4.4439392954e-002
Revenir à l'exemple d'article d'origine avec Stochastic and Williams' R, nous devons exporter trois colonnes séparées par des virgules, chaque colonne comporte des valeurs d'indicateur distinctes, nous devons donc développer le fichier et ajouter des tampons supplémentaires :
//+------------------------------------------------------------------+ //| ExportToEncog.mq5 | //| Copyright 2011, Investeo.pl | //| http:/Investeo.pl | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, Investeo.pl" #property link "http:/Investeo.pl" #property version "1.00" //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ // Export Indicator values for NN training by ENCOG extern string IndExportFileName = "mt5export.csv"; extern int trainSize = 2000; MqlRates srcArr[]; double StochKArr[], StochDArr[], WilliamsRArr[]; void OnStart() { //--- ArraySetAsSeries(srcArr, true); ArraySetAsSeries(StochKArr, true); ArraySetAsSeries(StochDArr, true); ArraySetAsSeries(WilliamsRArr, true); int copied = CopyRates(Symbol(), Period(), 0, trainSize, srcArr); if (copied!=trainSize) { Print("Not enough data for " + Symbol()); return; } int hStochastic = iStochastic(Symbol(), Period(), 8, 5, 5, MODE_EMA, STO_LOWHIGH); int hWilliamsR = iWPR(Symbol(), Period(), 21); CopyBuffer(hStochastic, 0, 0, trainSize, StochKArr); CopyBuffer(hStochastic, 1, 0, trainSize, StochDArr); CopyBuffer(hWilliamsR, 0, 0, trainSize, WilliamsRArr); int hFile = FileOpen(IndExportFileName, FILE_CSV | FILE_ANSI | FILE_WRITE | FILE_REWRITE, ",", CP_ACP); FileWriteString(hFile, "DATE,TIME,CLOSE,StochK,StochD,WilliamsR\n"); Print("Exporting indicator data to " + IndExportFileName); for (int i=trainSize-1; i>=0; i--) { string candleDate = TimeToString(srcArr[i].time, TIME_DATE); StringReplace(candleDate,".",""); string candleTime = TimeToString(srcArr[i].time, TIME_MINUTES); StringReplace(candleTime,":",""); FileWrite(hFile, candleDate, candleTime, DoubleToString(srcArr[i].close), DoubleToString(StochKArr[i], -10), DoubleToString(StochDArr[i], -10), DoubleToString(WilliamsRArr[i], -10) ); } FileClose(hFile); Print("Indicator data exported."); } //+------------------------------------------------------------------+
Le fichier de résultats doit comporter toutes les valeurs d'indicateur :
DATE,TIME,CLOSE,StochK,StochD,WilliamsR 20030707,0000,1.37370000,7.1743119266e+001,7.2390220187e+001,-6.2189054726e-001 20030708,0000,1.36870000,7.5140977444e+001,7.3307139273e+001,-1.2500000000e+001 20030709,0000,1.35990000,7.3831775701e+001,7.3482018082e+001,-2.2780373832e+001 20030710,0000,1.36100000,7.1421933086e+001,7.2795323083e+001,-2.1495327103e+001 20030711,0000,1.37600000,7.5398313027e+001,7.3662986398e+001,-3.9719626168e+000 20030714,0000,1.37370000,7.0955352856e+001,7.2760441884e+001,-9.6153846154e+000 20030715,0000,1.38560000,7.4975891996e+001,7.3498925255e+001,-2.3890784983e+000 20030716,0000,1.37530000,7.5354107649e+001,7.4117319386e+001,-2.2322435175e+001 20030717,0000,1.36960000,7.1775345074e+001,7.3336661282e+001,-3.0429594272e+001 20030718,0000,1.36280000,5.8474576271e+001,6.8382632945e+001,-3.9778325123e+001 20030721,0000,1.35400000,4.3498596819e+001,6.0087954237e+001,-5.4946524064e+001 20030722,0000,1.36130000,2.9036761284e+001,4.9737556586e+001,-4.5187165775e+001 20030723,0000,1.34640000,1.6979405034e+001,3.8818172735e+001,-6.5989159892e+001 20030724,0000,1.34680000,1.0634573304e+001,2.9423639592e+001,-7.1555555556e+001 20030725,0000,1.34400000,9.0909090909e+000,2.2646062758e+001,-8.7500000000e+001 20030728,0000,1.34680000,1.2264922322e+001,1.9185682613e+001,-8.2705479452e+001 20030729,0000,1.35250000,1.4960629921e+001,1.7777331716e+001,-7.2945205479e+001 20030730,0000,1.36390000,2.7553336360e+001,2.1035999930e+001,-5.3979238754e+001 20030731,0000,1.36990000,4.3307839388e+001,2.8459946416e+001,-4.3598615917e+001 20030801,0000,1.36460000,5.6996412096e+001,3.7972101643e+001,-5.2768166090e+001 20030804,0000,1.34780000,5.7070193286e+001,4.4338132191e+001,-8.1833910035e+001 20030805,0000,1.34770000,5.3512705531e+001,4.7396323304e+001,-8.2006920415e+001 20030806,0000,1.35350000,4.4481132075e+001,4.6424592894e+001,-7.1972318339e+001 20030807,0000,1.35020000,3.3740028156e+001,4.2196404648e+001,-7.7681660900e+001 20030808,0000,1.35970000,3.0395426394e+001,3.8262745230e+001,-6.1245674740e+001 20030811,0000,1.35780000,3.4155781326e+001,3.6893757262e+001,-6.4532871972e+001 20030812,0000,1.36880000,4.3488943489e+001,3.9092152671e+001,-4.5501730104e+001 20030813,0000,1.36690000,5.1160443996e+001,4.3114916446e+001,-4.8788927336e+001 20030814,0000,1.36980000,6.2467599793e+001,4.9565810895e+001,-2.5629290618e+001 20030815,0000,1.37150000,6.9668246445e+001,5.6266622745e+001,-2.1739130435e+001 20030818,0000,1.38910000,7.9908906883e+001,6.4147384124e+001,-9.2819614711e+000
Vous pouvez modifier le deuxième exemple pour produire facilement un script qui répondra à vos besoins.
7. Formation en réseau neuronal
La formation du réseau a déjà été préparée en C# par Heaton Research. ENCOG 2.6 implémente l'espace de noms Encog.App.Quant qui est une base pour la prédiction de séries chronologiques financières. Le script de formation est très flexible et peut être facilement ajusté à n'importe quel nombre d'indicateurs d'entrée. Vous ne devez modifier l'emplacement du répertoire MetaTrader 5 que dans la constante DIRECTORY.
L'architecture du réseau et les paramètres de formation peuvent être facilement personnalisés en modifiant les variables suivantes :
/// <summary> /// The size of the input window. This is the number of bars used to predict the next bar. /// </summary> public const int INPUT_WINDOW = 6; /// <summary> /// The number of bars forward we are trying to predict. This is usually just 1 bar. The future indicator used in step 1 may /// well look more forward into the future. /// </summary> public const int PREDICT_WINDOW = 1; /// <summary> /// The number of bars forward to look for the best result. /// </summary> public const int RESULT_WINDOW = 5; /// <summary> /// The number of neurons in the first hidden layer. /// </summary> public const int HIDDEN1_NEURONS = 12; /// <summary> /// The target error to train to. /// </summary> public const double TARGET_ERROR = 0.01;
Le code est très explicite, donc le mieux sera de le lire attentivement :
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Encog.App.Quant.Normalize; using Encog.Util.CSV; using Encog.App.Quant.Indicators; using Encog.App.Quant.Indicators.Predictive; using Encog.App.Quant.Temporal; using Encog.Neural.NeuralData; using Encog.Neural.Data.Basic; using Encog.Util.Simple; using Encog.Neural.Networks; using Encog.Neural.Networks.Layers; using Encog.Engine.Network.Activation; using Encog.Persist; namespace NetworkTrainer { public class Program { /// <summary> /// The directory that all of the files will be stored in. /// </summary> public const String DIRECTORY = "d:\\mt5\\MQL5\\Files\\"; /// <summary> /// The input file that starts the whole process. This file should be downloaded from NinjaTrader using the EncogStreamWriter object. /// </summary> public const String STEP1_FILENAME = DIRECTORY + "mt5export.csv"; /// <summary> /// We apply a predictive future indicator and generate a second file, with the additional predictive field added. /// </summary> public const String STEP2_FILENAME = DIRECTORY + "step2_future.csv"; /// <summary> /// Next the entire file is normalized and stored into this file. /// </summary> public const String STEP3_FILENAME = DIRECTORY + "step3_norm.csv"; /// <summary> /// The file is time-boxed to create training data. /// </summary> public const String STEP4_FILENAME = DIRECTORY + "step4_train.csv"; /// <summary> /// Finally, the trained neural network is written to this file. /// </summary> public const String STEP5_FILENAME = DIRECTORY + "step5_network.eg"; /// <summary> /// The size of the input window. This is the number of bars used to predict the next bar. /// </summary> public const int INPUT_WINDOW = 6; /// <summary> /// The number of bars forward we are trying to predict. This is usually just 1 bar. The future indicator used in step 1 may /// well look more forward into the future. /// </summary> public const int PREDICT_WINDOW = 1; /// <summary> /// The number of bars forward to look for the best result. /// </summary> public const int RESULT_WINDOW = 5; /// <summary> /// The number of neurons in the first hidden layer. /// </summary> public const int HIDDEN1_NEURONS = 12; /// <summary> /// The target error to train to. /// </summary> public const double TARGET_ERROR = 0.01; static void Main(string[] args) { // Step 1: Create future indicators Console.WriteLine("Step 1: Analyze MT5 Export & Create Future Indicators"); ProcessIndicators ind = new ProcessIndicators(); ind.Analyze(STEP1_FILENAME, true, CSVFormat.DECIMAL_POINT); int externalIndicatorCount = ind.Columns.Count - 3; ind.AddColumn(new BestReturn(RESULT_WINDOW,true)); ind.Process(STEP2_FILENAME); Console.WriteLine("External indicators found: " + externalIndicatorCount); //Console.ReadKey(); // Step 2: Normalize Console.WriteLine("Step 2: Create Future Indicators"); EncogNormalize norm = new EncogNormalize(); norm.Analyze(STEP2_FILENAME, true, CSVFormat.ENGLISH); norm.Stats[0].Action = NormalizationDesired.PassThrough; // Date norm.Stats[1].Action = NormalizationDesired.PassThrough; // Time norm.Stats[2].Action = NormalizationDesired.Normalize; // Close norm.Stats[3].Action = NormalizationDesired.Normalize; // Stoch K norm.Stats[4].Action = NormalizationDesired.Normalize; // Stoch Dd norm.Stats[5].Action = NormalizationDesired.Normalize; // WilliamsR norm.Stats[6].Action = NormalizationDesired.Normalize; // best return [RESULT_WINDOW] norm.Normalize(STEP3_FILENAME); // neuron counts int inputNeurons = INPUT_WINDOW * externalIndicatorCount; int outputNeurons = PREDICT_WINDOW; // Step 3: Time-box Console.WriteLine("Step 3: Timebox"); //Console.ReadKey(); TemporalWindow window = new TemporalWindow(); window.Analyze(STEP3_FILENAME, true, CSVFormat.ENGLISH); window.InputWindow = INPUT_WINDOW; window.PredictWindow = PREDICT_WINDOW; int index = 0; window.Fields[index++].Action = TemporalType.Ignore; // date window.Fields[index++].Action = TemporalType.Ignore; // time window.Fields[index++].Action = TemporalType.Ignore; // close for(int i=0;i<externalIndicatorCount;i++) window.Fields[index++].Action = TemporalType.Input; // external indicators window.Fields[index++].Action = TemporalType.Predict; // PredictBestReturn window.Process(STEP4_FILENAME); // Step 4: Train neural network Console.WriteLine("Step 4: Train"); Console.ReadKey(); INeuralDataSet training = (BasicNeuralDataSet)EncogUtility.LoadCSV2Memory(STEP4_FILENAME, inputNeurons, outputNeurons, true, CSVFormat.ENGLISH); BasicNetwork network = new BasicNetwork(); network.AddLayer(new BasicLayer(new ActivationTANH(), true, inputNeurons)); network.AddLayer(new BasicLayer(new ActivationTANH(), true, HIDDEN1_NEURONS)); network.AddLayer(new BasicLayer(new ActivationLinear(), true, outputNeurons)); network.Structure.FinalizeStructure(); network.Reset(); //EncogUtility.TrainToError(network, training, TARGET_ERROR); EncogUtility.TrainConsole(network, training, 3); // Step 5: Save neural network and stats EncogMemoryCollection encog = new EncogMemoryCollection(); encog.Add("network", network); encog.Add("stat", norm.Stats); encog.Save(STEP5_FILENAME); Console.ReadKey(); } } }
Vous remarquerez peut-être que j'ai commenté une ligne et changé la fonction de formation de EncogUtility.TrainToError() en EncogUtility.TrainConsole()
EncogUtility.TrainConsole(network, training, 3);
La méthode TrainConsole indique un nombre de minutes pour former le réseau. Dans l'exemple, j'entraîne le réseau pendant trois minutes. En fonction de la complexité du réseau et la taille des données de formation, la formation du réseau peut prendre quelques minutes, heures ou même jours. Je recommande de lire plus sur le calcul d’erreur and algorithmes de formation sur le site web de Heaton Research ou tout autre livre sur le thème..
Les méthodes EncogUtility.TrainToError() interrompent d'entraîner le réseau une fois qu'une erreur de réseau cible est atteinte. Vous pouvez commenter EncongUtiliy.TrainConsole() et décommenter EncogUtility.TrainToError() pour entraîner le réseau jusqu'à une erreur souhaitée comme dans l'exemple original
EncogUtility.TrainToError(network, training, TARGET_ERROR);
Veuillez noter que parfois le réseau ne peut pas être entraîné à une certaine erreur car le nombre de neurones peut être trop petit.
8. Utilisation d'un réseau neuronal formé pour créer un indicateur neuronal MetaTrader 5
Un réseau formé peut être utilisé par un indicateur de réseau neuronal qui tentera de prédire le meilleur rendement sur investissement.
L'indicateur neuronal ENCOG pour MetaTrader 5 se compose de deux parties. Une partie est écrite en MQL5 et prend essentiellement les mêmes indicateurs que ceux avec lesquels le réseau a été formé et alimente le réseau avec des valeurs d'indicateur de fenêtre d'entrée. La deuxième partie est écrite en C# et elle applique le timeboxing aux données d'entrée et renvoie la sortie du réseau neuronal à MQL5. La partie indicateur C# est axée sur mon article précédent sur l’Exposition du C# code to MQL5.
using System; using System.Collections.Generic; using System.Text; using RGiesecke.DllExport; using System.Runtime.InteropServices; using Encog.Neural.Networks; using Encog.Persist; using Encog.App.Quant.Normalize; using Encog.Neural.Data; using Encog.Neural.Data.Basic; namespace EncogNeuralIndicatorMT5DLL { public class NeuralNET { private EncogMemoryCollection encog; public BasicNetwork network; public NormalizationStats stats; public NeuralNET(string nnPath) { initializeNN(nnPath); } public void initializeNN(string nnPath) { try { encog = new EncogMemoryCollection(); encog.Load(nnPath); network = (BasicNetwork)encog.Find("network"); stats = (NormalizationStats)encog.Find("stat"); } catch (Exception e) { Console.WriteLine(e.StackTrace); } } }; class UnmanagedExports { static NeuralNET neuralnet; [DllExport("initializeTrainedNN", CallingConvention = CallingConvention.StdCall)] static int initializeTrainedNN([MarshalAs(UnmanagedType.LPWStr)]string nnPath) { neuralnet = new NeuralNET(nnPath); if (neuralnet.network != null) return 0; else return -1; } [DllExport("computeNNIndicator", CallingConvention = CallingConvention.StdCall)] public static int computeNNIndicator([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] double[] t1, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] double[] t2, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] double[] t3, int len, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5)] double[] result, int rates_total) { INeuralData input = new BasicNeuralData(3 * len); int index = 0; for (int i = 0; i <len; i++) { input[index++] = neuralnet.stats[3].Normalize(t1[i]); input[index++] = neuralnet.stats[4].Normalize(t2[i]); input[index++] = neuralnet.stats[5].Normalize(t3[i]); } INeuralData output = neuralnet.network.Compute(input); double d = output[0]; d = neuralnet.stats[6].DeNormalize(d); result[rates_total-1]=d; return 0; } } }
Si vous souhaitez utiliser un autre nombre d'indicateurs que trois, vous devez modifier la méthode computeNNIndicator() en fonction de vos besoins.
[DllExport("computeNNIndicator", CallingConvention = CallingConvention.StdCall)] public static int computeNNIndicator([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] double[] t1, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] double[] t2, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] double[] t3, int len, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5)] double[] result, int rates_total)
Dans ce cas, trois premiers paramètres d'entrée sont des tableaux qui comportent des valeurs d'entrée d'indicateur, le quatrième paramètre est la longueur de la fenêtre d'entrée.
SizeParamIndex = 3 points sur la variable de longueur de fenêtre d'entrée, car le nombre de variables d'entrée est augmenté à partir de 0. Le cinquième paramètre est un tableau qui comporte les résultats du réseau neuronal.
La partie indicateur MQL5 doit importer un C# EncogNNTrainDLL.dll et utiliser les fonctions initializeTrainedNN() et computeNNIndicator() exportées à partir de la dll.
//+------------------------------------------------------------------+ //| NeuralEncogIndicator.mq5 | //| Copyright 2011, Investeo.pl | //| http:/Investeo.pl | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, Investeo.pl" #property link "http:/Investeo.pl" #property version "1.00" #property indicator_separate_window #property indicator_plots 1 #property indicator_buffers 1 #property indicator_color1 Blue #property indicator_type1 DRAW_LINE #property indicator_style1 STYLE_SOLID #property indicator_width1 2 #import "EncogNNTrainDLL.dll" int initializeTrainedNN(string nnFile); int computeNNIndicator(double& ind1[], double& ind2[],double& ind3[], int size, double& result[], int rates); #import int INPUT_WINDOW = 6; int PREDICT_WINDOW = 1; double ind1Arr[], ind2Arr[], ind3Arr[]; double neuralArr[]; int hStochastic; int hWilliamsR; int hNeuralMA; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0, neuralArr, INDICATOR_DATA); PlotIndexSetInteger(0, PLOT_SHIFT, 1); ArrayResize(ind1Arr, INPUT_WINDOW); ArrayResize(ind2Arr, INPUT_WINDOW); ArrayResize(ind3Arr, INPUT_WINDOW); ArrayInitialize(neuralArr, 0.0); ArraySetAsSeries(ind1Arr, true); ArraySetAsSeries(ind2Arr, true); ArraySetAsSeries(ind3Arr, true); ArraySetAsSeries(neuralArr, true); hStochastic = iStochastic(NULL, 0, 8, 5, 5, MODE_EMA, STO_LOWHIGH); hWilliamsR = iWPR(NULL, 0, 21); Print(TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL5\Files\step5_network.eg"); initializeTrainedNN(TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL5\Files\step5_network.eg"); //--- return(0); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime& time[], const double& open[], const double& high[], const double& low[], const double& close[], const long& tick_volume[], const long& volume[], const int& spread[]) { //--- int calc_limit; if(prev_calculated==0) // First execution of the OnCalculate() function after the indicator start calc_limit=rates_total-34; else calc_limit=rates_total-prev_calculated; ArrayResize(neuralArr, rates_total); for (int i=0; i<calc_limit; i++) { CopyBuffer(hStochastic, 0, i, INPUT_WINDOW, ind1Arr); CopyBuffer(hStochastic, 1, i, INPUT_WINDOW, ind2Arr); CopyBuffer(hWilliamsR, 0, i, INPUT_WINDOW, ind3Arr); computeNNIndicator(ind1Arr, ind2Arr, ind3Arr, INPUT_WINDOW, neuralArr, rates_total-i); } //Print("neuralArr[0] = " + neuralArr[0]); //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+
Veuillez consulter la sortie de l'indicateur formé sur les données quotidiennes de l' USDCHF etStochastic et Williams %R indicateurs:
Figure 7. Indicateur d’ Encog neuronal
L'indicateur indique le meilleur rendement sur investissement prévu sur la barre suivante.
Vous avez peut-être remarqué que j'ai déplacé l'indicateur d'une barre à l'avenir :
PlotIndexSetInteger(0, PLOT_SHIFT, 1);
Ceci pour indiquer que l'indicateur est prédictif. Puisque nous avons élaboré un indicateur neuronal, nous sommes prêts à créer un Expert Advisor axé sur l'indicateur.
9. Expert Advisor basé sur un indicateur neuronal
L'Expert Advisor prend la sortie de l'indicateur neuronal et décide d'acheter ou de vendre un titre. Ma première impression était qu'il devrait acheter chaque fois que l'indicateur est supérieur à zéro et vendre lorsqu'il est inférieur à zéro, ce qui indique acheter lorsque la meilleure prédiction de rendement sur une fenêtre de temps donnée est positive et vendre lorsque la meilleure prédiction de rendement est négative.
Après quelques tests initiaux, il s'est avéré que les performances pourraient être meilleures. Donc, j’ai présenté les variables «forte tendance à la hausse» et «forte tendance à la baisse» indiquant qu’il y a aucune raison de quitter le trade quand nous nous retrouvons dans une tendance forte selon me fameuse règle «la tendance est ton ami».
De plus, on m'a conseillé sur le forum Heaton Research d'utiliser l 'ATR pour déplacer les stop loss, j'ai donc utilisé l'indicateur Chandelier ATR que j'ai trouvé sur leMQL5 forum Il a en effet augmenté le gain de fonds propres lors de la vérification a posteriori. Je colle le code source de l'Expert Advisor ci-dessous.
//+------------------------------------------------------------------+ //| NeuralEncogAdvisor.mq5 | //| Copyright 2011, Investeo.pl | //| http:/Investeo.pl | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, Investeo.pl" #property link "http:/Investeo.pl" #property version "1.00" double neuralArr[]; double trend; double Lots=0.3; int INPUT_WINDOW=8; int hNeural,hChandelier; //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- ArrayResize(neuralArr,INPUT_WINDOW); ArraySetAsSeries(neuralArr,true); ArrayInitialize(neuralArr,0.0); hNeural=iCustom(Symbol(),Period(),"NeuralEncogIndicator"); Print("hNeural = ",hNeural," error = ",GetLastError()); if(hNeural<0) { Print("The creation of ENCOG indicator has failed: Runtime error =",GetLastError()); //--- forced program termination return(-1); } else Print("ENCOG indicator initialized"); hChandelier=iCustom(Symbol(),Period(),"Chandelier"); Print("hChandelier = ",hChandelier," error = ",GetLastError()); if(hChandelier<0) { Print("The creation of Chandelier indicator has failed: Runtime error =",GetLastError()); //--- forced program termination return(-1); } else Print("Chandelier indicator initialized"); //--- return(0); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- long tickCnt[1]; int ticks=CopyTickVolume(Symbol(),0,0,1,tickCnt); if(tickCnt[0]==1) { if(!CopyBuffer(hNeural,0,0,INPUT_WINDOW,neuralArr)) { Print("Copy1 error"); return; } // Print("neuralArr[0] = "+neuralArr[0]+"neuralArr[1] = "+neuralArr[1]+"neuralArr[2] = "+neuralArr[2]); trend=0; if(neuralArr[0]<0 && neuralArr[1]>0) trend=-1; if(neuralArr[0]>0 && neuralArr[1]<0) trend=1; Trade(); } } //+------------------------------------------------------------------+ //| Tester function | //+------------------------------------------------------------------+ double OnTester() { //--- //--- return(0.0); } //+------------------------------------------------------------------+ void Trade() { double bufChandelierUP[2]; double bufChandelierDN[2]; double bufMA[2]; ArraySetAsSeries(bufChandelierUP,true); ArraySetAsSeries(bufChandelierUP,true); ArraySetAsSeries(bufMA,true); CopyBuffer(hChandelier,0,0,2,bufChandelierUP); CopyBuffer(hChandelier,1,0,2,bufChandelierDN); MqlRates rates[]; ArraySetAsSeries(rates,true); int copied=CopyRates(Symbol(),PERIOD_CURRENT,0,3,rates); bool strong_uptrend=neuralArr[0]>0 && neuralArr[1]>0 && neuralArr[2]>0 && neuralArr[3]>0 && neuralArr[4]>0 && neuralArr[5]>0 && neuralArr[6]>0 && neuralArr[7]>0; bool strong_downtrend=neuralArr[0]<0 && neuralArr[1]<0 && neuralArr[2]<0 && neuralArr[3]<0 && neuralArr[4]<0 && neuralArr[5]<0 && neuralArr[6]<0 && neuralArr[7]<0; if(PositionSelect(_Symbol)) { long type=PositionGetInteger(POSITION_TYPE); bool close=false; if((type==POSITION_TYPE_BUY) && (trend==-1)) if(!(strong_uptrend) || (bufChandelierUP[0]==EMPTY_VALUE)) close=true; if((type==POSITION_TYPE_SELL) && (trend==1)) if(!(strong_downtrend) || (bufChandelierDN[0]==EMPTY_VALUE)) close=true; if(close) { CTrade trade; trade.PositionClose(_Symbol); } else // adjust s/l { CTrade trade; if(copied>0) { if(type==POSITION_TYPE_BUY) { if(bufChandelierUP[0]!=EMPTY_VALUE) trade.PositionModify(Symbol(),bufChandelierUP[0],0.0); } if(type==POSITION_TYPE_SELL) { if(bufChandelierDN[0]!=EMPTY_VALUE) trade.PositionModify(Symbol(),bufChandelierDN[0],0.0); } } } } if((trend!=0) && (!PositionSelect(_Symbol))) { CTrade trade; MqlTick tick; MqlRates rates[]; ArraySetAsSeries(rates,true); int copied=CopyRates(Symbol(),PERIOD_CURRENT,0,INPUT_WINDOW,rates); if(copied>0) { if(SymbolInfoTick(_Symbol,tick)==true) { if(trend>0) { trade.Buy(Lots,_Symbol,tick.ask); Print("Buy at "+tick.ask+" trend = "+trend+" neuralArr = "+neuralArr[0]); } if(trend<0) { trade.Sell(Lots,_Symbol,tick.bid); Print("Sell at "+tick.ask+" trend = "+trend+" neuralArr = "+neuralArr[0]); } } } } } //+------------------------------------------------------------------+
L'Expert Advisor a été exécuté sur les données USDCHF de la devise D1. Environ 50% des données étaient hors de l'échantillon de la formation.
10. Expert Advisor Résultats du Test Renversé.
Je colle les résultats de la vérification a posteriori ci-dessous. La vérification a posteriori a été exécutée du 2000.01.01 au 2011.03.26.
Figure 8. Résultats de la vérification a posteriori de Neural Expert Advisor
Figure 9. Graphique de la vérification a posteriori solde/fonds propres de Neural Expert Advisor
Veuillez noter que cette performance peut être totalement différente pour d'autres délais et d'autres titres.
Veuillez considérer cette EA comme une évaluation éducative et en faire un point de départ pour des recherches ultérieures. Mon point de vue personnel est que le réseau pourrait être recyclé à chaque période de temps pour le rendre plus robuste, peut-être que quelqu'un le fera ou a déjà trouvé un bon moyen d'y parvenir. Il existe peut-être un meilleur moyen de faire des prédictions d'achat/vente axées sur un indicateur neuronal. J'encourage les lecteurs à expérimenter.
Conclusion
Dans l'article suivant, j'ai présenté un moyen d’élaborer un indicateur prédictif neuronal et un conseiller expert basé sur cet indicateur à l'aide du cadre d'apprentissage automatique ENCOG. Tout le code source, les binaires compilés, les DLL et un réseau formé exemplaire sont joints à l'article.
En raison du "double emballage de DLL dans .NET", les fichiers Cloo.dll, encog-core-cs.dll and log4net.dlldoivent se trouver dans le dossier du terminal client.
Le fichierEncogNNTrainDLL.dll doit se trouver dans le dossier \Terminal Data\MQL5\Libraries\.
Traduit de l’anglais par MetaQuotes Ltd.
Article original : https://www.mql5.com/en/articles/252





- Applications de trading gratuites
- Plus de 8 000 signaux à copier
- Actualités économiques pour explorer les marchés financiers
Vous acceptez la politique du site Web et les conditions d'utilisation