English Русский 中文 Español 日本語 Português 한국어 Français Italiano Türkçe
Einen automatisierten News-Trader kreieren

Einen automatisierten News-Trader kreieren

MetaTrader 5Handel | 27 Juni 2016, 13:39
1 357 0
laplacianlab
[Gelöscht]

Einleitung

Wie von Investopedia treffend beschrieben, handelt es sich bei einem News-Trader um „einen Trader oder Investor, dessen Handelsentscheidungen auf News & Nachrichten basieren“. Tatsächlich bewirken Dokumente wie beispielsweise Konjunkturberichte betreffend das BIP, Verbrauchervertrauensindexe und Arbeitslosenstatistiken eines Landes oft signifikante Veränderungen des Währungsmarktes. Haben Sie zum Beispiel jemals eine US-Non-Farm-Payroll-Veröffentlichung erlebt? Falls ja, dann wissen Sie wahrscheinlich bereits, dass diese Reporte die Zukunft einer Währung zu beeinflussen vermögen und dass sie als Katalysator für Trendwenden angesehen werden können.

Schwarzweiß-Zeitungen

Abbildung 1 Schwarzweiß-Zeitungen. Unter einer Creative Commons Lizenz auf Flickr veröffentlichtes Bild

1. Wir programmieren unseren EA


1.1 Die Idee des Handelssystems

Die Idee, die hinter diesem System steckt, haben wir oben diskutiert. Das hört sich natürlich cool an, aber wie können wir diese Tatsache mit der Welt des Programmierens in Verbindung bringen? Wir vertrauen primär auf zwei Aspekte von MQL5. Einerseits verwenden wir einen sogenannten Momentum-Indikator, um den Einfluss einer News auf ein Währungspaar zu messen. Andererseits werden wir mit MGL5-Dateifunktionen arbeiten, um unseren favorisierten News-Kalender in das Dateisystem zu integrieren und in ihm zu speichern. Wir streben dabei das Dateiformat CSV an. Wir werden diesen Roboter dahingehend programmieren, als dass wir das objektorientierte Paradigma sowie den bereits diskutierten, konzeptuellen Ansatz (Eine anderere MQL5-OOP-Klasse verwenden. Unser objektorientiertes Design wird die CSV-Datei in den Speicher des Computers laden, damit der EA aufgrund dieser Informationen verschiedene Entscheidungen treffen kann.


1.2 Zum OOP-Skelett des Roboters

Wir werden unsere EAs - von einem konzeptuellen Standpunkt her betrachtet - von nun an als lebende Organismen ansehen. Wir sind also jetzt objektorientierte Programmierer, erinnern Sie sich? Folglich werden wir insbesondere die Begriff Gehirn, Evolution, Indikatorset und News-Set verwenden. Ich werde all diese Dinge weiter unten ausführlicher erklären.

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

#property copyright     "Copyright © 2013, laplacianlab. Jordi Bassagañas"
#property link          "https://www.mql5.com/de/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);
  }
//+------------------------------------------------------------------+

Bei CNewsWatcher handelt es sich um die Hauptklasse des EAs. Sehen wir uns den Code an.

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

Seien Sie nicht beunruhigt, wenn Ihnen dieser zu Anfang ein wenig komplex erscheint, das ist ganz normal. Zunächst einmal müssen Sie alle Komponenten dieses EAs kennenlernen, um zu verstehen, wie er funktioniert. Ich empfehle Ihnen daher, vorliegenden Artikel zuerst zu überfliegen, um ihn im Anschluss daran noch einmal 2-3 Mal intensiver zu lesen. Wie auch immer Sie sich entscheiden sollten - ich würde Ihnen an dieser Stelle sehr gerne einiges zu den wichtigsten Teilen von CNewsWatcher kundtun.

Das wichtigste Element ist selbstverständlich die Methode OnTick, anhand der Sie erkennen, dass CNewsWatcher mit einem objektorientierten News-Container interagiert. Dieses Objekt, das als eine reale Zeitung betrachtet werden kann, enthält News, mit denen der Nutzer des EAs traden will.  

Wir rufen den News-Container folgendermaßen ab:

GetBrain().GetNewsContainer();

Und wir rufen die aktuelle News ab, damit diese wie folgt verarbeitet wird:

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

