English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
C++ 템플릿의 대안으로 가짜 템플릿 사용

C++ 템플릿의 대안으로 가짜 템플릿 사용

MetaTrader 5 | 4 8월 2021, 17:15
112 0
Mykola Demko
Mykola Demko


소개

템플릿을 언어 표준으로 구현하는 문제는 mql5.com 포럼에서 여러 번 제기되었습니다. MQL5 개발자들의 거부의 벽에 부딪히면서 커스텀 메소드를 사용한 템플릿 구현에 대한 관심이 커지기 시작했습니다. 내 연구 결과가 이 글에 나와 있습니다.


C 및 C++의 일부 내역

처음부터 C 언어는 시스템 작업을 수행할 수 있는 가능성을 제공하기 위해 개발되었습니다. C 언어의 제작자는 언어 실행 환경의 추상 모델을 구현하지 않았습니다. 그들은 단지 시스템 프로그래머의 요구를 위한 기능을 구현했습니다. 먼저 메모리와 직접 작업하는 방법, 제어의 구조 구성 및 응용 프로그램의 모듈 관리입니다.

사실, 그 언어에는 더 이상 아무것도 포함되지 않았습니다. 다른 모든 것은 런타임 라이브러리로 가져갔습니다. 그렇기 때문에 일부 나쁜 성향의 사람들은 때때로 C 언어를 구조적 어셈블러로 언급합니다. 그러나 그들이 무엇을 말하든 그 접근 방식은 매우 성공적인 것처럼 보였습니다. 그 덕분에 언어의 단순함과 힘 사이의 새로운 차원의 비율에 도달했습니다. 

따라서 C는 시스템 프로그래밍을 위한 보편적인 언어로 등장했습니다. 하지만 그 한계를 벗어나지 못했습니다. 80년대 후반에 Fortran을 리더십에서 제쳐두고 C는 전 세계 프로그래머들 사이에서 폭넓은 인기를 얻었고 다양한 응용 프로그램에서 널리 사용되었습니다. 그 인기에 크게 기여한 것은 새로운 세대의 프로그래머가 교육을 받은 대학에 Unix(및 C 언어)를 배포한 것입니다.

그러나 모든 것이 그렇게 흐려지지 않은 경우 다른 모든 언어가 여전히 사용되는 이유는 무엇이며 그 존재를 뒷받침하는 것은 무엇입니까? C 언어의 아킬레스건은 90년대를 배경으로 하기에는 너무 수준이 낮습니다. 이 문제는 두 가지 측면이 있습니다.

우선 언어에는 너무 낮은 수준의 수단이 포함되어 있습니다: 우선 메모리 및 주소 산술 작업이 이에 해당하죠. 따라서 프로세서 비트 수의 변경은 많은 C 응용 프로그램에 많은 문제를 일으킵니다. 반면에 C에는 추상 유형의 데이터 및 객체, 다형성 및 예외 처리와 같은 고급 수단이 부족합니다. 따라서 C 응용 프로그램에서 작업 구현 기술은 종종 물질적 측면을 지배합니다.

이러한 단점을 해결하기 위한 첫 번째 시도는 80년대 초반에 이루어졌습니다. 그 당시 AT&T Bell Labs의 Bjarne Stroustrup은 "C with classes"라는 C 언어의 확장을 개발하기 시작했습니다. 개발 스타일은 C 언어 자체의 생성 정신과 일치했습니다. 특정 그룹의 사람들이 더 편리하게 작업할 수 있도록 다양한 기능을 추가했습니다.

C++의 주요 혁신은 새로운 유형의 데이터를 사용할 수 있는 가능성을 제공하는 클래스 메커니즘입니다. 프로그래머는 클래스 객체의 내부 표현과 그 표현에 접근하기 위한 일련의 함수-메소드를 설명합니다. C++ 생성의 주된 목적 중 하나는 이미 작성된 코드의 재사용 비율을 높이는 것이었습니다.

