English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Construire un trader automatique de nouvelles

Construire un trader automatique de nouvelles

MetaTrader 5Trading | 13 janvier 2022, 10:57
336 0
laplacianlab
[Supprimé]

Introduction

Comme Investopedia, un trader de nouvelles est "un trader ou un investisseur qui prend des décisions de trading ou d’investissement basées sur des annonces de nouvelles". En effet, les rapports économiques tels que le PIB d’un pays, les indices de confiance des consommateurs et les données sur l’emploi des pays, entre autres, produisent souvent des mouvements importants sur les marchés des changes. Avez-vous déjà assisté à un communiqué sur les emplois non agricoles aux États-Unis (Non-Farm Payrolls) ? Si c’est le cas, vous savez déjà que ces rapports peuvent déterminer l’avenir récent des devises et agir comme des catalyseurs pour les inversions de tendances.

Newspapers B&W

Figure 1. Newspapers B&W. Image distribuée sous licence Creative Commons sur Flickr

1. Programmons notre EA


1.1. L’idée du système de trading

L’idée derrière ce système est ce dont nous avons discuté ci-dessus. Cela semble génial, mais comment pouvons-nous mettre en œuvre ce fait prouvé dans le monde de la programmation ? Nous nous appuyons principalement sur deux aspects MQL5. D’une part, nous utilisons l’indicateur Momentum pour mesurer l’impact de l’ensemble donné de nouvelles dans une paire de devises. D’autre part, nous travaillerons avec les fonctions de fichier MQL5 pour stocker notre calendrier d’actualités préféré dans le système de fichiers. Le format de fichier choisi est CSV. Nous allons programmer ce robot sous le paradigme orienté objet, bien sûr, avec l’approche conceptuelle discutée dans Une autre classe MQL5 POO. Notre conception orientée objet chargera le fichier CSV dans la mémoire de l’ordinateur afin que l’EA puisse prendre des décisions basées sur ces informations.


1.2. Le squelette de la POO du robot

Désormais, nous concevons nos EA du point de vue de concepts, comme s’il s’agissait de créatures vivantes. Nous sommes maintenant des gens de la POO, vous souvenez-vous ? Grâce à cette vision, nous pouvons composer notre Expert Advisor de plusieurs parties telles qu’un cerveau, ce que nous appelons l’évolution, un ensemble d'indicateurs et un ensemble de nouvelles. Je vais clarifier tout cela ci-dessous.

//+---------------------------------------------------------------------+
//|                                               ExpertNewsWatcher.mq5 |
//|                    Copyright © 2013, laplacianlab, Jordi Bassagañas | 
//+---------------------------------------------------------------------+

#property copyright     "Copyright © 2013, laplacianlab. Jordi Bassagañas"
#property link          "https://www.mql5.com/fr/articles"
#property version       "1.00"
#property tester_file   "news_watcher.csv"  

#include <..\Experts\NewsWatcher\CNewsWatcher.mqh>

input ENUM_TIMEFRAMES   Period=PERIOD_M1;
input int               StopLoss=400;
input int               TakeProfit=600;
input double            LotSize=0.01;
input string            CsvFile="news_watcher.csv";
 
MqlTick tick;
CNewsWatcher* NW = new CNewsWatcher(StopLoss,TakeProfit,LotSize,CsvFile);

int OnInit(void)
  {
   NW.Init();
   NW.GetTechIndicators().GetMomentum().SetHandler(Symbol(), Period, 13, PRICE_CLOSE);
   return(0);
  }

void OnDeinit(const int reason)
  {
   delete(NW);
  }

void OnTick()
  {
   SymbolInfoTick(_Symbol, tick);              
   NW.GetTechIndicators().GetMomentum().UpdateBuffer(2);
   NW.OnTick(tick.ask,tick.bid);
  }
//+------------------------------------------------------------------+

CNewsWatcher est la classe principale de l’EA. Jetons un coup d’œil au code.

