English Deutsch
preview
MQL5入門(第6部):MQL5における配列関数の入門ガイド

MQL5入門(第6部):MQL5における配列関数の入門ガイド

MetaTrader 5トレーディング | 23 5月 2024, 10:49
242 0
Israel Pelumi Abioye
Israel Pelumi Abioye

はじめに

MQL5の旅の第6部へようこそ。MQL5プログラミングの詳細を検討しながら、自動取引のダイナミックな世界をうまくナビゲートするために必要な知識とスキルを身につけるための、魅力的な連載の続きが待っています。 この章では、配列関数のトピックをさらに掘り下げていきます。前回(第5回)は、配列関数をいくつか紹介して基礎を固めました。

第6回では残りの配列関数について解説し、これらの便利なツールを完全に理解できるようにします。ここでの目的は、開発者としての経験レベルやアルゴリズム取引への精通度に関係なく、取引戦略を自動化するために必要な基本的な考え方をカバーすることです。これらの関数のニュアンスを掘り下げる目標は、読者がMQL5プログラミングの刻々と変化する地形を適切に乗り越えられるように、包括的な理解を促進することです。

この記事では、以下の配列関数を取り上げます。

  • ArrayPrint
  • ArrayInsert
  • ArraySize
  • ArrayRange
  • ArrarRemove
  • ArraySwap
  • ArrayReverse
  • ArraySort

1.ArrayPrint

MQL5では、定義済みの関数ArrayPrint()を使用して配列の要素を表示できます。この関数は、アルゴリズムやスクリプトの実行中に配列に保持されている値を表示するための迅速かつ実用的な方法を提供するため、デバッグに頻繁に使用されます。トレーダーや開発者がコードの様々なポイントでデータを追跡し、検証するのを助けるために、配列の要素がコンソールや操作ログに出力されます。

たとえ

本を収納する専用の本棚があるとします。どの本がどの棚にあるか忘れてしまうこともあるでしょう。ArrayPrint()を、本棚にあるすべての本を物理的に一冊一冊訪問することなく本の題名を表示するために使用する呪文として考えてみましょう。自分がどんな本を持っているか知りたいときはいつでも、「ArrayPrint()」と言えば、あなたのユニークな本棚にあるすべての本の題名の整然としたリストを見ることができます。本棚を素早くスキャンして、お気に入りの題名がすべてそこにあることを確認するのと似ています。

ArrayPrint()は、インテリジェントな本棚に題名を表示したり、特別に整理したいときに使用する魔法のコマンドだと考えてください。ただし、このツールは標準の出力に限定されません。このコマンドを使えば、著者や出版日など、それぞれの本にたいして必要な情報の量を指定したり、題名だけを表示したりすることができます。題名を表示する順番もカスタマイズできます。ArrayPrint()はもっと多くのことができますが、それについては後で説明します。本の題名を表示するだけにとどまりません。魔法を楽しみにお待ちください。

構文
ArrayPrint(array[], digit , Separator, Start, Count, Flags);

パラメータ

  • array[]:出力される配列です。異なるデータ型の配列でも、単純な構造体の配列でも構いません。
  • Digits:配列の各数値に対して表示する小数点以下の桁数を設定します。
  • Separator:出力時に配列の各要素の間に空けるスペースを指定します。
  • Start:出力を開始する要素のインデックスを指定します。
  • Count:出力する要素数を指定します。
  • Flags:出力を変更するために使用されます。デフォルトで有効になっているので、オプションです。ARRAYPRINT_HEADER:構造体配列のヘッダーを表示する、ARRAYPRINT_INDEX:左側のインデックスを表示する、ARRAYPRINT_LIMIT:配列の最初の100個と最後の100個の要素だけを表示する、ARRAYPRINT_ALIGN:出力値の整列を有効にする、ARRAYPRINT_DATE:日、月、年の日付を出力するの各フラグがあります。

void OnStart()
  {

// Define an array of doubles
   double ThisArray[] = { 1.46647, 2.76628, 3.83367, 4.36636, 5.9393};

// Print the entire array using ArrayPrint with 2 decimal places and a single spacing between array elements
   ArrayPrint(Array,2," ",0,WHOLE_ARRAY);

  }

説明

このコードスニペットでは、指定された名前のdouble値の配列を使用します。配列は5つの要素で定義され、それぞれが10進数を含みます。続く行では、ArrayPrint()関数を使って配列の内容全体を表示します。

ArrayPrint()関数で使われるパラメータを分解してみましょう。

  • ThisArray:出力する配列
  • 2:配列の各要素を表示する小数点以下の桁数
  • " ":配列要素間の区切り文字として空白を1つ設定
  • 0:配列の先頭から出力を開始するように指定
  • WHOLE_ARRAY:配列全体を出力するように指定
出力

図1:MetaTrader5でのコード出力

これは、double値のArrayPrint()関数の動作を端的に示しています。では、構造体を使用する例をもう少し詳しく見てみましょう。ArrayPrint()を使って構造体データを整理し、表示する可能性を探っていくうちに、もう少し複雑になります。

void OnStart()
  {

// Define a structure for storing information about students
   struct StudentsDetails
     {
      string         name;
      int            age;
      string         address;
      datetime       time; // Add a time field
     };

// Create an array of Students structures
   StudentsDetails Students[3];

// Fill in details for each person
   Students[0].name = "Abioye";
   Students[0].age = 25;
   Students[0].address = "123 MQL5 St";
   Students[0].time = TimeCurrent();

   Students[1].name = "Israel";
   Students[1].age = 26;
   Students[1].address = "456 MQL4 St";
   Students[1].time = TimeCurrent();

   Students[2].name = "Pelumi";
   Students[2].age = 27;
   Students[2].address = "789 MetaQuotes St";
   Students[2].time = TimeCurrent();

// Print the details of each person using ArrayPrint
   ArrayPrint(Students, 0, " | ", 0, WHOLE_ARRAY);

  }