C++ 언어의 혁신은 단순히 수업을 도입하는 것으로 끝나지 않습니다. 그것은 예외의 구조적 처리 메커니즘(그것의 부족은 오류 방지 응용 프로그램의 개발을 복잡하게 함), 템플릿 메커니즘 및 기타 여러 가지를 구현했습니다. 따라서 언어 개발의 주요 라인은 ANSI С와의 완전한 호환성을 유지하면서 새로운 고급 구성을 도입하여 가능성을 확장하는 것이었습니다. 


매크로 대체 메커니즘으로서의 템플릿

MQL5에서 템플릿을 구현하는 방법을 이해하려면 C++에서 템플릿이 작동하는 방식을 이해해야 합니다.

정의를 살펴보겠습니다.

템플릿은 함수와 클래스가 제네릭 형식으로 작동할 수 있도록 하는 C++ 프로그래밍 언어의 기능입니다. 이를 통해 함수 또는 클래스는 각각에 대해 다시 작성하지 않고도 다양한 데이터 유형에서 작업할 수 있습니다.

MQL5에는 템플릿이 없지만 템플릿으로 프로그래밍 스타일을 사용하는 것이 불가능하다는 의미는 아닙니다. C++ 언어에서 템플릿의 메커니즘은 실제로 언어에 깊이 내장된 정교한 매크로 생성 메커니즘입니다. 즉, 프로그래머가 템플릿을 사용할 때 컴파일러는 해당 함수가 선언된 위치가 아니라 해당 함수가 호출되는 데이터 유형을 결정합니다.

프로그래머가 작성하는 코드의 양을 줄이기 위해 C++에 도입된 템플릿. 그러나 프로그래머가 키보드에 입력한 코드는 컴파일러가 만든 코드와 동일하지 않다는 것을 잊어서는 안됩니다. 템플릿 자체의 메커니즘은 프로그램의 크기를 줄이는 결과를 가져오지 않았습니다. 그것은 단지 소스 코드의 크기를 줄였습니다. 그래서 템플릿을 사용하여 해결하는 주요 문제는 프로그래머가 입력하는 코드를 줄이는 것입니다.

기계어 코드는 컴파일 중에 생성되기 때문에 일반 프로그래머는 함수 코드가 한 번 생성되는지 여러 번 생성되는지 확인하지 못합니다. 템플릿 코드를 컴파일하는 동안 템플릿이 사용된 유형의 수만큼 함수 코드가 생성됩니다. 기본적으로 템플릿은 컴파일 단계에서 재정의됩니다.

C++에서 템플릿을 도입하는 두 번째 측면은 메모리 할당입니다. 문제는 C 언어의 메모리가 정적으로 할당된다는 것입니다. 이 할당을 보다 유연하게 하기 위해 배열의 메모리 크기를 설정하는 템플릿이 사용됩니다. 그러나 이 측면은 이미 MQL4 개발자들이 동적 배열 형태로 구현했으며 MQL5에서도 동적 객체 형태로 구현했습니다.

따라서 유형의 대체 문제만 해결되지 않은 상태로 남아 있습니다. MQL5의 개발자는 템플릿 대체 메커니즘을 사용하면 컴파일러가 크래킹될 수 있다고 언급하여 문제 해결을 거부했습니다.

글쎄, 그들은 그것을 더 잘 알고 있습니다. 그리고 우리는 이 패러다임을 맞춤형 방식으로 구현하는 단 하나의 선택만 할 수 있습니다.

먼저 컴파일러를 바꾸거나 언어의 표준을 바꾸지 않을 것임을 밝힙니다. 템플릿 자체에 대한 접근 방식을 변경하는 것이 좋습니다. 컴파일 단계에서 템플릿을 만들 수 없다고 해서 기계어를 작성할 수 없다는 의미는 아닙니다. 템플릿 사용을 바이너리 코드 생성 부분에서 텍스트 코드가 작성되는 부분으로 옮기는 것이 좋습니다. 이 접근 방식을 "가짜 템플릿"이라고 부르겠습니다.


