English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
자동 뉴스 거래자 구축

자동 뉴스 거래자 구축

MetaTrader 5트레이딩 | 3 9월 2021, 09:50
176 0
laplacianlab
[삭제]

소개

Investopedia에 따르면 뉴스 거래자는 "뉴스 발표에 따라 거래 또는 투자 결정을 내리는 거래자 또는 투자자"입니다. 실제로 한 국가의 GDP, 소비자 신뢰 지수 및 국가의 고용 데이터와 같은 경제 보고서는 종종 통화 시장에서 상당한 움직임을 생성합니다. 미국에 가본 적이 있습니까? 비농업 급여 발표? 그렇다면 이러한 보고서가 통화의 최근 미래를 결정하고 추세 반전의 촉매 역할을 할 수 있음을 이미 알고 있습니다.

B&W 신문

그림 1. B&W 신문. Flickr의 Creative Commons License에 따라 배포된 이미지

1. EA를 프로그래밍해봅시다


1.1. 거래 시스템의 아이디어

이 시스템의 이면에 있는 아이디어는 위에서 논의한 것입니다. 이것은 훌륭하게 들리지만 프로그래밍 세계에서 입증된 사실을 어떻게 구현할 수 있습니까? 주로 우리는 두 가지 MQL5 측면에 의존하고 있습니다. 한편으로는 모멘텀 지표를 사용하여 통화 쌍에서 주어진 뉴스 세트의 영향을 측정합니다. 반면에 MQL5 파일 기능을 사용하여 즐겨찾는 뉴스 캘린더를 파일 시스템에 저장합니다. 선택한 파일 형식은 CSV입니다. 물론 또 다른 MQL5 OOP 클래스에서 논의된 개념적 접근을 사용하여 객체 지향 패러다임에서 이 로봇을 프로그래밍할 것입니다. 우리의 객체 지향 설계는 CSV를 컴퓨터 메모리에 로드하여 EA가 이러한 정보를 기반으로 결정을 내릴 수 있도록 합니다.


1.2. 로봇의 OOP 스켈레톤

이제부터 우리는 EA를 마치 살아있는 생물처럼 개념의 관점에서 생각하고 있습니다. 우리는 이제 OOP 직원이 되었습니다. 기억하십니까? 이 비전 덕분에 우리는 두뇌, 진화라고 부르는 것, 지표 세트 및 뉴스 세트와 같은 여러 부분에 대한 Expert Advisor를 구성할 수 있습니다. 저는 이 모든 것을 아래에서 명확히 할 것입니다.

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

#property copyright     "Copyright © 2013, laplacianlab. Jordi Bassagañas"
#property link          "https://www.mql5.com/ko/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의 주요 클래스입니다. 코드를 살펴보겠습니다.

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

지금은 상황이 매우 명확하지 않은 경우 걱정하지 마십시오. 정상입니다. 먼저 모든 것이 어떻게 작동하는지 이해하려면 이 Expert Advisor의 모든 부분을 연구해야 합니다. 먼저 이 글을 피상적으로 읽은 다음 두 번째 및 세 번째 더 깊이 읽을 것을 권장합니다. 여하튼 이 시간에 CNewsWatcher의 몇 가지 핵심 부분을 설명하려고 합니다.

EA의 가장 중요한 부분은 물론 CNewsWatcher가 OO 뉴스 컨테이너를 사용하여 작동하는 것을 볼 수 있는 OnTick 방법입니다. 현실의 신문이라고 볼 수 있는 이 글에는 EA 유저가 거래하고 싶다는 소식이 담겨 있습니다. 

다음과 같이 뉴스 컨테이너를 검색합니다.

GetBrain().GetNewsContainer();

그리고 다음과 같이 처리할 현재 뉴스를 검색합니다.

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

이는 CBrain을 통해 수행됩니다. CBrain은 EA가 제대로 작동하는 데 필요한 요소를 포함하는 객체 지향 설계의 중요한 중심점이며, 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 기본적으로 컨테이너(신문)에 저장된 뉴스를 하나씩 읽습니다. 그 시점에 가격이 크게 상승하면 시장에서 주문을 합니다.

랏의 매수 또는 판매와 관련하여 로봇은 반응 방식으로 프로그래밍됩니다. 강한 상승 움직임이 발생하면 EA는 가격이 후퇴할 것이라고 가정하여 매도합니다. 마찬가지로, 강력한 하향 움직임이 있을 때 로봇은 가격이 단기간에 되돌릴 것이라고 생각하여 시장에서 매수 포지션을 취합니다. 이것은 물론 개선할 수 있습니다. 이 글에는 고효율 자동 뉴스 트레이더를 개발하기에 충분한 공간이 없습니다. 앞에서 말했듯이 목표는 계속해서 자신의 개발을 발전시킬 수 있도록 기술 기본 사항을 제공하는 것입니다.

Taff 위의 로봇

그림 2. Taff 위의 로봇. Flickr의 Creative Commons License에 따라 배포된 이미지


1.3. 기술 지표를 위한 객체 지향 컨테이너