Dies ist die Aufgabe von CBrain. Bitte erinnern Sie sich daran, dass CBrain ein wesentlicher Punkt unseres objektorientierten Designs darstellt, das all jene Komponenten besitzt, damit der EA richtig funktioniert. Es ist also eine Art Nur-Lese-Speicher (Read Only Memory, 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 liest - einfach ausgedrückt - Schritt für Schritt eine jede News aus, die im Container (die Zeitung) gespeichert ist. Sollte es zu dieser Zeit eine besonders starke Beschleunigung des Preisanstiegs geben, dann wird eine Market Order platziert.

Was dabei das Kaufen/Verkaufen von Lots betrifft, so ist der Roboter reaktiv programmiert. Falls es also beispielsweise zu einer starken Aufwärtsbewegung käme, so ginge der EA davon aus, dass der Preis zurückgeht, wodurch er verkaufen würden. Wenn es analog hierzu eine entsprechende Abwärtsbewegung gäbe, würde der Roboter mit einer Long Position antworten, da er in Kürze mit einer Preisverbesserung rechnen würde. Dies kann natürlich noch weiter verbessert werden. Allerdings weist der Artikel nicht genügend Platz auf, um einen hocheffektiven, automatisierten News-Trader zu entwickeln. Wie bereits gesagt, möchte ich Ihnen lediglich einige Basiskenntnisse vermitteln, sodass Sie selbst befähigt werden, Ihre eigenen Entwicklungen/Strategien zu verbessern.

Roboter & Taff

Abbildung 2 Roboter & Taff. Unter einer Creative Commons Lizenz auf Flickr veröffentlichtes Bild

1.3 Ein objektorientierter Container für technische Indikatoren


Noch einmal: Da wir uns entschieden haben, unsere Apps aus einem konzeptuellen Blickwinkel heraus zu betrachten, haben wir das Ziel, unsere eigenen objektorientierten Wrappers für technische Indikatoren zu programmieren, die mit unserem neuen Paradigma im Einklang stehen. Daher passt dieses Puzzlestück so gut zu allen anderen. Ich möchte im Folgenden dazu kommen, eine Art objektorientiertes Framework zu konstruieren, mit dem wir auf äußerst komfortable Weise mit MQL5-Elementen arbeiten können.

An dieser Stelle sei kurz auf die MQL5-Standard-Libary verwiesen. Diese Bibliothek wurde speziell dafür designt, Schreibprogramme von Endbenutzern zu unterstützen (Indikatoren, Skripte, Experts), um diesen den Zugriff auf verschiedene vorteilhafte internen Funktionen von MQL5 zu ermöglichen. Tatsächlich werden wir in der vorliegenden Übung auf einige Funktionen der Standard-Library zugreifen, da es sich aus einem OO-Blickwinkel gerade zu anbietet, dies zu tun. Ein hervorragendes Beispiel hierfür wäre der News-Container, den ich später noch ein wenig näher beschreiben will: So werden wir die MQL5-Klasse CArrayObj verwenden, um unseren objektorientierten, komplexen News-Typ im Arbeitsspeicher des Rechners abzulegen.

Studieren Sie bitte das Dokument Standard-Library, um ein wenig mehr über dieses Thema zu erfahren - wie beispielsweise den Umstand, dass die Standard-Library bereits über einige Klassen zum Arbeiten mit Indikatoren verfügt. Dieser Artikel widmet sich der Notwendigkeit, sich mit objektorientierten Materialien auseinanderzusetzen, indem wir uns einige Lehrbeispiele ansehen.

1.3.1 CTechIndicators, die technischen Indikatoren eines Containers
//+------------------------------------------------------------------+
//|                                              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 - ein objektorientierter Wrapper für 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 Ein objektorientierter Container für die Nachrichten

Abstrakte News stellen eines der fundamentalen Elemente dar, mit denen sich ein EA beschäftigen muss. Stellen wir uns eine Zeitung vor, die wir in einen objektorientierten News-Container einkapseln und verschließen. Einfach ausgedrückt: Der objektorientierte CNewsContainer ist nichts anderes als eine handelsübliche Gazette. CNew stellt dabei den Namen des Modells des News-Konzepts dar. Hierbei handelt es sich um unseren OO-Typ, der eine reale News repräsentiert.

1.4.1 CNewsContainer, der Container für die News

//+------------------------------------------------------------------+
//|                                               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 stellt das für uns möglicherweise wichtigste Methode von NewsContainer dar. Diese Methode liest die Informationen der CSV-Datei aus und lädt sie in Form eines CNew-Objekts in den Arbeitsspeicher des Rechners. Ich habe im Übrigen noch nicht erwähnt, dass sämtliche CSV-Dateien in dem Ordner data_folder\MQL5\FILES\ gespeichert werden müssen. Werfen Sie bitte einen Blick auf Dateifunktionen, um mehr Informationen betreffend die Funktionen zu erhalten, die in SetNews Verwendung finden.

1.4.2 CNew, die News höchstselbst

//+------------------------------------------------------------------+
//|                                                         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. ExpertNewsWatcher.mq5 im Backtest


2.1 Anhänge

ExpertNewsWatcher besteht aus den folgenden Dateien:

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

2.2 Installationsanweisungen

Zunächst einmal müssen Sie einen adäquaten Ordner erstellen, der Ihre zukünftigen, geänderten Dateien aufbewahren soll: MQL5\Include\Mine. Kopieren Sie danach bitte die Datei Enums.mqh hinein. Direkt danach müssen Sie den Ordner MQL5\Experts\NewsWatcher anlegen und die nachfolgenden Dateien nach dort kopieren:

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

Ein wichtiger Hinweis! Schließlich sollten Sie sich noch der Datei news_watcher.txt zuwenden: Benennen Sie diese in news_watcher.csv um und stecken Sie sie in den Ordner data_folder\MQL5\FILES\. Zum Zeitpunkt der Veröffentlichung dieses Artikels wird die Versendung von .csv-Dateien seitens MQL5 nicht unterstützt. Allerdings erlaubt MQL5 das Senden von .txt.Dateien.

Vergessen Sie nicht, das Ganze zu kompilieren. Nun können Sie ExpertNewsWatcher einem Backtest unterziehen, so wie Sie es mit jedem anderen EA tun würden.


2.3 Backtest-Resultate

ExpertNewsWatcher wurde anhand folgender Eingabeparameter getestet:

  • Periode = 1 Minute
  • StopLoss = 400
  • TakeProfit = 600
  • LotGröße = 0.01
  • CsvDatei = news_watcher.csv

Ursprünglich habe ich folgende Dummy-Daten (die fiktive News enthalten) verwendet, um zu sehen, wie sich unser EA innerhalb einer kontrollierten Umgebung verhält. Grund: Diese Perioden entsprechen genau den Vorbedingungen, das heißt, während dieser Zeiträume ist das Momentum groß genug, um Kaufen- oder VerkaufenAktionen auszulösen. Sie können mithilfe dieses Stylesheets testen, was auch immer Sie wollen.

Einige Dummy-Daten, um sie in news_watcher.csv zu speichern:

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


Mit Dummy-Daten erhaltene Ergebnisse

Abbildung 3 Mit Dummy-Daten erhaltene Ergebnisse

Der obige, fiktive News enthaltende Graph hilft Ihnen dabei, zu verstehen, wie sich der Roboter in einer realen Umgebung verhalten könnte. Bedienen Sie sich nun bitte der folgenden, realen Daten von DailyFX, füttern Sie damit news_watcher.csv und führen Sie noch einmal ExpertNewsWatcher aus.

Einige reale Daten, um sie in news_watcher.csv zu speichern.

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



Mit reellen Daten erhaltene Ergebnisse

Abbildung 4 Mit reellen Daten erhaltene Ergebnisse

Dieser einfache News-Prozessor kann nur einzelne News verarbeiten, die sich zu einer bestimmten Zeit ereignen. Nun gibt es den Fall, dass eine spezifische Zeit (Bsp: 15.07.2013 12:30:00) mehrere relevante News enthält. Falls zu einer bestimmten Zeit mehrere wichtige News gleichzeitig auftreten sollten, so würde ich Sie bitten, die CSV-Datei mit einem einzigen Eintrag zu versehen.

Nachdem dies gesagt wurde, werden Sie feststellen, dass der EA nur drei Marktoperationen gleichzeitig durchführt, falls er mit realen Daten jongliert. Die Ursache hierfür liegt darin begründet, dass sich einige reale News im Gegensatz zu fiktiven überlappen könnten. Unser Roboter ist so eingestellt, dass er zuerst die erste Order einer Serie schließen und eingehende News ignorieren wird, falls bereits eine offene Order existiert.

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


Fazit

Vorliegender Artikel stellt eine Fortsetzung des Artikels Eine andere MQL5-OOP-Klasse dar, der Ihnen bereits Tipps zum objektorientierten Programmieren vermittelt und der Ihnen gezeigt hat, wie Sie aus dem Nichts einen objektorientierten EA basteln. Gleichzeitig hat Ihnen dieser Text all die Mittel an die Hand gegeben, die Sie zur Entwicklung Ihres eigenen News-Traders benötigen. Wir haben außerdem über die Implementation objektorientierter Container / Wrappers gesprochen, um den komfortablen Umgang mit OO-Designs zu erlernen. Schließlich sind wir noch auf die MQL5-Standard-Library zu sprechen gekommen und haben uns angesehen, auf welche Art und Weise MQL5-Funktionen mit dem Dateisystem interagieren.

Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/719

Beigefügte Dateien |
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)
Creating Neural Network EAs Using MQL5 Wizard and Hlaiman EA Generator Creating Neural Network EAs Using MQL5 Wizard and Hlaiman EA Generator
Dieser Artikel befasst sich mit einer Methode zur automatischen Generierung von auf einem neuronalen Netzwerk basierenden EAs mithilfe des MQL5-Assistenten und Hlaiman EA Generator. Er zeigt Ihnen, wie Sie ganz einfach mit neuronalen Netzwerken arbeiten können - und zwar ohne großartige Hintergrundinformationen zu besitzen oder einen eigenen Code zu schreiben.
Der MQL5-Assistent: Wie man einem EA beibringt, einen bedingten Auftrag (Pending Order) eines beliebigen Preises zu platzieren Der MQL5-Assistent: Wie man einem EA beibringt, einen bedingten Auftrag (Pending Order) eines beliebigen Preises zu platzieren
Dieser Artikel beschreibt eine Methode, mit der man den Code eines Handelsignalmoduls so modifiziert, dass die Funktion zur Verfügung steht, einen bedingten Auftrag unabhängig des aktuellen Preises in Auftrag zu geben: Hierbei kann es sich um den Eröffnungs- oder Schlusskurs des vorherigen Balkens oder um den gleitenden Durchschnittswert handeln. Die Optionen sind grenzenlos. Entscheidend ist, dass Sie einen Eröffnungskurs für einen bedingten Auftrag einstellen können. Dieser Artikel richtet sich an all jene Trader, die sich mit bedingten Aufträgen (Pending Orders) auseinandersetzen.
Eine andere MQL5-OOP-Klasse Eine andere MQL5-OOP-Klasse
Dieser Artikel soll Sie damit vertraut machen, wie Sie von Grund auf einen objektorientierten Expert Advisor konstruieren: und zwar beginnend mit der theoretischen Konzeption bis hin zur praktischen Programmierung eines MQL5-EAs. Ich persönliche vertrete die Einstellung, dass nichts über die Learning-by-Doing-Methode geht. Ich werde Ihnen daher anhand eines praktischen Beispiels vorführen, wie Sie Ihre Ideen ordnen können, um Ihren Forex-Roboter mit einem Code zu versehen. Ich habe außerdem die Absicht, Ihnen einige OO-, also objektorientierte Prinzipien näherzubringen.
Versetzen Sie Ihre MQL5-Kunden mit einem Mix an verschiedenen Technologien ins Staunen! Versetzen Sie Ihre MQL5-Kunden mit einem Mix an verschiedenen Technologien ins Staunen!
MQL 5 versorgt Programmierer mit einem sehr umfassenden Set an Funktionen und objektorientierten Anwendungsprogrammschnittstellen, die ihnen eine - eine MetaTrader-Umgebung vorausgesetzt - nahezu unendliche Handlungsfreiheit verleihen. Web-Technologien stellen heute ein äußerst mächtiges Instrument dar, das Ihnen in vielen verschiedenen Situationen gute Dienste kann - wenn Ihnen beispielsweise die Zeit fehlt, einen bestimmten Teil der MT5-Standard-Library zu meistern - bzw. das Ihnen dabei hilft, Ihre Kunden einfach nur ins Staunen zu versetzen. Die heutige Übung soll Ihnen als ein praktisches Beispiel dafür dienen, wie Sie Ihre Entwicklungszeit beschleunigen, als auch einen wahren Cocktail an Technologien hervorbringen können.