English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
preview
Développer un Expert Advisor à partir de zéro (partie 7) : Ajout du Volume au Prix (I)

Développer un Expert Advisor à partir de zéro (partie 7) : Ajout du Volume au Prix (I)

MetaTrader 5Trading | 19 septembre 2022, 10:30
651 0
Daniel Jose
Daniel Jose

Introduction

Tout trader essayant d'avoir un certain degré de confiance doit avoir cet indicateur sur son graphique. Le plus souvent, l'indicateur est utilisé par ceux qui préfèrent utiliser la https://fr.wikipedia.org/wiki/Analyse_technique pendant le trading. De plus, l'indicateur peut être utilisé par ceux qui tradent uniquement sur la base de l'analyse de l'Action des Prix. Il s'agit d'un indicateur de volume horizontal extrêmement utile qui peut être utilisé pour analyser le volume des transactions qui ont eu lieu à un moment donné. Il peut être toutefois difficile de lire correctement cet indicateur. J'ajouterai un lien à la fin de l'article pour que vous puissiez en savoir plus à son sujet.

Nous ne nous attarderons pas ici sur la manière d'interpréter les lectures de l'indicateur, car cela dépasserait le cadre de cet article. L'objectif de cet article est de montrer comment concevoir et créer ce nouvel indicateur de manière à ce qu'il ne dégrade pas les performances de la plateforme MetaTrader 5. Bien que beaucoup pensent que cet indicateur doit être mis à jour en temps réel, un léger retard est en fait acceptable, à condition qu'il soit très faible. D'après ma propre expérience, je n'ai pas constaté de gros problèmes avec un retard d'environ 1 seconde dans la mise à jour des valeurs. Mais s'il est important pour vous d'utiliser le véritable temps réel, vous devrez procéder à de petits changements. Les modifications doivent être effectuées non pas dans l'indicateur lui-même, mais aux endroits où l’Expert Advisor l’appelle afin que l'appel se fasse en temps réel. Je pense cependant que l'impact sur les performances sera minime, et que donc le délai peut être négligé.


Interface de Contrôle

L'interface de contrôle de la classe Volume At Price est très simple. Mais pour un contrôle total, il est nécessaire de s'assurer des propriétés correctes du graphique sur lequel l'indicateur sera appliqué. Les propriétés sont présentées dans la figure ci-dessous, avec le principal contrôle principal en surbrillance.

Si la grille n'est pas visible, il ne sera pas possible de redimensionner l'indicateur comme le montrent les animations suivantes : Notez que l'interface est très simple et intuitive : elle ne comporte que deux contrôles, dont l'un indique la taille, et l'autre le point de départ de l'analyse du volume.

    

En général, cet indicateur est assez efficace et très intéressant dans sa mise en œuvre. Dans cet article, nous allons travailler avec son niveau le plus basique. Puis nous l'améliorerons dans l'article suivant.

Je n'ai rien de plus à dire sur l'interface. Nous pouvons passer à l'implémentation du code.


Implémentation

Pour simplifier le travail de création de l'indicateur, nous allons diviser notre code source en plusieurs parties, et également effectuer quelques modifications et ajouts. Commençons par décomposer le code en plusieurs parties. Une grande partie de ce dont nous avons besoin est déjà écrite ailleurs. L'essentiel se trouve dans la classe C_Wallpaper. Que devons-nous faire ? Allons-nous créer un indicateur basé sur un bitmap ? Oui, toute image sur un écran d'ordinateur doit être traitée comme une image BITMAP. Mais elle doit être construite d'une manière spéciale. La nouvelle classe d'objets C_Wallpaper ressemblera donc à ceci :

class C_WallPaper : public C_Canvas
{
        protected:
                enum eTypeImage {IMAGEM, LOGO, COR};
//+------------------------------------------------------------------+
        private :
        public  :
//+------------------------------------------------------------------+
                ~C_WallPaper()
                        {
                                Destroy();
                        }
//+------------------------------------------------------------------+
                bool Init(const string szName, const eTypeImage etype, const char cView = 100)
                        {
                                if (etype == C_WallPaper::COR) return true;
                                if (!Create(szName, 0, 0, Terminal.GetWidth(), Terminal.GetHeight())) return false;
                                if(!LoadBitmap(etype == C_WallPaper::IMAGEM ? "WallPapers\\" + szName : "WallPapers\\Logos\\" + _Symbol, cView)) return false;
                                ObjectSetInteger(Terminal.Get_ID(), szName, OBJPROP_BACK, true);

                                return true;
                        }
//+------------------------------------------------------------------+
                void Resize(void)
                        {
                                ResizeBitMap(Terminal.GetWidth(), Terminal.GetHeight());
                        }
//+------------------------------------------------------------------+
};


