
MQL5のプログラム構造について学ぶ必要があるすべて
はじめに
どのようなプログラミング言語でも、すべてのソフトウェアには構造があります。この構造を理解することで、ソフトウェアをスムーズに作成開発することができます。他のプログラミング言語と同じく、MQL5言語のプログラムには構造があり、プロジェクトの目的を円滑かつ効果的に達成するためには、開発者がそれを理解することが前提となっています。この記事では、できるだけ簡単にその内容を伝えられるように、この文脈で情報を提供していきます。以下のトピックを取り上げ、MQL5プログラムの構造を学びます。
- プリプロセッサ
- マクロ置換(#define)
- プログラムのプロパティ(#property)
- インクルードファイル(#include)
- 関数のインポート(#import)
- 条件付きコンパイル(#ifdef、#ifndef、#else、#endif)
- 入力変数とグローバル変数
- 関数、クラス
- イベントハンドラ
- MQL5プログラム例
- 結論
これらのトピックを通して、MQL5プログラムの構造をよく理解し、この構造に基づいてスムーズかつ効果的にソフトウェアを作成または開発できるようになると思います。
プリプロセッサ
この部分では、プログラミングの概念としてのプリプロセッサについて詳しく学びます。プリプロセッサは、コンパイルプロセスにおける重要なステップです。プログラムを実際にコンパイルする前に動作します。前処理ステップでは、ファイルのインクルード、ソフトウェアプロパティの決定、定数の定義、関数のインポートなど、さまざまなアクションが実行されます。
すべてのプリプロセッサディレクティブは「#」で始まります。 これらのディレクティブは言語ステートメントとはみなされないため、セミコロン(;)は不要です。プリプロセッサディレクティブの後にセミコロンを含めると、ディレクティブの種類によってはエラーが発生することがあります。
言い換えれば、プリプロセッサは、コンパイルの前にプログラムのソースコードを準備するためのものです。MQL5プログラムには、以下のようにパラメータをもとに決定する多種のプリプロセッサディレクティブがあります。
- マクロ置換(#define)
- プログラムのプロパティ(#property)
- ファイルのインクルード(#include)
- 関数のインポート(#import)
- 条件付きコンパイル(#ifdef、#ifndef、#else、#endif)
マクロ置換(#define):
#defineプリプロセッサディレクティブは、シンボリック定数を作成したり、プログラムで使用する定数を定義したりするのに使用できます。ご存じない場合、定数とは値が変化しない識別子のことです。また、#defineディレクティブは、特定の識別子に対する置換値を使用するため、定数にニーモニック名を割り当てるために使用することもできます。このプリプロセッサディレクティブの最初の書式は、以下のものと同じです。
#define identifier replacement-value
したがって、プログラムにこのコード行があります。つまり、プログラムをコンパイルする前に、識別子を置換値に置き換えるということです。この書式はパラメータなしの#defineディレクティブで「パラメータフリー」です。MQL5にはもう1つの書式があり、それは最大8つのパラメータを持つパラメトリック書式です。
#define identifier (param1, param2,... param5)
変数と同じルールが定数識別子にも適用されるます。
- 値は、integer、double、stringなど、どのような型でもかまいません。
- 式は複数のトークンになれますが行が終了した時点で終了し、次の行に移動することはできません。
以下はその一例です。
//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を使用します。これらのプロパティは、インクルードファイルではなく、メインのmql5ファイルで指定する必要があります。インクルードファイルで指定されたプロパティは無視されます。つまり、#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ディレクティブによるファイルのインクルードには、2つの書式があります。
#include <File_Name.mqh> #include "File_Name.mqh"
これらの2つの書式の違いは、コンパイラがインクルードされるファイルを探す場所です。最初のものは、コンパイラにMetaTrader 5のインクルードフォルダまたは標準ライブラリのヘッダーファイルでファイルを探させるもので、2番目のものは、コンパイラにプログラムファイルと同じディレクトリでファイルを探させるものです。
関数のインポート(#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を使うことで、このタイプのディレクティブは何行でも続けることができます。条件が真の場合、この2つの#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プログラムにおいて非常に重要なコンポーネントであるイベントハンドラについて説明します。イベントハンドラは、特定のイベントが発生したときに実行可能な関数です。例えば、新しい価格相場(エキスパートアドバイザーによって新しいティックイベントが発生)を受信すると、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で、ストラテジーテスターでのEAの最適化終了後に関数を呼び出すために使用 | void OnTesterDeinit(void); |
OnTesterPass | EAで、新しいデータフレームを受信したときに関数を呼び出すために使用 | void OnTesterPass(void); |
イベント処理については、MQL5のリファレンスで詳しく説明されています。
MQL5プログラム例
この部分では、今学んだことを応用して、正しいMQL5構造を使って簡単なアプリケーションを作成します。これらのコンポーネントの一部を使用する義務はないため、プログラムの種類と必要なタスクに基づいて MQL5 構造のコンポーネントを使用できると述べました。たとえば、外部ファイルをインクルードする必要がない場合、#includeプリプロセッサは使用しません。また、#propertyについても同じです。プログラム内でカスタムクラスや関数を作成する必要があるかどうかに加えて、#propertyを使用するかどうかはオプションであるためです。いずれにせよ、自分のプログラムに必要なものを使用することになります。以下は、さまざまなプログラムタイプに基づいて、必要な構造コンポーネントをすべて提示するための簡単なアプリケーションです。
スクリプトタイプ:
以下は、入力を使用してユーザーが入力した2つの数値を計算して加算し、その結果を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ソフトウェアを作成するために、そのタイプに基づいて必要なコンポーネントがわかったと思います。次のように、MQL5構造を構築するために学ぶ必要のあるものはすべて学びました。
- プリプロセッサ
- マクロ置換(#define)
- プログラムのプロパティ(#property)
- インクルードファイル(#include)
- 関数のインポート(#import)
- 条件付きコンパイル(#ifdef、#ifndef、#else、#endif)
- 入力変数とグローバル変数
- 機能とクラス
- イベントハンドラ
- OnStart
- OnInit
- OnDeinit
- OnTick
- OnCalculate
- OnTimer
- OnTrade
- OnTradeTransaction
- OnBookEvent
- OnChartEvent
- OnTester
- OnTesterInit
- OnTesterDeinit
- OnTesterPass
この記事がMQL5プログラム作成のお役に立てば幸いです。プロセスを円滑で効果的にするためには、その背景を理解することが不可欠です。一般的なテクニカル指標を使った取引システムの作成について詳しく知りたい場合は、このトピックについて掲載した私の過去の記事を参照してください。
さらに、EAでのカスタム指標の作成と使用、そしてオブジェクト指向プログラミング(OOP)や関数など、MQL5プログラミングにおけるその他の重要なトピックについても書きました。これらの記事が、読者のみなさんの学習と取引の旅に役立つと信じています。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/13021




- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索