가짜 템플릿

가짜 템플릿은 C++ 템플릿과 비교하여 장점과 단점이 있습니다. 단점은 파일 이동에 대한 추가 조작을 포함합니다. 장점은 언어의 표준에 의해 결정되는 것보다 더 유연한 가능성을 포함합니다. 말에서 행동으로 옮기자.

가짜 템플릿을 사용하려면 전처리기와 유사한 것이 필요합니다. 이를 위해 '템플릿' 스크립트를 사용합니다. 스크립트에 대한 일반적인 요구 사항은 다음과 같습니다. 지정된 파일을 읽고(데이터 구조 유지) 템플릿을 찾아 지정된 유형으로 바꿔야 합니다.

여기에서 제가 언급할 필요가 있습니다. 템플릿 대신 재정의 메커니즘을 사용할 것이기 때문에 재정의해야 하는 유형의 수만큼 코드를 다시 작성합니다. 즉, 분석을 위해 주어진 전체 코드에서 대체가 수행됩니다. 그런 다음 스크립트에 의해 코드가 여러 번 다시 작성되며 매번 새 대체 항목이 생성됩니다. 따라서 우리는 "기계가 수행하는 수동 작업"이라는 슬로건을 실현할 수 있습니다.


스크립트 코드 개발

필요한 입력 변수를 결정합시다.

  1. 처리할 파일의 이름입니다.
  2. 재정의할 데이터 유형을 저장할 변수입니다.
  3. 실제 데이터 유형 대신 사용할 템플릿의 이름입니다.
input string folder="Example templat";//name of file for processing

input string type="long;double;datetime;string"
                 ;//names of custom types, separator ";"
string TEMPLAT="_XXX_";// template name

스크립트가 코드의 일부만 곱하도록 하려면 마커의 이름을 설정하십시오. 여는 마커는 처리할 부품의 시작을 나타내고 닫는 마커는 끝을 나타냅니다.

스크립트를 사용하면서 마커를 읽는 문제에 직면했습니다.

분석하는 동안 MetaEditor에서 문서의 서식을 지정할 때 종종 주석 줄에 공백이나 표(상황에 따라 다름)가 추가된다는 것을 발견했습니다. 마커를 결정할 때 중요한 기호 앞뒤의 공백을 삭제하여 문제를 해결했습니다. 이 기능은 스크립트에서 자동으로 구현되는데 주의사항이 있습니다.

마커 이름은 공백으로 시작하거나 끝나서는 안 됩니다.

닫는 마커는 의무 사항이 아닙니다. 없는 경우 코드는 파일 끝까지 처리됩니다. 그러나 오프닝이 있어야 합니다. 마커의 이름은 일정하기 때문에 변수 대신 #define 전처리기 지시문을 사용합니다.

#define startread "//start point"
#define endread "//end point"

유형의 배열을 형성하기 위해 'type' 변수를 사용하여 type_dates[] 배열을 값으로 채우는 void ParserInputType(int i,string &type_d[],string text) 함수를 만들었습니다.    

스크립트가 파일 이름과 마커를 받으면 파일 읽기를 시작합니다. 문서의 서식을 저장하기 위해 스크립트는 정보를 한 줄씩 읽고 찾은 줄을 배열에 저장합니다.

물론 하나의 변수에서 모든 것을 플러시할 수 있습니다. 그러나 이 경우 하이픈이 사라지고 텍스트가 끝없는 줄로 바뀝니다. 그렇기 때문에 파일 읽기 기능은 새 문자열을 가져올 때마다 크기가 변경되는 문자열 배열을 사용합니다.

