English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
객체지향적 접근을 이용하여 EA 모드 프로그래밍하기

객체지향적 접근을 이용하여 EA 모드 프로그래밍하기

MetaTrader 5 | 12 10월 2021, 16:27
159 0
Denis Kirichenko
Denis Kirichenko

들어가며

이 문서에서는 MQL5 EA가 작업할 수 있는 프로그래밍 모드들에 대하여 논할 것입니다. 이 문서를 통해 달성하고자 하는 목표는 "각 모드는 자기들만의 방식으로 구현되어있다"라는 것을 설명해드리는 것입니다. 저는 일련의 과정을 통해 EA 개발의 각 단계에서 필요한 작업을 더욱 능률적으로 수행할 수 있을 것이라고 믿고 있습니다.

처음엔 EA 개발에 어떠한 단계가 필요한지 확인해야합니다. 그 다음엔 MetaTrader 5의 EA가 작업하고 도우미 프로그램들을 선택하는 모드를 확인합니다. 마지막으로 윗 아이디어를 구현하는데에 필요한 클래스들의 서열을 만드는 것으로 이 문서를 마칠 것입니다.


1. 개발 단계

트레이딩 봇 (EA)의 개발은 꽤나 다면적인 과정입니다. 여기서 핵심 블록은 아이디어의 알고리즘화 및 테스트입니다. 특히 EA의 거래 논리와 코드 알고리즘이 모두 테스트됩니다.

이 과정의 단계를 하나의 방식으로 표현하면 다음과 같습니다 (1번 그림).

1번 그림. EA 개발 단계와 구현

1번 그림. EA 개발 단계와 구현

다섯 번째 단계인 "알고리즘 트레이딩"은 관련된 개발자, 프로그래머, 분석가 및 기타 Expert의 작업을 보여줍니다. 이러한 모든 역할을 한 사람이 수행하는 경우가 종종 있습니다. 이게 트레이더-프로그래머라고 생각해봅시다.

이 스케마는 이후 업데이트해서 확장시킬 수 있습니다. 제 생각에는 EA 개발에서 가장 중요한 포인트를 보여주고 있습니다. 이 체계의 주기적인 패턴은 수명 동안 EA의 코드를 개선하고 수정할 수 있도록 합니다.

모든 단계에는 특정 도구, 지식 및 기술이 필요합니다.

제 생각에 개발자는 다음과 같은 간단한 변형 매트릭스를 보게 됩니다 (2번 그림).

2번 그림. 변형 매트릭스

2번 그림. 변형 매트릭스

보다시피, 양질의 코드로 성공적인 트레이딩 전략을 구현하는 트레이딩 봇 만이 5단계 "알고리즘 거래"에 도달하는 것입니다.


2. MQL5의 Expert Advisor 모드

MQL5 환경을 사용하면 다양한 모드에서 EA로 작업할 수 있습니다. 총 7개가 존재합니다. 지금부터 그 각각을 들여다 볼 것입니다.

프로그램 파일 타입을 위주로 보면 크게 두 그룹으로 나눌 수 있습니다.

  1. 소스 코드와 실행 파일을 필요로 하는 모드.
  2. 실행 파일만을 필요로 하는 모드.

디버그와 프로파일링 모드는 전자에 해당됩니다.

다른 분류 기준은 EA 상의 작업이 실제 스트림 데이터를 이용하는지, 아니면 과거 기록을 이용하는지입니다. 모든 테스트 모드는 과거 기록과 연결되어있습니다.

프로그래밍적으로 6개의 모드가 정의되어있습니다. EA가 통상 (배포) 모드로 작동할 수 있는가 없는가에 대한 결론은 그 결과에 달려있습니다. 금융시장 용도로 만들어진 완성 프로그램 (*.ex5 확장자로 된)이 이 모드에서 작동합니다. 동시에 완성 프로그램은 전략 테스터의 다른 모드들을 사용해서 활성화시키는 것도 가능합니다.

MQL 프로그램에서 실행가능한 모드들을 열거하는 ENUM_MQL_MODE를 만들어 봅시다.

//+------------------------------------------------------------------+
//| MQL Mode                                                         |
//+------------------------------------------------------------------+
enum ENUM_MQL_MODE
  {
   MQL_MODE_RELEASE=0,       // Release
   MQL_MODE_DEBUG=1,         // Debugging
   MQL_MODE_PROFILER=2,      // Profiling  
   MQL_MODE_TESTER=3,        // Testing
   MQL_MODE_OPTIMIZATION=4,  // Optimization
   MQL_MODE_VISUAL=5,        // Visual testing 
   MQL_MODE_FRAME=6,         // Gathering frames
  };
-->

이후 EA가 어떤 모드 타입으로 작업하고있는지 식별하기 위해 이 열거가 필요합니다.