Vous pouvez voir que le code est devenu beaucoup plus compact. Nous avons supprimé les parties communes entre les classes C_Wallpaper et C_VolumeAtPrice et nous avons tout mis dans la nouvelle classe C_C_Canvas.

Mais pourquoi ne pas utiliser la classe C_Canvas de MetaTrader 5 alors ? La question est plus personnelle que pratique. J'aime avoir plus de contrôle sur tout ce que j'écris et que je développe. Mais c'est plus une mauvaise habitude pour un programmeur C que quelque chose de vraiment nécessaire. C'est pourquoi je dois créer une classe pour dessiner ces objets à l'écran. Vous pouvez bien sûr utiliser la classe déjà disponible dans MetaTrader 5. Concentrons-nous maintenant sur la classe C_VolumeAtPrice, qui est l'objet principal de cet article. La classe a 7 fonctions présentées dans le tableau suivant :

Fonction Description Type d'accès 
Init Initialise la classe avec les valeurs spécifiées par l'utilisateur. Général
Update Met à jour les données de volume et de prix à des intervalles spécifiés. Général
Resize Modifie la taille de l'image du Volume au Prix sur le graphique, ce qui facilite l'analyse de certains détails. Général
DispatchMessage  Utilisé pour envoyer des messages à une classe d'objets. Général
FromNowOn  Initialise les variables du système Privé
SetMatrix Crée et maintient une matrice avec des les volumes. Privé
Redraw Crée une image des volumes Privé

Passons maintenant à l'implémentation du système, en commençant par la déclaration des variables :

