Otomatik Haber Yatırımcısı Oluşturma
Giriş
Investopedia'da belirtildiği üzere bir haber yatırımcısı, "yayınlanan haberlere göre alım satım veya yatırım kararı veren bir tüccar veya yatırımcıdır." Aslında, diğerlerinin yanı sıra bir ülkenin GSYİH'si, tüketici güven endeksleri ve ülkelerin istihdam verileri gibi ekonomik raporlar genellikle döviz piyasalarında önemli hareketlere neden olur. Siz hiç ABD Tarım Dışı İstihdam Verileri açıklamasına katıldınız mı? Katıldıysanız, bu raporların dövizlerin yakın geleceğini belirleyebileceğini ve trendlerin tersine çevrilmesi için katalizör görevi görebileceğini zaten biliyorsunuzdur.
Şekil 1. Newspapers B&W. Flickr üzerinde Creative Commons Lisansı kapsamında dağıtılan resim
1. EA'mızı Programlayalım
1.1. Alım Satım Sistemi Fikri
Bu sistemin arkasındaki fikir yukarıda tartıştığımız fikirdir. Bu kulağa harika geliyor, ancak bu kanıtlanmış gerçeği programlama dünyasına nasıl uygulayabiliriz? Temelde iki MQL5 yönüne güveniyoruz. Bir yandan, bir döviz çiftinde verilen haber dizisinin etkisini ölçmek için Momentum göstergesini kullanacağız. Diğer yandan, favori haber takvimimizi dosya sisteminde saklamak için MQL5 dosya fonksiyonları ile çalışacağız. Seçilen dosya biçimi CSV'dir. Bu robotu, elbette Bir diğer MQL5 OOP sınıfı içinde tartışılan kavramsal yaklaşım ile nesne yönelimli paradigma kapsamında programlayacağız. Nesne yönelimli tasarımımız, CSV'yi, EA'nın bu bilgilere dayanarak kararlar verebileceği şekilde bilgisayarın belleğine yükleyecektir.
1.2. Robotun OOP İskeleti
Şu andan itibaren EA'larımızı, sanki canlı varlıklarmış gibi, kavramlar bakış açısından tasarlayacağız. Şimdi OOP insanları olduk, hatırladınız mı? Bu vizyon sayesinde, Uzman Danışmanımızı bir beyin, evrim olarak adlandırabileceğimiz bir şey, bir dizi gösterge ve bir dizi haber gibi birkaç parçadan oluşturabiliriz. Bunların tamamını aşağıda açıklayacağım.
//+---------------------------------------------------------------------+ //| ExpertNewsWatcher.mq5 | //| Copyright © 2013, laplacianlab, Jordi Bassagañas | //+---------------------------------------------------------------------+ #property copyright "Copyright © 2013, laplacianlab. Jordi Bassagañas" #property link "https://www.mql5.com/tr/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 EA'nın ana sınıfıdır. Koda bir bakalım:
//+---------------------------------------------------------------------+ //| 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."); } //+------------------------------------------------------------------+
Şimdilik, her şeyi çok net anlamadıysanız endişelenmeyin, bu normal. İlk olarak, her şeyin nasıl çalıştığını anlamak için bu Uzman Danışmanın bütün bölümlerini incelemeniz gerekir. İlk olarak bu makaleyi yüzeysel olarak okumanızı, ardından daha derin ikinci ve üçüncü okumalar yapmanızı tavsiye ederim. Bu arada ben de CNewsWatcher'ın bazı kilit kısımlarını açıklamaya çalışacağım.
EA'nın en önemli kısmı, tabi ki, CNewsWatcher'ın çalışma için bir OO haber kapsayıcı kullandığını göreceğiniz OnTick yöntemidir. Gerçek dünyadaki bir gazete olarak görülebilecek bu parça, EA kullanıcısının alım satım yapmak istediği haberleri içerir.
Haber kapsayıcısını şu şekilde aldığımızı unutmayın:
GetBrain().GetNewsContainer();
Ve işlenecek güncel haberleri şu şekilde alıyoruz:
CNew *currentNew = GetBrain().GetNewsContainer().GetCurrentNew();
Bu da CBrain aracılığıyla yapılıyor. EA'nın doğru bir şekilde çalışması için gerekli olan şeyleri içeren nesne yönelimli tasarımımızda CBrain'in önemli bir merkezi nokta olduğunu unutmayın, bu salt okunur bellek (ROM) gibi bir şeydir.
//+------------------------------------------------------------------+ //| 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 temelde kapsayıcıda (gazete) saklanan haberleri sıra sıra okur. Bu sırada fiyatta güçlü bir ivmelenme varsa, piyasada bir emir verir.
Robot, lot alımı veya satımına dair reaktif bir şekilde programlanmıştır. Diyelim ki, güçlü bir yukarı yönlü hareket oluştuğunda, EA fiyatın geri çekileceğini varsayar ve dolayısıyla satış yapar. Benzer şekilde, güçlü bir aşağı yönlü hareket oluştuğunda, robot fiyatın kısa sürede geri çekileceğini düşünerek piyasada uzun bir pozisyon açar. Bu elbette geliştirilebilir; daha önce belirtildiği gibi, bu makalede yüksek ölçüde verimli bir otomatik haber yatırımcısı geliştirmek için yeterli alan yoktur, amaç sadece kendi geliştirmelerinizde ilerlemeye devam edebilmeniz için size teknik temel bilgileri sağlamaktır.
Şekil 2. Robot on the Taff. Flickr üzerinde Creative Commons Lisansı kapsamında dağıtılan görüntü
Bir kez daha, uygulamalarımızı kavram perspektifinden ele almaya karar verdiğimizden, yeni paradigmaya bağlı kalmak amacıyla teknik göstergeler için kendi nesne yönelimli sarmalayıcılarımızı programlamak ilginçtir. Bu şekilde, bu yapboz parçası her şeye çok daha iyi uymaktadır. Diyelim ki geliştirmemizin bu kısmında, orijinal haliyle pek de OO olmayan bu MQL5 ile daha rahat çalışabilmemiz için nesne yönelimli bir çerçeve gibi bir şey oluşturma avantajından yararlanıyoruz.
Bu noktada, MQL5 Standart Kitaplığından bahsetmek ilginç olacaktır. Bu kitaplık, son kullanıcılar için programları yazmayı (göstergeler, betikler, uzmanlar) kolaylaştırarak MQL5 dahili fonksiyonlarından çoğuna rahat erişim sağlamaktadır. Aslında, bazı Standart Kitaplık fonksiyonlarını bugünün alıştırmasında kullanacağız, çünkü belirtildiği gibi OO programlama bakış açısından bu şekilde çok daha rahat. Açık bir örnek, biraz sonra açıklayacağım haber kapsayıcıdır; burada, karmaşık türdeki özel nesne yönelimli haberlerimizi bilgisayarın RAM'inde saklamak için CarrayObj MQL5 sınıfını kullanacağız.
Lütfen bu konuya dair daha fazla bilgi edinmek için Standart Kitaplık başlıklı resmi belgelere göz atın ve göstergeler ile çalışmak için Standart Kitaplığın halihazırda bazı sınıflar ile birlikte geldiğini unutmayın. Bu makale, eğitim amacıyla bazı basit örnekler yoluyla nesne yönelimli materyaller ile çalışma gerekliliğini tartışmaktadır.
//+------------------------------------------------------------------+ //| 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, iMomentum için bir Nesne Yönelimli Sarmalayıcı
//+------------------------------------------------------------------+ //| 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. Haberler için bir Nesne Yönelimli Kapsayıcı
Haberler, kavram olarak, EA'mızın ilgilenmesi gereken temel bir parçadır. Bu kilit parçayı, bunu nesne yönelimli bir haber kapsayıcısına yerleştirmenin iyi bir fikir olduğu sonucuna varmak için, bir gazeteymiş gibi düşünebiliriz. Basitçe ifade edecek olursak, CNewsContainer adlı bu OO kapsayıcısı gazetedir. Ve tabii ki haberler içeren bir gazete hayal edebiliyorsak, aynı zamanda bizim nesneler etki alanımızda CNew olarak adlandırılan haber kavramını da modellememiz gerekir. Bu, gerçek dünyadaki haberleri temsil eden özel nesne yönelimli türümüzdür.
1.4.1. CNewsContainer, Haber Kapsayıcı
//+------------------------------------------------------------------+ //| 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, CNewsContainer'ın en önemli yöntemidir. Bu yöntem CSV dosyasını okur ve bunu CNew türünde nesneler biçiminde bilgisayarın RAM'ine yükler. Bu arada, CSV dosyalarının data_folder\MQL5\FILES\ içinde saklanması gerektiğini hala söylemedim. SetNews içinde kullanılan fonksiyonları daha iyi anlamak için lütfen Dosya fonksiyonlarına bakın.
1.4.2. CNew, Haberin Kendisi
//+------------------------------------------------------------------+ //| 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. Ekler
ExpertNewsWatcher aşağıdaki dosyalardan oluşur:
- Enums.mqh
- CBrain.mqh
- CEvolution.mqh
- CMomentum.mqh
- CNew.mqh
- CNewsContainer.mqh
- CNewsWatcher.mqh
- CTechIndicators.mqh
- ExpertNewsWatcher.mq5
- news_watcher.txt
2.2. Yükleme talimatları
İlk olarak, özel öğelerinizi saklamak için MQL5\Include\Mine klasörü oluşturmalı ve ardından Enums.mqh dosyasını buraya kopyalamalısınız. Bundan sonra, MQL5\Experts\NewsWatcher klasörü oluşturmalı ve aşağıdaki dosyaları kopyalamalısınız:
- CBrain.mqh
- CEvolution.mqh
- CMomentum.mqh
- CNew.mqh
- CNewsContainer.mqh
- CNewsWatcher.mqh
- CTechIndicators.mqh
- ExpertNewsWatcher.mq5
Çok önemli not! Son olarak, lütfen news_watcher.txtdosyasını alın, bunu news_watcher.csv olarak yeniden adlandırın ve data_folder\MQL5\FILES\ içine taşıyın. Bu belgenin yayınlandığı tarihte, MQL5 form gönderimi .csv dosyalarının gönderilmesine izin vermemektedir, ancak .txt dosyalarının gönderilmesine izin vermektedir.
Derlemeyi unutmayın. Bu noktadan itibaren, diğer herhangi bir Uzman Danışmanda yaptığınız gibi ExpertNewsWatcher'ı geriye dönük test edebilirsiniz.
2.3. Geriye dönük test sonuçları
ExpertNewsWatcher şu başlangıç giriş parametreleri ile çalıştırılmıştır:
- Dönem = 1 Dakika
- StopLoss = 400
- TakeProfit = 600
- LotSize = 0,01
- CsvFile = news_watcher.csv
Başlangıçta, robotun kontrollü bir ortamda nasıl davrandığını görmek için zaman aralıklı şekilde bir dizi farazi haber içeren aşağıdaki sahte verileri kullandım. Bunun nedeni, bu dönemlerin belirlenmiş önkoşulları karşılamasıdır, yani bu zamanlarda momentum, alış veya satış eylemlerini tetikleyecek kadar büyüktür. Düşündüğünüz her şeyi test etmek için bu girişler sayfasını kullanabilirsiniz.
news_watcher.csv içinde saklanacak bazı sahte veriler:
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
Şekil 3. Sahte veriler ile elde edilen sonuçlar
Farazi haberleri içeren yukarıdaki grafik, bu robotun gerçek bir ortamda nasıl davranabileceğini anlamanıza yardımcı olacaktır. Lütfen DailyFX adresinden alınan aşağıdaki gerçek verileri alın, bunları news_watcher.csv içine yerleştirin ve ExpertNewsWatcher'ı yeniden çalıştırın.
news_watcher.csv içinde saklanacak bazı gerçek veriler:
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
Şekil 4. Gerçek veriler ile elde edilen sonuçlar
Bu basit haber işlemcisi yalnızca belirli bir zamanda gerçekleşen tek bir habere yanıt verebilir. Bu nedenle, örneğin 2013.07.15 12:30:00 olan belirli bir saatte birkaç haber meydana gelebilir. Belirli bir zamanda birkaç önemli haber meydana geliyorsa, lütfen CSV dosyasına tek bir giriş yazın.
Buna ek olarak, EA'nın gerçek veriler ile çalışırken piyasaya yalnızca üç işlemi girdiğini gözlemleyin. Bunun nedeni, zamanı aralıklı önceki farazi haberlerin aksine, gerçek hayatta bazı haberlerin üst üste gelmesidir. Robotumuz, halihazırda açık bir pozisyon varken gelen bir haberi yok sayarak, seriden gelen ilk işlemi ilk önce kapatacak şekilde planlanmıştır.
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); }
Sonuç
Bu makale, size basit bir OO EA'nın sıfırdan nasıl oluşturulacağını gösteren ve nesne yönelimli programlamaya dair bazı ipuçları sağlayan Bir Diğer MQL5 OOP sınıfı makalesinin devamı niteliğinde olmuştur. Aynı anlayışla, bu metin de size kendi haber yatırımcılarınızı oluşturmanıza yardımcı olacak gerekli araçları sağlamıştır. OO tasarımlarımız ile rahatça çalışabilmemiz için, nesne yönelimli kapsayıcıların ve nesne yönelimli sarmalayıcıların uygulanmasını ele aldık. Ayrıca, dosya sistemi ile çalışmak için MQL5 Standart Kitaplığı ve MQL5 fonksiyonlarını da tartıştık.
MetaQuotes Ltd tarafından İngilizceden çevrilmiştir.
Orijinal makale: https://www.mql5.com/en/articles/719
- Ücretsiz ticaret uygulamaları
- İşlem kopyalama için 8.000'den fazla sinyal
- Finansal piyasaları keşfetmek için ekonomik haberler
Gizlilik ve Veri Koruma Politikasını ve MQL5.com Kullanım Şartlarını kabul edersiniz