2.1. 모드 식별 및 확인 함수

모든 모드를 반복하고 저널에 정보를 인쇄하는 간단한 함수를 작성하십시오.

//+------------------------------------------------------------------+
//| Checking all MQL modes                                           |
//+------------------------------------------------------------------+
void CheckMqlModes(void)
  {
//--- if it is debug mode
   if(MQLInfoInteger(MQL_DEBUG))
      Print("Debug mode: yes");
   else
      Print("Debug mode: no");
//--- if it is code profiling mode
   if(MQLInfoInteger(MQL_PROFILER))
      Print("Profile mode: yes");
   else
      Print("Profile mode: no");
//--- if it is test mode
   if(MQLInfoInteger(MQL_TESTER))
      Print("Tester mode: yes");
   else
      Print("Tester mode: no");
//--- if it is optimization mode
   if(MQLInfoInteger(MQL_OPTIMIZATION))
      Print("Optimization mode: yes");
   else
      Print("Optimization mode: no");
//--- if it is visual test mode
   if(MQLInfoInteger(MQL_VISUAL_MODE))
      Print("Visual mode: yes");
   else
      Print("Visual mode: no");
//--- if it is frame gathering optimization result mode
   if(MQLInfoInteger(MQL_FRAME_MODE))
      Print("Frame mode: yes");
   else
      Print("Frame mode: no");
  }

-->

모든 모드에서 이 함수가 작동하는지 확인합니다. 이는 OnInit() 이벤트 핸들러를 이용하여 호출될 수 있습니다.

호출 시험을 위해서 Test1_Modes_EA.mq5라는 EA의 템플릿을 만들어봅시다.

EA가 작동할 모드를 지정하는 옵션은 입력 패러미터에서 활성화됩니다. 올바른 모드의 이름이 지정되었는지 확인하는 것이 중요합니다. 만약 이름에 오류가 있다면 올바른 정보를 얻지 못하게 됩니다. 그리고 실제로 그런 일이 발생하였습니다.

아래 보이는 것은 릴리즈 모드입니다.

CL      0       17:20:38.932    Test1_Modes_EA (EURUSD.e,H1)     Current mode: MQL_MODE_RELEASE
QD      0       17:20:38.932    Test1_Modes_EA (EURUSD.e,H1)     Debug mode: no
KM      0       17:20:38.932    Test1_Modes_EA (EURUSD.e,H1)     Profile mode: no
EK      0       17:20:38.932    Test1_Modes_EA (EURUSD.e,H1)     Tester mode: no
CS      0       17:20:38.932    Test1_Modes_EA (EURUSD.e,H1)     Optimization mode: no
RJ      0       17:20:38.932    Test1_Modes_EA (EURUSD.e,H1)     Visual mode: no
GL      0       17:20:38.932    Test1_Modes_EA (EURUSD.e,H1)     Frame mode: no

-->

릴리즈 모드에서는 다른 모드 용의 플래그가 전부 0으로 처리됩니다. 따라서 우리의 식별 함수는 현재가 디버그 모드가 아니라는 것(Debug mode: no), 그리고 프로파일링 모드도 아니라는 것(Profile mode: no)을 확인한 상태인 상태입니다. 부정법을 활용하여 우리가 현재 릴리즈 모드에서 작업중이라는 것을 알 수 있습니다.

이제 디버그 모드는 어떤식으로 나타나는지 확인하겠습니다.

HG      0       17:27:47.709    Test1_Modes_EA (EURUSD.e,H1)     Current mode: MQL_MODE_DEBUG
LD      0       17:27:47.710    Test1_Modes_EA (EURUSD.e,H1)     Debug mode: yes
RS      0       17:27:47.710    Test1_Modes_EA (EURUSD.e,H1)     Profile mode: no
HE      0       17:27:47.710    Test1_Modes_EA (EURUSD.e,H1)     Tester mode: no
NJ      0       17:27:47.710    Test1_Modes_EA (EURUSD.e,H1)     Optimization mode: no
KD      0       17:27:47.710    Test1_Modes_EA (EURUSD.e,H1)     Visual mode: no
RR      0       17:27:47.710    Test1_Modes_EA (EURUSD.e,H1)     Frame mode: no

-->

디버그 모드는 올바르게 인식됩니다.

프로그래밍에 관한 책이라면 어느 것이건 디버깅을 통해 코드 내의 에러가 어느 부분에서 발생하는지 확인할 수 있음을 알려줍니다. 또한 디버깅은 프로그램의 특징도 부각시켜줍니다. MQL5 환경에서의 디버깅에 대한 보다 자세한 내용은 "Debugging MQL5 Programs"문서에서 확인하실 수 있습니다.

