English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
MQL5 마법사: 신호 거래 모듈을 만드는 방법

MQL5 마법사: 신호 거래 모듈을 만드는 방법

MetaTrader 5트레이딩 시스템 | 4 8월 2021, 16:50
101 0
MetaQuotes
MetaQuotes

소개

MetaTrader 5는 거래 아이디어를 빠르게 확인할 수 있는 강력한 도구를 제공합니다. 이것은 MQL5 마법사의 거래 전략 생성기입니다. Expert Advisor 코드의 자동 생성을 위한 MQL5 마법사의 사용은 "MQL5 마법사: 프로그래밍 없이 Expert Advisors 생성" 문서에 설명되어 있습니다. 코드 생성 시스템의 개방성을 통해 거래 신호, 자금 관리 시스템 및 후행 모듈의 고유한 클래스를 표준에 추가할 수 있습니다.

이 문서에서는 MQL5 마법사로 Expert Advisors를 생성할 때 이를 사용하기 위해 거래 신호 모듈을 작성하는 원칙을 설명합니다.

MQL5 Wizard로 생성된 Expert Advisor는 4개의 기본 요소(4개의 기본 클래스)를 기반으로 합니다.

그림 1. CExpert 기본 클래스의 구조

그림 1. CExpert 기본 클래스의 구조

CExpert 클래스(또는 하위 클래스)는 거래 로봇의 주요 "엔진"입니다. CExpert의 인스턴스에는 CExpertSignal, CExpertMoneyCExpertTrailing(또는 해당 하위 클래스)과 같은 각 클래스의 복사본이 하나씩 있습니다.

  1. CExpertSignal은 거래 신호 생성기의 기초입니다. CExpert에 포함된 CExpertSignal 파생 클래스의 인스턴스는 내장 알고리즘을 기반으로 시장 진입 가능성, 진입 수준 및 보호 주문 배치에 대한 정보를 Expert Advisor에게 제공합니다. 거래 작업 실행에 대한 최종 결정은 EA에서 내립니다.
  2. CExpertMoney는 자금 및 위험 관리 시스템의 기초입니다. CExpertMoney 파생 클래스의 인스턴스는 포지션 개설 및 보류 주문에 대한 거래량을 계산합니다. 볼륨에 대한 최종 결정은 EA가 합니다.
  3. CExpertTrailing - 오픈 포지션 지원 모듈의 기초입니다. CExpertTrailing 파생 클래스의 인스턴스는 위치의 보호 명령을 수정해야 할 필요성에 대해 EA에 알립니다. 주문 수정에 대한 최종 결정은 EA가 합니다.

또한 CExpert 클래스의 멤버는 다음 클래스의 인스턴스입니다.

  • CExpertTrade (거래용)
  • CIndicators(EA 작업과 관련된 지표 및 시계열 제어용).
  • CSymbolInfo (계측기에 대한 정보를 가져오기 위함)
  • CAAccountInfo(거래 계정 상태에 대한 정보를 얻기 위해)
  • CPositionInfo (포지션에 대한 정보를 얻기 위해)
  • CORderInfo(대기 중인 주문에 대한 정보를 얻기 위해)

이하 "전문가"란 CExpert 또는 그 하위 클래스의 인스턴스를 의미합니다.

CExpert 및 작업에 대한 자세한 내용은 별도의 문서에서 설명합니다.


1. 기본 클래스 CExpertSignal

CExpertSignal은 거래 신호 생성기의 기초입니다. "외부 세계"와의 통신을 위해 CExpertSignal에는 공개 가상 메소드 집합이 있습니다.

초기화

 기술

가상 초기화

클래스 인스턴스의 초기화는 EA의 데이터와 모듈 데이터의 동기화를 제공합니다.

가상 검증 설정

설정된 매개변수의 유효성 검사

가상 초기 지표

거래 신호 생성기 작동에 필요한 모든 지표 및 시계열 생성 및 초기화

포지션 열기/반전/닫기 신호

 

가상 CheckOpenLong

롱 포지션 오픈 신호 생성, 진입 수준 정의 및 보호 주문

가상 CheckOpenShort

숏 포지션 오픈 신호 생성, 진입 수준 정의 및 보호 주문

가상 CheckCloseLong

롱 포지션 청산 신호 생성, 종료 레벨 정의

가상 CheckCloseShort

매도 포지션 청산 신호 생성, 종료 레벨 정의

가상 CheckReverseLong

롱 포지션 반전 신호 생성, 반전 수준 정의 및 보호 주문

가상 CheckReverseShort

매도 포지션 반전 신호 생성, 반전 수준 정의 및 보호 주문

대기 중인 주문 관리

 

가상 CheckTrailingOrderLong

보류 중인 구매 주문의 수정 신호 생성, 새 주문 가격 정의

가상 CheckTrailingOrderShort

보류 중인 판매 주문의 수정 신호 생성, 새로운 주문 가격 정의

방법 설명

1.1. 초기화 방법:

1.1.1 초기화

Init() 메소드는 클래스 인스턴스가 전문가에게 추가된 직후 자동으로 호출됩니다. 메소드 재정의가 필요하지 않습니다.

virtual bool Init(CSymbolInfo* symbol, ENUM_TIMEFRAMES period, double adjusted_point);

1.1.2 검증 설정

ValidationSettings() 메소드는 모든 매개변수가 설정된 후 전문가로부터 바로 호출됩니다. 설정 매개변수가 있는 경우 메소드를 재정의해야 합니다.

virtual bool ValidationSettings();

재정의된 메소드는 모든 옵션이 유효한 경우(사용 가능한 경우) true를 반환해야 합니다. 매개변수 중 하나 이상이 올바르지 않으면 false를 리턴해야 합니다(추가 작업 불가능).

기본 클래스 CExpertSignal에는 조정 가능한 매개변수가 없으므로 기본 클래스 메소드는 검사를 수행하지 않고 항상 true를 반환합니다.

1.1.3 초기 지표

InitIndicators() 메소드는 필요한 모든 지표 및 시계열의 생성 및 초기화를 구현합니다. 모든 매개변수가 설정되고 그 정확성이 성공적으로 검증된 후 전문가로부터 호출됩니다. 거래 신호 생성기가 하나 이상의 지표 또는 시계열을 사용하는 경우 이 방법을 재정의해야 합니다.

virtual bool InitIndicators(CIndicators* indicators);

지표 및/또는 시계열은 표준 라이브러리의 적절한 클래스를 통해 사용해야 합니다. 모든 지표 및/또는 시계열의 포인터는 전문가의 지표 컬렉션에 추가되어야 합니다(매개변수로 전달되는 포인터).

재정의된 메소드는 지표 및/또는 시계열을 사용한 모든 조작이 성공한 경우 true를 반환해야 합니다(사용하기에 적합함). 지표 및/또는 시계열을 사용하여 하나 이상의 작업이 실패한 경우 메소드는 false를 반환해야 합니다(추가 작업은 불가능함).

기본 클래스 CExpertSignal은 지표 또는 시계열을 사용하지 않으므로 기본 클래스 메소드는 작업을 수행하지 않고 항상 true를 반환합니다.


1.2. 포지션 오픈 신호 확인 방법:

1.2.1 CheckOpenLong

CheckOpenLong() 메소드는 진입 레벨과 보호 주문의 레벨을 정의하는 롱 포지션의 오픈 신호를 생성합니다. 롱 포지션을 오픈해야 하는지 여부를 결정하기 위해 전문가가 명령을 내리게 됩니다. 롱 포지션 오픈 신호가 생성될 것으로 예상되는 경우 메소드를 재정의해야 합니다.

