English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
Costruire un trader automatico di notizie

Costruire un trader automatico di notizie

MetaTrader 5Trading | 11 gennaio 2022, 17:04
235 0
laplacianlab
[Eliminato]

Introduzione

Come afferma Investopedia, un trader di notizie è "un trader o un investitore che prende decisioni di trading o di investimento basate su annunci di notizie". In effetti, i rapporti economici come il PIL di un paese, gli indici di fiducia dei consumatori e i dati sull'occupazione dei paesi, tra gli altri, spesso producono movimenti significativi nei mercati valutari. Hai mai frequentato un U.S. Rilascio di non farm payrolls? In tal caso, sai già che questi rapporti possono determinare il futuro recente delle valute e fungere da catalizzatori per le inversioni di tendenza.

Quotidiani B/N

Figura 1. Quotidiani B/N Immagine distribuita sotto licenza Creative Commons su Flickr

1. Programmiamo il nostro EA


1.1. L'idea del sistema di trading

L'idea alla base di questo sistema è quella di cui abbiamo discusso sopra. Sembra fantastico, ma come possiamo implementare questo fatto comprovato nel mondo della programmazione? Principalmente ci affidiamo a due aspetti MQL5. Da un lato, stiamo usando l'indicatore Momentum per misurare l'impatto del dato insieme di notizie in una coppia di valute. D'altra parte, lavoreremo con le funzioni di file MQL5 per memorizzare il nostro calendario di notizie preferito nel filesystem. Il formato di file scelto è CSV. Programeremo questo robot sotto il paradigma orientato agli oggetti, ovviamente, con l'approccio concettuale discusso in Un'altra classe OOP MQL5. Il nostro design orientato agli oggetti caricherà il CSV nella memoria del computer in modo che l'EA possa prendere decisioni basate su tali informazioni.


1.2. Lo scheletro OOP del robot

D'ora in poi stiamo concependo i nostri EA come concetti, come se fossero creature viventi. Ora siamo persone OOP, ti ricordi? Grazie a questa visione possiamo comporre il nostro Expert Advisor di diverse parti come un cervello, qualcosa che chiamiamo evoluzione, un insieme di indicatori e una serie di notizie. Chiarirò tutto questo di seguito.

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

#property copyright     "Copyright © 2013, laplacianlab. Jordi Bassagañas"
#property link          "https://www.mql5.com/it/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 è la classe principale di EA. Diamo un'occhiata al codice.

//+---------------------------------------------------------------------+
//|                                                    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.");
  }
//+------------------------------------------------------------------+

Per ora, non preoccuparti se non vedi le cose molto chiaramente, è normale. Innanzitutto, devi studiare tutte le parti di questo Expert Advisor per capire come funziona tutto. Ti consiglio di leggere prima superficialmente questo articolo e poi fare una seconda e una terza lettura più approfondita. Ad ogni modo, cercherò di spiegare in questo momento alcune parti chiave di CNewsWatcher.

La parte più importante dell'EA è ovviamente il metodo OnTick in cui vedrai che CNewsWatcher utilizza un contenitore di notizie OO per funzionare. Questo pezzo, che può essere visto come un giornale del mondo reale, contiene le notizie che l'utente EA vuole scambiare. 

Si noti che recuperiamo il contenitore di notizie in questo modo:

GetBrain().GetNewsContainer();

E recuperiamo le notizie attuali da elaborare in questo modo:

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

Questo viene fatto tramite CBrain. Ricorda che CBrain è un importante punto centrale nel nostro design orientato agli oggetti contenente quelle cose necessarie affinché l'EA possa funzionare correttamente, è qualcosa come una memoria di sola lettura (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 sta fondamentalmente leggendo una per una le notizie memorizzate nel contenitore (il giornale). Se in quel momento c'è una forte accelerazione nel prezzo, allora inserisce un ordine sul mercato.

Per quanto riguarda l'acquisto o la vendita di lotti il robot è programmato in modo reattivo. Diciamo, quando si verifica un forte movimento al rialzo, l'EA presume che il prezzo si ritirerà e quindi vende. Allo stesso modo, quando c'è un forte movimento verso il basso, il robot posiziona una posizione lunga sul mercato pensando che il prezzo tornerà in breve. Questo può essere migliorato, ovviamente, in questo articolo non c'è spazio sufficiente per sviluppare un trader di notizie automatiche altamente efficiente, come detto prima, l'obiettivo è darti le basi tecniche per continuare a progredire nei tuoi sviluppi.

Robot sul robot Taff

Figura 2. Robot sul Taff. Immagine distribuita sotto licenza Creative Commons su Flickr


1.3. Un contenitore orientato agli oggetti per indicatori tecnici


