MQL4のArraySort関数を徹底解説|使い方から応用例まで

※記事内に広告を含む場合があります。
目次

1. はじめに

MQL4と配列操作の重要性

MQL4は、MetaTrader 4(MT4)プラットフォームで自動売買プログラム(EA)やカスタムインジケーターを作成するためのプログラミング言語です。金融市場でのデータ分析やトレード戦略の自動化を実現するMQL4では、配列を操作するスキルが非常に重要です。配列は、価格データやインジケーターの値を効率的に管理するための基本的なデータ構造だからです。

その中でも、ArraySort関数は、配列の要素を並び替えるための便利なツールです。この関数を正しく理解し活用することで、トレード戦略やデータ分析を効率化できます。

この記事の目的

この記事では、MQL4のArraySort関数について、基本的な使い方から応用的な活用方法までを詳しく解説します。初心者にも分かりやすく、実践的な例を交えながら進めていきます。

2. ArraySort関数とは?

ArraySort関数の概要

ArraySortは、MQL4で配列を昇順または降順に並び替えるための組み込み関数です。ソート処理は、価格データや時間データの整列、さらにはカスタム条件による並び替えに活用できます。

以下は、この関数のシンタックスです。

int ArraySort(
    void &array[],
    int count=WHOLE_ARRAY,
    int start=0,
    int direction=MODE_ASCEND
);

主なパラメータの説明

  1. array[]:
    ソート対象となる配列を指定します。この配列は1次元である必要があります。
  2. count:
    ソートする要素の数を指定します。デフォルトでは、配列全体(WHOLE_ARRAY)が対象です。
  3. start:
    ソートを開始するインデックスを指定します。デフォルトは0(配列の最初)です。
  4. direction:
    並び替えの方向を指定します。
  • MODE_ASCEND: 昇順(小さい順)
  • MODE_DESCEND: 降順(大きい順)

使用例:基本的なソート

以下は、基本的な昇順ソートの例です。

double prices[] = {1.2345, 1.1234, 1.5678, 1.3456};
ArraySort(prices);

// ソート後: {1.1234, 1.2345, 1.3456, 1.5678}

このコードでは、ArraySort関数を使って価格データを昇順に並び替えています。

3. 基本的な使い方

シンプルな配列のソート

最も基本的な使い方は、単一の配列を昇順または降順に並び替えることです。以下にその例を示します。

昇順ソート

double values[] = {5.5, 2.2, 8.8, 1.1};
ArraySort(values);

// ソート後: {1.1, 2.2, 5.5, 8.8}

降順ソート

double values[] = {5.5, 2.2, 8.8, 1.1};
ArraySort(values, WHOLE_ARRAY, 0, MODE_DESCEND);

// ソート後: {8.8, 5.5, 2.2, 1.1}

ソートの開始位置を指定

以下のコードでは、特定の部分だけを並び替える例を示します。

double data[] = {9.9, 7.7, 3.3, 5.5};
ArraySort(data, 2, 1); // 2つの要素をインデックス1から並び替え

// ソート後: {9.9, 3.3, 7.7, 5.5}

このコードでは、インデックス1(7.7)から始めて、2つの要素(7.7と3.3)が昇順で並び替えられます。

4. ArraySort関数の応用

複雑なソート条件の例

ArraySort関数は、基本的な昇順・降順の並び替えに加えて、特定の条件に応じたソートを行う際に非常に有効です。例えば、価格と時間を組み合わせて並び替えるような場面が考えられます。

複数条件での並び替え例

以下のコードは、日付と価格データを並べ替える例です。

// 日付データと価格データ
datetime dates[] = {20221101, 20221103, 20221102};
double prices[] = {1.2345, 1.1234, 1.3456};

// 日付を昇順にソートし、価格データを連動させる
ArraySort(dates); // 日付を並び替え

// 価格データも日付に基づいて手動で再構成
double sorted_prices[ArraySize(prices)];
for (int i = 0; i < ArraySize(prices); i++)
{
    int index = ArrayBsearch(dates, dates[i], 0, WHOLE_ARRAY);
    sorted_prices[i] = prices[index];
}

// ソート後:
// dates: {20221101, 20221102, 20221103}
// sorted_prices: {1.2345, 1.3456, 1.1234}

この例では、ArraySortArrayBsearchを組み合わせ、データの連動を維持しながらソートを行っています。

多次元配列の部分的なソート

MQL4では直接的に多次元配列をソートすることはできません。しかし、必要な列や行を1次元配列に抽出し、ソート後に再構成する方法が一般的です。

多次元配列のソート例

// 多次元配列(行: 日付, 列: 価格)
double data[][2] = {{20221101, 1.2345}, {20221103, 1.1234}, {20221102, 1.3456}};

// 日付を基準に並び替える
double temp[3]; // 一時的な1次元配列
for (int i = 0; i < ArraySize(data); i++)
    temp[i] = data[i][0]; // 日付を抽出

ArraySort(temp); // 日付を昇順にソート