説明

struct StudentsDetails
{
   string         name;
   int            age;
   string         address;
   datetime       time; // Add a time field
};

  • 生徒のデータを保存するために、StudentsDetailsという構造体が定義されます。
  • 名前、年齢、住所、現在の日時がすべて構造体のメンバーとして追加されます。
StudentsDetails Students[3];

  • StudentsDetails型のStudentsという名前の配列がサイズ3で作成され、3人の生徒を保存できます。

Students[0].name = "Abioye";
Students[0].age = 25;
Students[0].address = "123 MQL5 St";
Students[0].time = TimeCurrent();

Students[1].name = "Israel";
Students[1].age = 26;
Students[1].address = "456 MQL4 St";
Students[1].time = TimeCurrent();

Students[2].name = "Pelumi";
Students[2].age = 27;
Students[2].address = "789 MetaQuotes St";
Students[2].time = TimeCurrent();

  • 各生徒の詳細が記入されます。例えば、名前、年齢、住所、時間フィールドには値が割り当てられます。Students[0]は最初の生徒を表します。
ArrayPrint(Students, 0, " | ", 0, WHOLE_ARRAY);
  • 配列内のすべての生徒情報を表示するには、ArrayPrint()関数を使用します。フィールドの区切り文字を「|」に設定して、配列が出力されます。
出力

図2:MetaTrader5でのコード出力

各生徒に必要な詳細情報を入力した後、ArrayPrint()関数を利用して生徒情報を表示します。上の画像はデフォルトの出力で、余分な書式フラグなしで詳細が表示される様子を示しています。指定された区切り文字「|」を使って、各生徒の名前、年齢、住所、現在の日時がきれいに表示されます。これは最初の表現です。出力をさらにカスタマイズするために、書式オプションを追加する方法を見ていくことにしましょう。  

ArrayPrint()関数に特定の書式フラグを追加するとその書式フラグが適用されて他の書式フラグは無視されるということを知っておくことは非常に重要です。ARRAYPRINT_HEADERフラグが結果にどのような影響を与えるかを説明するために、このフラグを例に含めることにします。

ArrayPrint(Students, 0, " | ", 0, WHOLE_ARRAY,ARRAYPRINT_HEADER);

出力

図3:MetaTrader5でのコード出力


各フィールドを識別しやすくするために、このフラグは、構造体配列にヘッダー([name] [age] [address] [time])を含めるように関数に指示します。ARRAYPRINT_INDEXは、それぞれのフラグが単独でどのように機能するかを強調するため、今回は意図的に他のフラグを省いています。

比較画像ではARRAYPRINT_HEADERフラグを導入したため、2番目の出力が1番目の出力と異なることがわかります。このフラグは、ArrayPrint関数に各フィールドのヘッダーを含めるように指示し、表示される情報に明確なラベルを提供します。注目すべきは、2番目の出力にはインデックス情報がないことです。これは、各書式フラグが独立して動作し、特定のフラグを含めるとそれに応じて出力が変更されるという点を強調しています。 好みに合わせて出力を調整できる多様性を示すため、さまざまなフラグの組み合わせも試してみましょう。

時間データを扱う場合、ArrayPrint関数がさらに多様性を提供することに注意することが重要です。ARRAYPRINT_MINUTESやARRAYPRINT_SECONDSなどのフラグを使用して、時間の書式を調整することができます。これらのフラグにより、表示される時間情報の詳細度を調整することができ、好みに応じてカスタマイズされた表示が可能になります。 ARRAYPRINT_MINUTESフラグを選択すると、日付と秒が省略されて、現在の時間と分だけが出力されます。一方、ARRAYPRINT_SECONDSフラグを使用すると、出力はさらに絞り込まれ、時、分、秒のみが表示されます。これらのフラグにより、時間表現をきめ細かく制御することができ、不必要な詳細を含むことなく、出力が要件に正確に一致するようになります。

ArrayPrint(Students, 0, " | ", 0, WHOLE_ARRAY,ARRAYPRINT_MINUTES);

出力

図4:MetaTrader5でのコード出力

これらのフラグは相互に排他的なものではありません。複数のフラグを組み合わせて、さらに精密に出力を調整することができます。例えば、ARRAYPRINT_HEADERフラグとARRAYPRINT_MINUTESフラグの両方を一緒に適用すると、列のヘッダーを含み、現在の時間と分だけを表示する形式で時刻が表示されます。

ArrayPrint(Students,0," | ",0,WHOLE_ARRAY,ARRAYPRINT_HEADER | ARRAYPRINT_MINUTES);

出力

図5:MetaTrader5でのコード出力

これは、カスタマイズされた有益なアウトプットを提供するために、フラグがいかにシームレスに連携しているかを示しています。


2.ArrayInsert

ある配列から別の配列に要素を挿入する便利な方法は、ArrayInsert()関数を使用することです。ソース配列の要素を指定の位置に配置することで、ターゲット配列のサイズを大きくすることができます。パズルの全体的なデザインを崩すことなく、既存のパズルに新しいピースを組み込むようなものです。

ArrayInsertとArrayCopyの違い