이 모드는 매매 아이디어용 알고리즘을 구체화하고 만드는 단계에서 주로 사용됩니다.

프로그램을 짤 때 IS_DEBUG_MODE 매크로나 MQLInfoInteger()함수에 MQL_DEBUG 식별자를 씀으로서 디버깅을 활성화됩니다.

이제 프로파일링 모드를 들여다 보겠습니다.

GS      0       17:30:53.879    Test1_Modes_EA (EURUSD.e,H1)     Current mode: MQL_MODE_PROFILER
OR      0       17:30:53.879    Test1_Modes_EA (EURUSD.e,H1)     Debug mode: no
GE      0       17:30:53.879    Test1_Modes_EA (EURUSD.e,H1)     Profile mode: yes
QM      0       17:30:53.879    Test1_Modes_EA (EURUSD.e,H1)     Tester mode: no
CE      0       17:30:53.879    Test1_Modes_EA (EURUSD.e,H1)     Optimization mode: no
FM      0       17:30:53.879    Test1_Modes_EA (EURUSD.e,H1)     Visual mode: no
GJ      0       17:30:53.879    Test1_Modes_EA (EURUSD.e,H1)     Frame mode: no

-->

식별 함수는 프로파일러가 얽혀있는 것을 정확하게 알아냈습니다.

이 모드를 사용하면 프로그램이 얼마나 빠르게 작업하는지 확인할 수 있습니다. 이 프로파일러는 시간을 들여 프로그램 블록에 정보를 전달합니다. 프로파일러가 알고리즘 내의 병목 현상 위치를 파악하게 됩니다. 병목 현상을 언제나 처리할 수 있는 것은 아니지만 알아두는 것 만큼 중요한 것도 없습니다.

프로파일링은 IS_PROFILE_MODE 매크로 혹은 MQL_PROFILER 식별자를 활성화시킨 MQLInfoInteger() 함수를 통해 활성화시킬 수 있습니다.

이제 테스트 모드를 봅시다. 이 정보는 전략 테스터의 "Journal" 탭에 나타납니다.

EG      0       17:35:25.397    Core 1  2014.11.03 00:00:00   Current mode: MQL_MODE_TESTER
OS      0       17:35:25.397    Core 1  2014.11.03 00:00:00   Debug mode: no
GJ      0       17:35:25.397    Core 1  2014.11.03 00:00:00   Profile mode: no
ER      0       17:35:25.397    Core 1  2014.11.03 00:00:00   Tester mode: yes
ED      0       17:35:25.397    Core 1  2014.11.03 00:00:00   Optimization mode: no
NL      0       17:35:25.397    Core 1  2014.11.03 00:00:00   Visual mode: no
EJ      0       17:35:25.397    Core 1  2014.11.03 00:00:00   Frame mode: no

-->

테스트 모드가 올바르게 식별되었습니다.

이는 전략 테스터가 열렸을 때의 EA 기본 모드입니다.

이 모드용 매크로는 딱히 없기 때문에 MQL5에서 이를 판단하는 방법은 MQL_TESTER 식별자를 이용한 MQLInfoInteger() 함수를 쓰는 것 뿐입니다.

이제 최적화로 넘어가보겠습니다. 기록이 담긴 저널은 에이전트의 폴더에 담깁니다. 제 경우엔 경로는 다음과 같습니다. %Program Files\MetaTrader5\tester\Agent-127.0.0.1-3000\logs

OH      0       17:48:14.010    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Current mode: MQL_MODE_OPTIMIZATION
KJ      0       17:48:14.010    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Debug mode: no
NO      0       17:48:14.010    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Profile mode: no
FI      0       17:48:14.010    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Tester mode: yes
KE      0       17:48:14.010    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Optimization mode: yes
LS      0       17:48:14.010    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Visual mode: no
QE      0       17:48:14.010    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Frame mode: no

-->

만약 최적화 모드가 활성화 되어 있다면 기본적으로 테스트 모드도 활성화 됩니다.

최적화 모드는 만약 전략 테스터의 "Settings" 탭 안 "Optimization" 항목이 비활성화되어있지않다면 활성화된 상태로 설정됩니다.

EA가 현재 MQL5 최적화 모드로 테스트되고 있는지 알아보려면 MQL_OPTIMIZATION 식별자를 MQLInfoInteger() 함수에 패싱하여 확인할 수 있습니다.

이제 시각화 모드를 들여다 보겠습니다.

JQ      0       17:53:51.485    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Current mode: MQL_MODE_VISUAL
JK      0       17:53:51.485    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Debug mode: no
KF      0       17:53:51.485    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Profile mode: no
CP      0       17:53:51.485    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Tester mode: yes
HJ      0       17:53:51.485    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Optimization mode: no
LK      0       17:53:51.485    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Visual mode: yes
KS      0       17:53:51.485    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Frame mode: no

