📈 為何要學習 MQL 程式語言?
在瞬息萬變的金融市場中,交易者總在尋求能提升決策效率與精準度的工具。MetaTrader 平台(MT4/MT5)之所以廣受歡迎,其強大的 MQL(MetaQuotes Language) 程式語言功不可沒。學習如何使用 MQL 程式語言,意味著您不再受限於平台內建的指標與功能。您可以打造完全符合自己交易邏輯的客製化指標、開發自動執行的 EA(Expert Advisor)交易策略,甚至優化現有工具的運算效能。這不僅是技術上的提升,更是將您獨特的市場洞察力轉化為系統化交易優勢的關鍵一步。本篇教學將以最常見的「移動平均線(Moving Average, MA)」為例,帶您從一個最基礎的腳本,逐步深入 MQL 的世界,探索程式化交易的無限可能。
第一步:從基礎到進階,為指標注入靈魂的「參數化」
一個寫死的指標,其應用價值相當有限。真正的強大之處在於其「適應性」,也就是能根據不同市況、不同商品或不同交易策略,快速調整其核心參數。這就是為何參數化是 MQL 指標編寫的第一個核心技能。透過「input」關鍵字,我們可以將原本固定在程式碼中的數值,暴露到指標的設定介面中,讓使用者可以輕鬆修改。
🎯 設定核心計算參數:週期、位移、模式與價格
我們先從一個最基礎的 MA 程式開始。假設我們有一個僅能計算 20 週期簡單移動平均線的腳本。現在,我們要將它的所有核心計算因子都變成可調整的參數。
在 MetaEditor 中,我們在程式碼的開頭部分加入以下程式碼:
//--- 指標輸入參數
input int PERIOD = 20; // 週期
input int SHIFT = 0; // 位移
input ENUM_MA_METHOD METHOD = MODE_SMA; // MA 類別
input ENUM_APPLIED_PRICE PRICE = PRICE_CLOSE; // 適用價格
代碼解析:
- input:這是 MQL 中的一個修飾符,告訴編譯器,這個變數是一個外部輸入參數,需要在指標設定視窗中顯示出來。
- int:整數型別,用於定義像「週期(PERIOD)」和「位移(SHIFT)」這樣的純數字參數。
- ENUM_MA_METHOD / ENUM_APPLIED_PRICE:這是「列舉型別(Enumeration)」。您可以將它理解為一個預設好的下拉式選單。MT4 已經幫我們定義好了所有可用的 MA 計算方式(如 `MODE_SMA` 簡單移動、`MODE_EMA` 指數移動等)和適用價格(如 `PRICE_CLOSE` 收盤價、`PRICE_OPEN` 開盤價等),使用列舉型別能避免使用者輸入無效的數值,非常方便。
- = 20 / = 0 …:等號後面的是該參數的「預設值」。
- // 週期:雙斜線後面的文字是「註解」,它會顯示在設定視窗中,作為該參數的說明文字,幫助使用者理解其用途。
接著,我們需要將這些新定義的參數應用到核心計算函數 `iMA()` 中。找到 `OnCalculate` 函數裡計算 MA 的那一行,將原本寫死的數值替換成我們剛剛定義的參數變數:
// 修改前,數值是固定的
// MABuffer[i] = iMA(NULL, 0, 20, 0, MODE_SMA, PRICE_CLOSE, i);
// 修改後,使用我們定義的參數變數
MABuffer[i] = iMA(NULL, 0, PERIOD, SHIFT, METHOD, PRICE, i);
完成後,點擊 MetaEditor 工具列上的「編譯」(Compile)按鈕。如果沒有錯誤,回到 MT4 圖表,重新載入這個指標。您會驚喜地發現,指標的「輸入參數」標籤頁中,已經出現了我們剛剛設定的所有選項,並且可以自由調整!這就是如何使用 MQL 程式語言進行參數化的第一步,也是最關鍵的一步。
掌握如何使用 MQL 程式語言,將您的交易策略轉化為自動化執行的強大工具。
第二步:視覺化調整,讓指標更具可讀性
一個好的指標不僅要計算準確,視覺呈現也同樣重要。能夠自由變更線條的顏色、樣式與粗細,能幫助交易者在複雜的圖表中快速識別訊號。延續參數化的思路,我們同樣可以使用 `input` 將這些視覺設定也變成可調整的選項。
🎨 設定顏色、線條樣式與寬度
我們在參數區塊繼續加入以下程式碼:
//--- 指標外觀參數
input color CLR = clrWhite; // 顏色
input ENUM_LINE_STYLE STYLE = STYLE_SOLID; // 線條種類
input int WIDTH = 1; // 寬度
代碼解析:
- color:MQL 內建的顏色型別。預設值 `clrWhite` 是 MQL 預定義的顏色常數,代表白色。使用者可以在設定介面中點擊顏色方塊,從調色盤中選擇任意顏色。
- ENUM_LINE_STYLE:與 MA 模式類似,這是線條樣式的列舉型別,包含了 `STYLE_SOLID`(實線)、`STYLE_DASH`(虛線)、`STYLE_DOT`(點線)等多種選項。
定義好參數後,我們需要在指標的初始化函數 `OnInit()` 中應用它們。這個函數在指標第一次被加載到圖表時執行,是進行各種初始設定的絕佳位置。我們使用 `SetIndexStyle()` 函數來一次性設定繪圖緩衝區(我們指標線)的樣式。
int OnInit()
{
// ... 其他設定 ...
// 設定第0個繪圖緩衝區的樣式、寬度與顏色
SetIndexStyle(0, DRAW_LINE, STYLE, WIDTH, CLR);
// 為指標設定一個標籤名稱
SetIndexLabel(0, "MA");
return(INIT_SUCCEEDED);
}
同時,因為我們已經改用 `SetIndexStyle()` 進行動態設定,原本在程式碼開頭使用 `#property` 靜態定義的顏色、寬度等屬性就可以移除了。為了保持程式碼整潔,建議直接刪除或使用 `/* … */` 將其註解掉,這樣編譯器會忽略這段程式碼。
/* // 這些是舊的靜態設定,現在已被動態設定取代
#property indicator_label1 "MA"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrRed
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
*/
再次編譯並重新載入指標,您會看到設定介面中多了顏色、線條種類和寬度的選項。現在,您的指標不僅功能靈活,外觀也完全由您掌控了。
第三步:效能優化,避免不必要的重複計算
當您學習如何使用 MQL 程式語言編寫更複雜的策略時,效能將成為一個不可忽視的議題。一個 poorly-written 的指標,尤其是在處理大量歷史數據時,可能會拖慢整個 MT4 平台的運行速度。對於指標而言,最大的效能瓶頸通常來自於 `OnCalculate()` 函數。
在簡易版的程式中,每次市場有新的報價(tick)進來,`OnCalculate()` 都會被觸發,然後我們的迴圈會從頭到尾把圖表上所有 K 棒的 MA 值都重新計算一遍。這在 K 棒數量少的時候不成問題,但當圖表累積了成千上萬根 K 棒時,這就造成了巨大的資源浪費。因為絕大多數舊的 K 棒,其 MA 值是不會改變的。
🧠 引入增量計算邏輯
聰明的作法是「只計算需要更新的部分」。MQL4 為我們提供了一個絕佳的工具:`IndicatorCounted()`。這個函數會返回上一次 `OnCalculate()` 執行後,已經成功計算出的指標值的 K 棒總數。
我們可以利用這個數值來決定這次需要計算的範圍。修改 `OnCalculate()` 函數的開頭部分:
int OnCalculate(const int rates_total, // 當前圖表總 K 棒數
const int prev_calculated, // 上次計算完成的 K 棒數
...)
{
//--- 計算需要處理的 K 棒數量
int limit = rates_total - prev_calculated - 1;
// 如果是第一次載入或數據有重大變化,prev_calculated 可能為0
// 這種情況下,我們從圖表上幾乎最後一根 K棒開始完整計算一次
if (prev_calculated == 0)
{
limit = rates_total - 1;
}
// 為了數據穩定性,至少重新計算最新的兩根 K 棒
// (因為當前的第 0 根 K 棒尚未收盤,其值會變動)
if(limit = 0; i--)
{
MABuffer[i] = iMA(NULL, 0, PERIOD, SHIFT, METHOD, PRICE, i);
}
//--- 返回當前圖表的總 K 棒數,供下一次呼叫時作為 prev_calculated 的值
return(rates_total);
}
邏輯解析:
- `rates_total` 是 MT4 傳入的當前圖表總 K 棒數,`prev_calculated` 則是上次計算完畢的數量。它們的差值,就是新增加的 K 棒數量。
- 我們定義 `limit` 來確定迴圈的起點。`rates_total – prev_calculated – 1` 這個公式可以有效地找出新增 K 棒的索引位置。
- 改變迴圈的方向,從 `limit` 開始遞減至 `0`。這代表我們只計算從新 K 棒開始到當前最新的 K 棒這一段區間,而舊的、已經計算過且不會再改變的數據則被跳過,大大節省了運算資源。
- `if(limit < 1) limit = 1;` 是一個保險措施,確保即使沒有新 K 棒產生,我們至少也會重新計算第 1 根(剛收盤)和第 0 根(正在跳動)K 棒的數值,以保證指標的即時性。
透過這個簡單的修改,您的指標在效能上已經提升了一個檔次。對於需要同時在多個圖表上運行的交易者來說,這種優化至關重要。
第四步:提升專業度,善用內建工具與最佳實踐
✨ 使用「Styler」自動美化程式碼
程式碼不僅是給機器執行的指令,也是給人看的。清晰、一致的程式碼風格能大幅提升可讀性與未來維護的便利性。MetaEditor 內建了一個名為「Styler」(在工具列上顯示為「調整原始碼」)的強大功能,可以一鍵自動整理您的程式碼格式。
在使用前,您可以先設定自己偏好的風格。點擊選單「工具」→「選項」,在「格式化」標籤頁中,可以選擇不同的內建風格(如 MetaQuotes、Linux、Allman 等),並微調縮排、空格等細節。設定完成後,只需在您的程式碼編輯視窗中點擊一下「調整原始碼」按鈕,編輯器就會自動將您的程式碼整理得井井有條。
📚 深入理解不同移動平均線模式
我們的指標現在可以選擇不同的 MA 類型,但您是否了解它們之間的差異?這對於制定交易策略至關重要。以下是 MQL 中最常用的四種 MA 模式的比較:
MA 模式 (MQL 常數) | 全名 | 特性與應用場景 |
---|---|---|
MODE_SMA | Simple Moving Average | 簡單移動平均線:對週期內的價格取算術平均。走勢平滑,但對價格變動反應較慢。適合用於判斷長期趨勢。 |
MODE_EMA | Exponential Moving Average | 指數移動平均線:給予較近期的價格更高的權重。對價格變動反應靈敏,適合捕捉短期趨勢轉折。 |
MODE_SMMA | Smoothed Moving Average | 平滑移動平均線:考慮了更久遠的歷史數據,線條最為平滑。適合用於過濾市場噪音,觀察宏觀趨勢。 |
MODE_LWMA | Linear Weighted Moving Average | 線性加權移動平均線:給予近期價格線性遞增的權重。靈敏度介於 SMA 和 EMA 之間,是一種兼顧平滑與反應速度的選擇。 |
🔗 參考權威文件與社群
學習程式語言最好的夥伴就是官方文件。MetaQuotes 官方提供了非常詳盡的 MQL5 語言參考手冊,當您對某個函數不確定時,這是最權威的資訊來源。同時,MQL5 社群也是一個龐大的寶庫,裡面有世界各地的開發者分享程式碼、解決問題,是精進 MQL 技能的絕佳平台。
- 權威連結1: MQL5官方文件 – iMA 函數
- 權威連結2: MQL5 官方程式碼庫
完整程式碼參考
以下是我們經過上述所有步驟改造後的完整 MA 指標程式碼。您可以直接複製到 MetaEditor 中進行編譯和使用。
//+------------------------------------------------------------------+
//| MA_Pro.mq4 |
//| Copyright 2025, 理財研究室 fmstudio.blog |
//| https://fmstudio.blog |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, 理財研究室 fmstudio.blog"
#property link "https://fmstudio.blog"
#property version "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
//--- 輸入參數
input int PERIOD = 20; // 週期
input int SHIFT = 0; // 位移
input ENUM_MA_METHOD METHOD = MODE_SMA; // MA 類別
input ENUM_APPLIED_PRICE PRICE = PRICE_CLOSE; // 適用價格
input color CLR = clrDodgerBlue; // 顏色
input ENUM_LINE_STYLE STYLE = STYLE_SOLID; // 線條種類
input int WIDTH = 2; // 寬度
//--- 指標緩衝區
double MABuffer[];
//+------------------------------------------------------------------+
//| 自訂指標初始化函數 |
//+------------------------------------------------------------------+
int OnInit()
{
//--- 指標緩衝區映射
SetIndexBuffer(0, MABuffer);
//--- 設定線條樣式
SetIndexStyle(0, DRAW_LINE, STYLE, WIDTH, CLR);
//--- 設定指標標籤
string short_name = "MA(" + (string)PERIOD + ")";
IndicatorSetString(INDICATOR_SHORTNAME, short_name);
SetIndexLabel(0, short_name);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| 自訂指標迭代計算函數 |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
//--- 計算迴圈的起始位置
int limit;
if(prev_calculated == 0)
{
limit = rates_total - 1;
}
else
{
limit = rates_total - prev_calculated;
}
//--- 主計算迴圈
for(int i = limit; i >= 0; i--)
{
MABuffer[i] = iMA(NULL, 0, PERIOD, SHIFT, METHOD, PRICE, i);
}
//--- 返回已計算的 K 棒總數
return(rates_total);
}
//+------------------------------------------------------------------+
❓ MQL 常見問題 (FAQ)
- Q1: MQL4 和 MQL5 有什麼區別?我應該學習哪個?
- A1: MQL5 是 MQL4 的升級版,語法更嚴謹,更接近 C++,功能也更強大(例如支援更複雜的訂單類型和更精準的回測)。如果您是新手,且主要使用 MT4,從 MQL4 開始會比較容易上手。但 MQL5 是未來的趨勢,如果您有長遠的學習規劃,直接學習 MQL5 會更有價值。兩者核心概念相通,學會一個再轉另一個並不困難。
- Q2: 如果我的程式碼編譯(Compile)時出現錯誤,該如何除錯?
- A2: MetaEditor 的「工具箱」視窗會顯示詳細的錯誤訊息。通常會指出錯誤在哪一行、哪個字元,並給出錯誤代碼和描述。常見錯誤包括拼字錯誤、忘記分號 `;`、變數型別不符等。仔細閱讀錯誤訊息,並對照程式碼檢查,是解決問題的第一步。您也可以使用 `Print()` 函數在「EA 交易」標籤頁中輸出變數值,來觀察程式執行過程中的數據變化。
- Q3: 我可以將這個自訂指標應用在 EA 自動交易中嗎?
- A3: 當然可以!這正是自訂指標的強大之處。在 EA 自動交易 中,您可以使用 `iCustom()` 函數來呼叫任何自訂指標的數值。您需要提供指標名稱、所有輸入參數,然後指定要獲取哪個緩衝區(哪條線)以及哪一根 K 棒的數值。例如,您可以編寫一個「當快速 MA 上穿慢速 MA 時買入」的邏輯。
- Q4: 為什麼計算迴圈要從後面(最新的 K 棒)往前跑?
- A4: 在時間序列數據(如 K 線)的計算中,當前 K 棒的指標值往往依賴於前一根或前幾根 K 棒的數據。從最新的 K 棒(索引值較大)往最舊的 K 棒(索引值為 0)計算,可能會導致計算順序錯亂。而從舊到新(`for(int i = limit; i >= 0; i–)`)計算,可以確保在計算第 `i` 根 K 棒時,所有它所依賴的更舊的 K 棒(`i-1`, `i-2`…)都已經被計算出來了,這樣能保證數據的正確性和連續性。
結論
恭喜您!透過本篇教學,您不僅學會了如何使用 MQL 程式語言將一個簡單的 MA 指標,升級為一個參數可調、外觀可控、效能優化的專業級工具,更重要的是,您掌握了 MQL 指標開發的核心思想:參數化、模組化與效能意識。這套方法論可以應用於任何您想開發的指標上,無論是 RSI、MACD 還是您獨創的交易訊號。程式化交易的道路充滿挑戰,但也蘊藏著無限的潛力。持續學習,不斷實踐,您將能把自己的交易智慧,轉化為在市場中穩定獲利的強大系統。