//+---------------------------------------------------------------------+
//|                                                    CNewsWatcher.mqh |
//|                                  Copyright © 2013, Jordi Bassagañas |
//+---------------------------------------------------------------------+
#include <Trade\Trade.mqh>
#include <Mine\Enums.mqh>
#include <..\Experts\NewsWatcher\CBrain.mqh>
#include <..\Experts\NewsWatcher\CEvolution.mqh>
#include <..\Experts\NewsWatcher\CTechIndicators.mqh>
//+---------------------------------------------------------------------+
//| CNewsWatcher Class                                                  |
//+---------------------------------------------------------------------+
class CNewsWatcher
  {
protected:
   //--- Custom types
   CBrain               *m_brain;
   CEvolution           *m_evolution;
   CTechIndicators      *m_techIndicators; 
   //--- MQL5 types
   CTrade               *m_trade;
   CPositionInfo        *m_positionInfo;
public:
   //--- Constructor and destructor methods
                        CNewsWatcher(int stop_loss,int take_profit,double lot_size,string csv_file);
                        ~CNewsWatcher(void);
   //--- Getter methods
   CBrain               *GetBrain(void);
   CEvolution           *GetEvolution(void);
   CTechIndicators      *GetTechIndicators(void);
   CTrade               *GetTrade(void);
   CPositionInfo        *GetPositionInfo(void);
   //--- CNewsWatcher methods
   bool                 Init();
   void                 Deinit(void);
   void                 OnTick(double ask,double bid);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CNewsWatcher::CNewsWatcher(int stop_loss,int take_profit,double lot_size, string csv_file)
  {
   m_brain=new CBrain(stop_loss,take_profit,lot_size,csv_file);
   m_evolution=new CEvolution(DO_NOTHING);
   m_techIndicators=new CTechIndicators;
   m_trade=new CTrade();
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CNewsWatcher::~CNewsWatcher(void)
  {
   Deinit();
  }
//+------------------------------------------------------------------+
//| GetBrain                                                         |
//+------------------------------------------------------------------+
CBrain *CNewsWatcher::GetBrain(void)
  {
   return m_brain;
  }
//+------------------------------------------------------------------+
//| GetEvolution                                                     |
//+------------------------------------------------------------------+
CEvolution *CNewsWatcher::GetEvolution(void)
  {
   return m_evolution;
  }
//+------------------------------------------------------------------+
//| GetTechIndicators                                                |
//+------------------------------------------------------------------+
CTechIndicators *CNewsWatcher::GetTechIndicators(void)
  {
   return m_techIndicators;
  }  
//+------------------------------------------------------------------+
//| GetTrade                                                         |
//+------------------------------------------------------------------+
CTrade *CNewsWatcher::GetTrade(void)
  {
   return m_trade;
  }
//+------------------------------------------------------------------+
//| GetPositionInfo                                                  |
//+------------------------------------------------------------------+
CPositionInfo *CNewsWatcher::GetPositionInfo(void)
  {
   return m_positionInfo;
  }
//+------------------------------------------------------------------------+
//| CNewsWatcher OnTick                                                    |
//| Checks momentum's turbulences around the time of the news release      |
//+------------------------------------------------------------------------+
void CNewsWatcher::OnTick(double ask,double bid)
  {
//--- are there some news to process?  
   if(GetBrain().GetNewsContainer().GetCurrentIndex() < GetBrain().GetNewsContainer().GetTotal())
   {     
      double momentumBuffer[];
      
      GetTechIndicators().GetMomentum().GetBuffer(momentumBuffer, 2);
      
      //--- Number of seconds before the news releases. GMT +- timeWindow is the real time from which the robot starts 
      //--- listening to the market. For instance, if there is a news release programmed at 13:00 GMT you can set TimeWindow 
      //--- to 900 seconds so that the EA starts listening to the market fifteen minutes before that news release. 
      int timeWindow=600;
      
      CNew *currentNew = GetBrain().GetNewsContainer().GetCurrentNew();      
      int indexCurrentNew = GetBrain().GetNewsContainer().GetCurrentIndex();
            
      if(TimeGMT() >= currentNew.GetTimeRelease() + timeWindow)
      {
         GetBrain().GetNewsContainer().SetCurrentIndex(indexCurrentNew+1);
         return;
      }
      
      //--- is there any open position?
      if(!m_positionInfo.Select(_Symbol))
      {
         //--- if there is no open position, we try to open one
         bool timeHasCome = TimeGMT() >= currentNew.GetTimeRelease() - timeWindow && TimeGMT() <= currentNew.GetTimeRelease() + timeWindow;
             
         if(timeHasCome && momentumBuffer[0] > 100.10)
         {
            GetEvolution().SetStatus(SELL);
            GetBrain().GetNewsContainer().SetCurrentIndex(indexCurrentNew+1);
         }
         else if(timeHasCome && momentumBuffer[0] < 99.90)
         {
            GetEvolution().SetStatus(BUY);
            GetBrain().GetNewsContainer().SetCurrentIndex(indexCurrentNew+1);
         }
      }
      //--- if there is an open position, we let it work the mathematical expectation
      else 
      {
         GetEvolution().SetStatus(DO_NOTHING);         
      }  
      
      double tp;
      double sl; 

      switch(GetEvolution().GetStatus())
      {      
         case BUY:
            tp = ask + m_brain.GetTakeProfit() * _Point;
            sl = bid - m_brain.GetStopLoss() * _Point;
            GetTrade().PositionOpen(_Symbol,ORDER_TYPE_BUY,m_brain.GetSize(),ask,sl,tp);
            break;

         case SELL:
            sl = ask + m_brain.GetStopLoss() * _Point;
            tp = bid - m_brain.GetTakeProfit() * _Point;
            GetTrade().PositionOpen(_Symbol,ORDER_TYPE_SELL,m_brain.GetSize(),bid,sl,tp);
            break;

         case DO_NOTHING:
            // Nothing...
            break;
      }
   }   
//--- we exit when all the container's news have been processed
   else return;
  }
//+------------------------------------------------------------------+
//| CNewsWatcher initialization                                      |
//+------------------------------------------------------------------+
bool CNewsWatcher::Init(void)
  {
// Initialization logic here...
   return true;
  }
//+------------------------------------------------------------------+
//| CNewsWatcher deinitialization                                    |
//+------------------------------------------------------------------+
void CNewsWatcher::Deinit(void)
  {
   delete(m_brain);
   delete(m_evolution);
   delete(m_techIndicators);
   delete(m_trade);
   Print("CNewsWatcher deinitialization performed!");
   Print("Thank you for using this EA.");
  }
//+------------------------------------------------------------------+

Pour l’instant, ne vous inquiétez pas si vous ne voyez pas les choses très clairement, c’est normal. Tout d’abord, vous devez étudier toutes les parties de cet Expert Advisor pour comprendre comment tout fonctionne. Je vous recommande de lire d’abord superficiellement cet article, puis de faire une deuxième et une troisième lectures plus approfondies. Quoi qu’il en soit, je vais essayer d’expliquer à ce moment quelques parties clés de CNewsWatcher.

La partie la plus importante de l’EA est bien sûr la méthode OnTick où vous verrez que CNewsWatcher utilise un conteneur de nouvelles OO pour fonctionner. Cet article, qui peut être considéré comme un journal du monde réel, contient les nouvelles que l’utilisateur d’EA veut échanger. 

Notez que nous récupérons le conteneur de nouvelles comme ceci :

GetBrain().GetNewsContainer();

Et nous récupérons les nouvelles actuelles à traiter de cette façon :

CNew *currentNew = GetBrain().GetNewsContainer().GetCurrentNew();   

Cela se fait via CBrain. Rappelez-vous que CBrain est un point central important dans notre conception orientée objet contenant les choses nécessaires pour que l’EA puisse fonctionner correctement, c’est quelque chose comme une mémoire en lecture seule (ROM).

//+------------------------------------------------------------------+
//|                                                       CBrain.mqh |
//|                               Copyright © 2013, Jordi Bassagañas |
//+------------------------------------------------------------------+
#include <..\Experts\NewsWatcher\CNewsContainer.mqh>
//+------------------------------------------------------------------+
//| CBrain Class                                                     |
//+------------------------------------------------------------------+
class CBrain
  {
protected:
   double               m_size;                 // The size of the positions
   int                  m_stopLoss;             // Stop loss
   int                  m_takeProfit;           // Take profit
   CNewsContainer       *m_news_container;      // The news container

public:
   //--- Constructor and destructor methods
                        CBrain(int stopLoss,int takeProfit,double size,string csv);
                        ~CBrain(void);
   //--- Getter methods
   double               GetSize(void);
   int                  GetStopLoss(void);
   int                  GetTakeProfit(void);
   CNewsContainer       *GetNewsContainer(void);
   //--- Setter methods
   void                 SetSize(double size);
   void                 SetStopLoss(int stopLoss);
   void                 SetTakeProfit(int takeProfit);
   //--- CBrain specific methods
   bool                 Init();
   void                 Deinit(void);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CBrain::CBrain(int stopLoss,int takeProfit,double size,string csv)
  {
   m_size=size;
   m_stopLoss=stopLoss;
   m_takeProfit=takeProfit;
   m_news_container=new CNewsContainer(csv);   
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CBrain::~CBrain(void)
  {
   Deinit();
  }
//+------------------------------------------------------------------+
//| GetSize                                                          |
//+------------------------------------------------------------------+
double CBrain::GetSize(void)
  {
   return m_size;
  }
//+------------------------------------------------------------------+
//| GetStopLoss                                                      |
//+------------------------------------------------------------------+
int CBrain::GetStopLoss(void)
  {
   return m_stopLoss;
  }
//+------------------------------------------------------------------+
//| GetTakeProfit                                                    |
//+------------------------------------------------------------------+
int CBrain::GetTakeProfit(void)
  {
   return m_takeProfit;
  }
//+------------------------------------------------------------------+
//| GetNewsContainer                                                 |
//+------------------------------------------------------------------+
CNewsContainer *CBrain::GetNewsContainer(void)
  {
   return m_news_container;
  }
//+------------------------------------------------------------------+
//| SetSize                                                          |
//+------------------------------------------------------------------+
void CBrain::SetSize(double size)
  {
   m_size=size;
  }
//+------------------------------------------------------------------+
//| SetStopLoss                                                      |
//+------------------------------------------------------------------+
void CBrain::SetStopLoss(int stopLoss)
  {
   m_stopLoss=stopLoss;
  }
//+------------------------------------------------------------------+
//| SetTakeProfit                                                    |
//+------------------------------------------------------------------+
void CBrain::SetTakeProfit(int takeProfit)
  {
   m_takeProfit=takeProfit;
  }
//+------------------------------------------------------------------+
//| CBrain initialization                                            |
//+------------------------------------------------------------------+
bool CBrain::Init(void)
  {
// Initialization logic here...
   return true;
  }
//+------------------------------------------------------------------+
//| CBrain deinitialization                                          |
//+------------------------------------------------------------------+
void CBrain::Deinit(void)
  {
   delete(m_news_container);
   Print("CBrain deinitialization performed!");
  }
//+------------------------------------------------------------------+

CNewsWatcher lit essentiellement une par une les nouvelles stockées dans le conteneur (le journal). Si, à ce moment-là, il y a une forte accélération du prix, il passe un ordre sur le marché.

En ce qui concerne l’achat ou la vente de lots, le robot est programmé de manière réactive. Disons que lorsqu’un fort mouvement à la hausse se produit, l’EA suppose que le prix se rétractera et se vendra donc. De même, lorsqu’il y a un fort mouvement à la baisse, le robot place une position longue sur le marché en pensant que le prix va retracer en bref. Cela peut être amélioré, bien sûr, dans cet article, il n’y a pas assez d’espace pour développer un trader automatique de nouvelles très efficace, comme dit précédemment, l’objectif est de vous donner les bases techniques afin que vous puissiez continuer à avancer dans vos propres développements.

Robot on the Taff

Figure 2. Robot on the Taff. Image distribuée sous licence Creative Commons sur Flickr


1.3. Un conteneur orienté objet pour les indicateurs techniques


Encore une fois, comme nous avons décidé d’aborder nos applications du point de vue des concepts, il est intéressant de programmer nos propres wrappers orientés objet pour que les indicateurs techniques adhèrent au nouveau paradigme. Ainsi, cette pièce du puzzle s’adapte beaucoup mieux à tout. Disons que dans cette partie de notre développement, nous en profitons pour construire quelque chose comme un framework orienté objet afin de travailler plus confortablement avec ce matériel MQL5 qui n'est pas très OO à l'origine.

À ce stade, il est intéressant de noter qu’il existe la bibliothèque standard MQL5. Cette bibliothèque est conçue pour faciliter l’écriture de programmes (indicateurs, scripts, experts) aux utilisateurs finaux, offrant un accès pratique à la plupart des fonctions internes de MQL5. En fait, dans l’exercice d’aujourd’hui, nous utilisons certaines fonctionnalités de la bibliothèque standard car, comme on l’a dit, elles sont beaucoup plus confortables du point de vue de la programmation OO. Un exemple clair est le conteneur de nouvelles que j’expliquerai un peu plus tard, nous utiliserons la classe MQL5 CArrayObj là pour stocker dans la RAM de l’ordinateur nos nouvelles personnalisées orientées objet de type complexe.

Veuillez consulter la documentation officielle intitulée Bibliothèque standard pour en savoir plus sur ce sujet et notez que la bibliothèque standard est déjà livrée avec des classes pour travailler avec des indicateurs. Cet article traite de la nécessité de travailler avec du matériel orienté objet à travers quelques exemples simples à des fins d’enseignement.

1.3.1. CTechIndicators, le conteneur des indicateurs techniques
//+------------------------------------------------------------------+
//|                                              CTechIndicators.mqh |
//|                               Copyright © 2013, Jordi Bassagañas |
//+------------------------------------------------------------------+
#include <..\Experts\NewsWatcher\CMomentum.mqh>
//+------------------------------------------------------------------+
//| CTechIndicators Class                                            |
//+------------------------------------------------------------------+
class CTechIndicators
  {
protected:
   CMomentum               *m_momentum;
                  
public:
   //--- Constructor and destructor methods
                           CTechIndicators(void);
                           ~CTechIndicators(void);
   //--- Getter methods
   CMomentum               *GetMomentum(void);
   //--- CTechIndicators specific methods
   bool                 Init();
   void                 Deinit(void);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+   
CTechIndicators::CTechIndicators(void)
  {
   m_momentum = new CMomentum; 
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+               
CTechIndicators::~CTechIndicators(void)
  {
   Deinit();
  }
//+------------------------------------------------------------------+
//| GetMomentum                                                      |
//+------------------------------------------------------------------+        
CMomentum* CTechIndicators::GetMomentum(void)
  {
   return m_momentum;
  }
//+------------------------------------------------------------------+
//| CTechIndicators initialization                                   |
//+------------------------------------------------------------------+
bool CTechIndicators::Init(void)
  {
// Initialization logic here...
   return true;
  }
//+------------------------------------------------------------------+
//| CTechIndicators deinitialization                                 |
//+------------------------------------------------------------------+
void CTechIndicators::Deinit(void)
  {
   delete(m_momentum);
   Print("CTechIndicators deinitialization performed!");
  }
//+------------------------------------------------------------------+
1.3.2. CMomentum, un wrapper orienté objet pour iMomentum
//+------------------------------------------------------------------+
//|                                                    CMomentum.mqh |
//|                               Copyright © 2013, Jordi Bassagañas |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| CMomentum Class                                                  |
//+------------------------------------------------------------------+

class CMomentum
  {
protected:   
   int m_handler;
   double m_buffer[];
               
public:
   //--- Constructor and destructor methods
                           CMomentum(void);
                           ~CMomentum(void);
   //--- Getter methods
   int                     GetHandler(void);
   void                    GetBuffer(double &buffer[], int ammount);
   //--- Setter methods
   bool                    SetHandler(string symbol,ENUM_TIMEFRAMES period,int mom_period,ENUM_APPLIED_PRICE mom_applied_price);
   bool                    UpdateBuffer(int ammount);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+   
CMomentum::CMomentum(void)
  {
   ArraySetAsSeries(m_buffer, true);   
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+               
CMomentum::~CMomentum(void)
  {
   IndicatorRelease(m_handler);
   ArrayFree(m_buffer);
  }
//+------------------------------------------------------------------+
//| GetHandler                                                       |
//+------------------------------------------------------------------+        
int CMomentum::GetHandler(void)
  {
   return m_handler;
  }
//+------------------------------------------------------------------+
//| GetBuffer                                                        |
//+------------------------------------------------------------------+
void CMomentum::GetBuffer(double &buffer[], int ammount)
  {
   ArrayCopy(buffer, m_buffer, 0, 0, ammount);
  }
//+------------------------------------------------------------------+
//| SetHandler                                                       |
//+------------------------------------------------------------------+      
bool CMomentum::SetHandler(string symbol,ENUM_TIMEFRAMES period,int mom_period,ENUM_APPLIED_PRICE mom_applied_price)
  {   
   if((m_handler=iMomentum(symbol,period,mom_period,mom_applied_price))==INVALID_HANDLE)
   {
      printf("Error creating Momentum indicator");
      return false;
   }
   return true;
  }
//+------------------------------------------------------------------+
//| UpdateBuffer                                                     |
//+------------------------------------------------------------------+   
bool CMomentum::UpdateBuffer(int ammount)
  {   
   if(CopyBuffer(m_handler, 0, 0, ammount, m_buffer) < 0)
   { 
      Alert("Error copying Momentum buffers, error: " , GetLastError());
      return false;
   }
   return true;
  }
//+------------------------------------------------------------------+


1.4. Un conteneur orienté objet pour l’actualité

Les nouvelles dans l’abstrait sont une pièce fondamentale avec laquelle notre EA doit faire face. Nous pouvons penser dans cet article clé comme s’il s’agissait d’un journal afin de conclure que c’est une bonne idée de l’encapsuler dans un conteneur de nouvelles orienté objet. En termes simples, ce conteneur OO, nommé CNewsContainer, est le journal. Et bien sûr, si nous pouvons imaginer un journal avec des nouvelles, nous devons également modéliser le concept de l’information qui, dans notre domaine des choses, s’appelle CNew. Il s’agit de notre type personnalisé orienté objet représentant les nouvelles du monde réel.

1.4.1. CNewsContainer, le conteneur de nouvelles

//+------------------------------------------------------------------+
//|                                               CNewsContainer.mqh |
//|                               Copyright © 2013, Jordi Bassagañas |
//+------------------------------------------------------------------+
#include <Files\FileTxt.mqh>
#include <Arrays\ArrayObj.mqh>
#include <..\Experts\NewsWatcher\CNew.mqh>
//+------------------------------------------------------------------+
//| CNewsContainer Class                                             |
//+------------------------------------------------------------------+
class CNewsContainer
  {
protected:
   string               m_csv;                  // The name of the csv file
   CFileTxt             m_fileTxt;              // MQL5 file functionality
   int                  m_currentIndex;         // The index of the next news to be processed in the container
   int                  m_total;                // The total number of news to be processed
   CArrayObj            *m_news;                // News list in the computer's memory, loaded from the csv file

public:
   //--- Constructor and destructor methods
                        CNewsContainer(string csv);
                        ~CNewsContainer(void);
   //--- Getter methods
   int                  GetCurrentIndex(void);
   int                  GetTotal(void);
   CNew                 *GetCurrentNew();
   CArrayObj            *GetNews(void);
   //--- Setter methods
   void                 SetCurrentIndex(int index);
   void                 SetTotal(int total);
   void                 SetNews(void);
   //--- CNewsContainer methods
   bool                 Init();
   void                 Deinit(void);
  };
//+------------------------------------------------------------------+
//| Constuctor                                                       |
//+------------------------------------------------------------------+
CNewsContainer::CNewsContainer(string csv)
  {
   m_csv=csv;
   m_news=new CArrayObj;
   SetNews();
   }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CNewsContainer::~CNewsContainer(void)
  {
   Deinit();
  }
//+------------------------------------------------------------------+
//| GetCurrentIndex                                                  |
//+------------------------------------------------------------------+
int CNewsContainer::GetCurrentIndex(void)
  {   
   return m_currentIndex;
  }
//+------------------------------------------------------------------+
//| GetTotal                                                         |
//+------------------------------------------------------------------+
int CNewsContainer::GetTotal(void)
  {   
   return m_total;
  }
//+------------------------------------------------------------------+
//| GetNews                                                          |
//+------------------------------------------------------------------+
CArrayObj *CNewsContainer::GetNews(void)
  {   
   return m_news;
  }
//+------------------------------------------------------------------+
//| GetCurrentNew                                                    |
//+------------------------------------------------------------------+
CNew *CNewsContainer::GetCurrentNew(void)
  {   
   return m_news.At(m_currentIndex);
  }
//+------------------------------------------------------------------+
//| SetCurrentIndex                                                  |
//+------------------------------------------------------------------+
void CNewsContainer::SetCurrentIndex(int index)
  {
   m_currentIndex=index;
  }
//+------------------------------------------------------------------+
//| SetTotal                                                         |
//+------------------------------------------------------------------+
void CNewsContainer::SetTotal(int total)
  {
   m_total=total;
  }
//+------------------------------------------------------------------+
//| SetNews                                                          |
//+------------------------------------------------------------------+
void CNewsContainer::SetNews(void)
  {
   //--- let's first init some vars!
   SetCurrentIndex(0);
   string sep= ";";
   ushort u_sep;
   string substrings[];   
   u_sep=StringGetCharacter(sep,0);   
   //--- then open and process the CSV file
   int file_handle=m_fileTxt.Open(m_csv, FILE_READ|FILE_CSV);
   if(file_handle!=INVALID_HANDLE)
   {
      while(!FileIsEnding(file_handle))
      {               
         string line = FileReadString(file_handle);         
         int k = StringSplit(line,u_sep,substrings);         
         CNew *current = new CNew(substrings[0],(datetime)substrings[1],substrings[2]);         
         m_news.Add(current);
      }
      FileClose(file_handle);
      //--- and finally refine and count the news
      m_news.Delete(0); // --- here we delete the CSV's header!
      SetTotal(m_news.Total());
   }
   else
   {
      Print("Failed to open the file ",m_csv);
      Print("Error code ",GetLastError());
   }   
  }
//+------------------------------------------------------------------+
//| CNewsContainer initialization                                    |
//+------------------------------------------------------------------+
bool CNewsContainer::Init(void)
  {
// Initialization logic here...
   return true;
  }
//+------------------------------------------------------------------+
//| CNewsContainer deinitialization                                  |
//+------------------------------------------------------------------+
void CNewsContainer::Deinit(void)
  {
   m_news.DeleteRange(0, m_total-1);
   delete(m_news);
   Print("CNewsContainer deinitialization performed!");
  }
//+------------------------------------------------------------------+

SetNews est la méthode la plus importante de CNewsContainer. Cette méthode lit le fichier CSV et le charge dans la RAM de l’ordinateur sous la forme d’objets de type CNew. Au fait, je n’ai toujours pas dit, les fichiers CSV doivent être stockés dans data_folder\MQL5\FILES\. Veuillez consulter Fonctions de fichier pour une compréhension plus approfondie des fonctions utilisées dans SetNews.

1.4.2. CNew, les nouvelles elles-mêmes

//+------------------------------------------------------------------+
//|                                                         CNew.mqh |
//|                               Copyright © 2013, Jordi Bassagañas |
//+------------------------------------------------------------------+
#include <Object.mqh>
//+------------------------------------------------------------------+
//| CNew Class                                                       |
//+------------------------------------------------------------------+
class CNew : public CObject
  {
protected:
   string            m_country;           // The country's name
   datetime          m_time_release;      // The date and time of the news
   string            m_name;              // The name of the news
   
public:
   //--- Constructor and destructor methods
                     CNew(string country,datetime time_release,string name);
                    ~CNew(void);
   //--- Getter methods
   string            GetCountry(void);
   datetime          GetTimeRelease(void);
   string            GetName(void);
   //--- Setter methods
   void              SetCountry(string country);
   void              SetTimeRelease(datetime time_release);
   void              SetName(string name);
   //--- CNew specific methods
   bool              Init();
   void              Deinit(void);
  };
//+------------------------------------------------------------------+
//| Constuctor                                                       |
//+------------------------------------------------------------------+
CNew::CNew(string country,datetime time_release,string name)
  {
   m_country=country;
   m_time_release=time_release;
   m_name=name;
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CNew::~CNew(void)
  {
   Deinit();
  }
//+------------------------------------------------------------------+
//| GetCountry                                                       |
//+------------------------------------------------------------------+
string CNew::GetCountry(void)
  {
   return m_country;
  }  
//+------------------------------------------------------------------+
//| GetTimeRelease                                                   |
//+------------------------------------------------------------------+
datetime CNew::GetTimeRelease(void)
  {
   return m_time_release;
  }
//+------------------------------------------------------------------+
//| GetName                                                          |
//+------------------------------------------------------------------+
string CNew::GetName(void)
  {
   return m_name;
  }
//+------------------------------------------------------------------+
//| SetCountry                                                       |
//+------------------------------------------------------------------+
void CNew::SetCountry(string country)
  {
   m_country=country;
  }
//+------------------------------------------------------------------+
//| SetTimeRelease                                                   |
//+------------------------------------------------------------------+
void CNew::SetTimeRelease(datetime timeRelease)
  {
   m_time_release=timeRelease;
  }
//+------------------------------------------------------------------+
//| SetName                                                          |
//+------------------------------------------------------------------+
void CNew::SetName(string name)
  {
   m_name=name;
  }
//+------------------------------------------------------------------+
//| CNew initialization                                              |
//+------------------------------------------------------------------+
bool CNew::Init(void)
  {
//--- initialization logic here...
   return true;
  }
//+------------------------------------------------------------------+
//| CNew deinitialization                                            |
//+------------------------------------------------------------------+
void CNew::Deinit(void)
  {
//--- deinitialization logic here...
   Print("CNew deinitialization performed!");
  }
//+------------------------------------------------------------------+


2. Backtesting ExpertNewsWatcher.mq5


2.1. Pièces jointes

ExpertNewsWatcher est composé des fichiers suivants :

  • Enums.mqh
  • CBrain.mqh
  • CEvolution.mqh
  • CMomentum.mqh
  • CNew.mqh
  • CNewsContainer.mqh
  • CNewsWatcher.mqh
  • CTechIndicators.mqh
  • ExpertNewsWatcher.mq5
  • news_watcher.txt

2.2. Instructions d’installation

Tout d’abord, vous devez créer le dossier MQL5\Include\Mine pour stocker vos éléments personnalisés, puis copiez le fichier Enums.mqh là-bas. Juste après cela, vous devez créer le dossier MQL5\Experts\NewsWatcher et copier les fichiers ci-dessous:

  • CBrain.mqh
  • CEvolution.mqh
  • CMomentum.mqh
  • CNew.mqh
  • CNewsContainer.mqh
  • CNewsWatcher.mqh
  • CTechIndicators.mqh
  • ExpertNewsWatcher.mq5

Remarque très importante ! Enfin, veuillez prendre news_watcher.txt, renommez-le en news_watcher.csv et mettez-le dans data_folder\MQL5\FILES\. Au moment de la publication de ce document, la soumission de formulaire MQL5 ne permet pas l’envoi de fichiers .csv, mais elle permet l’envoi de fichiers .txt.

N’oubliez pas de compiler. À partir de ce point, vous pouvez backtester ExpertNewsWatcher comme vous le feriez pour n’importe quel autre Expert Advisor.


2.3. Résultats des backtests

ExpertNewsWatcher a été exécuté avec ces paramètres d’entrée initiaux.

  • Période = 1 minute
  • StopLoss = 400
  • TakeProfit = 600
  • LotSize = 0,01
  • CsvFile = news_watcher.csv

J’ai d’abord utilisé les données fictives suivantes contenant un ensemble de nouvelles fictives espacées dans le temps pour voir comment le robot se comportait dans un environnement contrôlé. En effet, ces périodes satisfont aux conditions préalables établies, c’est-à-dire qu’à ces moments-là, l’élan est suffisamment important pour déclencher les actions d’achat ou de vente. Vous pouvez prendre cette feuille d’entrées pour tester tout ce que vous considérez.

Quelques données factices à stocker dans news_watcher.csv :

Country;Time;Event
USD;2013.06.03 17:19:00;A. Momentum equals 100.47
USD;2013.06.13 17:09:00;B. Momentum equals 100.40
USD;2013.06.21 18:52:00;C. Momentum equals 100.19
USD;2013.07.01 17:32:00;D. Momentum equals 100.18 
USD;2013.07.08 15:17:00;E. Momentum equals 100.18
USD;2013.07.16 10:00:00;F. Momentum equals 99.81
USD;2013.07.24 09:30:00;G. Momentum equals 100.25


Résultats obtenus avec des données fictives

Figure 3. Résultats obtenus avec des données fictives

Le graphique ci-dessus contenant des nouvelles fictives vous aidera à comprendre comment ce robot pourrait se comporter dans un environnement réel. Veuillez prendre les données réelles suivantes tirées de DailyFX,, placez-les dans news_watcher.csv et exécutez à nouveau ExpertNewsWatcher.

Quelques données réelles à stocker dans news_watcher.csv :

Country;Time;Event
USD;2013.07.15 12:00:00;USD Fed's Tarullo Speaks on Banking Regulation in Washington 
USD;2013.07.15 12:30:00;USD Advance Retail Sales (JUN) and others
USD;2013.07.15 14:00:00;USD USD Business Inventories (MAY)
USD;2013.07.15 21:00:00;USD EIA Gasoline and Diesel Fuel Update
USD;2013.07.16 12:30:00;USD Several Consumer Price Indexes 
USD;2013.07.16 13:00:00;USD USD Net Long-term TIC Flows (MAY) & USD Total Net TIC Flows (MAY)
USD;2013.07.16 13:15:00;USD Industrial Production (JUN) and others
USD;2013.07.16 14:00:00;USD NAHB Housing Market Index (JUL)
USD;2013.07.16 18:15:00;USD Fed's George Speaks on Economic Conditions and Agriculture
USD;2013.07.22 12:30:00;USD Chicago Fed Nat Activity Index (JUN)
USD;2013.07.22 14:00:00;USD Existing Home Sales (MoM) (JUN) & Existing Home Sales (JUN)
USD;2013.07.22 21:00:00;USD EIA Gasoline and Diesel Fuel Update
USD;2013.07.23 13:00:00;USD House Price Index (MoM) (MAY)
USD;2013.07.23 14:00:00;USD Richmond Fed Manufacturing Index (JUL)
USD;2013.07.24 11:00:00;USD MBA Mortgage Applications (JUL 19)
USD;2013.07.24 12:58:00;USD Markit US PMI Preliminary (JUL)
USD;2013.07.24 14:00:00;USD USD New Home Sales (MoM) (JUN) & USD New Home Sales (JUN)
USD;2013.07.24 14:30:00;USD USD DOE U.S. Crude Oil Inventories (JUL 19) and others



Résultats obtenus avec des données réelles

Figure 4. Résultats obtenus avec des données réelles

Ce simple processeur de nouvelles ne peut répondre qu’à une seule nouvelle qui a lieu dans un certain temps. C’est pour cette raison qu’une heure spécifique, par exemple, 2013.07.15 12:30:00, peut contenir plusieurs nouvelles. Si plusieurs nouvelles importantes se produisent à un moment donné, veuillez écrire une seule entrée dans le fichier CSV.

Cela dit, observez que l’EA ne met que trois opérations sur le marché lorsqu’elle travaille avec des données réelles. En effet, dans la vie réelle, certaines nouvelles se chevaucheront, contrairement à l’ensemble précédent de nouvelles fictives espacées dans le temps. Notre robot est prévu pour fermer d’abord la première opération qui est venue de la série, ignorant une nouvelle entrante alors qu’il y a déjà une position ouverte.

       double momentumBuffer[];
      
      GetTechIndicators().GetMomentum().GetBuffer(momentumBuffer, 2);
      
      //--- Number of seconds before the news releases. GMT +- timeWindow is the real time from which the robot starts 
      //--- listening to the market. For instance, if there is a news release programmed at 13:00 GMT you can set TimeWindow 
      //--- to 900 seconds so that the EA starts listening to the market fifteen minutes before that news release. 
      int timeWindow=600;
      
      CNew *currentNew = GetBrain().GetNewsContainer().GetCurrentNew();      
      int indexCurrentNew = GetBrain().GetNewsContainer().GetCurrentIndex();
            
      if(TimeGMT() >= currentNew.GetTimeRelease() + timeWindow)
      {
         GetBrain().GetNewsContainer().SetCurrentIndex(indexCurrentNew+1);
         return;
      }
      
      //--- is there any open position?
      if(!m_positionInfo.Select(_Symbol))
      {
         //--- if there is no open position, we try to open one
         bool timeHasCome = TimeGMT() >= currentNew.GetTimeRelease() - timeWindow && TimeGMT() <= currentNew.GetTimeRelease() + timeWindow;
             
         if(timeHasCome && momentumBuffer[0] > 100.10)
         {
            GetEvolution().SetStatus(SELL);
            GetBrain().GetNewsContainer().SetCurrentIndex(indexCurrentNew+1);
         }
         else if(timeHasCome && momentumBuffer[0] < 99.90)
         {
            GetEvolution().SetStatus(BUY);
            GetBrain().GetNewsContainer().SetCurrentIndex(indexCurrentNew+1);
         }
      }
      //--- if there is an open position, we let it work the mathematical expectation
      else 
      {
         GetEvolution().SetStatus(DO_NOTHING);         
      }  


Conclusion

Cela a été la suite d’un autre article sur la classe MQL5 POO, qui vous a montré comment créer un EA OO simple à partir de zéro et vous a donné quelques conseils sur la programmation orientée objet. Suivant la même ligne, ce texte vous a donné les outils nécessaires pour vous aider à construire vos propres traders de nouvelles. Nous avons couvert la mise en œuvre de conteneurs orientés objet et d’emballages orientés objet afin de pouvoir travailler confortablement avec nos conceptions OO. Nous avons également discuté de la bibliothèque standard MQL5 et des fonctions MQL5 pour fonctionner avec le système de fichiers.

Traduit de l’anglais par MetaQuotes Ltd.
Article original : https://www.mql5.com/en/articles/719

Fichiers joints |
cbrain__2.mqh (4.82 KB)
cevolution__2.mqh (2.07 KB)
cmomentum.mqh (3.35 KB)
cnew.mqh (4.32 KB)
enums__2.mqh (0.92 KB)
news_watcher.txt (1.27 KB)
cnewscontainer.mqh (5.95 KB)
cnewswatcher.mqh (7.61 KB)
Le MQL5 Wizard : Comment apprendre à un EA à ouvrir des ordres en attente à n’importe quel prix Le MQL5 Wizard : Comment apprendre à un EA à ouvrir des ordres en attente à n’importe quel prix
L’article décrit une méthode de modification du code d’un module de signal de trading pour la mise en œuvre de la fonctionnalité vous permettant de définir des ordres en attente à n’importe quelle distance du prix actuel : il peut s’agir du prix close ou open de la barre précédente ou de la valeur de la moyenne mobile. Il y a beaucoup d’options. Il est important que vous puissiez définir n’importe quel prix d’ouverture pour un ordre en attente. Cet article sera utile aux traders qui tradent avec des ordres en attente.
Création d’EA de réseau de neurones en utilisant MQL5 Wizard et Hlaiman EA Generator Création d’EA de réseau de neurones en utilisant MQL5 Wizard et Hlaiman EA Generator
L’article décrit une méthode de création automatisée d’EA de réseau de neurones en utilisant MQL5 Wizard et Hlaiman EA Generator. Il vous montre comment vous pouvez facilement commencer à travailler avec des réseaux de neurones, sans avoir à apprendre tout le corps des informations théoriques et à écrire votre propre code.
Émerveillez vos clients MQL5 avec un cocktail de technologies utilisables ! Émerveillez vos clients MQL5 avec un cocktail de technologies utilisables !
MQL5 fournit aux programmeurs un ensemble très complet de fonctions et d'API orientées objet grâce auxquelles ils peuvent faire tout ce qu'ils veulent dans l'environnement MetaTrader. Cependant, la technologie Web est un outil extrêmement polyvalent de nos jours qui peut venir à la rescousse dans certaines situations lorsque vous devez faire quelque chose de très spécifique, voulez émerveiller vos clients avec quelque chose de différent ou tout simplement vous n'avez pas assez de temps pour maîtriser une partie spécifique de Bibliothèque standard MT5. L'exercice d'aujourd'hui vous présente un exemple pratique sur la façon dont vous pouvez gérer votre temps de développement tout en créant un cocktail technologique incroyable.
Une autre classe MQL5 OOP Une autre classe MQL5 OOP
Cet article vous montre comment créer un Expert Advisor orienté objet à partir de zéro, de la conception d'une idée de trading théorique à la programmation d'un EA MQL5 qui rend cette idée réelle dans le monde empirique. Apprendre par la pratique est à mon humble avis une approche solide pour réussir, je vous montre donc un exemple pratique afin que vous voyiez comment vous pouvez ordonner vos idées pour enfin coder vos robots Forex. Mon objectif est également de vous inviter à adhérer aux principes de l’OO.