MQL5 基本語法入門:從變數到函數的完整指南
📌 本文重點
深入學習 MQL5 核心語法:資料型別、變數宣告、運算子、條件判斷、迴圈、函數定義與常用內建函數。無論你是程式新手或有其他語言背景,本文都能讓你快速掌握 MQL5 語法基礎。
深入學習 MQL5 核心語法:資料型別、變數宣告、運算子、條件判斷、迴圈、函數定義與常用內建函數。無論你是程式新手或有其他語言背景,本文都能讓你快速掌握 MQL5 語法基礎。
前言:MQL5 是什麼語言?
MQL5(MetaQuotes Language 5)是 MetaTrader 5 平台的原生程式語言,語法結構與 C++ 非常相似。如果你有 C/C++/C# 或 Java 的基礎,上手 MQL5 會非常快;即使是程式新手,只要掌握本文介紹的核心語法,也能開始撰寫自己的 EA(Expert Advisor,專家顧問)。
MQL5 程式主要分為三類:
- Expert Advisor (EA):自動交易機器人,在
OnTick()中執行交易邏輯 - Custom Indicator(自訂指標):繪製技術分析線,在
OnCalculate()中計算數值 - Script(腳本):一次性執行的程式,在
OnStart()中完成任務
第一章:資料型別(Data Types)
MQL5 是強型別語言,每個變數在宣告時必須指定型別。以下是最常用的型別:
| 型別 | 大小 | 範圍 / 說明 | 典型用途 |
|---|---|---|---|
int |
4 bytes | -2,147,483,648 ~ 2,147,483,647 | 訂單 ID、計數器、週期 |
long |
8 bytes | ±9.2 × 10¹⁸ | 大整數、Position Ticket |
double |
8 bytes | 15-16 位有效數字 | 價格、止損、手數 |
bool |
1 byte | true / false | 條件旗標、開關 |
string |
可變 | Unicode 文字 | 品種名稱、日誌訊息 |
datetime |
8 bytes | 1970年起的秒數 | K 線時間、交易時間 |
color |
4 bytes | RGB 顏色值 | 指標線條顏色 |
第二章:變數宣告與初始化
// ===== 基本變數宣告 =====
// 整數 - 用於訂單編號、魔術數字
int magicNumber = 12345;
int barCount = 0;
// 浮點數 - 用於所有價格相關計算
double entryPrice = 1.08500;
double stopLoss = 1.08000;
double takeProfit = 1.09500;
double lotSize = 0.10;
// 布林值 - 條件旗標
bool isLongSignal = false;
bool isInitialized = true;
// 字串
string symbolName = "EURUSD";
string comment = "MA Cross Strategy";
// 日期時間
datetime lastBarTime = 0; // 初始化為 1970-01-01
datetime currentTime = TimeCurrent(); // 取得目前時間
// ===== 常數宣告(值不可修改)=====
const int MAX_POSITIONS = 3;
const double RISK_PERCENT = 2.0;
// ===== 輸入參數(可在 EA 設定介面調整)=====
input int InpFastPeriod = 10; // 快線週期
input int InpSlowPeriod = 30; // 慢線週期
input double InpLotSize = 0.1; // 交易手數
input bool InpUseFilter = true; // 啟用過濾器
第三章:運算子(Operators)
// ===== 算術運算子 =====
double a = 10.0, b = 3.0;
double sum = a + b; // 13.0
double diff = a - b; // 7.0
double product = a * b; // 30.0
double quotient = a / b; // 3.333...
int remainder = 10 % 3; // 1(取餘數,只適用整數)
// 自增 / 自減
int counter = 0;
counter++; // counter = 1
counter--; // counter = 0
counter += 5; // counter = 5
counter -= 2; // counter = 3
counter *= 2; // counter = 6
// ===== 比較運算子(回傳 bool)=====
bool isEqual = (a == b); // false
bool isNotEqual = (a != b); // true
bool isGreater = (a > b); // true
bool isLess = (a < b); // false
bool isGteq = (a >= b); // true
bool isLteq = (a <= b); // false
// ===== 邏輯運算子 =====
bool condition1 = true;
bool condition2 = false;
bool andResult = condition1 && condition2; // false(兩者都要 true)
bool orResult = condition1 || condition2; // true(只要一個 true)
bool notResult = !condition1; // false(反轉)
// 實際應用:多條件交易信號
bool isBuySignal = (fastMA > slowMA) && (rsi < 70) && !hasPosition;
第四章:條件判斷(If/Else/Switch)
// ===== 基本 if/else =====
double profit = PositionGetDouble(POSITION_PROFIT);
if (profit >= 100.0)
{
Print("獲利超過 $100,考慮獲利了結");
ClosePosition();
}
else if (profit <= -50.0)
{
Print("虧損超過 $50,觸發止損");
ClosePosition();
}
else
{
Print("部位進行中,當前盈虧: $", profit);
}
// ===== Switch(適合多個固定值的判斷)=====
int signal = GetSignal(); // 假設回傳 1=買, -1=賣, 0=無信號
switch (signal)
{
case 1:
OpenBuy();
break;
case -1:
OpenSell();
break;
case 0:
default:
// 無動作
break;
}
// ===== 三元運算子(簡化的 if/else)=====
string direction = (signal == 1) ? "BUY" : (signal == -1) ? "SELL" : "NONE";
Print("信號方向: ", direction);
第五章:迴圈(Loops)
// ===== For 迴圈 - 最常用,適合已知次數的迭代 =====
// 計算最近20根K線的平均收盤價
double sum = 0;
int period = 20;
for (int i = 0; i < period; i++)
{
sum += iClose(_Symbol, _Period, i);
}
double average = sum / period;
Print("20期平均收盤價: ", average);
// ===== 遍歷所有持倉(常用模式)=====
int totalPositions = PositionsTotal();
for (int i = totalPositions - 1; i >= 0; i--) // 從後往前遍歷,避免刪除時索引錯亂
{
string posSymbol = PositionGetSymbol(i);
if (posSymbol == _Symbol)
{
long magic = PositionGetInteger(POSITION_MAGIC);
Print("持倉 #", i, " | Magic: ", magic, " | 品種: ", posSymbol);
}
}
// ===== While 迴圈 - 條件未知時使用 =====
int retries = 0;
int maxRetries = 3;
bool success = false;
while (retries < maxRetries && !success)
{
success = TrySendOrder();
if (!success)
{
Print("下單失敗,重試 ", retries + 1, "/", maxRetries);
Sleep(1000); // 等待 1 秒後重試
retries++;
}
}
// ===== Break 和 Continue =====
for (int i = 0; i < 100; i++)
{
if (i == 10) break; // 當 i=10 時跳出迴圈
if (i % 2 == 0) continue; // 跳過偶數,繼續下一次迭代
Print("奇數: ", i);
}
第六章:函數定義與呼叫
// ===== 基本函數語法 =====
// 格式:返回型別 函數名稱(參數型別 參數名稱, ...)
// 無返回值(void)函數
void LogTradeInfo(string action, double price, double lots)
{
Print("[", TimeToString(TimeCurrent()), "] ",
action, " | 價格: ", DoubleToString(price, Digits()),
" | 手數: ", DoubleToString(lots, 2));
}
// 有返回值的函數
double CalculatePipValue(string symbol, double lots)
{
double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
double tickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
return lots * tickValue * (tickSize / point);
}
// 布林型函數(常用於檢查條件)
bool IsNewBar()
{
static datetime lastBarTime = 0;
datetime currentBarTime = iTime(_Symbol, _Period, 0);
if (currentBarTime != lastBarTime)
{
lastBarTime = currentBarTime;
return true; // 新K線出現
}
return false;
}
// 使用預設參數值
double NormalizeLots(double lots, string symbol = NULL)
{
if (symbol == NULL) symbol = _Symbol;
double minLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
double lotStep = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
lots = MathMax(lots, minLot);
lots = MathMin(lots, maxLot);
lots = MathRound(lots / lotStep) * lotStep;
return NormalizeDouble(lots, 2);
}
// ===== 在 OnTick() 中呼叫函數 =====
void OnTick()
{
if (!IsNewBar()) return;
double pv = CalculatePipValue(_Symbol, 0.1);
Print("每點價值: $", DoubleToString(pv, 4));
}
第七章:陣列(Arrays)
// ===== 靜態陣列 =====
double prices[5] = {1.0800, 1.0810, 1.0795, 1.0820, 1.0815};
Print("第一個價格: ", prices[0]); // 1.0800(索引從0開始)
// ===== 動態陣列 =====
double maBuffer[]; // 宣告動態陣列(空的)
ArrayResize(maBuffer, 100); // 調整大小為100個元素
ArraySetAsSeries(maBuffer, true); // 設為時間序列(索引0=最新數據)
// ===== 使用 CopyBuffer 填充指標數據 =====
int maHandle = iMA(_Symbol, _Period, 20, 0, MODE_SMA, PRICE_CLOSE);
double maValues[3];
ArraySetAsSeries(maValues, true);
if (CopyBuffer(maHandle, 0, 0, 3, maValues) == 3)
{
Print("當前MA: ", maValues[0]); // 最新K線的MA值
Print("前一根MA: ", maValues[1]); // 前一根K線的MA值
Print("前兩根MA: ", maValues[2]); // 前兩根K線的MA值
}
第八章:常用內建函數速查
// ===== 帳戶資訊 =====
double balance = AccountInfoDouble(ACCOUNT_BALANCE); // 帳戶餘額
double equity = AccountInfoDouble(ACCOUNT_EQUITY); // 淨值
double margin = AccountInfoDouble(ACCOUNT_MARGIN); // 已用保證金
double freeMargin = AccountInfoDouble(ACCOUNT_FREEMARGIN); // 可用保證金
long leverage = AccountInfoInteger(ACCOUNT_LEVERAGE); // 槓桿倍數
string currency = AccountInfoString(ACCOUNT_CURRENCY); // 帳戶貨幣
// ===== 品種資訊 =====
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); // 賣出價
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); // 買入價
double spread = SymbolInfoDouble(_Symbol, SYMBOL_SPREAD); // 點差
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); // 最小變動單位
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS); // 小數位數
// ===== K 線數據 =====
double openPrice = iOpen(_Symbol, _Period, 0); // 當前K線開盤價
double highPrice = iHigh(_Symbol, _Period, 0); // 最高價
double lowPrice = iLow(_Symbol, _Period, 0); // 最低價
double closePrice = iClose(_Symbol, _Period, 0); // 收盤價(即時更新)
datetime barTime = iTime(_Symbol, _Period, 0); // K線時間
long barVolume = iVolume(_Symbol, _Period, 0); // 成交量
// ===== 數學函數 =====
double absVal = MathAbs(-1.5); // 1.5(絕對值)
double maxVal = MathMax(1.5, 2.3); // 2.3(取較大值)
double minVal = MathMin(1.5, 2.3); // 1.5(取較小值)
double sqrtVal = MathSqrt(9.0); // 3.0(平方根)
double floorVal = MathFloor(3.7); // 3.0(向下取整)
double roundVal = MathRound(3.5); // 4.0(四捨五入)
// ===== 字串函數 =====
string upper = StringToUpper("eurusd"); // "EURUSD"
int len = StringLen("Hello MQL5"); // 10
string sub = StringSubstr("EURUSD", 0, 3); // "EUR"
string str = DoubleToString(1.23456, 2); // "1.23"
string strI = IntegerToString(12345); // "12345"
double val = StringToDouble("1.0850"); // 1.0850
// ===== 時間函數 =====
datetime now = TimeCurrent(); // 伺服器目前時間(UTC)
datetime local = TimeLocal(); // 本機時間
string strTime = TimeToString(now, TIME_DATE|TIME_MINUTES); // "2026.03.11 10:30"
總結:MQL5 語法核心要點
- 強型別:每個變數都有明確型別,
double用於價格,int用於計數 - 分號結尾:每條陳述式必須以
;結尾 - 大括號:用
{ }包住程式碼區塊 - input 參數:讓用戶在不修改程式碼的情況下調整 EA 設定
- 陣列從0開始:
array[0]是第一個元素;設為時間序列後,[0]是最新數據 - 函數要在使用前宣告或定義:或在檔案尾端定義,頂部宣告原型
延伸學習
本文由 James Lee 撰寫,轉載請註明出處。內容僅供教育目的,不構成投資建議。