-->

이를 통해 시각 테스트 모드와 표준 테스트 모드가 관련되어 있음을 알 수 있습니다.

만약 전략 테스터에서 "Settings" 탭 안의 "Visualizatiaon" 항목이 체크되어있다면 이 전략 테스터 안에서 EA는 이 모드로 작동하게 됩니다.

시각화 모드로 MQL5 프로그램 테스팅을 돌리려면 MQL_VISUAL_MODE 식별자를 활성화 시키고 MQLInfoInteger() 함수를 사용합니다.

마지막 모드는 프레임 모드입니다.

HI      0       17:59:10.177    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Current mode: MQL_MODE_FRAME
GR      0       17:59:10.177    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Debug mode: no
JR      0       17:59:10.177    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Profile mode: no
JG      0       17:59:10.177    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Tester mode: yes
GM      0       17:59:10.177    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Optimization mode: yes
HR      0       17:59:10.177    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Visual mode: no
MI      0       17:59:10.177    Test1_Modes_EA (EURUSD.e,H1)     2014.11.03 00:00:00   Frame mode: no

-->

흥미롭게도 이 함수는 프레임 플래그가 0이 될 때 테스트 및 최적화 모드만 인식했습니다. 함수 호출이 OnTesterInit() 핸들러로 전송되면 "Experts" 저널에 다음 항목이 포함됩니다.

IO      0       18:04:27.663    Test1_Modes_EA (EURUSD.e,H1)     Current mode: MQL_MODE_FRAME
GE      0       18:04:27.663    Test1_Modes_EA (EURUSD.e,H1)     Debug mode: no
ML      0       18:04:27.663    Test1_Modes_EA (EURUSD.e,H1)     Profile mode: no
CJ      0       18:04:27.663    Test1_Modes_EA (EURUSD.e,H1)     Tester mode: no
QR      0       18:04:27.663    Test1_Modes_EA (EURUSD.e,H1)     Optimization mode: no
PL      0       18:04:27.663    Test1_Modes_EA (EURUSD.e,H1)     Visual mode: no
GS      0       18:04:27.663    Test1_Modes_EA (EURUSD.e,H1)     Frame mode: yes

-->

사실상, 이제 프레임 수집 모드만 감지되었습니다.

이 모드는 "Settings" 탭의 "Optimization" 필드를 비활성화하지않으면 전략 테스터에서 사용됩니다. 경험에서 알 수 있듯이 이 모드는 OnTesterInit(), OnTesterPass()OnTesterDeinit() 핸들러의 본문에 정의되어 있습니다.

MQL_FRAME_MODE 식별자가 활성화된 채로 MQLInfoInteger() 함수를 사용하면 프레임 수집 모드에서 EA를 테스트한다는 사실을 쉽게 식별할 수 있습니다.

다음은 EA가 작동하는 모드를 자동으로 지정하는 서비스 함수 MqlMode()의 코드입니다.

//+------------------------------------------------------------------+
//| Identify the current MQL mode                                    |
//+------------------------------------------------------------------+
ENUM_MQL_MODE MqlMode(void)
  {
   ENUM_MQL_MODE curr_mode=WRONG_VALUE;

//--- if it is debug mode
   if(MQLInfoInteger(MQL_DEBUG))
      curr_mode=MQL_MODE_DEBUG;
//--- if it is code profiling mode
   else if(MQLInfoInteger(MQL_PROFILER))
      curr_mode=MQL_MODE_PROFILER;
//--- if it is visual test mode
   else if(MQLInfoInteger(MQL_VISUAL_MODE))
      curr_mode=MQL_MODE_VISUAL;
//--- if it is optimization mode
   else if(MQLInfoInteger(MQL_OPTIMIZATION))
      curr_mode=MQL_MODE_OPTIMIZATION;
//--- if it is test mode
   else if(MQLInfoInteger(MQL_TESTER))
      curr_mode=MQL_MODE_TESTER;
//--- if it is frame gathering optimization result mode
   else if(MQLInfoInteger(MQL_FRAME_MODE))
      curr_mode=MQL_MODE_FRAME;
//--- if it is release mode
   else
      curr_mode=MQL_MODE_RELEASE;
//---
   return curr_mode;
  }
-->

표준 테스트가 최적화 및 시각적 테스트 모드에서 식별되므로 최적화 및 시각화 모드 이후에 표준 테스트 모드를 확인합니다.

Test2_Modes_EA.mq5 EA의 두 번째 템플릿에서 함수의 작업을 살펴보면 템플릿이 실행될 때 저널에 새 항목이 나타나는 것을 볼 수 있습니다. 예를 들어, 프로파일링 모드의 경우 아래 항목이 만들어졌습니다.