//+------------------------------------------------------------------+
//| downloading file                                                 |
//+------------------------------------------------------------------+
void ReadFile()
  {
   string subfolder="Templates";
   int han=FileOpen(subfolder+"\\"+folder+".mqh",FILE_READ|FILE_SHARE_READ|FILE_TXT|FILE_ANSI,"\r"); 
   if(han!=INVALID_HANDLE)
     {
      string temp="";
      //--- scrolling file to the starting point
      do {temp=FileReadString(han);StringTrimLeft(temp);StringTrimRight(temp);}
      while(startread!=temp);

      string text=""; int size;
      //--- reading the file to the array until a break point or the end of the file
      while(!FileIsEnding(han))
        {
         temp=text=FileReadString(han);
         // deleting symbols of tabulation to check the end
         StringTrimLeft(temp);StringTrimRight(temp);
         if(endread==temp)break;
         // flushing data to the array
         if(text!="")
           {
            size=ArraySize(fdates);
            ArrayResize(fdates,size+1);
            fdates[size]=text;
           }
        }
      FileClose(han);
     }
   else
     {
      Print("File open failed"+subfolder+"\\"+folder+".mqh, error",GetLastError());
      flagnew=true;
     }
  }

사용의 편의를 위해 파일을 FILE_SHARE_READ 모드로 엽니다. 편집된 파일을 닫지 않고 스크립트를 시작할 수 있는 가능성을 제공합니다. 파일 확장자는 'mqh'로 지정됩니다. 따라서 스크립트는 포함 파일에 저장된 코드의 텍스트를 직접 읽습니다. 문제는 확장자가 'mqh'인 파일이 실제로는 텍스트 파일이라는 점입니다. 파일 이름을 'txt'로 바꾸고 텍스트 편집기를 사용하여 'mqh' 파일을 열어서 확인할 수 있습니다. 

읽기가 끝나면 배열의 길이는 시작 마커와 끝 마커 사이의 줄 수와 같습니다.

열린 파일의 이름은 "템플릿" 확장자를 가져야 합니다. 그렇지 않으면 초기 파일을 덮어쓰고 모든 정보를 잃게 됩니다.

이제 정보 분석으로 넘어가겠습니다. 정보를 분석하고 대체하는 기능은 쓰기 기능에서 파일 공백 (WriteFile(int count))으로 호출됩니다. 함수 내부에 주석이 제공됩니다.

