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[] : 指定要排序的陣列。此陣列必須為一維。
  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)開始,將兩個元素(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 無法直接對多維陣列進行排序。然而,通常會將所需的列或行抽取為一維陣列,排序後再重新組成。

多維陣列排序範例

// 多維陣列(行: 日期, 列: 價格)
double data[][2] = {{20221101, 1.2345}, {20221103, 1.1234}, {20221102, 1.3456}};

// 以日期為基準排序
double temp[3]; // 一時一維陣列
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. 使用適當的資料型別 : 選擇合適的資料型別可優化記憶體使用量(例如:使用 float 代替 double)。

5. ArraySort 函式的限制與注意事項

陣列型別的限制

ArraySort 函式僅適用於特定資料型別。請注意以下事項。

  1. 支援的資料型別 :
  • 數值型(intdoublefloat):可排序
  • 字串型(string):可排序
  • 其他型別(如:booldatetime):可排序,但需注意順序意義
  1. 當排序無效時 : 多維陣列無法直接套用 ArraySort。必須將多維陣列的特定列或行抽取為一維陣列進行排序,然後重新構成。

範例:不支援的多維陣列

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. 使用適當資料型別 : 選擇合適的資料型別可優化記憶體使用量(例如使用 float 代替 double)。

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:將多維陣列轉換為一維陣列後排序

將多維陣列的特定列或行抽取為一維陣列,並進行排序。

方法2:根據索引重新構造排序目標列

以下範例以第二列(價格資料)為基準,對多維陣列進行排序。

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

// 抽取第二列(價格資料)並排序
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.