English Русский 中文 Español Deutsch Português
preview
MQL5のプログラム構造について学ぶ必要があるすべて

MQL5のプログラム構造について学ぶ必要があるすべて

MetaTrader 5トレーディング | 25 9月 2023, 09:50
724 0
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

はじめに

どのようなプログラミング言語でも、すべてのソフトウェアには構造があります。この構造を理解することで、ソフトウェアをスムーズに作成開発することができます。他のプログラミング言語と同じく、MQL5言語のプログラムには構造があり、プロジェクトの目的を円滑かつ効果的に達成するためには、開発者がそれを理解することが前提となっています。この記事では、できるだけ簡単にその内容を伝えられるように、この文脈で情報を提供していきます。以下のトピックを取り上げ、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"

これらの値は、次の図のようにプログラムウィンドウで見ることができます。

property

前の図でわかるように、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

[入力]タブには以下のようなパラメータがあります。

入力1

ご覧の通り、パラメータは前の図とは異なっています。入力変数については、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

添付されたファイル |
リプレイシステムの開発—市場シミュレーション(第5回):プレビューの追加 リプレイシステムの開発—市場シミュレーション(第5回):プレビューの追加
現実的で利用しやすい方法で市場リプレイシステムを実装する方法を開発することができたので、プロジェクトを続けて、リプレイの動作を改善するためのデータを追加してみましょう。
DoEasy - コントロール(第32部):水平スクロールバー、マウスホイールスクロール DoEasy - コントロール(第32部):水平スクロールバー、マウスホイールスクロール
この記事では、水平スクロールバーオブジェクト機能の開発を完成します。また、スクロールバーのスライダーを動かしたり、マウスホイールを回転させたりしてコンテナの内容をスクロールできるようにするほか、MQL5の新しい注文実行ポリシーや新しいランタイムエラーコードを考慮したライブラリへの追加もおこないます。
リプレイシステムの開発—市場シミュレーション(第6回):最初の改善(I) リプレイシステムの開発—市場シミュレーション(第6回):最初の改善(I)
この記事では、システム全体の安定化を開始します。安定化がなければ次のステップに進むことができない可能性があります。
MQL4およびMQL5開発のフレームワーク内のOpenAI ChatGPT機能 MQL4およびMQL5開発のフレームワーク内のOpenAI ChatGPT機能
この記事では、エキスパートアドバイザー(EA)、指標、スクリプトの開発にかかる時間と労力を削減するという観点から、OpenAI ChatGPTの機能を理解するために、ChatGPTをいじっていきます。このテクノロジーについて簡単に説明し、MQL4およびMQL5でのプログラミングにこのテクノロジーを正しく使用する方法を説明します。