void WriteFile(int count)
  {
   ...
   if(han!=INVALID_HANDLE)
     {
      if(flagnew)// if the file cannot be read
        {
         ...
        }
      else
        {// if the file exists
         ArrayResize(tempfdates,count);
         int count_type=ArraySize(type_dates);
         //--- the cycle rewrites the contents of the file for each type of the type_dates template
         for(int j=0;j<count_type;j++)
           {
            for(int i=0;i<count;i++) // copy data into the temporary array
               tempfdates[i]=fdates[i];
            for(int i=0;i<count;i++) // replace templates with types
               Replace(tempfdates,i,j);

            for(int i=0;i<count;i++)
               FileWrite(han,tempfdates[i]); // flushing array in the file
           }
        }
     ...
  }

데이터는 그 자리에서 교체되고 배열은 변환 후 변경되기 때문에 복사본으로 작업합니다. 여기서 데이터의 임시 저장에 사용되는 tempfdates[] 배열의 크기를 설정하고 fdates[] 예제에 따라 채웁니다.

그런 다음 Replace() 함수를 사용하여 템플릿을 대체합니다. 함수의 매개변수는 처리할 배열(템플릿의 대체가 수행되는 위치), i 행의 카운터(배열 내부로 이동) 및 j 유형의 카운터입니다. (유형 배열을 탐색하기 위해).

두 개의 중첩 주기가 있으므로 지정된 유형만큼 소스 코드가 프린트됩니다.

//+------------------------------------------------------------------+
//| replacing templates with types                                   |
//+------------------------------------------------------------------+
void Replace(string &temp_m[],int i,int j)
  {
   if(i>=ArraySize(temp_m))return;
   if(j<ArraySize(type_dates))
      StringReplac(temp_m[i],TEMPLAT,type_dates[j]);// replacing  templat with types   
  }

Replace() 함수는 검사(배열의 존재하지 않는 인덱스 호출을 피하기 위해)를 포함하며 중첩 함수 StringReplac()을 호출합니다. 함수 이름이 표준 함수 StringReplace와 비슷하고 매개변수 수도 같은 데는 이유가 있습니다.

따라서 단일 문자 "e"를 추가하여 전체 교체 논리를 변경할 수 있습니다. 표준 함수는 '찾기' 예제의 값을 가져와 지정된 문자열 '교체'로 바꿉니다. 그리고 내 기능은 대체할 뿐만 아니라 '찾기' 앞에 기호가 있는지 분석합니다(즉, '찾기'가 단어의 일부인지 확인). 존재하는 경우 '찾기'를 '바꾸기'로 바꾸지만 대문자가 아니면 '바꾸기'를 그대로 수행합니다. 따라서 유형을 설정하는 것 외에도 재정의된 데이터의 이름으로 사용할 수 있습니다.


혁신

이제 사용하면서 추가된 혁신에 대해 말씀드리겠습니다. 스크립트를 사용하면서 마커를 읽는 문제가 있다고 이미 언급했습니다.

문제는 void ReadFile() 함수 내부의 다음 코드로 해결됩니다.

      string temp="";
      //--- scrolling the file to the start point
      do {temp=FileReadString(han);StringTrimLeft(temp);StringTrimRight(temp);}
      while(startread!=temp);

주기 자체는 이전 버전에서 구현되었지만 StringTrimLeft()StringTrimRight() 함수를 사용하여 표의 기호를 잘라내는 기능은 향상된 버전에서만 나타났습니다.

또한 출력 파일 이름에서 "템플릿" 확장자를 잘라내어 출력 파일을 사용할 준비가 되었습니다. 지정된 문자열에서 지정된 예제를 삭제하는 기능을 사용하여 구현합니다.

삭제 기능 코드:

//+------------------------------------------------------------------+
//| Deleting the 'find' template from the 'text' string              |
//+------------------------------------------------------------------+
string StringDel(string text,const string find)
  {
   string str=text;
   StringReplace(str,find,"");
   return(str);
  }

파일 이름 자르기를 수행하는 코드는 void WriteFile(int count) 함수에 있습니다.

   string newfolder;
   if(flagnew)newfolder=folder;// if it is the first start, create an empty file of pre-template
   else newfolder=StringDel(folder," templat");// or create the output file according to the template

그외에 프리템플릿을 준비하는 모드도 소개되어 있습니다. Files/Templates 디렉터리에 필요한 파일이 없으면 사전 템플릿 파일로 생성됩니다.

예:

//#define _XXX_ long
 
//this is the start point
 _XXX_
//this is the end point

해당 행을 생성하는 코드는 void WriteFile(int count) 함수에 있습니다.

      if(flagnew)// if the file couldn't be read
        {// fill the template file with the pre-template
         FileWrite(han,"#define "+TEMPLAT+" "+type_dates[0]);
         FileWrite(han," ");
         FileWrite(han,startread);
         FileWrite(han," "+TEMPLAT);
         FileWrite(han,endread);
         Print("Creating pre-template "+subfolder+"\\"+folder+".mqh");
        }

코드 실행은 전역 변수 flagnew에 의해 보호되며, 파일 읽기 오류가 발생한 경우 'true' 값을 취합니다.

스크립트를 사용하면서 템플릿을 추가했습니다. 두 번째 템플릿의 연결 과정은 동일합니다. 변경이 필요한 함수는 추가 템플릿 연결을 위해 OnStart() 함수에 더 가깝게 배치됩니다. 새 템플릿을 연결하는 경로는 두들겨 맞습니다. 따라서 필요한 만큼 템플릿을 연결할 수 있습니다. 이제 동작을 확인해봅시다.


작동 확인

먼저 모든 필수 매개변수를 지정하는 스크립트를 시작하겠습니다. 표시되는 창에서 "예제 템플릿" 파일 이름을 지정합니다.

';' 분리 기호를 사용하여 사용자 정의 데이터 유형의 필드를 채우십시오.

스크립트의 시작 창

"확인" 버튼을 누르자마자 템플릿 디렉토리가 생성됩니다. 사전 템플릿 파일 "Example templat.mqh"가 포함되어 있습니다.

이 이벤트는 다음 메시지와 함께 저널에 표시됩니다.

저널 메시지

사전 템플릿을 변경하고 스크립트를 다시 한 번 시작해 보겠습니다. 이번에는 파일이 이미 Templates 디렉토리(디렉토리 자체도 포함)에 존재하므로 파일 열기 오류에 대한 메시지가 표시되지 않습니다. 교체는 지정된 템플릿에 따라 수행됩니다.

//this_is_the_start_point
 _XXX_ Value_XXX_;
//this_is_the_end_point

생성된 파일 "Example.mqh"를 다시 한 번 엽니다.

 long ValueLONG;
 double ValueDOUBLE;
 datetime ValueDATETIME;
 string ValueSTRING;

보다시피 매개변수로 전달한 타입의 개수에 따라 한 줄에서 4개의 줄이 만들어집니다. 이제 템플릿 파일에 다음 두 줄을 작성합니다.

//this_is_the_start_point
 _XXX_ Value_XXX_;
 _XXX_ Type_XXX_;
//this_is_the_end_point

결과는 스크립트 작업의 논리를 명확하게 보여줍니다.

먼저 전체 코드를 한 유형의 데이터로 다시 작성한 다음 다른 유형의 처리를 수행합니다. 이것은 모든 유형이 처리될 때까지 수행됩니다.

 long ValueLONG;
 long TypeLONG;
 double ValueDOUBLE;
 double TypeDOUBLE;
 datetime ValueDATETIME;
 datetime TypeDATETIME;
 string ValueSTRING;
 string TypeSTRING;

이제 예제 텍스트에 두 번째 템플릿을 포함합니다.

//this_is_the_start_point
 _XXX_ Value_XXX_(_xxx_ ind){return((_XXX_)ind);};
 _XXX_ Type_XXX_(_xxx_ ind){return((_XXX_)ind);};

 //this_is_the_end_button

결과:

 long ValueLONG(int ind){return((long)ind);};
 long TypeLONG(int ind){return((long)ind);};
 
 double ValueDOUBLE(float ind){return((double)ind);};
 double TypeDOUBLE(float ind){return((double)ind);};
 
 datetime ValueDATETIME(int ind){return((datetime)ind);};
 datetime TypeDATETIME(int ind){return((datetime)ind);};
 
 string ValueSTRING(string ind){return((string)ind);};
 string TypeSTRING(string ind){return((string)ind);};

마지막 예에서는 의도적으로 마지막 줄 뒤에 공백을 넣었습니다. 이 공간은 스크립트가 한 유형의 처리를 끝내고 다른 유형의 처리를 시작하는 위치를 보여줍니다. 두 번째 템플릿과 관련하여 유형 처리가 첫 번째 템플릿과 유사하게 수행됨을 알 수 있습니다. 첫 번째 템플릿 유형에 해당하는 유형이 없으면 아무 것도 인쇄되지 않습니다.

이제 코드 디버깅에 대한 질문을 명확히 하고 싶습니다. 주어진 예제는 디버깅을 위해 매우 간단합니다. 프로그래밍하는 동안 코드의 꽤 많은 부분을 디버그하고 완료되자마자 곱해야 할 수도 있습니다. 이를 위해 사전 템플릿에 예약된 주석 줄이 있습니다. "//#define _XXX_ long".

주석을 제거하면 템플릿이 실제 유형이 됩니다. 즉, 템플릿이 어떻게 해석되어야 하는지 컴파일러에게 알려줄 것입니다.

유감스럽게도 이 방법으로 모든 유형을 디버그할 수는 없습니다. 그러나 한 가지 유형을 디버그한 다음 'define'에서 템플릿 유형을 변경할 수 있습니다. 모든 유형을 하나씩 디버그할 수 있습니다. 물론 디버깅을 위해서는 호출된 파일의 디렉터리나 Include 디렉터리로 파일을 이동해야 합니다. 이것은 앞서 가짜 템플릿의 단점을 이야기할 때 언급한 디버깅의 불편함입니다.


결론

결론적으로, 가짜 템플릿을 사용하는 아이디어가 흥미롭고 꽤 생산적이지만 구현의 시작이 작은 아이디어일 뿐이라고 말하고 싶습니다. 위에서 설명한 코드가 작동하고 코드를 작성하는 데 많은 시간을 절약했지만 여전히 많은 질문이 열려 있습니다. 우선, 표준을 개발하는 문제입니다.

내 스크립트는 템플릿의 블록 교체를 구현합니다. 그러나 이 접근 방식은 의무 사항이 아닙니다. 특정 규칙을 해석하는 더 복잡한 분석기를 만들 수 있습니다. 그러나 여기에 그 시작이 있습니다. 큰 토론이 있길 바랍니다. 생각은 갈등에서 번성하니까요. 행운을 빕니다!


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

파일 첨부됨 |
templates.mq5 (9.91 KB)
트레이딩 내 통계적 분산의 역할 트레이딩 내 통계적 분산의 역할
본 문서는 MQL5의 통계 확률 분포에 대해 논하고 이론적 통계 분산을 다루는 클래스들을 다룬 제 다른 문서의 논리적 후속작입니다. 이제 이론적 기반이 확보되었으므로 실제 데이터 셋으로 직접 이동하여 이 기반을 정보적으로 활용할 것을 제안합니다.
시계열 예측을 위한 ENCOG 머신 러닝 프레임워크와 함께 MetaTrader 5 지표 사용 시계열 예측을 위한 ENCOG 머신 러닝 프레임워크와 함께 MetaTrader 5 지표 사용
이 글에서는 MetaTrader 5를 ENCOG(Advanced Neural Network and Machine Learning Framework)에 연결하는 방법을 설명합니다. 여기에는 표준 기술 지표를 기반으로 하는 간단한 신경망 지표와 신경 지표를 기반으로 하는 Expert Advisor에 대한 설명과 구현이 포함되어 있습니다. 모든 소스 코드, 컴파일된 바이너리, DLL 및 훈련된 예시적인 네트워크가 글에 첨부되어 있습니다.
가격 상관 관계 통계 데이터를 기반으로 신호 필터링 가격 상관 관계 통계 데이터를 기반으로 신호 필터링
과거 가격 변동과 미래의 트렌드 사이엔 어떠한 관계가 있을까요? 왜 오늘날의 가격이 과거에 했던 변동을 반복할까요? 통계학을 통하여 가격의 변동성을 예측할 수 있을까요? 답은, 맞다는 것입니다. 만약 아니라고 생각한다면 이 문서는 당신을 위한 것입니다. MQL5에서 거래 시스템에 대한 작동 필터를 만드는 방법을 알려드리겠습니다. 가격 변동에 대한 흥미로운 패턴을 보여줍니다.
시장 가격 예측을 위한 범용 회귀 모델 시장 가격 예측을 위한 범용 회귀 모델
시장 가격은 다양한 경제적, 정치적, 심리적 요인에 따라 달라지는 수요와 공급 간의 안정적인 균형에서 형성됩니다. 이러한 요인들의 영향 요인과 성격의 차이로 인해 모든 구성 요소를 직접적으로 고려하기가 어렵습니다. 이 글은 정교한 회귀 모델을 기반으로 시장 가격을 예측하려는 시도를 설명합니다.