English
preview
MQL5入門(第3部):MQL5のコア要素をマスターする

MQL5入門(第3部):MQL5のコア要素をマスターする

MetaTrader 5エキスパートアドバイザー | 23 4月 2024, 14:50
83 0
Israel Pelumi Abioye
Israel Pelumi Abioye

はじめに

トレーダー仲間やアルゴリズム愛好家の皆さん、お帰りなさい。私たちはMQL5の旅の第3章に入って理論と実践の岐路に立ち、配列、カスタム関数、プリプロセッサ、そしてイベント処理に隠された秘密を解き明かそうとしています。私たちの使命は、プログラミングのバックグラウンドに関係なく、すべての読者にMQL5の基本要素を深く理解してもらうことです。

この旅をユニークなものにしているのは、明瞭さへのこだわりです。コードの一行一行が説明されるため、概念を理解するだけでなく、実践的なアプリケーションでそれが実現するのを目の当たりにすることができます。目標は、MQL5の言語が誰にでも理解できるような、包括的なスペースを作ることです。質問は歓迎なだけではなく激励されています。基本的なことから説明していきます。これはほんの始まりに過ぎず、この先に待ち受けている魅力的なコーディングの冒険のための土台作りに過ぎません。一緒に学び、作り、MQL5プログラミングの世界を探求しましょう。

集中力を高めて、この没入型探検にご参加ください。私たちは共に、理論的な知識を実践的な専門知識へと変換し、理解の抱擁がすべての人に広がるようにします。舞台は整い、コードも準備できました。さあ、MQL5マスターの世界に飛び込みましょう。

この記事では、以下のトピックを取り上げます。

  • 配列
  • カスタム関数
  • プリプロセッサ
  • イベント処理

第3部でMQL5コーディングの奥深さへのハンズオンジャーニーに乗り出す前に、エキサイティングなお知らせがあります。皆さんの学習体験を高めるために、私たちの探求の第2部の重要な概念とハイライトを要約したビデオを提供します。この視覚的な復習は、理解を強化し、複雑なトピックをより消化しやすくすることを目的としています。



1.  配列

配列について

配列は、データを整理して保存する効率的な方法を提供する、プログラミングの基本概念です。複数の値を1つの変数名で保存し、整理することができます。データごとに個別の変数を作成する代わりに、配列を使用して同じ型の要素のコレクションを保持することができます。これらの要素にはインデックスを使用してアクセスし、操作することができます。

たとえ

配列は魔法の箱のようなもので、似たようなものをまとめておくことができます。箱の列があり、それぞれの箱に番号があるとします。これらの数字は、自分のものを見つけ、整理するのに役立ちます。例えば、0、1、2、3...と番号が振られた箱が並んでいるとします(数え方は常に0から始まる)。それぞれの箱には、お気に入りのおもちゃやお菓子など、何か特別なものを入れておくことができます。特定のおもちゃで遊びたいときは、箱の番号を言えば出来上がりです。探していたものが見つかります。 つまり、プログラミングにおける配列とは、このように番号のついた箱の列のようなものです。似たものを一箇所に集め、特別な番号を使用して簡単に見つけることができます。これは、クールな整理整頓方法です。

1.1.配列の宣言方法

MQL5では、データ型と名前を指定して配列を宣言し、その後に配列の次元(ある場合)を指定します。

これが基本的な構文です。

data_type array_name[array_size];

  • data_type:配列が保持するデータの型(int、double、stringなど)。
  • array_name:配列につける名前
  • array_size:配列のサイズまたは長さ(配列が保持できる要素の数を指定)
例:
void OnStart()
  {

   int closePrices[5]; // An integer array with a size of 5, means the array has 5 integer elements
   double prices[10]; // A double-precision floating-point array with a size of 10

  }

1.2. 配列への値の割り当て

MQL5では、宣言時に配列に値を代入することも、宣言後に個別に値を代入することもできます。両方の方法を分解してみましょう。

1.2.1. 宣言後の値の割り当て

この方法では、まず配列を宣言してから、各要素に個別に値を代入します。プログラムの実行中や特定の条件に基づいて動的に値を割り当てることができます。 

例:

void OnStart()
  {

   int closePrices[5];
   closePrices[0] = 10;
   closePrices[1] = 20;
   closePrices[2] = 30;
   closePrices[3] = 40;
   closePrices[4] = 50;

  }

1.2.2.宣言時の値の割り当て

この方法では、配列を宣言し、中かっこ{}で値を指定します。配列のサイズは、指定した値の数によって決まります。この例では、配列closePricesはサイズ5で宣言され、値10、20、30、40、50で初期化されています。  どちらの方法も有効です。コーディングスタイルや特定のプログラムの要件に合う方を選択してください。

例:

void OnStart()
  {

   int closePrices[5] = {10, 20, 30, 40, 50};

  }

1.3. 配列の要素にアクセスする方法

MQL5を含むほとんどのプログラミング言語では、配列のインデックスは0から始まります。つまり、デフォルトでは、配列を宣言してその要素にアクセスすると、カウントは0から始まります。

図1:配列の要素へのアクセス

例:

void OnStart()
  {
  
// Declare an integer array with a size of 5
   int closePrices[5];

// Assign values to array elements
   closePrices[0] = 10;
   closePrices[1] = 20;
   closePrices[2] = 30;
   closePrices[3] = 40;
   closePrices[4] = 50;
   
   // Access and print array elements
   Print("Element at index 0: ", closePrices[0]); // Output: 10
   Print("Element at index 1: ", closePrices[1]); // Output: 20
   Print("Element at index 2: ", closePrices[2]); // Output: 30
   Print("Element at index 3: ", closePrices[3]); // Output: 40
   Print("Element at index 4: ", closePrices[4]); // Output: 50

  }

説明

配列の宣言:

int closePrices[5];

この行では、closePricesという名前の固定サイズ5要素の整数配列を宣言しています。MQL5では、配列は同じデータ型の要素を格納でき、インデックスは0から始まります。よって、この配列には0~4のインデックスがあります。

配列要素への値の割り当て

   closePrices[0] = 10;
   closePrices[1] = 20;
   closePrices[2] = 30;
   closePrices[3] = 40;
   closePrices[4] = 50;

ここでは、インデックスを使用して配列の各要素に値を割り当てます。配列closePricesには10、20、30、40、50の値がそれぞれの位置に保持されています。

配列要素へのアクセスと出力

   Print("Element at index 0: ", closePrices[0]); // Output: 10
   Print("Element at index 1: ", closePrices[1]); // Output: 20
   Print("Element at index 2: ", closePrices[2]); // Output: 30
   Print("Element at index 3: ", closePrices[3]); // Output: 40
   Print("Element at index 4: ", closePrices[4]); // Output: 50
Print文は、配列の特定のインデックスに格納されている値にアクセスして表示する方法を示しています。インデックス0~4がアクセスされ、対応する値がコンソールに表示されます。

MQL5配列の入門的な探求では、データのための組織化されたコンテナという比喩を使いながら、基本を明らかにしてきました。コード例を通して、配列要素の宣言、初期化、アクセスについて説明しました。  MQL5が強力な配列関数を備えていることは注目に値します。これらについては後で詳しく説明しますが、今は基本的な配列の概念に慣れることが重要です。


2.カスタム関数

共通関数について

カスタム関数は、ユーザー定義関数とも呼ばれ、プログラミング言語で特定のタスクや一連のタスクを実行するために作成する、特定のコードのセグメントです。アルゴリズム取引に使用されるMQL5の文脈では、カスタム関数は一連のアクション、計算、操作をカプセル化するためにプログラマーによって記述されます。 これらの関数を使用することで、コードをモジュール化し、より読みやすく、再利用しやすく、保守しやすくすることができます。プログラム内の複数の場所に同じコードを複製する代わりに、そのロジックをカプセル化したカスタム関数を作成し、特定のタスクを実行する必要があるときはいつでもその関数を呼び出すことができます。

アラート、コメント、プリントのような一般的な関数について説明した前回の記事で築いた基礎の上に、今度はMQL5で関数を作成するための強力な領域を掘り下げていきます。熟練した職人が道具に磨きをかけるように、カスタム関数を作成することで、取引戦略の要求に合わせてコードを正確に調整することができます。

たとえ

キッチンで楽しい食事(あなたのコード)の準備をしていると想像してください。プログラミングという料理の世界では、関数はレシピのようなもので、特定の料理を作るためのステップバイステップの手順を提供します。ここで、カスタム関数と共通関数の類似性を探ってみましょう。 共通関数は、料理本で広く認知されているレシピのようなものだと考えてください。これらのレシピは、コーヒーを入れたり、卵をゆでたりするような、標準的でよく使われるものです。プログラミング用語で言えば、Alert、Comment、Printなどの関数は、これらのよく知られたレシピに似ています。それらは特定の目的を果たすものであり、すぐに使用できます。

一方、カスタム関数は、自分だけの、秘密の家族レシピのようなものです。これらの料理は、味覚と好みに合わせて、あなたが創作したものです。同様に、コーディングにおけるカスタム関数とは、特定のタスクを実行するためにプログラマーが作成したパーソナライズされた命令セットのことです。それは、完璧なチョコレートケーキの秘密のレシピのように、特定の結果を達成するための一連のステップをカプセル化したものです。共通関数はインスタント食品のように便利で、素早く、幅広く応用できます。作り置きの夕食を温めるように、一般的な作業には効率的です。その反面、カスタム関数は精度とパーソナライズを提供します。ゼロから料理するようなもので、食材、味付け、テクニックを調整し、その料理独特の要求に応えることができます。

2.1.関数の作り方

MQL5で関数を作成するには、関数の名前を指定し、パラメータ(ある場合)を定義し、戻り値の型(値を返す場合)を指定し、関数本体を構成するコードブロックを提供します。

ステップ1:関数の目的を決める

関数が実行するタスクや計算を決めます。これは、関数の名前、入力パラメータ、戻り値の型(もしあれば)を決定するのに役立ちます。今回は、2つの数値を掛け合わせる関数を作ってみましょう。

ステップ2:関数の宣言

選択した名前、入力パラメータ、戻り値の型(該当する場合)で関数を宣言します。この宣言は、特定の関数やイベントハンドラの外、グローバルスコープでおこなわれるべきです。