HG      0       11:23:52.992    Test2_Modes_EA (EURUSD.e,H1)    Current mode: MQL_MODE_PROFILER
-->

지정된 모드에 해당하는 클래스 모델을 생성하기 위한 MQL5 Expert의 작동 모드에 대한 세부 사항에 대해 논의했습니다. 문서의 다음 부분에서 구현해 볼 것입니다.


3. 각기 다른 모드에서 작업하도록 설계된 EA 템플릿

다시 한 번 EA 개발 단계를 둘러보실 것을 추천드립니다.

알고리즘화 단계에서 프로그래머는 디버깅 및 프로파일링을 가장 자주 수행합니다. 프로그래머는 과거 데이터를 테스트하기 위해 전략 테스터의 모든 모드를 활용합니다. 최종 모드(배포 모드)는 온라인 트레이딩에 활용됩니다.

제 생각에 EA는 개발 및 테스트 단계의 요구 사항이 코드에 반영되어야 한다는 점에서 다면적이어야 합니다.

그런 관점에서는 기본 알고리즘이 유지될 것이고, 그로 인해 EA는 모드마다 다른 행동을 취하게 될 것입니다. 객체 지향 프로그래밍 도구 세트는 이 아이디어를 구현하는 데 완벽합니다.

2번 그림. 각기 다른 모드에서 작동하도록 설계된 EA 클래스 서열

3번 그림. 각기 다른 모드에서 작동하도록 설계된 EA 클래스 서열

각기 다른 모드에서 작동하도록 설계된 EA 클래스 서열은 3번 그림에 나타나있습니다.

모든 공통 항목을 캡슐화하는 기본 클래스 CModeBase에는 파생 클래스 2개 CModeReleaseCModeTester 클래스가 있습니다. 첫 번째는 디버깅 클래스의 부모가 되고 두 번째는 이력 데이터에 대한 EA 테스트와 연결된 클래스의 부모가 됩니다.

모드의 맥락에서 클래스 메소드를 개발할 때 절차적 접근 방식과 모듈식 접근 방식을 결합하는 아이디어를 개발해 보겠습니다. 예를 들어 다음 트레이딩 로직을 고려해 보겠습니다.

  1. 오픈 포지션이 없으면 시그널에 따라 오픈.
  2. 오픈 포지션이 있으면 시그널에 따라 청산
  3. 오픈 포지션이 있는 경우 추적 손절매(트레일링 스탑)

트레이딩 시그널은 새 막대가 나타날 때 표준 인디케이터 MACD에 의해 감지됩니다.

주요선 상승하고 MACD 인디케이터의 음의 영역에 있는 신호를 교차할 때 매수 신호가 나타납니다(4번 그림).

4번 그림. 매수 시그널

4번 그림. 매수 시그널

매도 신호는 주요선이 하락하고 인디케이터의 양의 영역에서 신호를 교차할 때 나타납니다(5번 그림).

5번 그림. 매도 시그널

5번 그림. 매도 시그널

반대 신호가 나타날 때 또는 포지션 지원 모드가 활성화된 경우에 배치되는 손절매에 의해 포지션이 닫힙니다.

그러면 기본 클래스 CModeBase의 정의는 다음과 같습니다.

//+------------------------------------------------------------------+
//| Class CModeBase                                                  |
//| Purpose: a base class for MQL-modes                              |            
//+------------------------------------------------------------------+
class CModeBase
  {
//--- === Data members === --- 
private:
   //--- a macd object & values
   CiMACD            m_macd_obj;
   double            m_macd_main_vals[2];
   double            m_macd_sig_vals[2];

protected:
   long              m_pos_id;
   bool              m_is_new_bar;
   uint              m_trailing_stop;
   uint              m_trail_step;
   //--- trade objects
   CSymbolInfo       m_symbol_info;
   CTrade            m_trade;
   CPositionInfo     m_pos_info;
   CDealInfo         m_deal_info;
   //--- mql mode
   ENUM_MQL_MODE     m_mql_mode;

   //--- a new bar object
   CisNewBar         m_new_bar;
   //--- current tick signal flag
   bool              m_is_curr_tick_signal;
   //--- close order type
   ENUM_ORDER_TYPE   m_close_ord_type;
   
//--- === Methods === --- 
public:
   //--- constructor/destructor
   void              CModeBase();
   void             ~CModeBase(void){};
   //--- initialization
   virtual bool      Init(int _fast_ema,int slow_ema,int _sig,ENUM_APPLIED_PRICE _app_price);
   virtual void      Deinit(void){};

   //--- Modules
   virtual void      Main(void){};

   //--- Procedures
   virtual void      Open(void){};
   virtual void      Close(void){};
   virtual void      Trail(void){};

   //--- Service
   static ENUM_MQL_MODE CheckMqlMode(void);
   ENUM_MQL_MODE     GetMqlMode(void);
   void              SetMqlMode(const ENUM_MQL_MODE _mode);
   void              SetTrailing(const uint _trailing,const uint _trail_step);

protected:
   //--- Functions
   ENUM_ORDER_TYPE   CheckOpenSignal(const ENUM_ORDER_TYPE _open_sig);
   ENUM_ORDER_TYPE   CheckCloseSignal(const ENUM_ORDER_TYPE _close_sig);
   ENUM_ORDER_TYPE   CheckTrailSignal(const ENUM_ORDER_TYPE _trail_sig,double &_sl_pr);
   //---
   double            GetMacdVal(const int _idx,const bool _is_main=true);

private:
   //--- Macros
   bool              RefreshIndicatorData(void);
   //--- Normalization
   double            NormalPrice(double d);
   double            NormalDbl(double d,int n=-1);
   double            NormalSL(const ENUM_ORDER_TYPE _ord_type,double op,double pr,
                              uint SL,double stop);
   double            NormalTP(const ENUM_ORDER_TYPE _ord_type,double op,double pr,
                              uint _TP,double stop);
   double            NormalLot(const double _lot);
  };

