
MQL5 프로그램 구조에 대해 알아야 할 모든 것
소개
어떠한 프로그래밍 언어든지 소프트웨어에는 구조가 있으며 이 구조를 이해하면 소프트웨어를 원활하게 만들고 개발할 수 있습니다. MQL5 언어의 프로그램은 다른 프로그래밍 언어가 가진 구조와 동일하며 개발자는 프로젝트의 목표를 원활하고 효과적으로 달성하기 위해 이 구조를 이해해야 합니다. 이 글에서는 가능한 한 쉽게 내용을 전달하고자 노력할 것입니다. 다음 주제를 다루면서 우리는 모든 MQL5 프로그램의 구조를 배웁니다:
- 전처리기
- 매크로 대체(#define)
- 프로그램 속성(#프로퍼티)
- 파일 포함하기(#include)
- 함수 가져오기(#import)
- 조건부 컴파일(#ifdef, #ifndef, #else, #endif)
- 입력 및 전역 변수
- 함수, 클래스
- 이벤트 핸들러
- MQL5 프로그램 예제
- 결론
이 주제들에 대해 알아보고 나면 MQL5 프로그램의 구조를 잘 이해하게 되고 이 구조를 기반으로 소프트웨어를 원활하고 효과적으로 만들고 개발할 수 있을 것입니다.
전처리기
이 부분에서는 전처리기에 대해 프로그래밍 개념의 측면에서 자세히 알아보겠습니다. 전처리기는 컴파일 프로세스에서 중요한 단계로 실제 프로그램을 컴파일하기 전에 발생합니다. 전처리 단계에서는 파일 포함하기, 소프트웨어 속성 결정, 상수 정의, 함수 가져오기 등 다양한 작업이 수행됩니다.
모든 전처리기 지시문은 (#)으로 시작합니다. 이러한 지시문은 언어가 진술된 것으로 간주되지 않습니다. 따라서 세미콜론(;)으로 끝내면 안 됩니다. 전처리기 지시어 끝에 세미콜론을 포함하면 지시어 유형에 따라 오류가 발생할 수 있습니다.
즉 전처리기는 컴파일 과정 전에 프로그램의 소스 코드를 준비하기 위한 것이라고 할 수 있습니다. MQL5 프로그램에서 우리가 결정 하는 매개변수를 기반으로 하는 전처리기 지시문에는 다음과 같이 여러 가지 유형이 있습니다:
- 매크로 대체(#define)
- 프로그램 속성(#property)
- 파일 포함하기(#include)
- 함수 가져오기(#import)
- 조건부 컴파일(#ifdef, #ifndef, #else, #endif)
매크로 대체(#define):
이 지시어는 심볼 상수를 만들거나 프로그램에서 사용할 상수를 정의하는 데 사용할 수 있습니다. 상수는 변하지 않는 값을 가진 식별자입니다. 특정 식별자의 대체 값을 사용하므로 #define 지시문을 사용하여 상수에 mnemonic 명을 지정할 수도 있습니다. 이 전처리기 지시어의 첫 번째 형식은 다음과 같습니다:
#define identifier replacement-value
프로그램을 컴파일하기 전에 식별자가 대체 값으로 대체되는 코드 줄이 있습니다. 이 형식은 매개변수가 없는 #define 지시어 또는 매개변수가 없는 형식이며 MQL5에는 #define 지시어와 함께 사용할 수 있는 최대 8개의 매개변수가 허용되는 파라메트릭 형식인 또 다른 형식이 있습니다. 다음과 같습니다:
#define identifier (param1, param2,... param5)
변수에 대한 동일한 규칙이 상수 식별자에 적용됩니다:
- 값은 정수, 더블 또는 문자열과 같은 모든 유형이 될 수 있습니다.
- 표현식은 여러 개의 토큰이 될 수 있으며 줄이 끝나면 끝나고 다음 코드 줄로 이동할 수 없습니다.
다음은 그 예입니다:
//Parameter-free format #define INTEGER 10 //int #define DOUBLE 10.50 //double #define STRING_VALUE "MetaQuotes Software Corp." //str #define INCOMPLETE_VALUE INTEGER+DOUBLE //Incomlete #define COMPLETE_VALUE (INTEGER+DOUBLE) //complete //Parametic format #define A 2+3 #define B 5-1 #define MUL(a, b) ((a)*(b)) double c=MUL(A,B); //function to print values void defValues() { Print("INTEGER Value, ",INTEGER); //result: INTEGER Value, 10 Print("DOUBLE Value, ",DOUBLE); //result: DOUBLE Value, 10.50 Print("STRING Value, ",STRING_VALUE); //result: STRING Value, MetaQuotes Software Corp. Print("INCOMPLETE Value, ",INCOMPLETE_VALUE*2); //result: INCOMPLETE Value, 31 Print("COMPLETE Value, ",COMPLETE_VALUE*2); //result: STRING Value, 41 Print("c= ",c); //result: c= 41 }
이전에 선언되거나 정의된 내용을 취소하는 (#undef) 전처리기 지시어도 있습니다.
프로그램 속성(#property):
소프트웨어를 만들다 보면 매개변수를 추가로 지정해야 하는 경우가 있는데 이때는 #property를 사용하여 지정할 수 있습니다. 이러한 속성은 include 파일이 아닌 기본 mql5 파일에 지정해야 하며 include 파일에 지정된 속성은 무시됩니다. 따라서 #property 지시어는 추가적인 속성을 프로그램에 지정한다고 할 수 있습니다. 가령 예시, 지표, 스크립트, 설명 정보 및 라이브러리 속성과 같은 많은 것들이 있습니다. 다른 전처리기 지시어와 마찬가지로 #property는 소스 코드의 맨 위에 지정되며 실행 시 프로그램 창의 공통 탭에 표시됩니다.
다음은 이러한 유형의 전처리기 지시어의 예입니다:
#property copyright "Copyright 2023, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property description "Property preprocessor"
다음 그림에서 프로그램 창에서 이러한 값들을 확인할 수 있습니다:
이전 그림에서 볼 수 있듯이 EA를 실행할 때 공통 탭에 나타나는 정의 된 속성이 있고 copyright 2023, MetaQuotes Ltd 텍스트에는 마우스를 가져 가면 하이퍼 링크가 표시되고 누르면 링크 속성의 링크로 연결되는 것을 확인할 수 있습니다.
파일 포함하기(#include):
보통 모든 #include 지시문은 프로그램 시작 부분에 배치됩니다. 특정 소프트웨어에 포함될 파일을 지정하는 것으로, 포함된 파일이 소프트웨어의 일부가 되어 변수, 함수, 클래스 등의 콘텐츠를 사용할 수 있다는 것을 의미합니다.
include 지시어로 파일을 포함할 수 있는 형식은 두 가지가 있습니다:
#include <File_Name.mqh> #include "File_Name.mqh"
두 형식의 차이점은 컴파일러가 포함할 파일을 찾는 위치에 있습니다. 첫 번째는 컴파일러가 MetaTrader 5의 인클루드 폴더 또는 표준 라이브러리 헤더 파일에서 파일을 찾도록 하는 것이고 두 번째는 컴파일러가 프로그램 파일과 같은 디렉토리에서 파일을 찾도록 하는 것입니다.
함수 가져오기(#import):
import 지시어는 컴파일된 MQL5 모듈(*.ex5 파일)과 운영 체제 모듈(*.dll 파일)에서 함수를 소프트웨어로 가져오는 데 사용됩니다. 함수는 완전히 설명되어야 하며 형식은 다음과 같아야 합니다:
#import "File_Name" func1 define; func2 define; ... funcN define; #import
조건부 컴파일(#ifdef, #ifndef, #else, #endif):
조건부 컴파일을 사용하면 프로그램 컴파일 외에도 전처리 지시어의 실행을 제어할 수 있습니다. 다음 형식 중 하나가로 특정 조건에 따라 프로그램 코드의 일부를 컴파일하거나 건너뛰거나 하는 것을 제어할 수 있습니다:
#ifdef identifier //If the identifier has been defined, the code here will be compiled. #endif
#ifndef identifier // If the identifier is not defined, the code here will be compiled. #endif
앞에서 만약 새로운 줄로 이동하면 전처리기 지시문이 계속되지 않는다고 언급했지만 여기서는 #else 및 #endif를 사용하여 이러한 유형의 지시문이 계속 이어질 수 있습니다. 조건이 참이면 이 두 #else와 #endif 사이의 줄은 무시됩니다. 그러나 조건이 충족되지 않으면 확인과 #else(또는 전자가 없는 경우 #endif) 사이의 줄은 무시됩니다.
MQL5의 전처리기에 대해서는 MQL 참조에서 더 확인할 수 있습니다.
입력 및 전역 변수
이 부분에서는 입력 및 전역 변수인 전처리기 지시어에 대해 살펴보고 MQL5 프로그램 구조의 다른 구성 요소에 대해 살펴봅니다. 데이터 유형을 지정하는 입력 수정자를 작성한 후 외부 변수를 정의하는 입력 변수부터 시작하겠습니다. 우리에게 입력 변수의 값과 입력 수정자의 값이 있는데 입력 수정자는 mql5 프로그램 내에서는 수정할 수 없지만 입력 창 또는 프로그램 속성의 탭에서 프로그램의 사영자가 변경할 수 있습니다. 우리가 입력 수정자를 통해 이러한 외부 변수를 정의할 때는 OnInIt()이 호출되기 전에 항상 초기화됩니다.
입력 변수의 형식은 다음과 같습니다:
input int MA_Period=20; input int MA_Shift=0; input ENUM_MA_METHOD MA_Method=MODE_SMA;
이후 다음 그림과 같이 사용자가 결정할 입력 창이 나옵니다:
보시다시피 MA 기간, MA 이동 및 MA 유형을 정의할 수 있습니다. 입력 매개변수가 입력 탭에서 어떻게 표시되는지 결정하려면 이전 예제와 같이 창에 표시할 내용을 코멘트로 배치하면 됩니다:
input int MA_Period=20; //Moving Average Period input int MA_Shift=0; //Moving Average Shift input ENUM_MA_METHOD MA_Method=MODE_SMA; //Moving Average Type
입력 탭에서 다음과 같은 매개변수를 찾을 수 있습니다:
보시다시피 매개변수가 이전 그림에서 보았던 것과 다르게 보입니다. 입력 변수에 대한 자세한 내용은 MQL5 레퍼런스에서 확인할 수 있습니다.
전역 변수는 이벤트 핸들러 외부에 생성하거나 동일한 수준의 함수에서 생성해야 하며 이러한 전역 변수의 예를 보면 다음과 같습니다:
int Globalvar; // Global variable before or outside the event handler and functions int OnInit() { ... }
전역 변수의 범위는 프로그램 전체라고 할 수 있으며 프로그램의 모든 함수에서 접근할 수 있고 프로그램이 로드 될 때 한 번 초기화되고 OnInit 이벤트 처리 또는 OnStart() 이벤트 처리 전에 초기화되며 이벤트 핸들러에 대해서는 나중에 이야기하겠지만 여기서는 MQL5 프로그램 구조에서 전역 변수의 위치를 보여드리기 위해 언급합니다.
글로벌 변수에 대한 자세한 내용은 MQL5 레퍼런스에서 확인할 수 있습니다.
함수, 클래스
이 부분에서는 전처리기, 입력, 전역 변수인 함수와 클래스에 이어 MQL5 프로그램 구조의 다른 구성 요소에 대해 설명하겠습니다. 함수에 대한 이전 문서 애플리케이션을 사용한 MQL5의 함수 이해를 통해 이러한 흥미로운 주제에 대해 자세히 알아볼 수 있습니다. 만약 여러분이 MQL5에서 객체 지향 프로그래밍(OOP)의 맥락에서 클래스에 대해 알아보고자 하신다면 이전 글인 MQL5 객체 지향 프로그래밍(OOP) 이해하기에서 관련 내용을 읽어보시면 도움이 되실 것입니다.
여기서는 소프트웨어의 어느 곳에나 정의할 수 있고 #include 지시문을 사용하여 인클루드 파일에서 정의할 수 있으며 사용자 정의 클래스와 마찬가지로 쓰이는 이 중요한 구성 요소의 위치에 대해 알아보겠습니다. 이벤트 핸들러 앞이나 뒤에 혹은 입력 및 전역 변수 아래에 배치할 수 있습니다.
함수 형식은 다음과 같습니다:
returnedDataType functionName(param1, param2) { bodyOfFunction }
클래스의 형식은 다음과 같습니다:
class Cobject { int var1; // variable1 double var2; // variable1 void method1(); // Method or function1 };
함수 및 클래스에 대한 자세한 내용은 MQL5 레퍼런스에서 확인할 수 있습니다.
이벤트 핸들러
이 파트에서는 mql5 프로그램에서 매우 중요한 구성 요소인 이벤트 핸들러에 대해 알아보겠습니다. 이벤트 핸들러는 EA가 새로운 가격 호가를 받을 때와 같이 특정 이벤트가 발생할 때 실행 가능한 함수입니다. 이 이벤트 핸들러에는 새로운 가격 또는 틱 이벤트가 발생할 때 실행되는 코드 본문이 있으므로 OnTick() 이벤트 핸들러가 실행 될 수 있습니다.
MQL5 프로그램의 유형에 따라 다양한 이벤트 핸들러가 있으며 다음은 이러한 이벤트 핸들러에 대한 설명입니다:
이벤트 핸들러 | 설명 | 형식 |
---|---|---|
OnStart | 이 핸들러는 스크립트형 프로그램에서 시작 이벤트가 발생할 때 함수를 호출하는 데 사용할 수 있습니다. |
int OnStart(void);
void OnStart(void); |
OnInit | EA 및 지표 프로그램에서 프로그램을 초기화할 때 함수를 호출하는 데 사용될 수 있습니다. |
int OnInit(void);
void OnInit(void); |
OnDeinit | EA 및 지표 프로그램에서 프로그램을 초기화 해제를 할 때 함수를 호출하는 데 사용될 수 있습니다. | void OnDeinit( const int reason // deinitialization reason code ); |
OnTick | EA와 지표에서 새로운 호가를 받을 때 함수를 호출하는 데 사용될 수 있습니다. | void OnTick(void); |
OnCalculate | 지표에서 Init 이벤트가 전송될 때와 가격 데이터가 변경될 때 함수를 호출하는 데 사용될 수 있습니다. |
int OnCalculate( const int rates_total, // price[] array size const int prev_calculated, // number of handled bars at the previous call const int begin, // index number in the price[] array meaningful data starts from const double& price[] // array of values for calculation );
int OnCalculate( const int rates_total, // size of input time series const int prev_calculated, // number of handled bars at the previous call const datetime& time{}, // Time array const double& open[], // Open array const double& high[], // High array const double& low[], // Low array const double& close[], // Close array const long& tick_volume[], // Tick Volume array const long& volume[], // Real Volume array const int& spread[] // Spread array ); |
OnTimer | 트레이딩 터미널에서 타이머 주기 이벤트가 발생하면 EA 및 지표에서 함수를 호출하는 데 사용될 수 있습니다. | void OnTimer(void); |
OnTrade | 거래 서버에서 거래 작업이 완료되면 EA에서 함수를 호출하는 데 사용될 수 있습니다. | void OnTrade(void); |
OnTradeTransaction | 거래 계좌에서 특정 작업을 수행할 때 EA가 함수를 호출하는 데 사용될 수 있습니다. | void OnTradeTransaction() const MqlTradeTransaction& trans, // trade transaction structure const MqlTradeRequest& request, // request structure const MqlTradeResult& result // response structure ); |
OnBookEvent | EA에서 사용되며 시장 심도가 변경될 때 함수를 호출하는 데 사용될 수 있습니다. | void OnBookEvent( const string& symbol // symbol ); |
OnChartEvent | 지표에서 사용될 수 있으며 사용자가 차트로 작업할 때 함수를 호출하는 데 사용될 수 있습니다. | void OnChartEvent() const int id, // event ID const long& lparam, // long type event parameter const double& dparam, // double type event parameter const string& sparam // string type event parameter ); |
OnTester | 히스토리 데이터에서 EA의 테스트가 종료되면 함수를 호출하기 위해 EA에서 사용될 수 있습니다. | double OnTester(void); |
OnTesterInit | 첫 번째 최적화 패스 전에 전략 테스터에서 최적화 시작과 함께 EA에서 함수를 호출하는 데 사용될 수 있습니다. |
int OnTesterInit(void);
void OnTesterInit(void); |
OnTesterDeinit | 전략 테스터에서 EA의 최적화가 종료된 후 함수를 호출하는 데 사용될 수 있습니다. | void OnTesterDeinit(void); |
OnTesterPass | EA에서 새로운 데이터 프레임이 수신될 때 함수를 호출하는 데 사용될 수 있습니다. | void OnTesterPass(void); |
이벤트 처리에 대한 자세한 내용은 MQL5 레퍼런스에서 확인할 수 있습니다.
MQL5 프로그램 예제
이 부분에서는 지금 배운 내용을 적용하고 올바른 MQL5 구조를 사용하여 간단한 애플리케이션을 만들어 보겠습니다. 예를 들어 #include 전처리기와 같은 일부 컴포넌트를 반드시 사용해야 하는 것은 아닙니다. #property와 동일한 외부 파일은 포함할 필요가 없을 수도 있습니다. 사용 여부는 선택 사항이므로 프로그램에 사용자 정의 클래스나 함수를 만들 수도 있고 만들지 않을 수도 있습니다. 이와 같이 프로그램의 유형과 필요한 작업에 따라 MQL5 구조의 구성 요소를 사용할 수 있는 것입니다. 어쨌든 여러분은 여러분의 프로그램에 필요한 것을 사용할 것입니다. 다음은 다양한 프로그램 유형에 따라 필요한 모든 구조 구성 요소를 보여주는 몇 가지 간단한 응용 프로그램입니다.
스크립트 유형:
다음은 입력값을 사용하여 사용자가 입력한 두 개의 숫자를 계산하여 더하고 Print 함수를 사용하여 시스템 트레이딩 탭에서 결과를 출력할 수 있는 스크립트 MQL5 프로그램의 간단한 예제입니다. 우리는 이 스크립트 프로그램에서 사용자가 숫자를 입력하는 스크립트 입력을 표시할 수 있는 #property를 추가할 것입니다.
//+------------------------------------------------------------------+ //| Script program example.mq5 | //| Copyright 2023, MetaQuotes Ltd.| //| https://www.mql5.com | //+------------------------------------------------------------------+ //property preprocessor #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #property script_show_inputs //inputs input int userEntryNum1; input int userEntryNum2; //global variable int result; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ //event handler void OnStart() { result=userEntryNum1+userEntryNum2; Print("Result: ", result); } //+------------------------------------------------------------------+
다른 EA 또는 지표 프로그램을 만들려면 프로그램 유형에 따라 다른 이벤트 핸들러를 사용해야 합니다. 예를 들어 EA 프로그램은 OnTick() 이벤트 핸들러를 사용하여 새로운 틱을 수신할 때 동작을 실행할 수 있습니다.
이제 MQL5 프로그램의 구조를 파악했습니다. 여러분은 프로그램 유형과 목표 또는 작업에 따라 구성 요소가 달라진다는 것을 알 수 있을 것입니다. 이러한 이해는 소프트웨어에서 각 구성 요소의 위치를 파악하는 데 도움이 됩니다.
이를 적용하기 위해 앞서 언급한 것처럼 간단한 스크립트 프로그램부터 시작할 수 있습니다.
결론
여러분이 이 글의 주제들을 통해 MQL5 프로그램의 구조를 이해했다면 다음의 순서대로 그 유형에 따라 여러분이 MQL5 소프트웨어를 만드는 데 필요한 구성 요소가 무엇인지 파악할 수 있을 것입니다:
- 전처리기(The Preprocessor)
- 매크로 대체(#define)(Macro substitution(#define))
- 프로그램 속성(#프로퍼티)(Program Properties(#property))
- 파일 포함하기(#include)(Including Files(#include))
- 함수 가져오기(#import)(Importing Functions(#import))
- 조건부 컴파일(#ifdef, #ifndef, #else, #endif)(Conditional Compilation (#ifdef, #ifndef, #else, #endif))
- 입력 및 전역 변수(Input and Global Variables)
- 함수 및 클래스(Functions and classes)
- 이벤트 핸들러(Event Handlers)
- OnStart
- OnInit
- OnDeinit
- OnTick
- OnCalculate
- OnTimer
- OnTrade
- OnTradeTransaction
- OnBookEvent
- OnChartEvent
- OnTester
- OnTesterInit
- OnTesterDeinit
- OnTesterPass
이 글이 MQL5 프로그램을 만드는 데 도움이 되었기를 바랍니다. 프로세스의 맥락을 이해하는 것이 필수적입니다. 인기 보조지표를 사용해 트레이딩 시스템을 만드는 방법에 대해 자세히 알아보려면 이전 글들을 참조하세요.
모든 EA에서 사용자 지정 지표를 만들고 사용하는 방법과 객체 지향 프로그래밍(OOP) 및 함수 등 MQL5 프로그래밍의 다른 필수 주제에 대해서도 작성한 글도 있습니다. 이 글들이 여러분의 학습과 트레이딩 여정에 도움이 되리라 믿습니다.
MetaQuotes 소프트웨어 사를 통해 영어가 번역됨
원본 기고글: https://www.mql5.com/en/articles/13021
경고: 이 자료들에 대한 모든 권한은 MetaQuotes(MetaQuotes Ltd.)에 있습니다. 이 자료들의 전부 또는 일부에 대한 복제 및 재출력은 금지됩니다.
이 글은 사이트 사용자가 작성했으며 개인의 견해를 반영합니다. Metaquotes Ltd는 제시된 정보의 정확성 또는 설명 된 솔루션, 전략 또는 권장 사항의 사용으로 인한 결과에 대해 책임을 지지 않습니다.




MQL5 프로그램의 구조에 대해 알아야 할 모든 것 문서가 게시되었습니다:
저자: 모하메드 압델마부드
설명 없이 반복되는 문서가 좀 더 줄어들었으면 좋겠습니다.
+