다시 한 번, 개념의 관점에서 앱을 다루기로 결정했기 때문에 기술 지표에 대한 자체 객체 지향 래퍼를 프로그래밍하여 새로운 패러다임을 고수하는 것이 흥미로웠습니다. 따라서 이 퍼즐 조각은 모든 것에 훨씬 더 잘 맞습니다. 개발의 이 부분에서 객체 지향 프레임워크와 같은 것을 구축하는 이점을 활용하여 즉시 사용 가능하지 않은 MQL5 항목으로 보다 편안하게 작업할 수 있다고 가정해보겠습니다.

이 시점에서 MQL5 표준 라이브러리가 있다는 점에 주목할 필요가 있습니다. 이 라이브러리는 최종 사용자가 프로그램(지표, 스크립트, Expert)을 쉽게 작성할 수 있도록 설계되어 대부분의 MQL5 내부 기능에 편리하게 액세스할 수 있습니다. 사실, 오늘의 연습에서 우리는 말했듯이 OO 프로그래밍의 관점에서 훨씬 더 편안하기 때문에 일부 표준 라이브러리의 기능을 사용하고 있습니다. 명확한 예는 나중에 설명할 뉴스 컨테이너입니다. 여기서 MQL5 클래스 CArrayObj 를 사용하여 컴퓨터의 RAM에 복잡한 유형의 사용자 정의 객체 지향 뉴스를 저장합니다.

이 주제에 대해 자세히 알아보려면 표준 라이브러리라는 제목의 공식 문서를 살펴보고 표준 라이브러리에는 이미 지표 작업을 위한 일부 클래스가 포함되어 있습니다. 이 글에서는 교육 목적을 위한 몇 가지 간단한 예를 통해 객체 지향 자료로 작업해야 할 필요성에 대해 설명합니다.

1.3.1. 기술 지표의 컨테이너, CTechIndicators
//+------------------------------------------------------------------+
//|                                              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. iMomentum용 객체 지향 래퍼 CMomentum
//+------------------------------------------------------------------+
//|                                                    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. 뉴스를 위한 객체 지향 컨테이너

추상적인 뉴스는 우리 EA가 다루어야 하는 근본적인 부분입니다. 우리는 이 핵심 부분에서 뉴스의 객체 지향 컨테이너에 그것을 캡슐화하는 것이 좋은 생각이라고 결론짓기 위해 마치 신문인 것처럼 생각할 수 있습니다. 간단히 말해서 CNewsContainer라는 이름의 이 OO 컨테이너는 신문입니다. 물론 뉴스가 있는 신문을 상상할 수 있다면 우리의 영역에서 CNew라는 이름의 뉴스 개념도 모델링해야 합니다. 이것은 실제 세계의 뉴스를 나타내는 우리의 사용자 정의 객체 지향 유형입니다.

1.4.1. CNewsContainer, CNewsContainer

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

SetNewsCNewsContainer의 가장 중요한 메소드입니다. 이 방법은 CSV 파일을 읽고 CNew 유형의 개체 형태로 컴퓨터의 RAM에 로드합니다. 그건 그렇고, 나는 여전히 CSV 파일이 data_folder\MQL5\FILES\에 저장되어야 한다고 말하지 않았습니다. SetNews에서 사용되는 기능에 대한 더 깊은 이해를 위해 파일 기능을 살펴보십시오.

1.4.2. CNew, 뉴스 그 자체

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


2.1. 첨부 파일

ExpertNewsWatcher는 다음 파일로 구성됩니다.

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

2.2. 설치 지침

우선, 사용자 정의 항목을 저장할 MQL5\Include\Mine 폴더를 만든 다음 Enums.mqh 파일을 거기에 복사해야 합니다. 그 직후 MQL5\Experts\NewsWatcher 폴더를 생성하고 아래 파일을 복사해야 합니다.

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

매우 중요한 메모입니다! 마지막으로, news_watcher.txt를 가져오고, 이름을news_watcher.csv로 변경하세요. 그리고 data_folder\MQL5\FILES\에 넣어보세요. 이 문서 발행 당시 MQL5 양식 제출은 .csv 파일 전송을 허용하지 않지만 .txt 파일 전송은 허용합니다.

컴파일하는 것을 잊지 마십시오. 이 시점부터 다른 Expert Advisor와 마찬가지로 ExpertNewsWatcher를 백테스트할 수 있습니다.


2.3. 백테스트 결과

ExpertNewsWatcher는 이러한 초기 입력 매개변수로 실행되었습니다.

  • 기간 = 1분
  • 손절매 = 400
  • 이익실현 = 600
  • 랏 크기 = 0.01
  • CSV 파일 = news_watcher.csv

나는 처음에 로봇이 통제된 환경에서 어떻게 행동하는지 보기 위해 시간 간격을 둔 일련의 가상 뉴스를 포함하는 다음 더미 데이터를 사용했습니다. 이는 해당 기간이 설정된 전제 조건을 충족하기 때문입니다. 이 항목 시트를 사용하여 고려하는 모든 항목을 테스트할 수 있습니다.

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


더미 데이터로 얻은 결과

그림 3. 더미 데이터로 얻은 결과