-->

상속자 클래스에서 사용되는 한 기본 클래스에는 무엇이든 포함될 수 있습니다.

MACD 데이터는 private 이기때문에 상속 클래스에서는 받아볼 수 없습니다.

이러한 메소드 중에는 Main(), Open(), Close(), Trail()과 같은 가상 메소드가 있습니다. 이 메소드들의 구현은 EA가 현재 작업 중인 모드에 따라 크게 달라집니다. 기본 클래스에서는 비어있게됩니다.

또한 기본 클래스는 모든 MQL 모드에 대해 동일한 거래 로직을 갖는 메소드로 구성됩니다. 그에 속하는 모든 신호 메소드.

  • CModeBase::CheckOpenSignal(),
  • CModeBase::CheckCloseSignal(),
  • CModeBase::CheckTrailSignal().

이 문서에서는 모든 MQL 모드 유형에 대한 코드 작성을 대상으로 하지 않는다는 점을 염두에 두어야 합니다. 표준 및 시각적 테스트가 예시가 될 것입니다.


3.1. 테스트 모드

알고리즘을 코딩하고 컴파일한 후에는 일반적으로 전략 테스터에서 과거 데이터에 대해 전략을 시도하여 설계된 대로 작동하는지 확인합니다.

대부분의 경우 시스템이 거래 신호를 얼마나 정확하게 구현하는지 확인해야 합니다. 어쨌든 이 단계에서 EA의 기본 목표는 출시 및 매매입니다.

정기 테스트를 위한 CModeTester 클래스는 다음과 같이 구현할 수 있습니다.

//+------------------------------------------------------------------+
//| Class CModeTester                                                |
//| Purpose: a class for the tester mode                             |            
//| Derives from class CModeBase.                                    |
//+------------------------------------------------------------------+
class CModeTester : public CModeBase
  {
//--- === Methods === --- 
public:
   //--- constructor/destructor
   void              CModeTester(void){};
   void             ~CModeTester(void){};

   //--- Modules
   virtual void      Main(void);

   //--- Procedures
   virtual void      Open(void);
   virtual void      Close(void);
   virtual void      Trail(void);
  };

-->

주요 모듈은 다음과 같이 구현됩니다.

//+------------------------------------------------------------------+
//| Main module                                                      |
//+------------------------------------------------------------------+
void CModeTester::Main(void)
  {
//--- 1) closure
   this.Close();
//--- 2) opening
   this.Open();
//--- 3) trailing stop
   this.Trail();
  }

-->

정기 테스트 모드의 경우 Joural에 매매 시그널에 대한 정보를 출력하십시오.

거래 신호의 소스로 간주되는 인디케이터 값이 포함된 문자열을 추가합니다.

아래 있는 것이 포지션 오픈 신호 후에 청산 신호가 따라온 것으로 Journal에 기록된 것의 일부입니다.