// ソート結果に基づき多次元配列を再構成
double sorted_data[3][2];
for (int i = 0; i < ArraySize(temp); i++)
{
    for (int j = 0; j < ArraySize(data); j++)
    {
        if (temp[i] == data[j][0])
        {
            sorted_data[i][0] = data[j][0];
            sorted_data[i][1] = data[j][1];
            break;
        }
    }
}

// ソート後: {{20221101, 1.2345}, {20221102, 1.3456}, {20221103, 1.1234}}

パフォーマンスを意識したソート

大量のデータを扱う場合、ソートのパフォーマンスが重要です。以下は、ArraySort関数を効率的に使用する際のヒントです。

  1. 不要なデータを事前にフィルタリング:
    配列内の不要な要素を削除することで、ソート対象を最小化します。
   ArrayResize(array, count); // 必要なサイズにリサイズ
  1. ソートの範囲を限定:
    配列全体ではなく、必要な部分だけを並び替えることで計算量を削減します。
   ArraySort(array, 50, 10); // 10番目から50個だけをソート
  1. 適切なデータ型を使用:
    データ型を適切に選ぶことでメモリ使用量を最適化します(例: doubleよりfloatを使用)。

5. ArraySort関数の制限と注意点

配列の型に関する制約

ArraySort関数は、特定のデータ型に対してのみ使用可能です。以下の点を注意してください。

  1. サポートされるデータ型:
  • 数値型(int, double, float): ソート可能
  • 文字列型(string): ソート可能
  • その他の型(例: bool, datetime): ソート可能だが、順序の意味に注意が必要
  1. ソートが無効な場合:
    多次元配列には直接ArraySortを適用できません。多次元配列の特定の列や行を1次元配列に抽出してソートし、再構成する必要があります。

例: サポートされない多次元配列

double matrix[][2] = {{1.2, 2.3}, {3.4, 4.5}};
// ArraySort(matrix); // エラーとなる

ソート結果の信頼性

ArraySortを使用すると、同じ値が複数含まれる場合、その順序は保証されません。これを安定ソート(ソート後も同じ値の順序が保持される)ではない、といいます。

例: 安定ソートではない場合

double array[] = {2.2, 1.1, 2.2, 3.3};
ArraySort(array);
// ソート結果: {1.1, 2.2, 2.2, 3.3} (順序は保持されない)

必要であれば、独自の条件を加えて安定ソートのような挙動を実装する必要があります。

エラーハンドリング

ArraySort関数が失敗することは少ないですが、配列の状態やパラメータの設定ミスによりエラーが発生することがあります。以下は代表的なエラーとその原因です。

  1. 配列が空の場合:
    配列が空(ArraySize(array) == 0)だとソートは行われません。
   double emptyArray[];
   ArraySort(emptyArray); // ソートされない
  1. 不正なインデックス指定:
    ソート範囲(startcount)が配列のサイズを超える場合、予期しない動作が発生します。
   double array[] = {5.0, 3.0, 1.0};
   ArraySort(array, 5, 2); // エラーや無効な動作の原因となる

エラーを防ぐためのコード例

double array[] = {1.0, 2.0, 3.0};
int size = ArraySize(array);

if (size > 0) {
   ArraySort(array, size, 0, MODE_ASCEND);
} else {
   Print("配列が空です");
}

パフォーマンスの問題

大量のデータをソートする場合、ソートアルゴリズムの計算量(O(n log n))に注意する必要があります。以下の方法でパフォーマンスを改善できます。

  1. 部分的なソート:
    必要な部分だけをソートすることで計算量を削減します。
   ArraySort(array, 50); // 最初の50個だけをソート
  1. 事前にデータをフィルタリング:
    ソート前に不要なデータを除外しておきます。
   ArrayResize(array, newSize);
  1. 適切なデータ型を使用:
    データ型を適切に選ぶことでメモリ使用量を最適化します(例: doubleよりfloatを使用)。

6. 実践的な活用例

トレード履歴データのソート

以下は、トレード履歴のデータをArraySortを用いて整理する例です。

実際のコード例

// トレード履歴データ(日時と利益額)
datetime tradeDates[] = {20221102, 20221101, 20221103};
double profits[] = {100.0, 50.0, 150.0};

// 日付を昇順にソートし、利益額を連動させる
ArraySort(tradeDates);

double sorted_profits[ArraySize(profits)];
for (int i = 0; i < ArraySize(tradeDates); i++) {
   int index = ArrayBsearch(tradeDates, tradeDates[i], 0, WHOLE_ARRAY);
   sorted_profits[i] = profits[index];
}

// ソート後:
// tradeDates: {20221101, 20221102, 20221103}
// sorted_profits: {50.0, 100.0, 150.0}

カスタムインジケーターでの利用

例えば、特定の条件に基づいて移動平均値を並び替える場合もArraySortを活用できます。

7. よくある質問(FAQ)

配列の一部だけをソートするにはどうすれば良いですか?

ArraySort関数のstartパラメータとcountパラメータを使用することで、配列の一部だけを並び替えることができます。

例: 配列の一部をソート