ArrayInsert()とArrayCopy()の主な違いは、すでに存在する要素をどのように扱うかです。ArrayCopy()は、指定された位置の要素を別の配列の要素に置き換えることで、元の配列を変更することができます。一方、ArrayInsert()は、現在の要素を移動して新しい要素を入れるスペースを作ることで、配列の構造と順序を保持します。基本的に、ArrayInsert()は、MQL5で配列を操作するための汎用的なメソッドを提供します。これは、他の部分を移動させずにシーケンスに新しい要素を追加するのと似ています。この違いを理解することで、プログラミングで配列操作を正確におこなうことができます。

静的配列の場合、挿入される要素数が配列サイズ以上である場合、ArrayInsert()は挿入元配列から挿入先配列に要素を追加しないことに注意してください。このような状況では、挿入は、挿入先配列のインデックス0から始まる場合にのみおこなわれます。このような場合、挿入先配列は事実上、挿入元配列に完全に置き換えられます。

たとえ

2セットの積み木(配列)があり、それぞれで何かが作られているとしましょう。既存の構造を壊さずに、これらのセットを組み合わせたいとしましょう。ArrayInsert()は魔法のツールのようなもので、一方のセットからもう一方のセットの特定の場所に新しい積み木をスムーズに挿入し、コレクション全体を拡張することができます。

次に、ArrayInsert()とArrayCopy()を比較してみましょう。ArrayCopy()を使用するのは、いくつかの積み木を別のセットの新しい積み木に置き換えることで、元のセットを並べ替えるようなものです。反面、ArrayInsert()はよりデリケートです。積み木を移動して新しく入ってきた積み木のためのスペースを確保することで、既存の秩序が損なわれないようにするのです。まるで、それぞれの積み木をどこに置けばセットの元のデザインが保たれるかを正確に把握している几帳面なアシスタントがいるようなものです。

静的セット(配列)には重要なルールがあります。新しい積み木の数がセットで処理できないほど多い場合、ArrayInsert()はそれらを強制的に挿入しません。しかし、挿入処理をセットの先頭(インデックス0)から始めると、セット全体を新しいブロックに効果的に置き換えることができます。これらの概念を理解することで、MQL5プログラミングの世界でマスタービルダーになることができます。

構文

ArrayInsert(DestinationArray[],SourceArray[],DestinationIndexStart,SourceIndexStart,count);

パラメータ

  • DestinationArray[]:ソース配列から受け取った要素を挿入する配列
  • SourceArray[]:挿入先配列に挿入される配列
  • DestinationIndexStart:挿入先配列で挿入を開始するインデックス
  • SourceIndexStart:挿入する要素のコピーに使用する、コピー元配列内のインデックス
  • Count:ソース配列から挿入先配列に挿入されるべき要素数
void OnStart()
  {

// Declare two dynamic arrays
   int SourceArray[];
   int DestinationArray[];

// Resizing the dynamic arrays to have 5 elements each
   ArrayResize(SourceArray, 5);
   ArrayResize(DestinationArray, 5);

// Assigning values to dynamic array elements
   SourceArray[0] = 1;
   SourceArray[1] = 3;
   SourceArray[2] = 5;
   SourceArray[3] = 7;
   SourceArray[4] = 9;

// Assigning different values to DestinationArray
   DestinationArray[0] = 15;
   DestinationArray[1] = 20;
   DestinationArray[2] = 25;
   DestinationArray[3] = 30;
   DestinationArray[4] = 35;

// Print the elements of SourceArray before ArrayInsert/ArrayCopy
   Print("Elements of SourceArray before ArrayInsert/ArrayCopy: ");
   ArrayPrint(SourceArray, 2, " ", 0, WHOLE_ARRAY);

// Print the elements of DestinationArray before ArrayInsert/ArrayCopy
   Print("Elements of DestinationArray before ArrayInsert/ArrayCopy: ");
   ArrayPrint(DestinationArray, 2, " ", 0, WHOLE_ARRAY);

// Using ArrayInsert to insert SourceArray into DestinationArray at index 2
   ArrayInsert(DestinationArray, SourceArray, 2, 0, WHOLE_ARRAY);

// Print the modified DestinationArray after ArrayInsert
   Print("Elements of DestinationArray after using ArrayInsert: ");
   ArrayPrint(DestinationArray, 2, " ", 0, WHOLE_ARRAY);

// Reset DestinationArray to demonstrate ArrayCopy
   ArrayFree(DestinationArray);
   ArrayResize(DestinationArray, 5);

   DestinationArray[0] = 15;
   DestinationArray[1] = 20;
   DestinationArray[2] = 25;
   DestinationArray[3] = 30;
   DestinationArray[4] = 35;

// Using ArrayCopy to copy elements from SourceArray to DestinationArray
   ArrayCopy(DestinationArray, SourceArray, 2, 0, WHOLE_ARRAY);

// Print the modified DestinationArray after ArrayCopy
   Print("Elements of DestinationArray after using ArrayCopy: ");
   ArrayPrint(DestinationArray, 2, " ", 0, WHOLE_ARRAY);

  }
説明

int SourceArray[];
int DestinationArray[];

  • SourceArrayとDestinationArrayの2つの動的配列が宣言されます。これらの配列には整数の値が保持されます。

ArrayResize(SourceArray, 5);
ArrayResize(DestinationArray, 5);

  • 動的配列は、それぞれ5つの要素を含むようにサイズ変更されます。そのためにArrayResize()関数が使われます。

SourceArray[0] = 1;
SourceArray[1] = 3;
SourceArray[2] = 5;
SourceArray[3] = 7;
SourceArray[4] = 9;

  • SourceArray要素に値が与えられます。