virtual bool CheckOpenLong(double& price, double& sl, double& tp, datetime& expiration);

이 방법은 롱 포지션 오픈 조건을 확인하는 알고리즘을 구현해야 합니다. 조건이 충족되면 변수 price, sl, tp 및 만료(매개변수로 전달되는 참조)에 적절한 값이 할당되어야 하고 메소드는 true를 반환해야 합니다. 조건이 충족되지 않으면 메소드는 false를 반환해야 합니다.

기본 클래스 CExpertSignal에는 긴 위치 열기 신호를 생성하는 내장 알고리즘이 없으므로 기본 클래스 메소드는 항상 false를 반환합니다.

1.2.2 CheckOpenShort

CheckOpenShort() 메소드는 진입 레벨과 보호 주문의 레벨을 정의하여 매도 포지션의 개시 신호를 생성합니다. 숏 포지션을 열어야 하는지 여부를 판단하기 위해 전문가가 명령을 내리게 됩니다. 매도 포지션 개시 신호가 생성될 것으로 예상되는 경우 메소드를 재정의해야 합니다. 

virtual bool CheckOpenShort(double& price, double& sl, double& tp, datetime& expiration);

메소드는 매도 포지션을 열기 위한 조건을 확인하는 알고리즘을 구현해야 합니다. 조건이 충족되면 변수 price, sl, tp 및 만료(매개변수로 전달되는 참조)에 적절한 값이 할당되어야 하고 메소드는 true를 반환해야 합니다. 조건이 충족되지 않으면 메소드는 false를 반환해야 합니다.

기본 클래스 CExpertSignal에는 매도 포지션 시작 신호를 생성하는 내장 알고리즘이 없으므로 기본 클래스 메소드는 항상 false를 반환합니다.


1.3. 포지션 청산 신호 확인 방법:

1.3.1 CheckCloseLong

CheckCloseLong() 메소드는 롱 포지션의 청산 신호를 생성하여 종료 레벨을 정의합니다. 롱 포지션을 청산해야 하는지 여부를 결정하기 위해 전문가가 명령을 내리게 됩니다. 롱 포지션 청산 신호가 생성될 것으로 예상되는 경우 메소드를 재정의해야 합니다.

virtual bool CheckCloseLong(double& price);

메소드는 롱 포지션을 청산하기 위한 조건을 확인하는 알고리즘을 구현해야 합니다. 조건이 충족되면 변수 price(매개변수로 전달되는 참조)에 적절한 값이 할당되어야 하고 메소드는 true를 반환해야 합니다. 조건이 충족되지 않으면 메소드는 false를 반환해야 합니다.

기본 클래스 CExpertSignal에는 긴 위치 닫기 신호를 생성하는 내장 알고리즘이 없으므로 기본 클래스 메소드는 항상 false를 반환합니다.

1.3.2 CheckCloseShort

CheckCloseShort() 메소드는 엑시트 레벨을 정의하는 숏 포지션의 청산 신호를 생성합니다. 숏 포지션을 청산해야 하는지 여부를 결정하기 위해 전문가가 명령을 내리게 됩니다. 매도 포지션 청산 신호가 생성될 것으로 예상되는 경우 메소드를 재정의해야 합니다.

virtual bool CheckCloseShort(double& price);

메소드는 매도 포지션을 청산하기 위해 조건을 확인하는 알고리즘을 구현해야 합니다. 조건이 충족되면 변수 price(매개변수로 전달되는 참조)에 적절한 값이 할당되어야 하고 메소드는 true를 반환해야 합니다. 조건이 충족되지 않으면 메소드는 false를 반환해야 합니다.

기본 클래스 CExpertSignal에는 매도 위치 종료 신호를 생성하는 내장 알고리즘이 없으므로 기본 클래스 메소드는 항상 false를 반환합니다.


1.4. 포지션 반전 신호 확인 방법:

1.4.1 CheckReverseLong

CheckReverseLong 메소드는 롱 포지션의 반전 신호를 생성하여 반전 수준과 보호 주문의 수준을 정의합니다. 롱 포지션을 되돌릴 필요가 있는지 여부를 결정하기 위해 전문가가 명령을 내리게 됩니다. 롱 포지션 반전의 신호가 생성될 것으로 예상되는 경우 이 방법을 재정의해야 합니다.

virtual bool CheckReverseLong(double& price, double& sl, double& tp, datetime& expiration);

이 방법은 롱 포지션 반전의 조건을 확인하기 위한 알고리즘을 구현해야 합니다. 조건이 충족되면 변수 price, sl, tp 및 만료(매개변수로 전달되는 참조)에 적절한 값이 할당되어야 하고 메소드는 true를 반환해야 합니다. 조건이 충족되지 않으면 메소드는 false를 반환해야 합니다.

CExpertSignal 기본 클래스에서 긴 위치 반전 신호를 생성하기 위한 다음 알고리즘이 구현됩니다.

  1. 롱 포지션을 청산하라는 신호를 확인하고 있습니다.
  2. 숏 포지션을 열기 위한 신호를 확인하고 있습니다.
  3. 두 신호가 모두 활성화되고(조건이 충족됨) 종가와 시가가 일치하면 price, sl, tp 및 만료 변수(매개변수로 전달되는 참조)에 적절한 값이 할당되고 메소드가 true를 반환합니다.
조건이 충족되지 않으면 메소드는 false를 반환합니다.

1.4.2 CheckReverseShort

CheckReverseShort 방법은 매도 포지션의 반전 신호를 생성하여 반전 수준과 보호 주문의 수준을 정의합니다. 숏 포지션을 되돌릴 필요가 있는지 여부를 결정하기 위해 전문가가 명령을 내리게 됩니다. 기본 클래스에서 구현된 알고리즘과 다른 알고리즘에 따라 롱 포지션 반전의 신호가 생성될 것으로 예상되는 경우 메소드를 재정의해야 합니다.

virtual bool CheckReverseShort(double& price, double& sl, double& tp, datetime& expiration);

방법은 매도 포지션 반전의 조건을 확인하기 위한 알고리즘을 구현해야 합니다. 조건이 충족되면 변수 price, sl, tp 및 만료(매개변수로 전달되는 참조)에 적절한 값이 할당되어야 하고 메소드는 true를 반환해야 합니다. 조건이 충족되지 않으면 메소드는 false를 반환해야 합니다.

CExpertSignal 기본 클래스에서 숏 포지션 반전 신호를 생성하기 위한 다음 알고리즘이 구현됩니다.

  1. 숏 포지션을 청산하라는 신호를 확인하고 있습니다.
  2. 롱 포지션을 여는 신호를 확인하고 있습니다.
  3. 두 신호가 모두 활성화되고(조건이 충족됨) 종가와 시가가 일치하면 price, sl, tp 및 만료 변수(매개변수로 전달되는 참조)에 적절한 값이 할당되고 메소드가 true를 반환합니다.

조건이 충족되지 않으면 메소드는 false를 반환합니다.


1.5. 주문 수정 보류 신호 확인 방법:

1.5.1 CheckTrailingOrderLong

CheckTrailingOrderLong() 메소드는 보류 중인 구매 주문의 수정 신호를 생성하여 새 주문 가격을 정의합니다. 보류 중인 구매 주문을 수정해야 하는지 여부를 결정하기 위해 전문가가 명령을 내리게 됩니다. 보류 중인 구매 주문의 수정 신호가 생성될 것으로 예상되는 경우 메소드를 재정의해야 합니다.