注:MQL5のイベントハンドラとは、市場価格の変化(OnTick)、チャートの相互作用(OnChartEvent)、時間間隔(OnTimer)など、特定のイベントに自動的に応答する関数です。これらは、MetaTraderプラットフォームのリアルタイムまたはスケジュールされた発生に基づくコードの実行を合理化します。  詳しい説明は後ほど。

構文

return_type FunctionName(parameter1_type parameter1, parameter2_type parameter2, ...) 
   {
    // Function body (code block)
    // Perform actions or calculations
    // Optionally, return a value using the 'return' keyword if the function has a return type
   }

ステップ3:関数本体の定義

関数の中に、目的のタスクや計算を実行するコードを追加します。必要な変数とロジックを含めます。

例:

double MyFunction(int param1, double param2)
     {
      // Function body: Calculate the product of the two parameters
      double result = param1 * param2;

      // Return the result
      return result;
     }

説明

double MyFunction(int param1, double param2)

  • この行はMyFunctionという名前の関数を定義します。 この関数は2つのパラメータを取ります。param1はint(整数)型、param2はdouble(浮動小数点数)型です。この関数はdouble型の値を返します。

{

  • 中括弧「{」は、関数本体の始まりを示します。本体は、関数の実際のコードが存在する場所です。

“double result = param1 * param2;”:

  • この行は、param1とparam2の積を計算し、結果をresultという変数に格納します。param1とparam2はどちらも数値型なので、乗算演算(*)の結果はdoubleになります。

return result;

  • この行は関数MyFunctionを終了し、result変数に格納された値を関数を呼び出したコードに戻します。関数の戻り値の型はdoubleなので、呼び出し側はdouble値を受け取ることを期待していることになります。

"}"

  • 閉じ中括弧「}」は、関数本体の終わりを示します。

ステップ4:関数の使用

コードの他の部分から関数を呼び出します。この関数は、イベントハンドラや他の関数、あるいは適切な文脈で使用することができます。

例:
void OnStart()
  {

// Calling the custom function
   double result = MyFunction(5, 3.5);

// Printing the result
   Print("The result is: ", result); // The output will be 17.5

  }

提供されている関数MyFunctionは、2つの数値を自動的に掛け算するように設計されています。この関数を呼び出し、必要な数値を引数として与えることで、計算がシームレスに実行され、結果が返されます。この抽象化によって掛け算のプロセスが単純化され、コードの可読性と再利用性が向上します。

積極的にコンテンツを使用して、何かあればお気軽にご質問ください。読者の理解を第一に考え、関連するあらゆるトピックについて、明確または詳細に説明をしていきます。質問は、より豊かな学習経験に貢献します。遠慮せずにご連絡ください。迅速に対応し、記事で説明されている概念を理解してもらえるよう、最善を尽くします。


3.プリプロセッサ

プリプロセッサについて

MQL5プログラミングのダイナミックな世界では、プリプロセッサはコードが解釈され実行される方法を形成する重要なツールです。プリプロセッサは、実際のコンパイル処理が始まる前にソースコード上で動作する特殊なソフトウェアコンポーネントです。その主な役割は、結果としてのプログラムの動作、構造、特性に影響を与える命令や指令を扱うことです。

プリプロセッサは、元のソースコードを変換または前処理することで機能します。プリプロセッサは、ハッシュ記号(#)で示された特定のディレクティブを解釈し、それに従って動作し、コンパイルされる前にコードの内容を変更します。 これらのディレクティブはプリプロセッサディレクティブとも呼ばれ、定数の定義、外部ファイルの取り込み、プログラムのプロパティの設定、条件付きコンパイルの有効化など、さまざまな機能を含んでいます。各ディレクティブは、開発者の要求に従ってコードを形成するための明確な目的を果たします。

プリプロセッサの特徴は、実際のコンパイルがおこなわれる前に実行できる点にあります。このコード操作の初期段階によって、開発者は、最終的にコンパイルされたプログラムに影響を与える特定の条件、構成、または包含を確立することができます。

図2:MetaEditorのプリプロセッサ


注:MQL5プログラミングでは、プリプロセッサは通常の文のようにセミコロン(;)で終わらず、コードのグローバル空間で宣言されることを覚えておく必要があります。マクロを表す#defineやファイルをインクルードする#includeなどのユニークなディレクティブは、プログラムの動作や構造を形成する上で重要な役割を果たします。したがって、プリプロセッサを使用する場合は、セミコロンをスキップして、グローバルスポットライトの中に独自のスペースを確保します。

たとえ

コードを書くことは、ロボットに指示を出すようなものだと想像してみましょう。さて、ロボットに伝える前に、「プリプロセッサ」と呼ばれる特別な友達がいます。 この友達は、ロボットが私たちの指示を完璧に理解できるように、すべての準備を整えてくれます。プリプロセッサは、ロボットが命令を実行する前に、私たちの命令を見てくれる魔法のヘルパーだと思ってください。その仕事は、物事をよりシンプルに、より整理整頓することです。 例えば、数字の10の代わりにMAGIC_NUMBERと言うように、時々、私たちは何か重要なことを意味する特別な言葉を使いたいことがあります。プリプロセッサは、これらの特殊な単語を理解し、実数に置き換えることで私たちを助けてくれます。

例:

#define MAGIC_NUMBER 10

//+------------------------------------------------------------------+
//|                                                                                 |
//+------------------------------------------------------------------+
void OnStart()
  {

   int result = MAGIC_NUMBER + 5;
   Comment(result); // Output will be 15

  }

説明

#define MAGIC_NUMBER 10

  • この行は、プリプロセッサに、コードでMAGIC_NUMBERという単語を見かけたら常に数字の10に置き換えるようにプリプロセッサに伝えているようなものです。 特定の値を表す特別な言葉を作るようなものです。

void OnStart()

  • この部分が主なアクションの始まりです。OnStartはMQL4の特別な関数で、スクリプトの実行開始時に実行されます。

int result = MAGIC_NUMBER + 5;

  • ここでは、特別な言葉MAGIC_NUMBERを使用します。 プリプロセッサはこれを見て、MAGIC_NUMBERを10に置き換えます。つまり、この行は「intresult=10+5;」と言っているのと同じです。

Comment(result); // Output will be 15

  • Comment関数は、ロボットに何かを言うように指示するようなものです。この場合、ロボットにresultの値である15を言うように指示しています。つまり、このスクリプトを実行すると、チャートのコメントに「15」と表示されます。

クールなのは、プリプロセッサがロボットに指示を出す前から機能することです。私たちの特別な言葉を見て、すべてを準備し、ロボットが作業を開始するときには、すでに何をすべきかを知っています。つまり、プリプロセッサは私たちの秘密の友達のようなもので、私たちの指示が明確であること、コードがきちんとしていること、そしてロボットが従うようにすべてが完璧に設定されていることを確認してくれます。コーディングの世界にスーパーヒーローの友達を持つようなものです。


3.1.プリプロセッサのカテゴリ

3.1.1.マクロ置換(#define)

コーディングの世界では、マクロは定数の作成に使用されます。定数は不変の値のようなものです。マクロを使えば、これらの値を表す特別な単語を作ることができます。

例:

#define MAGIC_NUMBER 10

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {

   int result = MAGIC_NUMBER + 5;

  }

ここでは、毎回10という数字を使用するのではなく、単にMAGIC_NUMBERという単語を使用することで、コードをすっきりさせ、読みやすくしています。

3.1.1.1.  パラメータ化マクロ(関数ライクマクロ)

魔法のようなレシピがあって、ときどき重要な材料を変えたくなるとします。パラメータ化されたマクロにより、柔軟な命令を作成できます。

例:

#define MULTIPLY(x, y) (x * y)

//+------------------------------------------------------------------+
//|                                                                                 |
//+------------------------------------------------------------------+
void OnStart()
  {

   int result = MULTIPLY(3, 5); // Result is 15

  }

ここでは、マクロMULTIPLYは2つの材料(数字)を受け取り、それらを掛け合わせます。これは、コードに魔法の関数があるようなものです。

説明

#define MULTIPLY(x, y) (x * y)

  • この行は、「MULTIPLY」と言うときはいつでも、2つの数字(仮にxとyと呼ぶ)を取って掛け合わせるという意味だとコンピュータに伝えているようなものです。 魔法の言葉を使用して掛け算マシーンを作るようなものです。

int result = MULTIPLY(3, 5);

  • ここでは、魔法の言葉MULTIPLYを使用します。 コンピュータはこれを見て、「3と5を掛け算する」という意味だとわかります。 つまり、MULTIPLY(3, 5)を(3 * 5)に置き換えます。

// Result is 15

  • 3と5を掛けた結果は15です。つまり、コンピュータが計算した後、resultの値は15になります。

要するに、このコードは掛け算のプロセスを単純化するものです。「3 * 5」と直接書く代わりに、MULTIPLYという魔法の言葉を使用することで、コードがより読みやすく、理解しやすくなります。コードの中にミニ数学アシスタントがいるようなものです。

3.1.1.2.#undefディレクティブ

#undefディレクティブは、「さっき言ったことは忘れて、新しくやり直しましょう」と言っているようなものです。 MQL5プログラミングの世界では、以前に定義したマクロの定義を解除、つまり「作成解除」することができます。これは、魔法のホワイトボードのメモを消すようなものです。

例:

#define MAGIC_NUMBER 10

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {

   int result = MAGIC_NUMBER + 5;
#undef MAGIC_NUMBER // Undefining MAGIC_NUMBER


  }

説明

#define MAGIC_NUMBER 10

  • 最初に、MAGIC_NUMBERというマクロを定義し、その値を10に設定します。MAGIC_NUMBER'を使用するときはいつも10を意味すると言うようなものです。

int result = MAGIC_NUMBER + 5;

  • MAGIC_NUMBERを計算で使用し、結果は15になります。

#undef  MAGIC_NUMBER

  • 「#undef MAGIC_NUMBER」は、MAGIC_NUMBERが以前何を意味していたかは忘れるように支持します。 定義を消して、MAGIC_NUMBERを未定義にしているようなものです。
これで、#undef行の後にMAGIC_NUMBERを使用しようとすると、コンピュータはMAGIC_NUMBERが何を意味するのかわからなくなり、エラーとなります。これは、コードの特定の部分でマクロを再定義したり、使用を停止したりする場合に便利です。コンピュータに、「この魔法の言葉をしばらく使用したけど、次は別の言葉にしよう」と言っているようなものです。

3.1.2.プログラムのプロパティ(#property)

コーディングの世界では、どのプログラムも物語の登場人物のように独自の特徴を持っています。#propertyを使えば、プログラムに特別な特徴や質を与えることができます。コンピュータに、何がプログラムを特別なものにしているかを伝えるようなものです。 本や曲を書いているとき、誰がいつ作ったかを伝えたいと思うかもしれません。#propertyは、プログラムで同じことをするのに役立ちます。これは、コードの先頭に「このプログラムはバージョン1.0で、2022年に作成しました」という小さなメモを追加するようなものです。

例:

#property copyright "crownsoyin"
#property version   "1.00"

結果コード実行後

図3:MT5でコードを実行した結果

#propertyは、本の表紙や映画のオープニングクレジットのようなものです。これは、雰囲気を作り、プログラムに関する情報を提供し、コーダーや後でコードを読むかもしれない人を含むすべての人が、何が起こっているのかを理解するのに役立ちます。

3.1.3 #includeディレクティブ

インクルードファイルについて

魔法のレシピ本があるとします。そして、いくつかのレシピは別の本に保存されているとします。#includeは、他の本からレシピを持ってきて、1つの大きなレシピ集にまとめようと言っているようなものです。 コーディングでは、外部ファイルをメインのコードにマージし、すべてを一箇所でアクセスできるようにするのに役立ちます。 コーディングは、さまざまな部屋を持つ家を建てるようなものだと考えてください。それぞれの部屋は、台所や寝室のように特定の機能を持っています。#includeを使えば、これらの部屋(関数や構造体)を他の家(プログラム)で再利用することができます。この素晴らしい台所を作ったのだから、一から作らなくてもすべての家で使えると言っているようなものです。

例:

#include "extraRecipes.mqh" // Include external file with extra recipes

説明

#include

  • #includeは、「特別なものを別の場所から持ってきて、ここに追加する」という魔法のコマンドだと思ってください。 私たちのレシピに必要な材料を追加で調達するための秘密のポータルがあるようなものです。

"extraRecipes.mqh"

  • 二重引用符の中のテキストは、インクルードしたい外部ファイルの名前です。この場合はextraRecipes.mqhです。 このファイルには、メインプログラムで使いたい追加レシピやコードが含まれています。

つまり、#include"extraRecipes.mqh"と書くと、秘密の料理本を開いて、メインの調理法にこれらの追加レシピを加えようと言っているようなものです。 これにより、メインのコードをすっきりと整理しながら、extraRecipes.mqhからさらなる魔法にアクセスすることができます。 魔法の料理本に呪文や魔力を足すようなものです。 #includeを使用して外部ファイルをインクルードすると、その外部ファイルで定義された関数や構造体にアクセスできるようになり、メインコードで使用できるようになります。

外部ファイル:"extraRecipes.mqh"

// extraRecipes.mqh
int MultiplyByTwo(int number) // function from an external file  
{
    return number * 2;
}

メインコード

// Your main code
#include "extraRecipes.mqh" // Include external file with extra recipes
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {

   int result = MultiplyByTwo(5);  // Using the function from the included file
   Print("Result: ", result); // Output: Result: 10

  }


この例では、MultiplyByTwo関数は外部ファイルextraRecipes.mqhで定義されています。 メインコードで#include'"extraRecipes.mqh"'を使用することで、MultiplyByTwo関数をメインコードで直接定義されているかのように呼び出して使用することができます。

コードインクルージョンと関数の使い方は、最初は理解するには少し複雑に思えるかもしれません。プログラミングは新しい言語を学ぶようなもので、すべての旅は最初の一歩から始まります。頭を悩ませたり、少し不可解に感じたりしたら、ためらわずに質問してください。好奇心は学習プロセスを促進します。どんな謎でも解明する御手伝いをします。学習の冒険を受け入れ、質問こそがより深い理解を解き明かす鍵であることを忘れないでください。質問があったら気軽に問い合わせてください。コーディングの旅に一緒に出かけましょう。

3.1.4.コンパイル条件(#ifdef、#ifndef、#else、#endif)

コンパイル条件によって、コンパイルの過程でコードの一部を含めたり除外したりすることができます。これは、コンパイラが特定の条件に基づいて何を含めるべきかを導く特別な指示を持つようなものです。

3.1.4.1. #ifdefディレクティブ

MQL5の#ifdefディレクティブは、特定の銘柄が定義されているかどうかを確認するプリプロセッサディレクティブです。銘柄が定義されている場合は、#ifdefに続くコードブロックがコンパイル時に含まれ、そうでない場合は、#elseまたは#endifに続くコードブロックが含まれます。

例:

#define MAGIC_NUMBER 10
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {

#ifdef MAGIC_NUMBER
   Print(MAGIC_NUMBER);
#else
   Print(MAGIC_NUMBER);
#endif


  }

説明

  • この例では、MAGIC_NUMBERは#defineを使用して定義されています。
  • 「#ifdef MAGIC_NUMBER」は、MAGIC_NUMBERが定義されているかどうかを確認します。
  • 定義されているので、#ifdefに続くコードブロックが含まれ、最初のPrint文がコンパイルされます。
  • もしMAGIC_NUMBERが定義されていなければ、#elseに続くコードブロックが含まれ、2番目のPrint文がコンパイルされます。

#ifdefは条件付きコンパイルによく使われ、開発者は定義済みの銘柄に基づいて特定のコード部分を含めたり除外したりできます。これは、適応可能で設定可能なコードを作成するための貴重なツールであり、開発者はコンパイルプロセス中に定義された銘柄や条件に基づいてアプリケーションを調整することができます。

3.1.4.2. #ifndefディレクティブ

MQL5の#ifndefディレクティブは、特定のシンボルが定義されていないかどうかを確認するプリプロセッサディレクティブです。マクロが定義されていない場合は、#ifndefに続くコードブロックがコンパイル時に含まれ、そうでない場合は、#elseまたは#endifに続くコードブロックが含まれます。

例:

void OnStart()
  {

#ifndef MAGIC_NUMBER
   Print(MAGIC_NUMBER);
#else
   Print(MAGIC_NUMBER);
#endif


  }

説明

  • 「#ifndef MAGIC_NUMBER」は、MAGIC_NUMBERが定義されていないかどうかを確認します。
  • MAGIC_NUMBERが定義されていない場合、#ifndefに続くコードブロックが含まれ、MAGIC_NUMBERが定義されていないことを示すメッセージが表示されます。
  • MAGIC_NUMBERが定義されている場合、#elseに続くコードブロックが含まれ、MAGIC_NUMBERの値が表示されます。

このコードは、特定のマクロ(この場合はMAGIC_NUMBER)が定義されているか否かに基づいて条件付きコンパイルをおこなうことを示しています。マクロの有無によって、コンパイル時に含まれるコードブロックが異なります。

注:この例ではMAGIC_NUMBERが定義されていません。

3.1.4.3. #endifディレクティブ

MQL5の#endifディレクティブは、#ifdefや#ifndefなどのディレクティブによって開始された条件付きコードブロックの終わりを示します。これは、条件付きコンパイルセクションが終了し、後続のコードがコンパイルのために処理されるべきであることをプリプロセッサに知らせるシグナルとして機能します。条件やパラメータを持たず、条件付きコンパイルブロックの終わりを示すことが目的です。

例:

#define MAGIC_NUMBER 10
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {

#ifndef MAGIC_NUMBER
   Print(MAGIC_NUMBER);
#else
   Print(MAGIC_NUMBER);
#endif

  }

説明

  • #endifは条件ブロックの終わりを示し、それ以降のコードは正常に処理されます。

注:適切な構文を維持し、コンパイルエラーを回避するために、#endifは常に開始条件指示文(#ifdefまたは#ifndef)と対にしてください。

MQL5プリプロセッサの簡単な説明では、定数を作成するためのマクロ、特性を定義するためのプログラムプロパティ(#properties)、モジュール化のためのインクルードファイル、柔軟なコードのための条件付きコンパイルについて説明しました。これは序章のようなものですが、もっと多くの発見があります。これらのツールは、効率的なMQL5プログラミングの構成要素を形成し、汎用性と適応性を提供します。強力な取引アルゴリズムを作り上げる旅を続ける中で、遠慮なく質問し、これらの概念をさらに深く掘り下げてください。好奇心を受け入れ、プリプロセッサへの理解を有機的に成長させましょう。


4.イベント処理

イベントについて

プログラミングにおけるイベントとは、プログラムの実行中に起こる特定の出来事やハプニングを指します。イベントは、ユーザーとのインタラクションやシステム状態の変化など、さまざまなアクションによってトリガーされます。MQL5の文脈では、イベントは、市場の状況に動的に反応するアルゴリズム取引スクリプトを開発するために非常に重要です。

イベントハンドラについて

イベントハンドラは、特定のタイプのイベントに応答する責任を負うコードの指定されたセクションです。MQL5では、イベントハンドラは特定のイベントが発生したときに実行するように設計された関数です。これらの関数はあらかじめ定義されており、さまざまなイベントに対して指定された応答メカニズムとして機能します。それぞれのタイプのイベントには、対応するイベントハンドラ関数があります。

たとえ

あなたが魔法の人形劇を見ていると想像してください。観客が拍手したときや特別なボタンが押されたときなど、特定のことが起こるたびに人形が動いたり話したりします。さて、人形をコンピュータプログラムのさまざまな部分と考え、魔法のボタンをイベントと考えます。イベントハンドラは、舞台裏で人形使いのように、特定の瞬間(イベント)が起こるのを待っています。イベントが起きると、イベントハンドラが動き出し、プログラムに何か特別な動作をさせます。ちょうど人形使いが、観客の歓声やボタンが押されたときに人形を踊らせたりしゃべらせたりするようにです。つまり、プログラミングの世界では、イベントハンドラは、特定のイベントが起こったときに物事に命を吹き込む魔法の人形使いのようなものです。

4.1.イベントハンドラの種類

図4:イベントハンドラのいくつかの種類


4.1.1.OnInit

MQL5では、OnInitはエキスパートアドバイザー(EA)で使用される特別な関数で、EAが初めてチャートに読み込まれたときに初期化します。

たとえ

さて、魔法のロボットの友達がいるとしましょう。ロボットが動き回ったり、変な音を出したりといったエキサイティングなことを始める前に、準備をする必要があります。準備の部分は、ロボットのOnInitの瞬間のようなものです。 つまり、最初にスイッチを入れると、ロボットは特別な部屋(OnInit関数)に入り、そこで準備をします。ここで好きな色を設定し、どのくらいのスピードで動くかを決め、すべてがちょうどいい状態になるようにします。すべての設定が終わると、ロボットは登場し、踊ったりギャグを言ったりと、クールな芸を始める準備が整います。

コンピュータプログラムでは、OnInit関数が同様の働きをします。それは、プログラムが仕事を始める前に準備をする特別な部屋です。プログラムの開会式のようなもので、すべてが整い、準備が整っていることを確認します。

// Declare global variables
double LotSize;
int TakeProfit;
int StopLoss;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
// OnInit function
int OnInit()
  {
// Set EA parameters
   LotSize = 0.1;
   TakeProfit = 50;
   StopLoss = 30;

// Display initialization message
   Print("EA is getting ready. Lot Size: ", LotSize, ", Take Profit: ", TakeProfit, ", Stop Loss: ", StopLoss);

   return(INIT_SUCCEEDED);
  }

説明

  • EAが使用する可能性のあるグローバル変数をいくつか宣言します。
  • OnInit関数は、これらの変数を初期化し、必要な設定をおこなうところです。この例では、LotSize、TakeProfit、StopLossに値を設定します。
  • Print文は、EAが初期化されたことを知らせるためにコンソールに送るメッセージのようなものです。ロボットが「準備しています、設定はこれです」と言っているようなものです。

このEAをチャートに取り付けると、OnInit関数が一度実行され、コンソールに初期化メッセージが表示されます。これにより、EAが取引やその他のアクションを開始する前に、その設定が完了していることを確認できます。

4.1.2.OnStart

MQL5では、OnStart関数はスクリプトやEAの重要な部分です。スクリプトの主な役割は、スクリプトが起動または開始されたときに一度だけコマンドを実行することです。OnStartは、スクリプト実行の最初のエントリポイントです。 スクリプトの場合、OnStart関数は定義されたロジックを実行し、これには取引の発注、計算、その他のアクションが含まれます。ただし、OnStart関数で継続的に実行され、条件を再評価するEAとは異なり、スクリプトは通常、そのロジックを1回だけ実行して停止します。

そのため、MQL5スクリプトのOnStart関数に取引関連のアクションを設定すると、スクリプトが起動したときにそれらのアクションが実行されますが、スクリプトが継続的に市場を監視したり、追加の取引を実行したりすることはできません。

例:

/+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
// This script prints a message to the console when activated

// Entry point when the script is started
void OnStart()
  {
// Print a message to the console
   Print("Script Activated! Hello, Traders!");
  }

説明

  • OnStart関数はスクリプトのエントリーポイントです。
  • Print関数は、MetaTrader端末の端末ウィンドウの[EA]タブにメッセージを表示するために使用されます。
  • このスクリプトをチャートに添付したり、MetaEditorで実行すると、コンソールに指定されたメッセージが表示されます。スクリプトの要件に応じて、Print文を自由に変更し、より複雑なロジックを追加してください。

このスクリプトがチャートに添付されると、OnStart関数が一度だけ実行されます。スクリプトのOnStart関数の目的は、通常、スクリプトがチャートにアタッチされた瞬間に初期化タスクを実行したり、特定のアクションを実行したりすることです。スクリプトはロジックを実行した後、動作を完了します。

 

4.1.3.OnTick

MQL5では、OnTick関数はEAの重要な部分です。その主な役割は、市場の各ティックで実行されるべき中核的な取引ロジックとアクションを格納することです。EAはOnTickを使用して価格の変化を監視し、市場の状況を分析し、事前に定義された取引戦略に基づいて意思決定をおこないます。ポジションを建て、変更し、閉じるといった注文関連のアクションは、一般的にOnTick関数内に配置されます。

たとえ

OnTick関数は、TickTraderという取引友達が、忙しい市場を探検しているようなものだと思ってください。すべてのティックは、新しいチャンスや変化のようなものです。TickTraderは、活気のある市場で最高の取引を探すときのように、常に良い取引を探しています。

TickTraderは、市場が落ち着いているときは、すぐに売り買いをせずに、ゆっくりと見て回ることもあります。同様に、OnTick関数が、ティックごとに物事が落ち着いているのを見れば、市場をさりげなく見回すなど、注意深くなることを示唆するかもしれません。価格が突然上昇すれば、TickTraderは得と判断して買うことを決断するかもしれません。同様に、OnTick関数がティックごとに大きな価格変動に気づいたとき、それはちょうど忙しい市場で大きな取引を得るように、良い機会を利用することを示唆するかもしれません。

この活気ある市場シーンにおいて、TickTraderは常に次のチャンスに備え、刻々と訪れるティックに合わせて決断を下しています。同様に、OnTick関数はリアルタイムで動作し、各ティックに調整し、ダイナミックな市場での取引行動を導きます。

例:
// Declare a variable to store the last tick's close price
double lastClose;

//+------------------------------------------------------------------+
//| Expert initialization function                                     |
//+------------------------------------------------------------------+
// OnInit function
int OnInit()
  {

// Initialize the variable with the current close price
   lastClose = iClose(_Symbol, PERIOD_CURRENT, 0);

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {

// Get the current close price
   double currentClose = iClose(_Symbol, PERIOD_CURRENT, 0);

// Check if the close price has changed
   if(currentClose != lastClose)
     {
      // Print a message when the close price changes
      Print("Close price changed! New close price: ", currentClose);

      // Update the last close price
      lastClose = currentClose;
     }


  }

説明

変数宣言

// Declare a variable to store the last tick's close price
double lastClose;

double型の変数lastCloseを宣言し、最後のティックの終値を格納します。

初期化(OnInit関数)

nt OnInit()
  {

// Initialize the variable with the current close price
   lastClose = iClose(_Symbol, PERIOD_CURRENT, 0);

   return(INIT_SUCCEEDED);
  }

OnInit関数では、iClose関数を使用して、直近のローソク足の終値でlastCloseを初期化します。パラメータ_Symbol、PERIOD_CURRENT、0は、それぞれ現在の銘柄、現在の時間枠、直近のローソク足を示します。

OnTick関数

void OnTick()
  {

// Get the current close price 
   double currentClose = iClose(_Symbol, PERIOD_CURRENT, 0);

// Check if the close price has changed
   if(currentClose != lastClose)
     {
      // Print a message when the close price changes
      Print("Close price changed! New close price: ", currentClose);

      // Update the last close price
      lastClose = currentClose;
     }


  }

  • OnTick関数では、iCloseを使用して現在の終値を取得し、currentClose変数に格納します。
  • 次に、現在の終値が最後に記録された終値と異なるかどうかを確認します(currentClose!=lastClose)。
  • 変更があれば、変更を示すメッセージを表示し、lastClose変数を更新します。

このコードは基本的に、各ティックで終値が変化するたびに、それを監視してメッセージを表示します。OnTick関数を使用して、市場の動きにリアルタイムで対応する方法を紹介しています。


結論

この記事では、MQL5の基本的な側面を掘り下げ、配列、カスタム関数、プリプロセッサ、イベント処理の概念を探りました。学びの旅を受け入れ、疑問が生じたらお気軽にご質問ください。これらの基本的な要素を理解することで、強力な取引ボットの作成に関する今後のディスカッションへの道が開けます。 知識は好奇心とともに成長し、質問はより深い理解の種となることを忘れないでください。次回は、一緒に取引ボットを作るエキサイティングな旅に出ましょう。お楽しみに。とりあえず、これらの核となる概念に時間をかけて慣れ親しんでください。コーディングに幸あれ。そして、知識の探求と同様に、取引の試みが繁栄しますように。

MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/14099

MQL5入門(第4部):構造体、クラス、時間関数をマスターする MQL5入門(第4部):構造体、クラス、時間関数をマスターする
最新記事でMQL5プログラミングの秘密を解き明かしましょう。構造体、クラス、時間関数の本質に迫り、コーディングの旅に力を与えます。初心者から経験豊富な開発者まで、個のガイドは、MQL5をマスターするための貴重な洞察を提供し、複雑な概念を簡素化します。プログラミングのスキルを高め、アルゴリズム取引の世界で一歩先を行きましょう。
MQL5入門(第2部):定義済み変数、共通関数、制御フロー文の操作 MQL5入門(第2部):定義済み変数、共通関数、制御フロー文の操作
連載第2部の光り輝く旅に出かけましょう。これらの記事は単なるチュートリアルではなく、プログラミング初心者と魔法使いが共に集う魔法の世界への入り口です。この旅を本当に魔法のようなものにしているのは何でしょうか。連載第2部は、複雑な概念を誰にでも理解できるようにした、さわやかなシンプルさが際立っています。読者の質問にお答えしながら、双方向的に私たちと関わることで、充実した個別学習体験をお約束します。MQL5を理解することが誰にとっても冒険となるようなコミュニティを作りましょう。魔法の世界へようこそ。
データサイエンスと機械学習(第19回):AdaBoostでAIモデルをパワーアップ データサイエンスと機械学習(第19回):AdaBoostでAIモデルをパワーアップ
AdaBoostは、AIモデルのパフォーマンスを向上させるために設計された強力なブースティングアルゴリズムです。AdaBoostはAdaptive Boostingの略で、弱い学習機をシームレスに統合し、その集合的な予測力を強化する洗練されたアンサンブル学習技法です。
母集団最適化アルゴリズム:スマート頭足類(SC、Smart Cephalopod)を使用した変化する形状、確率分布の変化とテスト 母集団最適化アルゴリズム:スマート頭足類(SC、Smart Cephalopod)を使用した変化する形状、確率分布の変化とテスト
この記事では、確率分布の形状を変えることが最適化アルゴリズムの性能に与える影響について検証します。最適化問題の文脈における様々な確率分布の効率を評価するために、スマート頭足類(SC、Smart Cephalopod)テストアルゴリズムを用いた実験をおこないます。