Ancora una volta, poiché abbiamo deciso di affrontare le nostre app dal punto di vista dei concetti, è interessante programmare i nostri wrapper orientati agli oggetti per indicatori tecnici per aderire al nuovo paradigma. Quindi questo pezzo del puzzle si adatta molto meglio a tutto. Diciamo che in questa parte del nostro sviluppo approfittiamo per costruire qualcosa come un framework orientato agli oggetti in modo da poter lavorare più comodamente con quella roba MQL5 non molto OO fuori dalla scatola.

A questo punto, è interessante notare che esiste il MQL5 Standard Library. Questa libreria è progettata per facilitare la scrittura di programmi (indicatori, script, esperti) agli utenti finali, fornendo un comodo accesso alla maggior parte delle funzioni interne di MQL5. In effetti, nell'esercizio di oggi stiamo usando alcune funzionalità di Standard Library perché, come è stato detto, è molto più comodo dal punto di vista della programmazione OO. Un chiaro esempio è il contenitore di notizie che spiegherò un po 'più tardi, useremo la classe MQL5 CArrayObj lì per memorizzare nella RAM del computer le nostre notizie personalizzate orientate agli oggetti di tipo complesso.

Per favore, dai un'occhiata alla documentazione ufficiale intitolata Libreria standard per saperne di più su questo argomento e nota che la Libreria standard viene già fornita con alcune classi per lavorare con gli indicatori. Questo articolo discute la necessità di lavorare con materiale orientato agli oggetti attraverso alcuni semplici esempi per scopi didattici.

1.3.1. CTechIndicators, il contenitore degli indicatori tecnici
//+------------------------------------------------------------------+
//|                                              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 involucro orientato agli oggetti per 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 contenitore orientato agli oggetti per le notizie

La notizia in abstract è un tassello fondamentale con cui la nostra EA deve fare i conti. Possiamo pensare in questo pezzo chiave come se fosse un giornale per concludere che è una buona idea incapsularlo in un contenitore di notizie orientato agli oggetti. In parole povere, questo contenitore OO, chiamato CNewsContainer, è il giornale. E naturalmente se possiamo immaginare un giornale con notizie dobbiamo anche modellare il concetto di notizia che nel nostro dominio delle cose si chiama CNew. Questo è il nostro tipo personalizzato orientato agli oggetti che rappresenta le notizie del mondo reale.

1.4.1. CNewsContainer, il contenitore delle notizie

//+------------------------------------------------------------------+
//|                                               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 è il metodo più importante di CNewsContainer. Questo metodo legge il file CSV e lo carica nella RAM del computer sotto forma di oggetti di tipo CNew. A proposito, non ho ancora detto, i file CSV devono essere memorizzati in data_folder \ MQL5 \ FILES \. Si prega di dare un'occhiata a Funzioni file per una comprensione più approfondita delle funzioni utilizzate in SetNews.

1.4.2. CNew, le notizie stesse

//+------------------------------------------------------------------+
//|                                                         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. Allegati

ExpertNewsWatcher è composto dai seguenti file:

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

2.2. Istruzioni per l'installazione

Prima di tutto, devi creare la cartella MQL5 \ Include \ Mine per archiviare le tue cose personalizzate, quindi copia il file Enums.mqh lì. Subito dopo, è necessario creare la cartella MQL5\Experts\NewsWatcher e copiare i file seguenti:

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

Nota molto importante! Infine, prendi ,news_watcher.txt,news_watcher.txt, rinominalo in news_watcher.csv e inseriscilo in data_folder \ MQL5 \ FILES \. Al momento della pubblicazione di questo documento, l'invio del modulo MQL5 non consente l'invio di file .csv, ma consente l'invio di file .txt.

Non dimenticare di compilare. Da questo punto, puoi eseguire il backtest di ExpertNewsWatcher come faresti con qualsiasi altro Expert Advisor.


2.3. Risultati del test

ExpertNewsWatcher è stato eseguito con questi parametri di input iniziali.

  • Periodo = 1 minuto
  • StopLoss = 400
  • TakeProfit = 600
  • Dimensione del lotto = 0,01
  • CsvFile = news_watcher.csv

Inizialmente ho usato i seguenti dati fittizi contenenti una serie di notizie fittizie distanziate nel tempo per vedere come si comportava il robot in un ambiente controllato. Questo perché quei periodi soddisfano le precondizioni stabilite, cioè in quei momenti lo slancio è abbastanza grande da innescare le azioni di acquisto o vendita. Puoi prendere questo foglio di voci per testare qualsiasi cosa tu consideri.

Alcuni dati fittizi da memorizzare in 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


Risultati ottenuti con dati fittizi