double data[] = {9.0, 3.0, 7.0, 1.0, 5.0};
ArraySort(data, 3, 1); // インデックス1から3つの要素を昇順にソート

// ソート後: {9.0, 1.0, 3.0, 7.0, 5.0}

この例では、インデックス1(3.0)から始めて3つの要素だけが並び替えられます。

降順ソートが正しく動作しません。どうすれば良いですか?

降順ソートを行う場合、directionパラメータにMODE_DESCENDを指定する必要があります。これが指定されていないとデフォルトで昇順になります。

降順ソートの正しい例

double data[] = {2.2, 3.3, 1.1};
ArraySort(data, WHOLE_ARRAY, 0, MODE_DESCEND);

// ソート後: {3.3, 2.2, 1.1}

注意: MODE_DESCENDが指定されていない場合、結果が意図しない順序になることがあります。

多次元配列を効率的に処理する方法はありますか?

MQL4ではArraySort関数が多次元配列に直接対応していないため、次のような方法で効率的に処理することをおすすめします。

方法1: 1次元配列に変換してソート

多次元配列の特定の列や行を1次元配列として抽出し、それをソートします。

方法2: ソート対象の列をインデックスに基づいて再構成

次の例では、2列目(価格データ)を基準に多次元配列をソートしています。

double data[][2] = {{1.0, 3.3}, {2.0, 1.1}, {3.0, 2.2}};
double temp[ArraySize(data)];

// 2列目(価格データ)を抽出してソート
for (int i = 0; i < ArraySize(data); i++) {
   temp[i] = data[i][1];
}
ArraySort(temp); // 価格を昇順にソート

// ソート結果に基づき多次元配列を再構成
double sorted_data[ArraySize(data)][2];
for (int i = 0; i < ArraySize(temp); i++) {
   for (int j = 0; j < ArraySize(data); j++) {
       if (temp[i] == data[j][1]) {
           sorted_data[i][0] = data[j][0];
           sorted_data[i][1] = data[j][1];
           break;
       }
   }
}

// ソート後:
// sorted_data: {{2.0, 1.1}, {3.0, 2.2}, {1.0, 3.3}}

配列が空の場合にエラーを防ぐ方法はありますか?

ArraySortは空の配列に対しては動作しません。そのため、事前に配列が空かどうかをチェックする必要があります。

配列が空かどうかをチェックする例

double data[];

if (ArraySize(data) > 0) {
   ArraySort(data);
} else {
   Print("配列が空です。");
}

配列内の重複した値を正しく処理できますか?

ArraySortは配列内の重複値を正しく並び替えることができますが、同じ値が複数ある場合の順序は保証されません(非安定ソート)。安定ソートが必要な場合、以下のように手動で調整する必要があります。

手動で順序を保持する例

// 配列内の値と元のインデックスを記録
double data[] = {2.2, 1.1, 2.2, 3.3};
int indexes[ArraySize(data)];
for (int i = 0; i < ArraySize(data); i++) {
   indexes[i] = i;
}

// ソート用の補助関数を作成してカスタムソートを実装
// ソート後に元のインデックスを再構成

8. まとめと次のステップ

ArraySort関数の要点を振り返る

  • 基本的な役割:
    ArraySort関数は、配列を昇順または降順に並び替える便利なツールです。
  • 主な機能:
    配列の部分ソート、特定の条件による並び替え、多次元配列の間接的な操作など、幅広い用途で利用できます。
  • 制約と注意点:
    配列の型や多次元配列の扱い、安定ソートが保証されない点など、いくつかの制約があります。

次のステップ

MQL4での配列操作をさらに深めるために、以下の内容を学習することをおすすめします。

  1. ArrayResize関数:
    配列のサイズ変更方法を理解し、動的なデータ操作を可能にする。
  2. ArrayCopy関数:
    配列を効率的にコピーし、データ操作の幅を広げる。
  3. カスタムソートロジックの実装:
    複雑なソート条件を必要とする場合の応用技術。
  • 次のステップとして、他の記事や公式ドキュメントを参考にしながら、自身のEAでArraySortを実践的に使ってみましょう!

参考サイト

ArraySort - Array Functions - MQL4 Reference…

EXPO blog 投資の翼

配列操作の重要性 MQL4における配列操作は、効率的なプログラム作成の鍵です。配列を使用することで、大量のデータを一元管…

※記事内に広告を含む場合があります。
佐川 直弘: MetaTraderを活用したFX自動売買の開発で15年以上の経験を持つ日本のパイオニア🔧

トレーデンシー大会'15世界1位🥇、EA-1グランプリ準優勝🥈の実績を誇り、ラジオ日経出演経験もあり!
現在は、株式会社トリロジーの役員として活動中。
【財務省近畿財務局長(金商)第372号】に登録
され、厳しい審査を経た信頼性の高い投資助言者です。


【主な活動内容】
・高性能エキスパートアドバイザー(EA)の開発と提供
・最新トレーディング技術と市場分析の共有
・FX取引の効率化と利益最大化を目指すプロの戦略紹介

トレーダー向けに役立つ情報やヒントを発信中!

This website uses cookies.