#define def_SizeMaxBuff                 4096
//+------------------------------------------------------------------+
#define def_MsgLineLimit                "Starting point from Volume At Price"
//+------------------------------------------------------------------+
class C_VolumeAtPrice : private C_Canvas
{
#ifdef macroSetInteger
        ERROR ...
#endif
#define macroSetInteger(A, B) ObjectSetInteger(Terminal.Get_ID(), m_Infos.szObjEvent, A, B)
        private :
                uint    m_WidthMax,
                        m_WidthPos;
                bool    m_bChartShift,
                        m_bUsing;
                double  m_dChartShift;
                struct st00
                {
                        ulong   nVolBuy,
                                nVolSell,
                                nVolTotal;
                        long    nVolDif;
                }m_InfoAllVaP[def_SizeMaxBuff];
                struct st01
                {
                        ulong    memTimeTick;
                        datetime StartTime,
                                 CurrentTime;
                        int      CountInfos;
                        ulong    MaxVolume;
                        color    ColorSell,
                                 ColorBuy,
                                 ColorBars;
                        int      Transparency;
                        string   szObjEvent;
                        double   FirstPrice;
                }m_Infos;


La partie surlignée de ce code est ce à quoi vous devez faire attention. Cette partie garantit que la définition ne provient pas d'un autre fichier d'une manière qui entrerait en conflit avec la définition que nous utiliserons dans ce fichier. En effet, le compilateur MQL5 affiche un avertissement lorsque vous essayez de remplacer une définition existante. Dans certains cas, il est difficile de savoir comment résoudre ce problème. Pour nous faciliter un peu la vie, nous utilisons donc le test mis en évidence dans le code ci-dessus. Le reste du code n'est pas particulièrement intéressant. La seule chose à laquelle vous devez prêter attention est la définition de def_SizeMaxBuff. Elle indique quelle sera la taille de notre tableau de données de volume. Si nécessaire, vous pouvez changer cette valeur pour une autre. Mais selon les résultats des tests, cette valeur est plus que suffisante pour la grande majorité des cas. Elle représente les variations en ticks entre le prix le plus bas et le prix actuel. La valeur actuelle peut donc gérer un très grand nombre de cas.


La fonction Init : c’est là que tout commence

Cette fonction initialise correctement toutes les variables. Elle est appelé dans l’Expert Advisor comme suit :

//.... Initial data....

input color     user10   = clrForestGreen;      //Take Profit line color
input color     user11   = clrFireBrick;        //Stop line color
input bool      user12   = true;                //Day Trade?
input group "Volume At Price"
input color     user15  = clrBlack;             //Color of bars
input char      user16  = 20;                   //Transparency (from 0 to 100 )
//+------------------------------------------------------------------+
C_SubWindow             SubWin;
C_WallPaper             WallPaper;
C_VolumeAtPrice         VolumeAtPrice;
//+------------------------------------------------------------------+          
int OnInit()
{
        Terminal.Init();
        WallPaper.Init(user03, user05, user04);
        if ((user01 == "") && (user02 == "")) SubWin.Close(); else if (SubWin.Init())
        {
                SubWin.ClearTemplateChart();
                SubWin.AddThese(C_TemplateChart::SYMBOL, user02);
                SubWin.AddThese(C_TemplateChart::INDICATOR, user01);
        }
        SubWin.InitilizeChartTrade(user06, user07, user08, user09, user10, user11, user12);
        VolumeAtPrice.Init(user10, user11, user15, user16);

// ... Rest of the code

Il n'y a pas beaucoup de paramètres ici. Ils représentent principalement les informations sur les couleurs à utiliser. Regardons ensuite le code interne de cette fonction. Le code ci-dessous montre comment tout est initialisé :

void Init(color CorBuy, color CorSell, color CorBar, char cView)
{
        m_Infos.FirstPrice = Terminal.GetRatesLastDay().open;
        FromNowOn(macroSetHours(macroGetHour(Terminal.GetRatesLastDay().time), TimeLocal()));
        m_Infos.Transparency = (int)(255 * macroTransparency(cView));
        m_Infos.ColorBars = CorBar;
        m_Infos.ColorBuy = CorBuy;
        m_Infos.ColorSell = CorSell;
        if (m_bUsing) return;
        m_Infos.szObjEvent = "Event" + (string)ObjectsTotal(Terminal.Get_ID(), -1, OBJ_EVENT);
        CreateObjEvent();
        m_bChartShift = ChartGetInteger(Terminal.Get_ID(), CHART_SHIFT);
        m_dChartShift = ChartGetDouble(Terminal.Get_ID(), CHART_SHIFT_SIZE);
        ChartSetInteger(Terminal.Get_ID(), CHART_SHIFT, true);
        ChartSetDouble(Terminal.Get_ID(), CHART_SHIFT_SIZE, 0.1);
        Create("VaP" + (string)MathRand(), 0, 0, 1, 1);
        Resize();
        m_bUsing = true;
};


Comme vous pouvez le constater, tout est très simple. Certaines caractéristiques rendent pourtant le code intéressant. L'une d'elle est Terminal.GetRatesLastDay().open. Bien que cela puisse paraître étrange, il s'agit en fait d'une situation très courante lorsque l'on suit les principes de la Programmation Orientée Objet (POO). L'un de ces principes dit que rien d'extérieur à la classe ne doit avoir accès aux variables internes de la classe. Mais comment alors obtenir les valeurs des variables à l'intérieur de la classe ? La bonne méthode consiste à utiliser une forme qui n'apparaît que dans la POO. Voyons donc comment la fonction GetRatesLastDay est déclarée dans la classe C_Terminal. Voici le code :

inline MqlRates GetRatesLastDay(void) const { return m_Infos.Rates; }


Voyons ensemble comment cela fonctionne réellement. Commençons par le mot réservé inline. Il indiquera au compilateur que le code doit être placé à tous les endroits où il apparaît. Au lieu de générer un appel de fonction, le compilateur copie tout le code de la fonction jusqu'au point où la fonction est référencée. Cela accélère grandement l'exécution du code en raison d'une moindre consommation de mémoire. Mais dans un cas spécifique, la variable m_Infos.Rates est référencée. Cette variable est de type MqlRates, c'est-à-dire que nous pouvons accéder aux valeurs de la structure MqlRates. Dans ce cas, nous ne transmettons pas l'adresse de la référence de la variable. Mais dans certains cas, pour rendre le code plus rapide, on passe l'adresse de la référence, auquel cas il est possible de changer la valeur de la variable à l'intérieur de la classe, ce qui devrait être interdit. Pour éviter que cela ne se produise, nous utilisons le mot réservé const, qui garantit que la variable ne pourra jamais être modifiée sans la classe elle-même. Alors que de nombreux mots réservés du C++ sont également documentés dans MQL5, certains ne le sont pas encore, mais font partie de MQL5 car le langage est très proche du C++. À la fin de l'article, j'ajouterai des liens pour ceux qui veulent en savoir plus sur le C++ et comment utiliser ces mêmes connaissances dans la programmation MQL5.

Dans le code de la fonction Init, nous avons maintenant une partie intéressante à voir. Je l'ai mise en évidence ci-dessous pour expliquer ce qu'elle fait :

m_bChartShift = ChartGetInteger(Terminal.Get_ID(), CHART_SHIFT);
m_dChartShift = ChartGetDouble(Terminal.Get_ID(), CHART_SHIFT_SIZE);
ChartSetInteger(Terminal.Get_ID(), CHART_SHIFT, true);
ChartSetDouble(Terminal.Get_ID(), CHART_SHIFT_SIZE, 0.1);


Lorsque l'EA est lancé, il modifie le graphique. Mais il est bon de réinitialiser le système à son état initial lorsque l'utilisateur le ferme. Nous enregistrons donc les paramètres de défilement du graphique, puis nous créons un défilement minimal. Cela se fait avec les lignes en surbrillance. Nous devons donc voir la grille sur le graphique afin de pouvoir ajuster les dimensions. Cela se fait de manière interactive, comme indiqué au début de l'article. Vous pouvez voir CHART_SHIFT pour plus d'informations.


Sécuriser les objets à l'écran

Bien que les fonctions internes de la classe soient très simples, certains points méritent notre attention. Le premier est un système de sécurité qui ne permet pas à l'utilisateur de retirer le point indiquant le début de l'analyse du volume :


Le point est très petit, il faut donc le remarquer.

Note Importante : Si vous souhaitez modifier le point d'analyse, faites attention à l'horizon temporel du graphique. Par exemple, si vous devez déplacer l'analyse de 9:00 à 9:02, vous devez utiliser un intervalle de temps de 1 ou 2 minutes. Si vous utilisez un graphique de 5 minutes par exemple, vous ne pouvez pas le faire.

Nous devons ensuite veiller à ce que l'utilisateur ne supprime pas accidentellement cet élément. Ceci est fait avec le code suivant :

void DispatchMessage(int iMsg, string sparam)
{
        switch (iMsg)
        {

// ... The inside of the code

                case CHARTEVENT_OBJECT_DELETE:
                        if ((sparam == m_Infos.szObjEvent) && (m_bUsing))
                        {
                                m_bUsing = false;
                                CreateObjEvent();
                                Resize();
                                m_bUsing = true;
                        }
                break;
        }                       
};


Lorsque la classe s'aperçoit que l'objet a été supprimé, elle le recrée immédiatement, ce qui évite que l'utilisateur se retrouve sans un objet nécessaire à la classe et soit donc obligé de relancer l'EA. Vous pouvez utiliser ce modèle à chaque fois que vous devez vous assurer que l'utilisateur ne supprime pas un objet sensible. Mais nous devons aussi ajouter du code supplémentaire pour nous assurer que l'événement est remarqué par l'EA :

ChartSetInteger(m_Infos.ID, CHART_EVENT_OBJECT_DELETE, 0, true);

Cette simple ligne garantit que la plateforme MetaTrader 5 signalera la suppression de l'objet. Vous pouvez voir CHART_EVENT_OBJECT_DELETE pour plus d'informations.


Construire le graphique de Volume au Prix

C'est le cœur de la classe. Il a trois fonctions : une publique et deux privées. Commençons par la fonction publique. Elle est présentée ci-dessous :

inline virtual void Update(void)
{
        MqlTick Tick[];
        int i1, p1;

        if (m_bUsing == false) return;
        if ((i1 = CopyTicksRange(Terminal.GetSymbol(), Tick, COPY_TICKS_TRADE, m_Infos.memTimeTick)) > 0)
        {
                if (m_Infos.CountInfos == 0)
                {
                        macroSetInteger(OBJPROP_TIME, m_Infos.StartTime = macroRemoveSec(Tick[0].time));
                        m_Infos.FirstPrice = Tick[0].last;
                }                                               
                for (p1 = 0; (p1 < i1) && (Tick[p1].time_msc == m_Infos.memTimeTick); p1++);
                for (int c0 = p1; c0 < i1; c0++) SetMatrix(Tick[c0]);
                if (p1 == i1) return;
                m_Infos.memTimeTick = Tick[i1 - 1].time_msc;
                m_Infos.CurrentTime = macroRemoveSec(Tick[i1 - 1].time);
                Redraw();
        };      
};

Les lignes en surbrillance sont très importantes pour le système. Lorsque le système s’exécute, il ne sait pas exactement par où commencer. Ces lignes actualisent les points. Elles informent l'utilisateur du point de départ de l'analyse et du prix de départ, afin que le système puisse créer une table interne. Le système attendra donc toujours l'arrivée d'un nouveau tick. Une fois déclenché, nous avons les données à analyser et à collecter pour les présenter à l'écran. Voici la fonction :

inline void SetMatrix(MqlTick &tick)
{
        int pos;
                                
        if ((tick.last == 0) || ((tick.flags & (TICK_FLAG_BUY | TICK_FLAG_SELL)) == (TICK_FLAG_BUY | TICK_FLAG_SELL))) return;
        pos = (int) ((tick.last - m_Infos.FirstPrice) / Terminal.GetPointPerTick()) * 2;
        pos = (pos >= 0 ? pos : (pos * -1) - 1);
        if ((tick.flags & TICK_FLAG_BUY) == TICK_FLAG_BUY) m_InfoAllVaP[pos].nVolBuy += tick.volume; else
        if ((tick.flags & TICK_FLAG_SELL) == TICK_FLAG_SELL) m_InfoAllVaP[pos].nVolSell += tick.volume;
        m_InfoAllVaP[pos].nVolDif = (long)(m_InfoAllVaP[pos].nVolBuy - m_InfoAllVaP[pos].nVolSell);
        m_InfoAllVaP[pos].nVolTotal = m_InfoAllVaP[pos].nVolBuy + m_InfoAllVaP[pos].nVolSell;
        m_Infos.MaxVolume = (m_Infos.MaxVolume > m_InfoAllVaP[pos].nVolTotal ? m_Infos.MaxVolume : m_InfoAllVaP[pos].nVolTotal);
        m_Infos.CountInfos = (m_Infos.CountInfos == 0 ? 1 : (m_Infos.CountInfos > pos ? m_Infos.CountInfos : pos));
}


Cette fonction n'est peut-être pas si importante, puisqu'elle ne fait que stocker et conserver les valeurs des volume en prix. Mais les lignes qui y sont mises en évidence constituent le cœur du système. Pour bien comprendre ce qui se passe dans ces deux lignes, réfléchissons-y. Qu'est-ce qui est le plus rapide - stocker chacun des prix et noter les volumes dans chacun d'eux, ou ne stocker que les volumes, en se demandant quel est le prix ? La 2ème option est la plus rapide, alors économisons les volumes et trouvons le prix. Mais quel sera le 1er prix du système ? Car nous avons besoin d'une valeur initiale, sans laquelle tout s'écroule. Pourquoi ne pas utiliser le prix du premier tick tradé ? Oui, c'est une bonne idée. Très bien. Mais nous avons un problème : si le prix augmente, c'est parfait, toutes les données peuvent être facilement stockées dans un tableau. Mais que se passe-t-il si le prix descend ? Dans ce cas, nous aurons des valeurs négatives et nous ne pourrons pas accéder au tableau avec un indice négatif. Nous pourrions utiliser deux tableaux au lieu d'un seul, mais cela entraînerait une charge supplémentaire inutile. Il existe une solution plus simple. Regardons le tableau suivant :


Si l'indice est positif, nous n'avons pas à nous inquiéter. Mais s'il est négatif, nous aurons des problèmes car nous utilisons un tableau bidirectionnel, où la valeur zéro représente le prix du premier tick. Les valeurs négatives sont celles qui ont baissé, et les valeurs positives sont celles qui ont augmenté. Si nous avons deux directions, en multipliant l'indice par 2, nous obtenons la colonne du milieu. Ça ne semble pas nous aider. Mais si nous convertissons les valeurs négatives en valeurs positives et que nous soustrayons 1, alors nous obtenons la bonne colonne. Si vous regardez attentivement, vous pouvez voir que les valeurs sont imbriquées dans la colonne de droite. Ceci nous donne l'indice parfait pour accéder au tableau dont nous savons qu'il va croître, mais nous ne savons pas de combien. Et c'est exactement ce que font les deux lignes mises en évidence : elles créent un index pour notre tableau, en alternant les valeurs supérieures et inférieures au prix de départ. Mais bien que ce soit une très bonne solution, elle ne servira à rien si nous ne pouvons pas montrer les données à l'écran. C’est ce que fait la fonction suivante.

void Redraw(void)
{
        uint x, y, y1, p;
        double reason = (double) (m_Infos.MaxVolume > m_WidthMax ? (m_WidthMax / (m_Infos.MaxVolume * 1.0)) : 1.0);
        double desl = Terminal.GetPointPerTick() / 2.0;
        Erase();
        p = m_WidthMax - 8;
        for (int c0 = 0; c0 <= m_Infos.CountInfos; c0++)
        {
                if (m_InfoAllVaP[c0].nVolTotal == 0) continue;
                ChartTimePriceToXY(Terminal.Get_ID(), 0, 0, m_Infos.FirstPrice + (Terminal.GetPointPerTick() * (((c0 & 1) == 1 ? -(c0 + 1) : c0) / 2)) + desl, x, y);
                y1 = y + Terminal.GetHeightBar();
                FillRectangle(p + 2, y, p + 8, y1, macroColorRGBA(m_InfoAllVaP[c0].nVolDif > 0 ? m_Infos.ColorBuy : m_Infos.ColorSell, m_Infos.Transparency));
                FillRectangle((int)(p - (m_InfoAllVaP[c0].nVolTotal * reason)), y, p, y1, macroColorRGBA(m_Infos.ColorBars, m_Infos.Transparency));
        }
        C_Canvas::Update();
};

Cette fonction trace le graphique du volume. La partie en surbrillance se charge d'inverser le calcul effectué lors de la capture du volume. Afin d'obtenir l'affichage au bon endroit, le prix se déplace un peu pour que les barres soient positionnées correctement. Le reste de la fonction n'est que le code du dessin. Quelques explications sont quand même nécessaires ici. Notez qu'il y a deux appels à FillRectangle. Mais pourquoi ? Le 1er appel indique quel volume a été le plus important (les vendeurs ou les acheteurs), et le 2nd appel indique le volume. Mais pourquoi ne pas les construire en même temps en répartissant la bande de volume entre les acheteurs et les vendeurs ? La raison est que lorsque le volume augmente dans une fourchette de prix, il commence à interférer avec l'analyse d'autres fourchettes de prix, plus petites. Il devient alors difficile de déterminer quel volume était le plus important, celui des ventes ou celui des achats. Par contre; lorsqu'il est placé de cette manière, ce problème disparaît, ce qui rend la lecture des données plus facile et plus compréhensible. Par conséquent, le graphique ressemblera à la figure ci-dessous :


Toutes les autres fonctions de la classe servent de support aux fonctions expliquées précédemment. Elles ne sont donc pas si importantes et n’ont pas besoin d’être couvertes en détail.


Conclusion

Je vous ai présenté ici une version très simple du Volume au Prix. Mais c'est un outil extrêmement efficace. Si vous commencez à apprendre à coder et que vous voulez vous concentrer sur la Programmation Orientée Objet (POO), vous devez étudier attentivement ce code, car il comporte plusieurs concepts qui sont très bons, car tout le code est basé sur une approche 100% orientée objet.

L'application contient l'Expert Advisor jusqu'au stade actuel de son développement.


Liens utiles



Traduit du portugais par MetaQuotes Ltd.
Article original : https://www.mql5.com/pt/articles/10302

Fichiers joints |
EA_1.06.zip (3280.48 KB)
Développer un Expert Advisor à partir de zéro (partie 8) : Un saut conceptuel Développer un Expert Advisor à partir de zéro (partie 8) : Un saut conceptuel
Quel est le moyen le plus facile d'implémenter de nouvelles fonctionnalités ? Dans cet article, nous allons faire un pas en arrière, puis deux pas en avant.
Science des Données et Apprentissage Automatique (partie 03) : Matrices de Régression Science des Données et Apprentissage Automatique (partie 03) : Matrices de Régression
Cette fois-ci, nos modèles sont faits avec des matrices. Ceci permet une certaine flexibilité tout en nous permettant de faire des modèles puissants pouvant gérer non seulement cinq variables indépendantes mais aussi de nombreuses variables (tant que nous restons dans les limites de calcul d'un ordinateur). Cet article va être une lecture intéressante, c'est certain.
Développer un Expert Advisor à partir de zéro (partie 9) : Un saut conceptuel (2) Développer un Expert Advisor à partir de zéro (partie 9) : Un saut conceptuel (2)
Dans cet article, nous allons placer Chart Trade dans une fenêtre flottante. Dans la partie précédente, nous avions créé un système de base qui permettait l'utilisation de modèles dans une fenêtre flottante.
Apprendre à concevoir un système de trading basé sur l’ATR Apprendre à concevoir un système de trading basé sur l’ATR
Dans cet article, nous allons découvrir un nouvel outil technique pouvant utilisé en trading, dans la continuité de la série dans laquelle nous apprenons à concevoir des systèmes de trading simples. Nous allons cette fois travailler avec un autre indicateur technique populaire : l’Average True Range (ATR).