DestinationArray[0] = 15;
DestinationArray[1] = 20;
DestinationArray[2] = 25;
DestinationArray[3] = 30;
DestinationArray[4] = 35;
  • DestinationArray要素に値が与えられます。
Print("Elements of SourceArray before ArrayInsert/ArrayCopy: ");
ArrayPrint(SourceArray, 2, " ", 0, WHOLE_ARRAY);
  • ArrayPrint()関数を使用して、コンソールにメッセージを表示した後、SourceArrayの要素を表示します。スペースが区切り文字として使われ、小数点以下2桁が表示されます。
Print("Elements of DestinationArray before ArrayInsert/ArrayCopy: ");
ArrayPrint(DestinationArray, 2, " ", 0, WHOLE_ARRAY);
  • 前の行と同様に、メッセージを表示し、次にDestinationArrayの要素を表示します。
ArrayInsert(DestinationArray, SourceArray, 2, 0, WHOLE_ARRAY);
  • ArrayInsert()関数を使用して、インデックス2から始まってSourceArrayの要素をDestinationArrayに挿入します。
Print("Elements of DestinationArray after using ArrayInsert: ");
ArrayPrint(DestinationArray, 2, " ", 0, WHOLE_ARRAY);
  • ArrayInsert()操作の後、メッセージに続いてDestinationArrayの変更された要素を表示します。
ArrayFree(DestinationArray);
ArrayResize(DestinationArray, 5);
  • メモリを解放した後、5つの要素を含むようにDestinationArrayのサイズを変更します。
DestinationArray[0] = 15;
DestinationArray[1] = 20;
DestinationArray[2] = 25;
DestinationArray[3] = 30;
DestinationArray[4] = 35;
  • DestinationArray要素には再び値が与えられます。
ArrayCopy(DestinationArray, SourceArray, 2, 0, WHOLE_ARRAY);
  • ArrayCopy関数を使って、インデックス2から始まりSourceArrayからDestinationArrayに要素をコピーします。
Print("Elements of DestinationArray after using ArrayCopy: ");
ArrayPrint(DestinationArray, 2, " ", 0, WHOLE_ARRAY);
  • ArrayCopy()操作の後に、メッセージとDestinationArrayの変更された要素を表示します。

出力

図6:MetaTrader5でのコード出力

このコードサンプルの目的は、MQL5の ArrayInsert()関数とArrayCopy()関数の違いを示すことです。配列要素を操作することは両関数の共通の用途ですが、両者の機能は異なります。この例では2つの動的配列SourceArrayとDestinationArrayが使用されています。操作を実行する前に、スクリプトはこれらの配列に含まれる要素を表示します。そして、SourceArrayからDestinationArray()内の指定された位置に要素を挿入するために、ArrayInsertが利用されます。その後、配列はリセットされ、ArrayCopy()を使用してSourceArrayの要素がDestinationArray()にコピーされます。行動が最も乖離しているのは、次の部分です。挿入先配列の特定の位置に要素を挿入する場合、ArrayInsert()は既存の要素を移動して新しい要素のためのスペースを確保します。希望するインデックスに要素を配置するのに便利です。ArrayCopy()では、コピー元配列の要素がコピー先配列の既存の要素に置き換えられます。すでに設定されている値に影響を与えることなく、配列間の要素のコピーが効率的におこなわれます。


3.配列サイズ

MQL5のArraySize()関数は、1次元配列に含まれる要素の数を確認するためのものです。指定された配列内の要素の総数を表す整数を返すことで、配列のサイズを決定する処理が簡単になります。

たとえ

本棚にさまざまな本があり、それぞれが配列の要素を表現しているとします。司書のように、ArraySize()関数は、この本棚にある本の正確な数を教えてくれます。同様に、ArraySize()を使用することで、より効果的にデータを管理配置することができます。ArraySize()を配列に適用すると、その配列に含まれる要素の総数がわかります。プログラマーは、配列のサイズを把握し、コーディングに必要な「本」の数を確認するための便利なツールとしてこれを使用することができます。

構文
ArraySize( array[]);

パラメータ

  • array[]:サイズを求める配列

void OnStart()
  {

// Declare an array
   int array[5];

// Get the size of the array using ArraySize
   int arraySize = ArraySize(array);

// Print the array size
   Print("The size of array is: ", arraySize); // Output will be 5

  }

説明

int array[5]

  • arrayという名前と5というサイズを持つ整数配列が宣言されます。

int arraySize = ArraySize(array);

  • arraySizeという新しい整数変数を作成し、その値を代入演算子「=」を使って ArraySize(配列)の結果に設定します。配列のサイズは常に整数なので、int型が利用されます。MQL5が提供する配列のサイズを決定する関数は ArraySize(AとSは大文字)と呼ばれ、その結果を格納するために宣言した変数はarraySize(全部小文字)と呼ばれます。プログラミング言語の大文字と小文字の区別には注意が必要です。大文字を含むArraySizeは組み込みの配列を表し、小文字のarraySizeは特定の変数を表します。

Print("The size of array is: ", arraySize);

  • Print関数を使ってコンソールにメッセージを表示します。arraySize変数に由来する配列のサイズを示します。

MQL5プログラミングの素晴らしい世界をより深く探求するために、時間をかけて、私たちが出会うすべての関数の複雑さを学ばなければなりません。ArraySize、ArrayInsert、ArrayPrintといった関数を理解するのは、職人の工房で道具の使い方を学ぶのと似ています。時間をかけて微妙な違いを学び、理解しましょう。後の記事で取り上げるより複雑なアイデアは、これらの関数を基礎としています。


