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
);
主要參數說明
- array[] : 指定要排序的陣列。此陣列必須為一維。
- count : 指定要排序的元素數量。預設為整個陣列(
WHOLE_ARRAY)。 - start : 指定排序開始的索引。預設為 0(陣列起始)。
- 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}
此範例結合了 ArraySort 與 ArrayBsearch,在保持資料同步的同時進行排序。
多維陣列的部分排序
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 函式時的效能優化建議。
- 事先過濾不必要的資料 : 刪除陣列中不需要的元素,將排序對象縮小。
ArrayResize(array, count); // 重新調整至必要大小
- 限定排序範圍 : 只對需要的區段排序,減少計算量。
ArraySort(array, 50, 10); // 從第10個到第50個排序
- 使用適當的資料型別 : 選擇合適的資料型別可優化記憶體使用量(例如:使用
float代替double)。
5. ArraySort 函式的限制與注意事項
陣列型別的限制
ArraySort 函式僅適用於特定資料型別。請注意以下事項。
- 支援的資料型別 :
- 數值型(
int、double、float):可排序 - 字串型(
string):可排序 - 其他型別(如:
bool、datetime):可排序,但需注意順序意義
- 當排序無效時 : 多維陣列無法直接套用
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 函式失敗的情況很少,但由於陣列狀態或參數設定錯誤可能會發生錯誤。以下列出代表性錯誤及其原因。
- 陣列為空時 : 若陣列為空(
ArraySize(array) == 0),則不會進行排序。
double emptyArray[];
ArraySort(emptyArray); // 不會排序
- 不正的索引指定 : 若排序範圍(
start與count)超過陣列大小,將產生不可預期的行為。
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))。以下方法可改善性能。
- 部分排序 : 只對需要的部分進行排序,以減少計算量。
ArraySort(array, 50); // 只排序前 50 個元素
- 事先過濾資料 : 在排序前排除不需要的資料。
ArrayResize(array, newSize);
- 使用適當資料型別 : 選擇合適的資料型別可優化記憶體使用量(例如使用
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 的陣列操作,建議學習以下內容。
ArrayResize函式 : 了解陣列尺寸變更方法,實現動態資料操作。ArrayCopy函式 : 高效複製陣列,擴展資料操作範圍。- 實作自訂排序邏輯 : 當需要複雜排序條件時的應用技術。
- 作為下一步,參考其他文章或官方文件,並在自己的 EA 中實際使用
ArraySort!
參考網站
ArraySort - Array Functions - MQL4 Reference…
配列操作の重要性 MQL4における配列操作は、効率的なプログラム作成の鍵です。配列を使用することで、大量のデータを一元管…