HE      0       13:34:04.118    Core 1  2014.11.14 22:15:00   ---=== Signal to open: SELL===---
FI      0       13:34:04.118    Core 1  2014.11.14 22:15:00   A bar before the last one, main: 0.002117; signal: 0.002109
DL      0       13:34:04.118    Core 1  2014.11.14 22:15:00   The last bar, main: 0.002001; signal: 0.002118
LO      0       13:34:04.118    Core 1  2014.11.14 22:15:00   market sell 0.03 EURUSD.e (1.25242 / 1.25251 / 1.25242)
KH      0       13:34:04.118    Core 1  2014.11.14 22:15:00   deal #660 sell 0.03 EURUSD.e at 1.25242 done (based on order #660)
GE      0       13:34:04.118    Core 1  2014.11.14 22:15:00   deal performed [#660 sell 0.03 EURUSD.e at 1.25242]
OD      0       13:34:04.118    Core 1  2014.11.14 22:15:00   order performed sell 0.03 at 1.25242 [#660 sell 0.03 EURUSD.e at 1.25242]
IK      0       13:34:04.118    Core 1  2014.11.14 22:15:00   CTrade::OrderSend: market sell 0.03 EURUSD.e [done at 1.25242]
IL      0       13:34:04.118    Core 1  2014.11.17 13:30:20   
CJ      0       13:34:04.118    Core 1  2014.11.17 13:30:20   ---=== Signal to close: SELL===---
GN      0       13:34:04.118    Core 1  2014.11.17 13:30:20   A bar before the last one, main: -0.001218; signal: -0.001148
QL      0       13:34:04.118    Core 1  2014.11.17 13:30:20   The last bar, main: -0.001123; signal: -0.001189
EP      0       13:34:04.118    Core 1  2014.11.17 13:30:20   market buy 0.03 EURUSD.e (1.25039 / 1.25047 / 1.25039)
FG      0       13:34:04.118    Core 1  2014.11.17 13:30:20   deal #661 buy 0.03 EURUSD.e at 1.25047 done (based on order #661)
OJ      0       13:34:04.118    Core 1  2014.11.17 13:30:20   deal performed [#661 buy 0.03 EURUSD.e at 1.25047]
PD      0       13:34:04.118    Core 1  2014.11.17 13:30:20   order performed buy 0.03 at 1.25047 [#661 buy 0.03 EURUSD.e at 1.25047]
HE      0       13:34:04.118    Core 1  2014.11.17 13:30:20   CTrade::OrderSend: market buy 0.03 EURUSD.e [done at 1.25047]
-->

전략 테스터에는 친숙한 저널 "Experts"가 없습니다. 모든 정보는 테스트 및 최적화 중에 전략 테스터가 수행한 작업에 대한 기록이 포함된 "Journal" 탭에서 찾을 수 있습니다.

그렇기 때문에 필요한 문자열을 검색해야 합니다. 항목 정보를 분리해야 하는 경우 파일에 기록할 수 있습니다.

표준 테스트 전략은 TestMode_tester.mq5 EA 코드에 구현되어 있습니다.


3.2. 시각 테스팅 모드

때로는 라이브 차트를 참조하고 EA가 현재 상황을 어떻게 처리하고 있는지 확인해야 합니다.

간단한 시각화를 통해 거래 시스템이 틱에 어떻게 반응하는지 확인할 수 있을 뿐만 아니라 테스트 종료 시 유사한 가격 모델을 비교할 수도 있습니다.

시각적 테스트를 위한 CModeVisual 클래스의 정의는 다음과 같습니다.

//+------------------------------------------------------------------+
//| Class CModeVisual                                                |
//| Purpose: a class for the tester mode                             |            
//| Derived from class CModeBase.                                    |
//+------------------------------------------------------------------+
class CModeVisual : public CModeTester
  {
//--- === Data members === --- 
private:
   CArrayObj         m_objects_arr;
   double            m_subwindow_max;
   double            m_subwindow_min;
   
//--- === Methods === --- 
public:
   //--- constructor/destructor
   void              CModeVisual(void);
   void             ~CModeVisual(void);

   //--- Procedures
   virtual void      Open(void);
   virtual void      Close(void);

private:
   bool              CreateSignalLine(const bool _is_open_sig,const bool _is_new_bar=true);
   bool              CreateRectangle(const ENUM_ORDER_TYPE _signal);
   void              RefreshRectangles(void);
  };

-->

이 클래스에는 몇몇 숨겨진 멤버가 있습니다. m_objects_arr 클래스의 멤버는 CArrayObj 유형의 동적 배열을 구현합니다. 선이나 사각형 같은 그래픽 객체가 이에 속합니다. 다른 두 클래스 멤버(m_subwindow_max, m_subwindow_min)는 인디케이터 하위 창의 최대 및 최소 크기를 제어합니다.

개인 메소드는 그래픽 개체 작업을 담당합니다.

이 클래스에는 Main()Trail() 메소드가 포함되어 있지 않습니다. 상위 유사체인 CModeTester::Main()CModeTester::Trail()이 각각 호출됩니다.

그래픽 객체는 시각적 테스트 모드에서 만들 수 있습니다. 이는 전략 테스터의 다른 모드에서는 안됩니다.

진입 신호가 나타날 때 차트에 빨간색 수직선을 그리고 퇴장 신호를 수신할 때 파란색 수직선을 그리도록 합니다. 인디케이터의 하위 창에서 해당 색상의 직사각형으로 진입점과 퇴장점 사이의 공간을 채웁니다.

롱 포지션인 경우 직사각형은 하늘색으로 그려집니다. 만약 숏 포지션인 경우 분홍색으로 그려집니다 (6번 그림).

6번 그림. 시각 테스팅 모드의 그래픽 객체

6번 그림. 시각 테스팅 모드의 그래픽 객체

직사각형의 높이는 생성 시 차트의 하위 창의 최대값과 최소값에 따라 달라집니다. 모든 사각형의 크기를 동일하게 하려면 차트 하위 창의 좌표가 변경되는 경우에 대비하여 사각형 좌표 변경 블록을 코드에 추가해야 합니다.

따라서 MACD 인디케이터의 하위 창에서 다음 영역을 얻습니다. 무색(포지션 없음), 분홍색(숏 포지션), 하늘색(롱 포지션).

시각적 테스트 모드에 대한 전략은 TestMode_visual_tester.mq5 EA 코드에서 구현됩니다.


마치며

지금까지 이 문서에서는 MetaTrader 5 터미널과 MQL5 언어의 모드 기능을 설명했습니다.. 거래 알고리즘 프로그래밍에 대한 다중 모드 접근 방식은 한편으로는 더 많은 비용을 수반하며, 다른 한편으로는 각 개발 단계를 차례로 고려할 기회가 주어집니다 객체 지향 프로그래밍은 이 경우 프로그래머에게 유용한 도움이 됩니다.

최적화 및 프레임 수집 모드는 거래 시스템의 통계 속성에 대한 향후 문서에서 강조될 것입니다.


MetaQuotes 소프트웨어 사를 통해 러시아어가 번역됨.
원본 기고글: https://www.mql5.com/ru/articles/1246

파일 첨부됨 |
cisnewbar.mqh (13.74 KB)
modes.mqh (62.77 KB)
test1_modes_ea.mq5 (9.43 KB)
test2_modes_ea.mq5 (10.01 KB)
모스크바 거래소의 파생 상품 시장 사례를 통한 거래소 가격 책정 원칙 모스크바 거래소의 파생 상품 시장 사례를 통한 거래소 가격 책정 원칙
이 문서에서는 모스크바 거래소의 파생 상품 시장 사례를 통하여 거래소 가격 책정 및 청산의 세부 이론에 대해 알아보겠습니다. 이 문서는 파생 상품 거래에 대한 첫 번째 교환 경험을 얻고자 하는 초보자와 중앙 집중식 교환 플랫폼에서 거래를 고려하고 있는 숙련된 외환 트레이더를 위한 포괄적인 문서입니다.
트레이더의 통계 도우미: 가설들 트레이더의 통계 도우미: 가설들
이 문서에서는 수리통계학의 기초 중 하나인 가설에 대해 다뤄보겠습니다. 다양한 가설들은 실제 예시에 수리통계적 관점으로 접근해서 검토, 검증됩니다. 실제 데이터는 비모수적 방법을 사용하여 일반화됩니다. 데이터 처리에는 Statistica 패키지와 포팅된 ALGLIB MQL5 수리분석 라이브러리가 사용됩니다.
HedgeTerminal 패널을 이용하여 MetaTrader 5로 양방향 매매와 포지션 헤징하기, 파트 1 HedgeTerminal 패널을 이용하여 MetaTrader 5로 양방향 매매와 포지션 헤징하기, 파트 1
이 문서는 포지션 헤징에 대한 새로운 접근 방식을 설명하고 이 문제에 대해 MetaTrader 4와 MetaTrader 5 사용자 간의 논쟁에 종지부를 찍을 것입니다. 헤징을 신뢰할 수 있게 하는 알고리즘은 일반인의 용어로 설명되고 간단한 차트와 다이어그램으로 설명됩니다. 이 문서는는 MetaTrader 5 내의 새로운 완전 기능 트레이딩 터미널이자 새로운 패널인 HedgeTerminal에 전면적으로 집중할 것입니다. HedgeTerminal과 그를 통한 매매 가상화를 통하여 MetaTrader 4와 비슷한 방식으로 포지션을 관리할 수 있게 되었습니다.
MQL5 프로그래밍 기초: 터미널 글로벌 변수 MQL5 프로그래밍 기초: 터미널 글로벌 변수
이 문서에서는 터미널에서 글로벌 변수 작업을 용이하게 하는 객체 생성을 위한 MQL5 언어의 객체 지향 기능에 중점을 두고 알아보겠습니다. 실전적인 예를 들어보자면, 글로벌 변수가 프로그램 단계 구현을 위한 제어점으로 사용되는 경우를 고려합니다.