4.配列範囲

MQL5プログラミングのArrayRange()関数は、多次元配列の指定された次元の要素数を把握するために不可欠です。これは複雑な配列を扱う開発者にとって便利なツールであり、多次元配列の指定した階層や次元にいくつの要素があるかを正確に知ることができます。すべての次元にまたがる全体的な要素の数を把握する複雑さを扱うことなく、この関数は特定の次元に集中することで、詳細な洞察を提供します。

ArrayRangeとArraySizeの違い

ここで、ArraySize()とArrayRange()の違いをみてみましょう。どちらも配列の次元に関する洞察を提供しますが、関数のそれぞれのスコープは異なります。一次元配列の全要素数はArraySize()で求めることができます。 

一次元配列と多次元配列は、データの並べ方や構造の点で互いに異なります。要素が1行に並んだ単純なリストは、1次元配列に似ています。要素は、この線形構造のどこにあるかを参照することでアクセスできます。

とはいえ、多次元配列は構造のレベルを増やします。構成要素が行と列に配置され、行列や表に似ています。多次元配列内の要素にアクセスするには行インデックスと列インデックスを指定する必要があり、より構造化されたデータの編成と取得の方法が提供されます。一次元配列は基本的に単純な線形配列であるのに対し、多次元配列は要素を格子状に並べることで複雑さを増しています。

たとえ

多次元配列を表す広大な本棚があり、それぞれの棚が異なる次元を持っているとしましょう。MQL5のArrayRange()関数は魔法の虫眼鏡のようなもので、特定の棚に焦点を当て、その棚にある本(要素)の正確な数を明らかにすることができます。このツールは、複雑なライブラリの情報を扱うときに非常に便利です。

ArraySize()とArrayRange()を対比してみましょう。本が一次元配列のように直線的に整理されている場合、ArraySize()は本棚全体の本の総数を表します。あるいは、ArrayRange()を使って本棚の特定の部分を拡大し、そこにある本の数を正確に数えるることもできます。

構文

ArrayRange(array[], dimensionIndex);

パラメータ

  • array[]:検証する範囲を持つ配列
  • dimensionIndex :範囲を確認する必要がある、0 から始まる次元インデックス

void OnStart()
  {

// Declare a three-dimensional array
   double my3DArray[][2][4];

// Get the range of the first dimension (index 0)
   int dimension1Index = ArrayRange(my3DArray, 0);

// Get the range of the second dimension (index 1)
   int dimension2Index = ArrayRange(my3DArray, 1);

// Get the range of the third dimension (index 2)
   int dimension3Index = ArrayRange(my3DArray, 2);

   Print("Number of elements in dimension 1: ", dimension1Index);
   Print("Number of elements in dimension 2: ", dimension2Index);
   Print("Number of elements in dimension 3: ", dimension3Index);

  }

説明

double my3DArray[][2][4];
  • my3DArrayという3次元配列が宣言されます。

int dimension1Index = ArrayRange(my3DArray, 0);
  • この場合、my3DArrayの1次元目(インデックス0)の範囲(要素数)は、ArrayRange()関数を使用して確認されます。変数dimension1Indexには結果が格納されます。
int dimension2Index = ArrayRange(my3DArray, 1);
  • 同様に、my3DArrayの2番目の次元(インデックス1)の範囲を取得し、変数dimension2Indexに格納します。

int dimension3Index = ArrayRange(my3DArray, 2);

  • この行は、変数dimension3Indexの値をmy3DArrayの3次元目の範囲(インデックス2)に代入します。

Print("Number of elements in dimension 1: ", dimension1Index);
Print("Number of elements in dimension 2: ", dimension2Index);
Print("Number of elements in dimension 3: ", dimension3Index);

  • 最後に、Print関数を使って結果と各次元の要素数を示します。出力された情報には、3次元配列のサイズの1次元、2次元、3次元が含まれています。
出力

図7:MetaTrader5でのコード出力



5.ArrayRemove

ArrayRemove()関数は、プログラマーが配列から特定の要素を削除するための効果的なツールです。配列のサイズと構造は、削除に合わせて自動的に調整され、シームレスな削除プロセスが保証されます。配列を操作する際に開始インデックスと削除したい要素の数を指定できるため、柔軟性があります。プログラムの状況の変化に応じて動的に変更しなければならない配列を扱う場合、この関数は特に役に立ちます。

ただし、ArrayRemove()に関しては、静的配列か動的配列かによって動作が異なります。動的配列の場合,この関数は,指定された要素を効果的に削除し,配列のサイズをスムーズに調整することで,効率的な削除処理を保証します.一方、ArrayRemove()は、静的配列を扱う場合、指定された要素を削除し、元の配列サイズを維持しますが、静的配列の固定的な性質を克服するために、この関数は配列の末尾の後に来る要素を複製して空いたスペースを埋めます。このメソッドによって、サイズを固定したまま要素を削除できるようになり、ArrayRemove()はさまざまな配列シナリオをより微妙に理解できるようになりました。このセクションを進めるにつれ、より多くの例と洞察が、ArrayRemove()と、それがさまざまな配列のシナリオでどのように機能するのかを、より深く理解するのに役立つでしょう。

たとえ

配列を本棚に見立て、個々の本が情報の断片を表していると考えてみましょう。さて、MQL5ではArrayRemove()という本棚整理のようなユニークなツールが用意されています。この整理ツールを使えば、本棚から特定の本を取り除き、隙間を埋めるように残りの本をきれいに並べることができます。