virtual bool CheckTrailingOrderLong(COrderInfo* order, double& price)

이 메소드는 보류 중인 구매 주문의 수정 조건을 확인하는 알고리즘을 구현해야 합니다. 조건이 충족되면 변수 price(매개변수로 전달되는 참조)에 적절한 값이 할당되어야 하고 메소드는 true를 반환해야 합니다. 조건이 충족되지 않으면 메소드는 false를 반환해야 합니다.

기본 클래스 CExpertSignal에는 보류 중인 구매 주문의 수정 신호를 생성하기 위한 기본 제공 알고리즘이 없으므로 기본 클래스 메소드는 항상 false를 반환합니다.

1.5.2 CheckTrailingOrderShort

CheckTrailingOrderShort() 메소드는 새로운 주문 가격을 정의하는 보류 중인 판매 주문의 수정 신호를 생성합니다. 보류 중인 판매 주문을 수정해야 하는지 여부를 결정하기 위해 전문가가 명령을 내리게 됩니다. 보류 중인 판매 주문의 수정 신호가 생성될 것으로 예상되는 경우 메소드를 재정의해야 합니다.

virtual bool CheckTrailingOrderShort(COrderInfo* order, double& price)

메소드는 보류 중인 판매 주문의 수정 조건을 확인하는 알고리즘을 구현해야 합니다. 조건이 충족되면 변수 price(매개변수로 전달되는 참조)에 적절한 값이 할당되어야 하고 메소드는 true를 반환해야 합니다. 조건이 충족되지 않으면 메소드는 false를 반환해야 합니다.

기본 클래스 CExpertSignal에는 보류 중인 판매 주문의 수정 신호를 생성하는 기본 제공 알고리즘이 없으므로 기본 클래스 메소드는 항상 false를 반환합니다.


2. 자신만의 거래 신호 생성기 개발

이제 CExpertSignal 기본 클래스의 구조를 검토한 후 고유한 거래 신호 생성기를 만들 수 있습니다.

위에서 언급한 바와 같이 CExpertSignal 클래스는 공개 가상 "로프"의 집합입니다. 이 메소드를 사용하면 전문가가 시장 진입에 대한 거래 신호 생성기의 의견을 알 수 있습니다.

따라서 우리의 주요 목표는 CExpertSignal 클래스에서 파생된 자체 거래 신호 생성기 클래스를 만들고 적절한 가상 메소드를 재정의하여 필요한 알고리즘을 구현하는 것입니다.

두 번째 문제(덜 중요하지 않음)는 MQL5 마법사에 클래스를 "보이게" 만드는 것입니다. 하지만, 먼저.

2.1. 거래 신호 생성기 클래스 생성

시작합시다.

먼저 mqh 확장자를 가진 포함 파일을 생성합니다(예: 동일한 MQL5 마법사 사용).

파일 메뉴에서 "만들기"를 선택하고(또는 Ctrl+N 키 조합을 누름) 포함된 파일의 생성을 나타냅니다.

그림 2. MQL5 마법사를 사용하여 포함 파일을 작성하십시오.

그림 2. MQL5 마법사를 사용하여 포함 파일 만들기

파일이 신호 생성기로 MQL5 Wizard에 의해 "감지"되기 위해서는 Include\Expert\Signal\ 폴더에 생성되어야 합니다.

표준 라이브러리에서 휴지통을 제거하지 않으려면 MQL5 마법사에서 다음 매개변수를 지정하여 SampleSignal.mqh 파일을 생성하는 자체 폴더 Include\Expert\Signal\MySignals를 생성합니다.

그림 3. 포함 파일의 위치 설정

그림 3. 포함 파일의 위치 설정

MQL5 Wizard 작업의 결과로 다음과 같은 패턴이 나타납니다.

//+------------------------------------------------------------------+
//|                                                 SampleSignal.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| defines                                                          |
//+------------------------------------------------------------------+
// #define MacrosHello   "Hello, world!"
// #define MacrosYear    2010
//+------------------------------------------------------------------+
//| DLL imports                                                      |
//+------------------------------------------------------------------+
// #import "user32.dll"
//   int      SendMessageA(int hWnd,int Msg,int wParam,int lParam);
// #import "my_expert.dll"
//   int      ExpertRecalculate(int wParam,int lParam);
// #import
//+------------------------------------------------------------------+
//| EX5 imports                                                      |
//+------------------------------------------------------------------+
// #import "stdlib.ex5"
//   string ErrorDescription(int error_code);
// #import
//+------------------------------------------------------------------+

다음은 "수동" 작업일 뿐입니다. 불필요한 부분을 제거하고 필요한 것을 추가하십시오(표준 라이브러리의 ExpertSignal.mqh 파일 및 현재 비어 있는 클래스 설명 포함).

//+------------------------------------------------------------------+
//|                                                 SampleSignal.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| include files                                                    |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
//+------------------------------------------------------------------+
//| The CSampleSignal class.                                         |
//| Purpose: Class of trading signal generator.                      |
//|          It is derived from the CExpertSignal class.             |
//+------------------------------------------------------------------+
class CSampleSignal : public CExpertSignal
  {
  };
//+------------------------------------------------------------------+

이제 알고리즘을 선택해야 합니다.

거래 신호 생성기의 기초로 우리는 "가격이 이동 평균을 교차"하는 광범위한 모델을 사용합니다. 그러나 우리는 한 가지 더 가정합니다. "이동 평균을 넘은 후 가격은 뒤로 이동하고 그 다음에야 올바른 방향으로 이동합니다." 이것을 우리 파일에 반영하십시오.

일반적으로 글을 쓸 때 댓글에 인색하게 굴지 마세요. 시간이 지나면 주의 깊게 주석 처리된 코드를 읽는 것이 매우 편해질 것입니다.

//+------------------------------------------------------------------+
//|                                                 SampleSignal.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| include files                                                    |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
//+------------------------------------------------------------------+
//| Class CSampleSignal.                                             |
//| Purpose: Class of trading signal generator when price            |
//|          crosses moving average,                                 |
//|          entering on the subsequent back movement.               |
//|          It is derived from the CExpertSignal class.             |
//+------------------------------------------------------------------+
class CSampleSignal : public CExpertSignal
  {
  };
//+------------------------------------------------------------------+

이제 거래 신호 생성에 대한 결정을 내리는 데 필요한 데이터를 정의해 보겠습니다. 우리의 경우 이것은 이전 바의 시가와 종가이며 동일한 이전 바의 이동 평균 값입니다.

이러한 데이터에 액세스하기 위해 표준 라이브러리 클래스 CiOpen, CiCloseCiMA를 사용합니다. 지표와 시계열에 대해서는 나중에 논의할 것입니다.

그동안 생성기에 대한 설정 목록을 정의해 보겠습니다. 먼저 이동 평균을 설정해야 합니다. 이러한 매개변수에는 기간, 시간 축을 따른 이동, 평균화 방법 및 평균화 대상이 포함됩니다. 둘째, 우리는 보류 주문으로 작업할 것이기 때문에 보호 주문의 진입 수준과 배치 수준 및 보류 주문의 수명을 설정해야 합니다.

생성기의 모든 설정은 class의 보호된 데이터 멤버에 저장됩니다. 설정에 대한 액세스는 적절한 공개 방법을 통해 구현됩니다.

다음 변경 사항을 파일에 포함시켜봅시다:

//+------------------------------------------------------------------+
//|                                                 SampleSignal.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| include files                                                    |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
//+------------------------------------------------------------------+
//| The CSampleSignal class.                                         |
//| Purpose: Class of trading signal generator when price            |
//|             crosses moving average,                              |
//|             entering on the subsequent back movement.            |
//|             It is derived from the CExpertSignal class.          |
//+------------------------------------------------------------------+
class CSampleSignal : public CExpertSignal
  {
protected:
   //--- Setup parameters
   int                m_period_ma;       // averaging period of the MA
   int                m_shift_ma;        // shift of the MA along the time axis
   ENUM_MA_METHOD     m_method_ma;       // averaging method of the MA
   ENUM_APPLIED_PRICE m_applied_ma;      // averaging object of the MA
   double             m_limit;           // level to place a pending order relative to the MA
   double             m_stop_loss;       // level to place a stop loss order relative to the open price
   double             m_take_profit;     // level to place a take profit order relative to the open price
   int                m_expiration;      // lifetime of a pending order in bars

public:
   //--- Methods to set the parameters
   void               PeriodMA(int value)                 { m_period_ma=value;   }
   void               ShiftMA(int value)                  { m_shift_ma=value;    }
   void               MethodMA(ENUM_MA_METHOD value)      { m_method_ma=value;   }
   void               AppliedMA(ENUM_APPLIED_PRICE value) { m_applied_ma=value;  }
   void               Limit(double value)                 { m_limit=value;       }
   void               StopLoss(double value)              { m_stop_loss=value;   }
   void               TakeProfit(double value)            { m_take_profit=value; }
   void               Expiration(int value)               { m_expiration=value;  }
  };
//+------------------------------------------------------------------+

보호된 데이터 멤버를 사용하기 때문에 클래스 생성자를 추가해야 합니다. 여기서 이러한 데이터는 기본값으로 초기화됩니다.

매개변수를 확인하기 위해 기본 클래스의 설명에 따라 가상 메소드 ValidationSettings를 재정의해 보겠습니다.

클래스 설명:

class CSampleSignal : public CExpertSignal
  {
protected:
   //--- Setup parameters
   int                m_period_ma;       // averaging period of the MA
   int                m_shift_ma;        // shift of the MA along the time axis
   ENUM_MA_METHOD     m_method_ma;       // averaging method of the MA
   ENUM_APPLIED_PRICE m_applied_ma;      // averaging object of the MA
   double             m_limit;            // level to place a pending order relative to the MA
   double             m_stop_loss;        // level to place a stop loss order relative to the open price
   double             m_take_profit;      // level to place a take profit order relative to the open price
   int                m_expiration;       // lifetime of a pending order in bars

public:
                      CSampleSignal();
   //--- Methods to set the parameters
   void               PeriodMA(int value)                 { m_period_ma=value;   }
   void               ShiftMA(int value)                  { m_shift_ma=value;    }
   void               MethodMA(ENUM_MA_METHOD value)      { m_method_ma=value;   }
   void               AppliedMA(ENUM_APPLIED_PRICE value) { m_applied_ma=value;  }
   void               Limit(double value)                 { m_limit=value;       }
   void               StopLoss(double value)              { m_stop_loss=value;   }
   void               TakeProfit(double value)            { m_take_profit=value; }
   void               Expiration(int value)               { m_expiration=value;  }
   //--- Methods to validate the parameters
   virtual bool       ValidationSettings();
  };

ValidationSettings() 메소드 구현:


//+------------------------------------------------------------------+
//| Validation of the setup parameters.                              |
//| INPUT:  No.                                                      |
//| OUTPUT: true if the settings are correct, otherwise false.       |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::ValidationSettings()
  {
//--- Validation of parameters
   if(m_period_ma<=0)
     {
      printf(__FUNCTION__+": the MA period must be greater than zero");
      return(false);
     }
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+

이제 대부분의 준비 작업을 마치면 지표 및 시계열에 대해 더 자세히 설명하겠습니다.

지표와 시계열은 의사 결정을 위한 주요 정보 소스입니다(물론 동전 던지기 또는 달의 위상을 사용할 수 있지만 공식화하기는 상당히 어렵습니다).

위에서 이미 정의했듯이 의사 결정을 내리기 위해서는 이전 바의 시가, 이전 바의 종가 및 동일한 이전 바의 이동 평균 값과 같은 정보가 필요합니다.

이러한 데이터에 액세스하려면 표준 라이브러리의 다음 클래스를 사용합니다.

  • CiOpen - 이전 바의 시가에 접근하기 위해,
  • CiClose - 이전 바의 종가에 액세스하려면,
  • CiMA   - 이전 바의 이동 평균 값에 하려면.

"왜 단일 숫자를 얻기 위해 클래스에서 " 래핑된" 지표 또는 시계열을 사용합니까?"

숨겨진 의미가 있는데 지금부터 공개하겠습니다.

지표 또는 시계열의 데이터를 사용하는 방법은 무엇입니까?

먼저 지표를 만들어야 합니다.

둘째, 필요한 양의 데이터를 중간 버퍼에 복사해야 합니다.

셋째, 복사가 완료되었는지 확인해야 합니다.

이 단계를 거쳐야 데이터를 사용할 수 있습니다.

표준 라이브러리의 클래스를 사용하면 지표 생성, 중간 버퍼의 가용성, 데이터 로드 또는 핸들 해제에 대해 걱정할 필요가 없습니다. 적절한 클래스의 객체가 당신을 위해 그렇게 할 것입니다. 필요한 모든 지표는 초기화 단계에서 신호 생성기에 의해 생성되며 모든 지표는 필요한 임시 버퍼와 함께 제공됩니다. 또한 컬렉션에 지표 또는 시계열 개체(특수 클래스의 개체)를 추가하면 데이터 관련성에 신경쓰지 않아도 됩니다(데이터는 전문가에 의해 자동으로 업데이트됨).

이러한 클래스의 개체를 보호된 데이터 멤버에 배치합니다. 각 개체에 대해 초기화 방법과 데이터 액세스 방법을 만듭니다.

기본 클래스의 설명에 따라 가상 메소드 InitIndicators를 재정의해 보겠습니다.

클래스 설명:

class CSampleSignal : public CExpertSignal
  {
protected:
   CiMA               m_MA;              // object to access the values om the moving average
   CiOpen             m_open;            // object to access the bar open prices
   CiClose            m_close;           // object to access the bar close prices
   //--- Setup parameters
   int                m_period_ma;       // averaging period of the MA
   int                m_shift_ma;        // shift of the MA along the time axis
   ENUM_MA_METHOD     m_method_ma;       // averaging method of the MA
   ENUM_APPLIED_PRICE m_applied_ma;      // averaging object of the MA
   double             m_limit;            // level to place a pending order relative to the MA
   double             m_stop_loss;        // level to place a stop loss order relative to the open price
   double             m_take_profit;      // level to place a take profit order relative to the open price
   int                m_expiration;      // lifetime of a pending order in bars

public:
                      CSampleSignal();
   //--- Methods to set the parameters
   void               PeriodMA(int value)                 { m_period_ma=value;              }
   void               ShiftMA(int value)                  { m_shift_ma=value;               }
   void               MethodMA(ENUM_MA_METHOD value)      { m_method_ma=value;              }
   void               AppliedMA(ENUM_APPLIED_PRICE value) { m_applied_ma=value;             }
   void               Limit(double value)                 { m_limit=value;                  }
   void               StopLoss(double value)              { m_stop_loss=value;              }
   void               TakeProfit(double value)            { m_take_profit=value;            }
   void               Expiration(int value)               { m_expiration=value;             }
   //--- Method to validate the parameters
   virtual bool       ValidationSettings();
   //--- Method to validate the parameters
   virtual bool       InitIndicators(CIndicators* indicators);

protected:
   //--- Object initialization method
   bool               InitMA(CIndicators* indicators);
   bool               InitOpen(CIndicators* indicators);
   bool               InitClose(CIndicators* indicators);
   //--- Methods to access object data
   double             MA(int index)                       { return(m_MA.Main(index));       }
   double             Open(int index)                     { return(m_open.GetData(index));  }
   double             Close(int index)                    { return(m_close.GetData(index)); }
  };

InitIndicators, InitMA, InitOpen, InitClose 메소드 구현:

//+------------------------------------------------------------------+
//| Initialization of indicators and timeseries.                     |
//| INPUT:  indicators - pointer to the object - collection of       |
//|                      indicators and timeseries.                  |
//| OUTPUT: true in case of success, otherwise false.                |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::InitIndicators(CIndicators* indicators)
  {
//--- Validation of the pointer
   if(indicators==NULL)       return(false);
//--- Initialization of the moving average
   if(!InitMA(indicators))    return(false);
//--- Initialization of the timeseries of open prices
   if(!InitOpen(indicators))  return(false);
//--- Initialization of the timeseries of close prices
   if(!InitClose(indicators)) return(false);
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialization of the moving average                             |
//| INPUT:  indicators - pointer to the object - collection of       |
//|                      indicators and timeseries.                  |
//| OUTPUT: true in case of success, otherwise false.                |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::InitMA(CIndicators* indicators)
  {
//--- Initialization of the MA object
   if(!m_MA.Create(m_symbol.Name(),m_period,m_period_ma,m_shift_ma,m_method_ma,m_applied_ma))
     {
      printf(__FUNCTION__+": object initialization error");
      return(false);
     }
   m_MA.BufferResize(3+m_shift_ma);
//--- Adding an object to the collection
   if(!indicators.Add(GetPointer(m_MA)))
     {
      printf(__FUNCTION__+": object adding error");
      return(false);
     }
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialization of the timeseries of open prices.                 |
//| INPUT:  indicators - pointer to the object - collection of       |
//|                      indicators and timeseries.                  |
//| OUTPUT: true in case of success, otherwise false.                |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::InitOpen(CIndicators* indicators)
  {
//--- Initialization of the timeseries object
   if(!m_open.Create(m_symbol.Name(),m_period))
     {
      printf(__FUNCTION__+": object initialization error");
      return(false);
     }
//--- Adding an object to the collection
   if(!indicators.Add(GetPointer(m_open)))
     {
      printf(__FUNCTION__+": object adding error");
      return(false);
     }
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialization of the timeseries of close prices.                |
//| INPUT:  indicators - pointer to the object - collection of       |
//|                      indicators and timeseries.                  |
//| OUTPUT: true in case of success, otherwise false.                |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::InitClose(CIndicators* indicators)
  {
//--- Initialization of the timeseries object
   if(!m_close.Create(m_symbol.Name(),m_period))
     {
      printf(__FUNCTION__+": object initialization error");
      return(false);
     }
//--- Adding an object to the collection
   if(!indicators.Add(GetPointer(m_close)))
     {
      printf(__FUNCTION__+": object adding error");
      return(false);
     }
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+

모든 준비 작업이 완료되었습니다. 모든 준비가 된 물건입니다.

보시다시피, 우리 클래스는 크게 성장했습니다.

그림 4. 이동 평균을 넘는 가격에 대한 거래 신호

그림 4. 이동 평균을 넘는 가격에 대한 거래 신호

알고리즘을 다시 자세히 살펴보겠습니다.

1. 이전 바에서 다음 조건이 충족되면 매수 신호가 나타납니다.

  • 바 시가가 이동 평균 값보다 작거나,
  • 바 종가가 이동 평균 값보다 작거나,
  • 이동 평균이 증가하고 있는 경우.

이 경우 설정에 의해 정의된 매개변수를 사용하여 보류 중인 구매 주문을 할 것을 제안합니다. 이를 위해 가상 메소드 CheckOpenLong을 재정의하고 해당 기능으로 채웁니다.

2. 이전 바에서 다음 조건이 충족되면 매도 신호가 나타납니다.

  • 바 시가가 이동 평균 값보다 크거나,
  • 바 종가가 이동 평균 값보다 작거나,
  • 이동평균선이 감소하고 있는 경우.

이 경우 설정에 의해 정의된 매개변수를 사용하여 보류 중인 판매 주문을 제안합니다. 이를 위해 가상 메소드 CheckOpenShort를 재정의하고 해당 기능으로 채웁니다.

3. 포지션을 청산하라는 신호를 생성하지 않습니다. 손절매/이익 실현으로 포지션을 청산하세요.

따라서 가상 메소드 CheckCloseLongCheckCloseShort를 재정의하지 않습니다.

4. 우리는 설정에 의해 지정된 "거리"에서 이동 평균을 따라 보류 주문의 수정을 제안합니다.

 이를 위해 가상 메소드 CheckTrailingOrderLongCheckTrailingOrderShort를 재정의하여 해당 기능으로 채웁니다.

클래스 설명:

class CSampleSignal : public CExpertSignal
  {
protected:
   CiMA               m_MA;              // object to access the values of the moving average
   CiOpen             m_open;            // object to access the bar open prices
   CiClose            m_close;           // object to access the bar close prices
   //--- Setup parameters
   int                m_period_ma;       // averaging period of the MA
   int                m_shift_ma;        // shift of the MA along the time axis
   ENUM_MA_METHOD     m_method_ma;       // averaging method of the MA
   ENUM_APPLIED_PRICE m_applied_ma;      // averaging object of the MA
   double             m_limit;            // level to place a pending order relative to the MA
   double             m_stop_loss;        // level to place a stop loss order relative to the open price
   double             m_take_profit;      // level to place a take profit order relative to the open price
   int                m_expiration;       // lifetime of a pending order in bars

public:
                      CSampleSignal();
   //--- Methods to set the parameters

   void               PeriodMA(int value)                 { m_period_ma=value;              }
   void               ShiftMA(int value)                  { m_shift_ma=value;               }
   void               MethodMA(ENUM_MA_METHOD value)      { m_method_ma=value;              }
   void               AppliedMA(ENUM_APPLIED_PRICE value) { m_applied_ma=value;             }
   void               Limit(double value)                 { m_limit=value;                  }
   void               StopLoss(double value)              { m_stop_loss=value;              }
   void               TakeProfit(double value)            { m_take_profit=value;            }
   void               Expiration(int value)               { m_expiration=value;             }
   //--- Method to validate the parameters
   virtual bool       ValidationSettings();
   //--- Method to validate the parameters
   virtual bool       InitIndicators(CIndicators* indicators);
   //--- Methods to generate signals to enter the market
   virtual bool      CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration);
   virtual bool      CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration);
   //--- Methods to generate signals of pending order modification
   virtual bool      CheckTrailingOrderLong(COrderInfo* order,double& price);
   virtual bool      CheckTrailingOrderShort(COrderInfo* order,double& price);

protected:
   //--- Object initialization method
   bool               InitMA(CIndicators* indicators);
   bool               InitOpen(CIndicators* indicators);
   bool               InitClose(CIndicators* indicators);
   //--- Methods to access object data
   double             MA(int index)                       { return(m_MA.Main(index));       }
   double             Open(int index)                     { return(m_open.GetData(index));  }
   double             Close(int index)                    { return(m_close.GetData(index)); }
  };

CheckOpenLong, CheckOpenShort, CheckTrailingOrderLong, CheckTrailingOrderShort 메소드 구현:

//+------------------------------------------------------------------+
//| Check whether a Buy condition is fulfilled                       |
//| INPUT:  price      - variable for open price                     |
//|         sl         - variable for stop loss price,               |
//|         tp         - variable for take profit price              |
//|         expiration - variable for expiration time.               |
//| OUTPUT: true if the condition is fulfilled, otherwise false.     |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration)
  {
//--- Preparing the data
   double spread=m_symbol.Ask()-m_symbol.Bid();
   double ma    =MA(1);
   double unit  =PriceLevelUnit();
//--- Checking the condition
   if(Open(1)<ma && Close(1)>ma && ma>MA(2))
     {
      price=m_symbol.NormalizePrice(ma-m_limit*unit+spread);
      sl   =m_symbol.NormalizePrice(price-m_stop_loss*unit);
      tp   =m_symbol.NormalizePrice(price+m_take_profit*unit);
      expiration+=m_expiration*PeriodSeconds(m_period);
      //--- Condition is fulfilled
      return(true);
     }
//--- Condition is not fulfilled
   return(false);
  }
//+------------------------------------------------------------------+
//| Check whether a Sell condition is fulfilled.                     |
//| INPUT:  price      - variable for open price,                    |
//|         sl         - variable for stop loss,                     |
//|         tp         - variable for take profit                    |
//|         expiration - variable for expiration time.               |
//| OUTPUT: true if the condition is fulfilled, otherwise false.     |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration)
  {
//--- Preparing the data
   double ma  =MA(1);
   double unit=PriceLevelUnit();
//--- Checking the condition
   if(Open(1)>ma && Close(1)<ma && ma<MA(2))
     {
      price=m_symbol.NormalizePrice(ma+m_limit*unit);
      sl   =m_symbol.NormalizePrice(price+m_stop_loss*unit);
      tp   =m_symbol.NormalizePrice(price-m_take_profit*unit);
      expiration+=m_expiration*PeriodSeconds(m_period);
      //--- Condition is fulfilled
      return(true);
     }
//--- Condition is not fulfilled
   return(false);
  }
//+------------------------------------------------------------------+
//| Check whether the condition of modification                      |
//|  of a Buy order is fulfilled.                                    |
//| INPUT:  order - pointer at the object-order,                     |
//|         price - a variable for the new open price.               |
//| OUTPUT: true if the condition is fulfilled, otherwise false.     |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::CheckTrailingOrderLong(COrderInfo* order,double& price)
  {
//--- Checking the pointer
   if(order==NULL) return(false);
//--- Preparing the data
   double spread   =m_symbol.Ask()-m_symbol.Bid();
   double ma       =MA(1);
   double unit     =PriceLevelUnit();
   double new_price=m_symbol.NormalizePrice(ma-m_limit*unit+spread);
//--- Checking the condition
   if(order.PriceOpen()==new_price) return(false);
   price=new_price;
//--- Condition is fulfilled
   return(true);
  }
//+------------------------------------------------------------------+
//| Check whether the condition of modification                      |
//| of a Sell order is fulfilled.                                    |
//| INPUT:  order - pointer at the object-order,                     |
//|         price - a variable for the new open price.               |
//| OUTPUT: true if the condition is fulfilled, otherwise false.     |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::CheckTrailingOrderShort(COrderInfo* order,double& price)
  {
//--- Checking the pointer
   if(order==NULL) return(false);
//--- Preparing the data
   double ma  =MA(1);
   double unit=PriceLevelUnit();
   double new_price=m_symbol.NormalizePrice(ma+m_limit*unit);
//--- Checking the condition
   if(order.PriceOpen()==new_price) return(false);
   price=new_price;
//--- Condition is fulfilled
   return(true);
  }
//+------------------------------------------------------------------+

그래서 우리는 첫 번째 문제를 해결했습니다. 위의 코드는 우리의 주요 작업을 충족하는 거래 신호 생성기 클래스의 소스 코드입니다.


2.2. MQL5 Wizard에 대한 거래 신호의 생성된 클래스에 대한 설명 준비

이제 두 번째 문제를 해결합니다. 우리의 신호는 거래 전략 MQL5 Wizard의 생성기에 의해 "인식"되어야 합니다.

첫 번째 필수 조건을 완료했습니다. MQL5 마법사가 "찾을" 위치에 파일을 배치했습니다. 하지만 이것만으로는 충분하지 않습니다. MQL5 마법사는 파일을 "찾아야" 할 뿐만 아니라 "인식"해야 합니다. 이렇게 하려면 MQL5 마법사의 원본 텍스트에 클래스 설명자를 추가해야 합니다.

클래스 설명자는 특정 규칙에 따라 구성된 주석 블록입니다.

이러한 규칙을 고려해봅시다.

1. 주석 블록은 다음 줄로 시작해야 합니다.

// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |

2. 다음 줄은 "//| Title=<Text> |" 형식의 텍스트 설명자(신호를 선택할 때 MQL5 마법사에서 볼 수 있음)입니다. 텍스트가 한 줄에 비해 너무 크면 그 뒤에 한 줄을 더 추가할 수 있습니다(그러나 그 이상은 아님). 

우리의 경우 다음을 얻습니다.

//| Title=Signal on the crossing of a price and the MA               |
//| entering on its back movement                                    |

3. 그런 다음 "//| Type=<Type> |" 형식으로 지정된 클래스 유형의 줄이 나옵니다. <Type> 필드에는 신호 값이 있어야 합니다(신호 외에도 MQL5 마법사는 다른 유형의 클래스를 알고 있습니다).

쓰다:

//| Type=Signal                                                      |

4. "//| Name=<Name> |" 형식의 다음 줄 신호의 짧은 이름입니다(전문가의 전역 변수 이름을 생성하기 위해 MQL5 마법사에서 사용됨).

우리는 다음을 얻습니다.

//| Name=Sample                                                      |

5. 클래스의 이름은 설명의 중요한 요소입니다. "//| Class=<ClassNameа> |" 형식의 줄에서 <ClassName> 매개변수는 클래스 이름과 일치해야 합니다.

//| Class=CSampleSignal                                              |

6. 이 줄은 작성하지 않았지만 반드시 있어야 합니다(언어 참조 섹션에 대한 링크임).

//| Page=                                                            |

7. 또한 신호 설정 매개변수에 대한 설명이 있습니다.

이것은 행의 집합입니다(행의 수는 매개변수의 수와 같습니다).

각 줄의 형식은 "//| Parameter=<NameOfMethod>,<TypeOfParameter>,<DefaultValue> |"입니다.

다음은 매개변수 세트입니다.

//| Parameter=PeriodMA,int,12                                        |
//| Parameter=ShiftMA,int,0                                          |
//| Parameter=MethodMA,ENUM_MA_METHOD,MODE_EMA                       |
//| Parameter=AppliedMA,ENUM_APPLIED_PRICE,PRICE_CLOSE               |
//| Parameter=Limit,double,0.0                                       |
//| Parameter=StopLoss,double,50.0                                   |
//| Parameter=TakeProfit,double,50.0                                 |
//| Parameter=Expiration,int,10                                      |

8. 주석 블록은 다음 줄로 끝나야 합니다.

//+------------------------------------------------------------------+
// wizard description end

소스 코드에 디스크립터를 추가해 보겠습니다.

//+------------------------------------------------------------------+
//|                                                 SampleSignal.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| include files                                                    |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Signal on crossing of the price and the MA                 |
//| entering on the back movement                                    |
//| Type=Signal                                                      |
//| Name=Sample                                                      |
//| Class=CSampleSignal                                              |
//| Page=                                                            |
//| Parameter=PeriodMA,int,12                                        |
//| Parameter=ShiftMA,int,0                                          |
//| Parameter=MethodMA,ENUM_MA_METHOD,MODE_EMA                       |
//| Parameter=AppliedMA,ENUM_APPLIED_PRICE,PRICE_CLOSE               |
//| Parameter=Limit,double,0.0                                       |
//| Parameter=StopLoss,double,50.0                                   |
//| Parameter=TakeProfit,double,50.0                                 |
//| Parameter=Expiration,int,10                                      |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| CSampleSignal class.                                             |
//| Purpose: Class of trading signal generator when price            |
//|             crosses moving average,                              |
//|             entering on the subsequent back movement.            |
//|             It is derived from the CExpertSignal class.          |
//+------------------------------------------------------------------+
class CSampleSignal : public CExpertSignal
  {
protected:
   CiMA               m_MA;               // object to access the values of the moving average
   CiOpen             m_open;             // object to access the bar open prices
   CiClose            m_close;            // object to access the bar close prices
   //--- Setup parameters
   int                m_period_ma;        // averaging period of the MA
   int                m_shift_ma;         // shift of the MA along the time axis
   ENUM_MA_METHOD     m_method_ma;        // averaging method of the MA
   ENUM_APPLIED_PRICE m_applied_ma;       // averaging object of the MA
   double             m_limit;            // level to place a pending order relative to the MA
   double             m_stop_loss;        // level to place a stop loss order relative to the open price
   double             m_take_profit;      // level to place a take profit order relative to the open price
   int                m_expiration;       // lifetime of a pending order in bars

public:
                      CSampleSignal();
   //--- Methods to set the parameters
   void               PeriodMA(int value)                 { m_period_ma=value;              }
   void               ShiftMA(int value)                  { m_shift_ma=value;               }
   void               MethodMA(ENUM_MA_METHOD value)      { m_method_ma=value;              }
   void               AppliedMA(ENUM_APPLIED_PRICE value) { m_applied_ma=value;             }
   void               Limit(double value)                 { m_limit=value;                  }
   void               StopLoss(double value)              { m_stop_loss=value;              }
   void               TakeProfit(double value)            { m_take_profit=value;            }
   void               Expiration(int value)               { m_expiration=value;             }
   //---Method to validate the parameters
   virtual bool       ValidationSettings();
   //--- Method to validate the parameters
   virtual bool       InitIndicators(CIndicators* indicators);
   //--- Methods to generate signals to enter the market
   virtual bool      CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration);
   virtual bool      CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration);
   //--- Methods to generate signals of pending order modification
   virtual bool      CheckTrailingOrderLong(COrderInfo* order,double& price);
   virtual bool      CheckTrailingOrderShort(COrderInfo* order,double& price);

protected:
   //--- Object initialization method
   bool               InitMA(CIndicators* indicators);
   bool               InitOpen(CIndicators* indicators);
   bool               InitClose(CIndicators* indicators);
   //--- Methods to access object data
   double             MA(int index)                       { return(m_MA.Main(index));       }
   double             Open(int index)                     { return(m_open.GetData(index));  }
   double             Close(int index)                    { return(m_close.GetData(index)); }
  };
//+------------------------------------------------------------------+
//| CSampleSignal Constructor.                                       |
//| INPUT:  No.                                                      |
//| OUTPUT: No.                                                      |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
void CSampleSignal::CSampleSignal()
  {
//--- Setting the default values
   m_period_ma  =12;
   m_shift_ma   =0;
   m_method_ma  =MODE_EMA;
   m_applied_ma =PRICE_CLOSE;
   m_limit      =0.0;
   m_stop_loss  =50.0;
   m_take_profit=50.0;
   m_expiration =10;
  }
//+------------------------------------------------------------------+
//| Validation of parameters.                                        |
//| INPUT:  No.                                                      |
//| OUTPUT: true if the settings are correct, otherwise false.       |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::ValidationSettings()
  {
//--- Validation of parameters
   if(m_period_ma<=0)
     {
      printf(__FUNCTION__+": the MA period must be greater than zero");
      return(false);
     }
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialization of indicators and timeseries.                     |
//| INPUT:  indicators - pointer to the object - collection of       |
//|                      indicators and timeseries.                  |
//| OUTPUT: true in case of success, otherwise false.                |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::InitIndicators(CIndicators* indicators)
  {
//--- Validation of the pointer
   if(indicators==NULL)       return(false);
//--- Initialization of the moving average
   if(!InitMA(indicators))    return(false);
//--- Initialization of the timeseries of open prices
   if(!InitOpen(indicators))  return(false);
//--- Initialization of the timeseries of close prices
   if(!InitClose(indicators)) return(false);
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialization of the moving average                             |
//| INPUT:  indicators - pointer to the object - collection of       |
//|                      indicators and timeseries.                  |
//| OUTPUT: true in case of success, otherwise false.                |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::InitMA(CIndicators* indicators)
  {
//--- Initialization of the MA object
   if(!m_MA.Create(m_symbol.Name(),m_period,m_period_ma,m_shift_ma,m_method_ma,m_applied_ma))
     {
      printf(__FUNCTION__+": object initialization error");
      return(false);
     }
   m_MA.BufferResize(3+m_shift_ma);
//--- Adding an object to the collection
   if(!indicators.Add(GetPointer(m_MA)))
     {
      printf(__FUNCTION__+": object adding error");
      return(false);
     }
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialization of the timeseries of open prices.                 |
//| INPUT:  indicators - pointer to the object - collection of       |
//|                      indicators and timeseries.                  |
//| OUTPUT: true in case of success, otherwise false.                |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::InitOpen(CIndicators* indicators)
  {
//--- Initialization of the timeseries object
   if(!m_open.Create(m_symbol.Name(),m_period))
     {
      printf(__FUNCTION__+": object initialization error");
      return(false);
     }
//--- Adding an object to the collection
   if(!indicators.Add(GetPointer(m_open)))
     {
      printf(__FUNCTION__+": object adding error");
      return(false);
     }
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialization of the timeseries of close prices.                |
//| INPUT:  indicators - pointer to the object - collection of       |
//|                      indicators and timeseries.                  |
//| OUTPUT: true in case of success, otherwise false.                |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::InitClose(CIndicators* indicators)
  {
//--- Initialization of the timeseries object
   if(!m_close.Create(m_symbol.Name(),m_period))
     {
      printf(__FUNCTION__+": object initialization error");
      return(false);
     }
//--- Adding an object to the collection
   if(!indicators.Add(GetPointer(m_close)))
     {
      printf(__FUNCTION__+": object adding error");
      return(false);
     }
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+
//| Check whether a Buy condition is fulfilled                       |
//| INPUT:  price      - variable for open price                     |
//|         sl         - variable for stop loss price,               |
//|         tp         - variable for take profit price              |
//|         expiration - variable for expiration time.               |
//| OUTPUT: true if the condition is fulfilled, otherwise false.     |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration)
  {
//--- Preparing the data
   double spread=m_symbol.Ask()-m_symbol.Bid();
   double ma    =MA(1);
   double unit  =PriceLevelUnit();
//--- Checking the condition
   if(Open(1)<ma && Close(1)>ma && ma>MA(2))
     {
      price=m_symbol.NormalizePrice(ma-m_limit*unit+spread);
      sl   =m_symbol.NormalizePrice(price-m_stop_loss*unit);
      tp   =m_symbol.NormalizePrice(price+m_take_profit*unit);
      expiration+=m_expiration*PeriodSeconds(m_period);
      //--- Condition is fulfilled
      return(true);
     }
//--- Condition is not fulfilled
   return(false);
  }
//+------------------------------------------------------------------+
//| Check whether a Sell condition is fulfilled.                     |
//| INPUT:  price      - variable for open price,                    |
//|         sl         - variable for stop loss,                     |
//|         tp         - variable for take profit                    |
//|         expiration - variable for expiration time.               |
//| OUTPUT: true if the condition is fulfilled, otherwise false.     |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration)
  {
//--- Preparing the data
   double ma  =MA(1);
   double unit=PriceLevelUnit();
//--- Checking the condition
   if(Open(1)>ma && Close(1)<ma && ma<MA(2))
     {
      price=m_symbol.NormalizePrice(ma+m_limit*unit);
      sl   =m_symbol.NormalizePrice(price+m_stop_loss*unit);
      tp   =m_symbol.NormalizePrice(price-m_take_profit*unit);
      expiration+=m_expiration*PeriodSeconds(m_period);
      //--- Condition is fulfilled
      return(true);
     }
//--- Condition is not fulfilled
   return(false);
  }
//+------------------------------------------------------------------+
//| Check whether the condition of modification                      |
//|  of a Buy order is fulfilled.                                    |
//| INPUT:  order - pointer at the object-order,                     |
//|         price - a variable for the new open price.               |
//| OUTPUT: true if the condition is fulfilled, otherwise false.     |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::CheckTrailingOrderLong(COrderInfo* order,double& price)
  {
//--- Checking the pointer
   if(order==NULL) return(false);
//--- Preparing the data
   double spread   =m_symbol.Ask()-m_symbol.Bid();
   double ma       =MA(1);
   double unit     =PriceLevelUnit();
   double new_price=m_symbol.NormalizePrice(ma-m_limit*unit+spread);
//--- Checking the condition
   if(order.PriceOpen()==new_price) return(false);
   price=new_price;
//--- Condition is fulfilled
   return(true);
  }
//+------------------------------------------------------------------+
//| Check whether the condition of modification                      |
//| of a Sell order is fulfilled.                                    |
//| INPUT:  order - pointer at the object-order,                     |
//|         price - a variable for the new open price.               |
//| OUTPUT: true if the condition is fulfilled, otherwise false.     |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::CheckTrailingOrderShort(COrderInfo* order,double& price)
  {
//--- Checking the pointer
   if(order==NULL) return(false);
//--- Preparing the data
   double ma  =MA(1);
   double unit=PriceLevelUnit();
   double new_price=m_symbol.NormalizePrice(ma+m_limit*unit);
//--- Checking the condition
   if(order.PriceOpen()==new_price) return(false);
   price=new_price;
//--- Condition is fulfilled
   return(true);
  }
//+------------------------------------------------------------------+

그게 전부입니다. 신호를 사용할 준비가 되었습니다.

발전기 거래 전략 MQL5 마법사가 신호를 사용할 수 있으려면 MetaEditor를 다시 시작해야 합니다(MQL5 마법사는 부팅 시에만 Include\Expert 폴더를 검색합니다).

MetaEditor를 다시 시작한 후 생성된 거래 신호 모듈을 MQL5 마법사에서 사용할 수 있습니다.

그림 5. MQL5 마법사에서 생성된 거래 신호 생성기

그림 5. MQL5 마법사에서 생성된 거래 신호 생성기

이제 거래 신호 생성기의 매개변수 설명 섹션에 지정된 입력 매개변수를 사용할 수 있습니다.

그림 6. MQL5 마법사에서 생성된 거래 신호 생성기의 입력 매개변수

그림 6. MQL5 마법사에서 생성된 거래 신호 생성기의 입력 매개변수

구현된 거래 전략의 입력 매개변수의 최상의 값은 MetaTrader 5 터미널의 Strategy Tester를 사용하여 찾을 수 있습니다.


결론

MQL5 마법사의 거래 전략 생성기는 거래 아이디어 테스트를 크게 단순화합니다. 생성된 전문가의 코드는 표준 라이브러리의 거래 전략 클래스를 기반으로 하며, 이는 거래 신호 클래스, 자금 및 위험 관리 클래스 및 포지션 지원 클래스의 특정 구현을 생성하는 데 사용됩니다. 

이 글에서는 가격과 이동 평균의 교차에 대한 신호 구현과 함께 MQL5 마법사에 대해 생성된 클래스 설명의 구조 및 형식 뿐 아니라 자신만의 거래 신호 클래스를 작성하는 방법과 이를 MQL5 마법사의 거래 전략 생성기에 포함시키는 방법에 대해 설명해봤습니다.

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

파일 첨부됨 |
samplesignal.mqh (15.49 KB)
MQL5의 전자 테이블 MQL5의 전자 테이블
이 문서에서는 1차원에 서로 다른 유형의 데이터가 포함된 동적 2차원 배열의 클래스를 설명합니다. 데이터를 테이블 형태로 저장하는 것은 서로 다른 유형의 바인딩된 정보로 배열, 저장 및 작동의 광범위한 문제를 해결하는 데 편리합니다. 테이블 작업 기능을 구현한 클래스의 소스 코드는 글에 첨부되어 있습니다.
차트 분석에 대한 계량학적 접근 차트 분석에 대한 계량학적 접근
이 글에서는 계량경제학적 분석 방법, 자기 상관 분석 및 특히 조건부 분산 분석에 대해 설명합니다. 여기에 설명된 접근 방식의 이점은 무엇입니까? 비선형 GARCH 모델을 사용하면 수학적 관점에서 공식적으로 분석된 시리즈를 표현하고 지정된 단계 수에 대한 예측을 생성할 수 있습니다.
MQL5 마법사: 위험 및 자금 관리 모듈을 만드는 방법 MQL5 마법사: 위험 및 자금 관리 모듈을 만드는 방법
MQL5 Wizard의 거래 전략 생성기는 거래 아이디어 테스트를 크게 단순화합니다. 이 문서에서는 맞춤형 위험 및 자금 관리 모듈을 개발하고 MQL5 마법사에서 활성화하는 방법을 설명합니다. 예를 들어 우리는 거래량의 크기가 이전 거래의 결과에 따라 결정되는 자금 관리 알고리즘을 고려했습니다. MQL5 마법사용으로 생성된 클래스의 설명 구조 및 형식도 이 글에서 설명합니다.
마이크로, 미들, 메인 추세의 지표 마이크로, 미들, 메인 추세의 지표
이 글의 목적은 James Hyerczyk의 "Pattern, Price & Time: Using Gann Theory in Trading Systems"라는 책의 몇 가지 아이디어를 기반으로 지표 및 Expert Advisor의 형태로 거래 자동화 및 분석의 가능성을 조사하는 것입니다. 완전하다고 주장하지 않고 여기서 우리는 Gann 이론의 첫 번째 부분인 모델만 조사합니다.