在 MetaEditor 實際跑一次
MqlRates、一個自訂 struct 與動態陣列
存成 MQL5/Scripts/Lesson9Structures.mq5。它把 K 線複製進一個 struct 陣列、建立一個自訂 struct,並設定動態陣列的大小——後面每一個 EA 背後的模式。
//+------------------------------------------------------------------+
//| Lesson 9 - MqlRates, custom structs, dynamic arrays |
//+------------------------------------------------------------------+
#property copyright "Strategist Academy"
#property version "1.00"
// A tiny value object - MQL5 lets you group related fields like this.
struct Level
{
double price;
string label;
bool isSupport;
};
void OnStart()
{
int bars = 50;
// --- MqlRates: one struct per bar ---------------------------------
MqlRates rates[];
ArraySetAsSeries(rates, true); // 0 = newest
int copied = CopyRates(_Symbol, _Period, 0, bars, rates);
if(copied != bars)
{
Print("CopyRates returned ", copied, " of ", bars, ". Error: ", GetLastError());
return;
}
double hi = rates[1].high;
double lo = rates[1].low; // bar 0 is still forming
for(int i = 2; i < bars && !IsStopped(); i++)
{
hi = MathMax(hi, rates[i].high);
lo = MathMin(lo, rates[i].low);
}
Print("Newest completed bar close: ", DoubleToString(rates[1].close, _Digits));
Print("Bar time: ", TimeToString(rates[1].time, TIME_DATE | TIME_MINUTES));
// --- Custom struct -------------------------------------------------
Level levels[2];
levels[0].price = hi;
levels[0].label = "50-bar high";
levels[0].isSupport = false;
levels[1].price = lo;
levels[1].label = "50-bar low";
levels[1].isSupport = true;
for(int i = 0; i < 2; i++)
Print(levels[i].label, ": ", DoubleToString(levels[i].price, _Digits),
" support=", levels[i].isSupport ? "yes" : "no");
// --- Dynamic array -------------------------------------------------
double closes[];
ArrayResize(closes, bars);
for(int i = 0; i < bars; i++)
closes[i] = rates[i].close;
Print("closes[0] (newest) = ", DoubleToString(closes[0], _Digits));
Print("closes[", bars - 1, "] (oldest) = ", DoubleToString(closes[bars - 1], _Digits));
Print("Series order set on rates? ", ArrayGetAsSeries(rates) ? "yes" : "no");
}
如何執行
- 1. 從 MT5 開啟 MetaEditor(按 F4), 選擇這支程式該放的資料夾——Experts、Indicators 或 Scripts。
- 2. 開新檔案、把這段程式貼上去,然後按 F7 編譯。Errors 分頁顯示的錯誤 都修掉。
- 3. 回到 MT5,把它拖到圖表上——如果是 EA,就打開 Strategy Tester。
你會一直遇到的結構
MQL5 內建一組 struct,它們是這套 API 的通用貨幣。學會這五個,大多數文件就會變得可讀:
MqlRates——一根 K 線:time, open, high, low, close, tick_volume, spread, real_volume。
MqlTick——一個 tick:bid, ask, last, volume, time_msc, flags。
MqlTradeRequest——你想送出的那張單。
MqlTradeResult——伺服器實際做了什麼。
MqlDateTime——拆開來的行事曆時間。
你也可以用 struct 宣告自己的——像這堂課那樣,把一個價格跟一個標籤綁在一起就很方便。
動態陣列與 ArrayResize
用 double arr[]; 宣告一個空陣列,再用 ArrayResize(arr, n) 設定大小。許多 API 函式會幫你調整大小——CopyRates 會——但如果你是自己在組一個,先 resize。
ArraySetAsSeries 決定你的索引方式
如果你要索引 0 是最新那根 K 線,在複製之前呼叫它。複製之後才呼叫,那你已經用另一種順序把陣列填滿了。搞錯這個會產生一個看起來能跑、但數值被位移或反轉的指標——當數字看起來怪時,先檢查這裡。
類別,簡短講
MQL5 支援類別:private/public 區段、建構子、解構子、繼承。你不需要寫一個才能有生產力,但你必須讀得懂它們,因為整個標準函式庫(CTrade、CPositionInfo、CSymbolInfo)都是類別架構。實例化、呼叫方法、往下走。
字串是物件,不是字元陣列
與 C 不同,MQL5 的字串自己管理記憶體。用 + 串接,用 == 或 StringCompare 比較,不用煩惱 buffer。