本の追加や削除が簡単にできるダイナミックな本棚を想像してみてください。この場合、整理ツールは本を取り出した後、問題なくスムーズに棚を調整します。しかし、本棚が固定サイズのディスプレイに似てサイズを変更できない場合(静的配列)のように、静的配列を扱う場合、ArrayRemove()は本棚のサイズを変更できないので、配列の最後にある本を巧みに複製して空のスロットを埋めます。本棚の最後の本のコピーを作り、取り除かれた本の隙間に置くようなものです。こうすることで、固定サイズの本棚は完全性を保ち、スペースを無駄にしません。

そのため、本棚の真ん中から本を取り出した場合、ArrayRemove()によって、本棚の端が確実にコピーされて隙間を埋め、配列の構造が維持されます。これは、維持するスロット(要素)の数が決まっている場合に特に便利で、サイズを変えずに本棚を整理する方法を提供します。

 

構文
ArrayRemove(array[],start_index,count);
パラメータ

  • array[]:要素を削除する配列です。収納スペース、つまり本棚は、変更を加えたい場所です。
  • start_index:配列内の除去の開始点を示します。例えば、3番目の棚から始まる本を排除するには、インデックスを3に設定します。
  • count:配列から取り除かれる要素の数。3冊の本を削除したい場合は、カウントを3に設定します。
void OnStart()
  {

// Declare fixed-size array
   int fixedSizeArray[5] = {11, 13, 17, 21, 42};

// Declare dynamic array
   int dynamicArray[];
   ArrayResize(dynamicArray, 5);
   dynamicArray[0] = 11;
   dynamicArray[1] = 13;
   dynamicArray[2] = 17;
   dynamicArray[3] = 21;
   dynamicArray[4] = 42;

// Print initial arrays
   Print("Initial fixedSizeArray: ");
   ArrayPrint(fixedSizeArray, 0, " ", 0, WHOLE_ARRAY);

   Print("Initial dynamicArray: ");
   ArrayPrint(dynamicArray, 0, " ", 0, WHOLE_ARRAY);

// Remove two elements at index 2 from both arrays
   ArrayRemove(fixedSizeArray, 2, 2);
   ArrayRemove(dynamicArray, 2, 2);

// Print arrays after removal
   Print("After removing 3 elements at index 2 - fixedSizeArray: ");
   ArrayPrint(fixedSizeArray, 0, " ", 0, WHOLE_ARRAY);

   Print("After removing 3 elements at index 2 - dynamicArray: ");
   ArrayPrint(dynamicArray, 0, " ", 0, WHOLE_ARRAY);

  }
説明

// Declare fixed-size array
   int fixedSizeArray[5] = {11, 13, 17, 21, 42};

// Declare dynamic array
   int dynamicArray[];
   ArrayResize(dynamicArray, 5);
   dynamicArray[0] = 11;
   dynamicArray[1] = 13;
   dynamicArray[2] = 17;
   dynamicArray[3] = 21;
   dynamicArray[4] = 42;

  • 固定サイズ5の整数静的配列をfixedSizeArrayと呼ぶことを宣言します。配列の初期化には値11、13、17、21、42を使用します。
  • 初期サイズを指定せずに、dynamicArrayという名前の整数動的配列を宣言します。ArrayResize()を使用して、dynamicArrayを5にリサイズします。

Print("Initial fixedSizeArray: ");
ArrayPrint(fixedSizeArray, 0, " ", 0, WHOLE_ARRAY);

Print("Initial dynamicArray: ");
ArrayPrint(dynamicArray, 0, " ", 0, WHOLE_ARRAY);

  • ArrayPrint()を使用して、fixedSizeArrayとdynamicArrayの初期要素を表示します。
ArrayRemove(fixedSizeArray, 2, 2);
ArrayRemove(dynamicArray, 2, 2);
  • ArrayRemove()を使用して、インデックス2から始まってfixedSizeArrayとdynamicArrayから2つの要素を削除します。
Print("After removing 3 elements at index 2 - fixedSizeArray: ");
ArrayPrint(fixedSizeArray, 0, " ", 0, WHOLE_ARRAY);

Print("After removing 3 elements at index 2 - dynamicArray: ");
ArrayPrint(dynamicArray, 0, " ", 0, WHOLE_ARRAY);
  • 除去処理後、ArrayPrint()を使用して、fixedSizeArrayとdynamicArrayの要素を出力します。
出力

 

図8:MetaTrader5でのコード出力

指定されたコードの出力は上の画像に示されており、ArrayRemove()関数が静的配列と動的配列の両方でどのように動作するかを示しています。動的配列に関しては、その手順は非常に単純で、指定されたインデックスで指定された要素を削除するだけです。静的配列では、削除によってできた空白を埋めるために、配列の末尾以降に現れる要素が複製されます。この微妙な動作は、ArrayRemove()がさまざまな配列タイプに適応する方法を示しています。

ArrayRemove()の概念は、これらの記事を読み、実際の例題に入っていくにつれて、より明確になっていくでしょう。ためらわずにもっと質問してください。一緒に、これらの概念を探求し、理解していきましょう。


6.ArraySwap

MQL5プログラミングにおけるArraySwap()関数の目的は、2つの動的配列の内容全体を入れ替えることです。この関数を使えば、2つの配列間のすべての要素をより簡単に交換することができます。これは、データセット全体を配列間で切り替える簡単な方法を提供し、MQL5で配列の内容を並べ替える処理を迅速化します。

たとえ

