MQL5プログラムの構造 P65
MQL5プログラムの開発を開始する前にMQL5プログラムの構造について説明します。すべてのMQL5プログラムは同じ基本構造を共有しています。ファイルの先頭には、プリプロセッサ ディレクティブがあります。次は入力変数とグローバル変数です。最後にプログラムの関数、クラス、及びイベントハンドラを定義します。
Preprocessorディレクティブ P65
プリプロセッサ ディレクティブはプログラムプロパティの設定、定数の定義、ファイルのインクルードおよび関数のインポートに使用されます。プリプロセッサ ディレクティブは通常、プログラムファイルの最上部で宣言されます。ほぼすべてのMQL5プログラムで見られる#propertyプリプロセッサディレクティブから始めましょう。
#property ディレクティブ P65
#propertyディレクティブは説明情報、インジケータ、スクリプト、ライブラリプロパティなど、プログラムのプロパティを定義します。インジケータ、スクリプトおよびライブラリのプロパティについては適切な章で説明します。
MQL5ウィザードを使用してプログラムを作成すると作成者、リンクおよびバージョンのプロパティが自動的に挿入されます。descriptionプロパティを手動で追加することもできます。これらはEAの【プロパティ】ダイアログの【共通】タブに表示されます。これはプログラムを配布する場合に役立ちます。
#propertyディレクティブはプログラムの一番上に配置されます。インクルードファイル内のプロパティディレクティブは無視されるため、これらはメインプログラムファイルで定義する必要があります。説明的な#propertyディレクティブの例を次に示します。
#prorerty copyright “アンドリュー・R・ヤング”
#prorerty link “http://www.expertadvisorbook.com”
#prorerty version “1.02”
#prorerty description “トレーリングストップ付きデュアル移動平均クロス”
上記の#propertyディレクティブがEAプロパティウィンドウの【Common(共通)】タブにどのように表示されるかを次に示します。
図7.1-#propertyを表示するEAの【プロパティ】ウィンドウの【共通】タブソースコードファイルで定義されているディレクティブ
上記の著作権はハイパーリンクを兼ねています。マウスをその上に置いてクリックすると、ユーザーはlinkプロパティで定義されたwebサイトに移動します。
#defineディレクティブ P66
#defineディレクティブはプログラム全体で使用する定数を定義するために使用されます。17ページで定数について説明しました。要約すると#defineディレクティブは定数値を持つ識別子を指定します。規則では、識別子名にはすべて大文字を使用します。#defineディレクティブを使用した定数の例を次に示します。
#define PI3.14159265
#define MAX_BARS 100
#define COMPANY_NAME” Easy Expert Forex ”
定数を使用するには定数値を識別子名に置き換えます。プログラムでPiの値を使用する場合、識別子PIはコンパイラによって3.14159265として解釈されます。
double diameter = 5;
double circumference = PI * diameter;
Print(circumference); //Output : 15.70796325
上記の例では、Piの値に円の直径を掛けて円周を計算します。
パラメトリック形式と呼ばれる#defineディレクティブの2番目のバリアントがあります。#defineディレクティブのパラメトリック形式は、関数と同じようにパラメータを受け入れます。パラメトリック#defineディレクティブには最大8つのパラメータを含めることができます。結果は、プログラムで計算及び置換される式です。
#define PI 3.14159265
#define CIRC(dia) PI * dia
defineディレクティブCIRC(dia)は円の直径である1つの引数diaを取ります。diaの値は定数PIで乗算され、結果がプログラムに返されます。
double diameter =5;
double circumference = CIRC(diameter);
Print(circumference); //Output : 15.70796325
上記の例では、CIRC(dia)パラメータ定数を使用して円周を計算しています。直径変数の値はパラメータとしてCIRC(dia)定数に渡されます。diaパラメータにPI定数を掛けて、結果を円周変数に入れます。
頻繁に使用される単純な数式がある場合#defineディレクティブのパラメトリック形式は専用の関数を記述する代わりに使用できます。ただし、関数を使用すると結果を指定された桁数に正規化するなど、より高度な操作が可能になります。
#includeディレクティブ P67
#includeディレクティブは、プログラムに含めるインクルードファイルを指定します。インクルードファイルには、メインプログラムで使用される変数、関数、およびクラスが含まれています。#includeディレクティブには2つのバリエーションがあります。
#include <Trade.mqh>
#include “Trade.mqh”
#includeディレクティブの最初のバリアントはインクルードファイル名を山括弧(<>)で囲みます。これは、コンパイラがディフォルトのインクルードリディレクトリ(MetaTrader5インストールフォルダの\MQL5\Includeサブフォルダ)でインクルードファイルを探すことを示します。これは、ファイルを含めるための推奨される方法であり本書で使用する方法です。
#includeディレクティブの2番目のバリアントはインクルードファイル名を二重引用符(“)で囲みます。これによりプログラムファイルと同じディレクトリでインクルードファイルを探すようにコンパイラに指示します。何らかの理由でインクルードファイルを保存した場合、プログラムと同じディレクトリにある場合は#includeディレクティブで二重引用符を使用します。
ライブラリやDLLから関数をインポートするために使用される#importディレクティブという追加のプリプロセッサディレクティブがあります。#importディレクティブの使用方法については第21章で説明します。
入力変数とグローバル変数 P68
プリプロセッサディレクティブの後、MQL5プログラムの次のセクションは入力およびグローバル変数宣言になります。どちらが先かは必ずしも重要ではありませんが、入力変数の宣言を先に置くのが慣例です。ご存じのように入力変数はプログラムのユーザー調節可能な設定です。
使用しているすべてのグローバル変数は、関数またはイベントハンドラの外部で宣言する必要があります。規則では、入力変数の後にファイルの先頭に配置します。これにより、宣言される前に関数によって呼び出されることはありません。
クラスと関数 P68
カスタムクラスまたはカスタム関数は、プログラムのどこにでも定義できます。特に#includeディレクティブを使用してインクルードファイルを含めることができます。通常、メインプログラムファイルに存在するクラスまたは関数は、イベントハンドラの前又は後に配置できますが、ファイル内の入力変数またはグローバル変数の下に配置する必要があります。
イベントハンドラ P68
イベントハンドラは特定のイベントが発生するたびに実行される関数です。イベントハンドラはMQL5プログラムを実行する方法です。例えば、受信価格見積もりがEVによって受信されると、NewTickイベントが発生します。これによりOnTick()イベントハンドラが実行されます。OnTickイベントハンドラには価格変更が発生するたびに実行されるコードが含まれています。
各プログラムタイプには独自のイベントハンドラがあります。EAとインジケータはintイベントを使用してプログラムの開始時に一度実行されるOnInit()イベントハンドラを実行します。スクリプトはOnStart()イベントハンドラによって処理されるStartイベントを使用します。インジケータはCalculateイベントとOnCalculate()イベントハンドラを使用してインジケータを計算を実行します。各プログラムのイベントハンドラについては関連する章で詳しく説明します。
サンプルプログラム P69
上記のすべての要素と、それらがMQL5プログラムにどのように適合するかを示す簡単な例を次に示します。すべての要素がすべてのプログラムに含まれるわけではありません。例えば、外部ファイルから関数や変数を含めない場合、#includeディレクティブは必要ありません。通常、#propertyディレクティブはオプションです。ほとんどのプログラムには入力変数がありますが、グローバル変数はオプションです。また、独自のクラスや関数を作成する必要がある場合とない場合があります。
イベントハンドラはプログラムの種類によって異なります。この例はOnInit()およびOnTick()イベントハンドラを使用したEAプログラムを示しています。
//プリプロセッサディレクティブ
#property copyright “アンドリュー・R・ヤング”
#property link “http:www.expertadisorbook.com”
#property description “MQL5プログラム構造の例”
#define PI 3.14159265
//入力変数
input double Radius = 1.5;
//グローバル変数
double RadiusSq;
//イベントハンドラ
int OnInit()
{
RadiusSq = MathPow(Radius,2);
return(0);
}
void OnTick()
{
double area = CalcArea();
Print(“The area of a circle with a radius of”+Radius+”is”+area);
}
//関数
double CalcArea()
{
double result = PI * RadiusSq;
return result;
}
上記は半径を指定して円の面積を計算する簡単なプログラムです。#propertyディレクティブが最初に来て、プログラムに関する説明情報がいくつかあります。#defineディレクティブはPIの定数を定義します。
Radiusという名前の入力変数を使用すると、ユーザーは円の半径を入力できます。最後にRadiusSqという名前のグローバル変数をプログラムのすべての関数で使用できます。
このプログラムは2つのイベントハンドラがあります。OnInit()イベントハンドラはプログラムの開始時に1回実行されます。Rudius変数の2乗が計算され、グローバル変数RadiusSqに格納されます。OnInit()が実行された後、OnTick()イベントハンドラは着信する価格変更ごとに実行されます。
OnTick()イベントハンドラはプログラムの最後に定義されている関数CalcArea()を呼び出します。この関数は円の面積を計算し、結果をOnTick()関数に返します。Print()関数はRadiusのディフォルト値が使用されていると仮定して次の文字列をログに出力します。
//半径1.5の円の面積は7.0685834625
The area of a circle with a radius of 1.5 is 7.0685834625
それでおしまい。MQL5プログラムの基本構造を説明したいだけなので、このプログラムには取引関数を追加していません。次の章ではEAの作成を開始します。