가상의 뉴스가 포함된 위의 그래프는 이 로봇이 실제 환경에서 어떻게 행동하는지 이해하는 데 도움이 될 것입니다. DailyFX에서 가져온 다음 실제 데이터를 가져와 news_watcher.csv에 넣고 ExpertNewsWatcher 를 다시 실행하십시오.

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



실제 데이터로 얻은 결과

그림 4. 실제 데이터로 얻은 결과

이 간단한 뉴스 프로세서는 특정 시간에 발생하는 단일 뉴스에만 응답할 수 있습니다. 이러한 이유로 특정 시간(예: 2013.07.15 12:30:00)에 여러 뉴스가 포함될 수 있습니다. 여러 중요한 뉴스가 동시에 발생하는 경우 CSV 파일에 하나의 항목을 작성하십시오.

하지만 EA는 실제 데이터로 작업할 때 세 가지 작업만 시장에 내놓습니다. 그 이유는 이전의 가상 뉴스 세트와 달리 실제 상황에서는 일부 뉴스가 겹칠 수 있기 때문입니다. 우리 로봇은 이미 열린 포지션이 있을 때 들어오는 뉴스를 무시하고 시리즈에서 나온 첫 번째 작업을 먼저 닫을 예정입니다.

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


결론

이것은 처음부터 간단한 OO EA를 구축하는 방법을 보여주고 객체 지향 프로그래밍에 대한 몇 가지 팁을 제공한 또 다른 MQL5 OOP 클래스 글의 연속이었습니다. 같은 줄을 따라 이 텍스트는 자신의 뉴스 거래자를 구축하는 데 도움이 되는 필요한 도구를 제공했습니다. OO 디자인으로 편안하게 작업할 수 있도록 객체 지향 컨테이너와 객체 지향 래퍼의 구현을 다루었습니다. 또한 파일 시스템과 함께 작동하는 MQL5 표준 라이브러리 및 MQL5 기능에 대해서도 논의했습니다.

MetaQuotes 소프트웨어 사를 통해 영어가 번역됨
원본 기고글: https://www.mql5.com/en/articles/719

파일 첨부됨 |
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 마법사: EA가 모든 가격으로 보류 중인 주문을 열도록 가르치는 방법 MQL5 마법사: EA가 모든 가격으로 보류 중인 주문을 열도록 가르치는 방법
이 글은 현재 가격에서 어떤 거리에서도 보류 주문을 설정할 수 있도록 하는 기능의 구현을 위해 거래 신호 모듈의 코드를 수정하는 방법을 설명합니다. 즉, 이는 이전 바의 종가 또는 시가 또는 이동 평균 닫거나 오픈할 수 있습니다. 많은 옵션이 있습니다. 중요한 것은 보류 중인 주문에 대해 시작 가격을 설정할 수 있다는 것입니다. 이 글은 보류 중인 주문으로 거래하는 거래자에게 유용합니다.
MQL5 마법사 및 Hlaiman EA 생성기를 사용하여 신경망 EA 생성 MQL5 마법사 및 Hlaiman EA 생성기를 사용하여 신경망 EA 생성
이 글에서는 MQL5 Wizard 및 Hlaiman EA Generator를 사용하여 신경망 EA를 자동으로 생성하는 방법을 설명합니다. 이론적인 정보 전체를 배우고 코드를 작성하지 않고도 신경망 작업을 쉽게 시작할 수 있는 방법을 보여줍니다.
사용 가능한 기술 칵테일로 MQL5 고객을 놀래켜보세요! 사용 가능한 기술 칵테일로 MQL5 고객을 놀래켜보세요!
MQL5는 프로그래머가 MetaTrader 환경 내에서 원하는 모든 작업을 수행할 수 있는 매우 완전한 기능 세트와 객체 지향 API를 제공합니다. 그러나 웹 기술은 오늘날 매우 다재다능한 도구로, 매우 구체적인 작업을 수행해야 하거나 고객을 뭔가 다른 것으로 놀라게 하고 싶거나 특정 MT5 Standard Library를 마스터할 시간이 충분하지 않은 경우에 도움이 될 수 있습니다. 오늘의 연습에서는 놀라운 기술 칵테일을 만드는 동시에 개발 시간을 관리할 수 있는 방법에 대한 실용적인 예를 안내해드립니다.
또 다른 MQL5 OOP 클래스 또 다른 MQL5 OOP 클래스
이 글은 이론적인 거래 아이디어를 구상하는 것부터 그 아이디어를 경험적 세계에서 현실로 만드는 MQL5 EA를 프로그래밍하는 것에 이르기까지 처음부터 객체 지향 Expert Advisor를 구축하는 방법을 보여줍니다. 행동으로 배우는 것은 IMHO 성공을 위한 확실한 접근 방식입니다. 그래서 저는 여러분이 Forex 로봇을 최종적으로 코딩하기 위해 아이디어를 주문하는 방법을 볼 수 있도록 실용적인 예를 보여주고 있습니다. 저의 목표는 또한 당신이 OO 원칙을 준수하도록 초대하는 것입니다.