本でいっぱいの本棚が2つあるとします。ArraySwap()関数を使えば、魔術師の呪文のように、ある本棚のすべての本を他の本と入れ替えることができます。棚Aと棚Bに本があって、棚Aのすべての本を棚Bに移動させ、棚Bのすべての本を棚Aに移動させるには、ArraySwap()の呪文を使用することができます。特定の本を気にすることなく、2つの棚にあるすべての本を簡単に入れ替えることができます。

構文
ArraySwap(dynamic_array1, dynamic_array2);

パラメータ

本でいっぱいの本棚が2つあるとします。ArraySwap()関数を使えば、魔術師の呪文のように、ある本棚のすべての本を他の本と入れ替えることができます。棚Aと棚Bに本があって、棚Aのすべての本を棚Bに移動させ、棚Bのすべての本を棚Aに移動させるには、ArraySwap()の呪文を使用することができます。特定の本を気にすることなく、2つの棚にあるすべての本を簡単に入れ替えることができます。

void OnStart()
  {

// Declare dynamic arrays
   int dynamic_array1[];
   int dynamic_array2[];

// Resize dynamic arrays to have 5 elements each
   ArrayResize(dynamic_array1, 5);
   ArrayResize(dynamic_array2, 5);

// Assign values to dynamic arrays
   dynamic_array1[0] = 1;
   dynamic_array1[1] = 3;
   dynamic_array1[2] = 5;
   dynamic_array1[3] = 7;
   dynamic_array1[4] = 9;

   dynamic_array2[0] = 11;
   dynamic_array2[1] = 13;
   dynamic_array2[2] = 15;
   dynamic_array2[3] = 17;
   dynamic_array2[4] = 19;

// Print initial dynamic arrays
   Print("Initial dynamic_array1: ");
   ArrayPrint(dynamic_array1, 0, " ", 0, WHOLE_ARRAY);

   Print("Initial dynamic_array2: ");
   ArrayPrint(dynamic_array2, 0, " ", 0, WHOLE_ARRAY);

// Swap the contents of dynamic_array1 and dynamic_array2
   ArraySwap(dynamic_array1, dynamic_array2);

// Print dynamic arrays after swapping
   Print("After swapping - dynamic_array1: ");
   ArrayPrint(dynamic_array1, 0, " ", 0, WHOLE_ARRAY);

   Print("After swapping - dynamic_array2: ");
   ArrayPrint(dynamic_array2, 0, " ", 0, WHOLE_ARRAY);
  }

説明

// Declare dynamic arrays
   int dynamic_array1[];
   int dynamic_array2[];

// Resize dynamic arrays to have 5 elements each
   ArrayResize(dynamic_array1, 5);
   ArrayResize(dynamic_array2, 5);

  • 動的整数配列dynamic_array1とdynamic_array2が宣言されます。 各動的配列のサイズは、ArrayResize関数を使って5に設定されます。

// Assign values to dynamic arrays
   dynamic_array1[0] = 1;
   dynamic_array1[1] = 3;
   dynamic_array1[2] = 5;
   dynamic_array1[3] = 7;
   dynamic_array1[4] = 9;

   dynamic_array2[0] = 11;
   dynamic_array2[1] = 13;
   dynamic_array2[2] = 15;
   dynamic_array2[3] = 17;
   dynamic_array2[4] = 19;

  • dynamic_array1とdynamic_array2の各要素に特定の値を与えます。
// Print initial dynamic arrays
   Print("Initial dynamic_array1: ");
   ArrayPrint(dynamic_array1, 0, " ", 0, WHOLE_ARRAY);

   Print("Initial dynamic_array2: ");
   ArrayPrint(dynamic_array2, 0, " ", 0, WHOLE_ARRAY);
  • dynamic_array1とdynamic_array2の初期値をコンソールに表示します。
// Swap the contents of dynamic_array1 and dynamic_array2
   ArraySwap(dynamic_array1, dynamic_array2);
  • ArraySwap()関数を利用して、dynamic_array1の内容をすべてdynamic_array2に置き換えます。
// Print dynamic arrays after swapping
   Print("After swapping - dynamic_array1: ");
   ArrayPrint(dynamic_array1, 0, " ", 0, WHOLE_ARRAY);

   Print("After swapping - dynamic_array2: ");
   ArrayPrint(dynamic_array2, 0, " ", 0, WHOLE_ARRAY);
  • 交換処理の後、コンソールにdynamic_array1と dynamic_array2の更新値を表示します。
出力

図9:MetaTrader5でのコード出力



7.ArrayReverse

ArrayReverse()関数を使用すれば、配列の要素を並べ替えたり順番を入れ替えたりすることができます。この関数を使えば、開発者はシーケンス内の要素を素早く反転させ、最後の要素を最初の要素にしたり、その逆にしたりすることができます。この操作により、さまざまなデータ型を含む配列内の要素の配置を、柔軟かつ効果的に変更することができます。プログラミングで要素の順序を逆にする必要がある場合、ArrayReverse()を使用すると処理が簡単になり、コードがより簡潔で読みやすくなります。

たとえ

本がずらりと並んだ棚を想像してください。まるで、これらの本がArrayReverse()関数で魔法のように並べ替えられ、右端の本が左端になる、またその逆もしかりです。これは、本棚の本の並び順を変更する簡単な方法です。ArrayReverse()を使えば、リストや配列の項目の順番を、最後の項目から順番に反転させることができます。最後から始めて最初まで進みます。まるで、自分の配列に後ろ向きの呪文をかけるようなものです。

構文
ArrayReverse(array[], start, count);

パラメータ 

  • array[]:反転させたい配列
  • start:反転を開始したい配列内のインデックス
  • count:配列の要素を反転させる数