Figura 3. Risultati ottenuti con dati fittizi

Il grafico sopra contenente notizie fittizie ti aiuterà a capire come questo robot potrebbe comportarsi in un ambiente reale. Si prega di prendere i seguenti dati reali presi da DailyFX, inserirli in news_watcher.csv ed eseguire nuovamente ExpertNewsWatcher.

Alcuni dati reali da memorizzare in 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



Risultati ottenuti con dati reali

Figura 4. Risultati ottenuti con dati reali

Questo semplice elaboratore di notizie può rispondere solo a una singola notizia che si svolge in un determinato tempo. È per questo motivo che un orario specifico, ad esempio 2013.07.15 12:30:00, può contenere diverse notizie. Se si verificano diverse notizie importanti in un dato momento, si prega di scrivere una singola voce nel file CSV.

Detto questo, osserva che l'EA mette solo tre operazioni sul mercato quando lavora con dati reali. Questo perché nella vita reale alcune notizie si sovrapporranno, a differenza della precedente serie di notizie fittizie distanziate nel tempo. Il nostro robot ha in programma di chiudere prima la prima operazione che proveniva dalla serie, ignorando una notizia in arrivo quando c'è già una posizione aperta.

       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);         
      }  


Conclusione

Questa è stata la continuazione di un altro articolo sulla classe OOP MQL5, che ha mostrato come costruire un semplice EA OO da zero e ti ha dato alcuni suggerimenti sulla programmazione orientata agli oggetti. Seguendo la stessa linea, questo testo ti ha fornito gli strumenti necessari per aiutarti a costruire i tuoi trader di notizie. Abbiamo coperto l'implementazione di contenitori orientati agli oggetti e involucri orientati agli oggetti per poter lavorare comodamente con i nostri progetti OO. Abbiamo anche discusso mqL5 Standard Library e mql5 funzioni per lavorare con il file system.

Tradotto dall’inglese da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/en/articles/719

File allegati |
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)
MQL5 Wizard: Come insegnare a un EA ad aprire ordini pendenti a qualsiasi prezzo MQL5 Wizard: Come insegnare a un EA ad aprire ordini pendenti a qualsiasi prezzo
L'articolo descrive un metodo di modifica del codice di un modulo di segnale di trading per l'implementazione della funzionalità che consente di impostare ordini pendenti a qualsiasi distanza dal prezzo corrente: può essere il prezzo di chiusura o apertura della barra precedente o il valore della media mobile. Ci sono molte opzioni. Importante è che è possibile impostare qualsiasi prezzo di apertura per un ordine pendente. Questo articolo sarà utile ai trader che commerciano con ordini pendenti.
Creazione di EA di reti neurali utilizzando MQL5 Wizard e Hlaiman EA Generator Creazione di EA di reti neurali utilizzando MQL5 Wizard e Hlaiman EA Generator
L'articolo descrive un metodo di creazione automatizzata di EA di reti neurali utilizzando MQL5 Wizard e Hlaiman EA Generator. Ti mostra come puoi facilmente iniziare a lavorare con le reti neurali, senza dover imparare l'intero corpo di informazioni teoriche e ti mostra come scrivere il tuo codice.
Stupisci i tuoi clienti MQL5 con un cocktail di tecnologie! Stupisci i tuoi clienti MQL5 con un cocktail di tecnologie!
MQL5 fornisce ai programmatori un set molto completo di funzioni e API orientate agli oggetti grazie alle quali possono fare tutto ciò che vogliono all'interno dell'ambiente MetaTrader. Tuttavia, la tecnologia Web è uno strumento estremamente versatile al giorno d'oggi. Essa può venire in soccorso in alcune situazioni in cui è necessario fare qualcosa di molto specifico, oppure quando vuoi stupire i tuoi clienti con qualcosa di diverso o semplicemente quando non si ha abbastanza tempo per padroneggiare una parte specifica della libreria standard MT5. L'esercizio di oggi ti guida attraverso un esempio pratico su come puoi gestire il tuo tempo di sviluppo allo stesso tempo in cui crei anche un fantastico cocktail tecnologico.
Un'altra classe OOP MQL5 Un'altra classe OOP MQL5
Questo articolo mostra come costruire da zero un Expert Advisor orientato agli oggetti. Dal concepimento di un'idea di trading teorica alla programmazione di un MQL5 EA che porta quell’idea nel mondo reale. Imparare facendo è IMHO un approccio solido per avere successo. Mostrerò un esempio pratico per farti vedere come potrai codificare trasformare le tue idee in codice, per creare i tuoi robot Forex. Il mio obiettivo è anche quello di invitarvi ad aderire ai principi OO.