void OnStart()
  {

// Declare and initialize a 10-element array
   int array[10] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};

// Print the original array
   Print("Original Array: ");
   ArrayPrint(array, 0, " ", 0, WHOLE_ARRAY);

// Reverse the array starting from index 4
   ArrayReverse(array, 4, WHOLE_ARRAY);

// Print the array after reversal
   Print("Array after reversal from index 4: ");
   ArrayPrint(array, 0, " ", 0, WHOLE_ARRAY);

  }

このコードでは、配列を指定された要素で初期化し、元の配列を表示し、インデックス4から反転させて、結果を表示します。


出力

図10:MeterTrader5でのコード出力



8.ArraySort

配列の要素を昇順に並び替えるには、ArraySort()関数が便利です。この関数を使用すると、配列の要素を小さい値から順に、大きい値まで素早く並べることができます。この関数は、数値を保持する配列を扱うときに特に便利です。

たとえ

ごちゃ混ぜになった数字のコレクションを、小さいものから大きいものへときれいに並べたいと想像してみましょう。ArraySort()関数を使えば、これらの数字を適切な順番に並べ替えることができます。このように、数字をきれいに並べ替える簡単なコマンドを1つ使用するだけで、リストの中で最も小さい数字と最も大きい数字を簡単に識別することができます。ArraySort()関数の魔法のおかげで、理解しやすく構造化された形で数字を見ることができます。

構文

ArraySort(array[]); // array[]は昇順に並べ替えたい配列

void OnStart()
  {

// Declare an array of numbers
   double array[5] = {9.5, 2.1, 7.8, 1.3, 5.6};

// Print the array before sorting
   Print("Array before sorting: ");
   ArrayPrint(array, 1, " ", 0, WHOLE_ARRAY);

// Use ArraySort to arrange the array in ascending order
   ArraySort(array);

// Print the array after sorting
   Print("Array after sorting: ");
   ArrayPrint(array, 1, " ", 0, WHOLE_ARRAY);

  }
出力

図11:MetaTrader5でのコード出力


結論

ここまで、ArrayPrint、ArrayInsert、ArraySize、ArrayRange、ArrarRemove、ArraySwap、ArrayReverse、ArraySortなど、MQL5における配列管理の重要なアイデアの多くを説明してきました。目的は、この連載を通して、取引戦略の自動化の基礎となる基本的な考え方を幅広くカバーすることです。これらの配列関数を理解することは、特に過去のデータを使ってエキスパートアドバイザー(EA)を作成する際には非常に重要です。経験レベルに関係なく、すべての読者がこれらの基本的な概念を習得し、MQL5プログラミングとアルゴリズム取引への実りある旅への基礎を築くことをお約束します。 

この記事の締めくくりとして、皆さんには忍耐と好奇心を持ってそれぞれのアイデアに取り組むことをお勧めします。これらの基本的な構成要素は今後の記事でも重要になり、信頼性の高い自動取引システムの開発が、やりがいがあり、かつ取り組みやすいものになるからです。私の最優先事項は読者の理解です。この記事のどんな部分についてでもヘルプや説明が必要な場合は、ご遠慮なく声をかけて質問してください。次回は、第5回と第6回で取り上げた配列関数の全側面をカバーする徹底的なビデオセッションに入ります。残された疑問を払拭するために、このビデオでは、これらの重要なMQL5プログラミングのアイデアを理解するためのビジュアルマニュアルを提供します。

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

制約付きCustom Maxを実装するための一般的な最適化定式化(GOF) 制約付きCustom Maxを実装するための一般的な最適化定式化(GOF)
この記事では、MetaTrader 5端末の設定タブでCustom Maxを選択する際に、複数の目的と制約条件を持つ最適化問題を実装する方法を紹介します。最適化問題の例は、ドローダウンが10%未満、連敗回数が5回未満、1週間の取引回数が5回以上となるように、プロフィットファクター、ネットプロフィット、リカバリーファクターを最大化するといったものです。
Pythonを使用したEA用ディープラーニングONNXモデルの季節性フィルタと期間 Pythonを使用したEA用ディープラーニングONNXモデルの季節性フィルタと期間
Pythonでディープラーニングのモデルを作成する際、季節性から恩恵を受けることはできるのでしょうか。ONNXモデルのデータをフィルタすることでより良い結果が得られるのでしょうか。どの期間を使用するべきでしょうか。この記事では、これらすべてを取り上げます。
データサイエンスと機械学習(第21回):ニューラルネットワークと最適化アルゴリズムの解明 データサイエンスと機械学習(第21回):ニューラルネットワークと最適化アルゴリズムの解明
ニューラルネットワーク内部で使用される最適化アルゴリズムを解明しながら、ニューラルネットワークの核心に飛び込みます。この記事では、ニューラルネットワークの可能性を最大限に引き出し、モデルを精度と効率の新たな高みへと押し上げる重要なテクニックご紹介します。
知っておくべきMQL5ウィザードのテクニック(第13回):ExpertSignalクラスのためのDBSCAN 知っておくべきMQL5ウィザードのテクニック(第13回):ExpertSignalクラスのためのDBSCAN
DBSCAN (Density-Based Spatial Clustering of Applications with Noise)は、データをグループ化する教師なし形式であり、入力パラメータをほとんど必要としません。入力パラメータは2つだけであり、K平均法などの他のアプローチと比較すると利点が得られます。ウィザードで組み立てたEAを使用してテストし、最終的に取引するために、これがどのように建設的であり得るかを掘り下げます。