MT4 那一系列寫完之後停了好幾年,中間 MT5 已經變成主流,我自己也早就整個搬到 MT5 上了。所以重新開一個系列,這次用 MT5 跟 MQL5,從零開始,目標是自己寫出能跑的 EA(Expert Advisor,自動交易程式)。
第一篇不談策略,只做三件事:把環境裝好、寫一支不會下單只會印字的 EA、看到它真的跑起來。這樣後面每篇才有東西可以動手。
- MT5、MetaEditor、MQL5 分別是什麼
- 找到 MQL5 資料夾,知道檔案該放哪裡
- 用精靈建立 EA,補上程式碼,編譯成 .ex5
- 掛到圖表上看輸出;沒報價的時候改用策略測試器看
MT5、MetaEditor、MQL5 是什麼
MetaTrader 5(MT5)是交易平台本身,看圖、下單都在這裡。MetaEditor是寫程式的編輯器兼編譯器,裝 MT5 就會一起裝好,不用另外找。MQL5是在 MetaEditor 裡面寫的語言,長得很像 C++,寫過任何一種 C 系語言看到會覺得眼熟;完全沒寫過也沒關係,這系列會從變數、判斷、迴圈慢慢來,跟以前 MT4 系列一樣。
MQL5 能寫三種程式,先知道差別就好:
| 種類 | 放的資料夾 | 什麼時候執行 |
|---|---|---|
| EA(EA 交易) | Experts | 掛在圖表上,每來一個報價執行一次,可以下單 |
| 指標(Indicator) | Indicators | 掛在圖表上,負責算數字畫線,不能下單 |
| 腳本(Script) | Scripts | 拖上圖表執行一次就結束,例如一鍵平倉 |
安裝 MT5 並登入模擬帳號
到券商網站下載 MT5 安裝檔就好,我用的是 Tickmill。不同券商的 MT5 程式本體都一樣,差別只在能交易的商品跟點差。裝完先登入一個模擬帳號,開模擬帳號的流程跟以前 MT4 那篇 差不多,只是伺服器要選 MT5 的 Demo。
第一次開發強烈建議用模擬帳號。這篇的程式不會下單,但之後的會,寫錯一行就是真的錢。
找到 MQL5 資料夾
MT5 的程式碼、編譯結果、設定檔全部放在「資料資料夾」底下的 MQL5。在 MT5 主選單點「檔案 → 打開數據文件夾」(快速鍵 Ctrl+Shift+D)就會用檔案總管打開,不用自己猜路徑。
MQL5\
├─ Experts\ EA(自動交易程式)放這裡 ← 這系列主要在這
├─ Indicators\ 自訂技術指標
├─ Scripts\ 腳本:跑一次就結束的小工具
├─ Include\ .mqh 標頭檔,可重複使用的程式碼
├─ Libraries\ 編譯好的函式庫
├─ Files\ 程式讀寫檔案只能在這個沙盒裡
├─ Images\ 圖片資源
└─ Profiles\ 圖表範本(templates)、測試器參數(Tester)補充一個路徑的小知識,之後找不到檔案的時候會用到:
- 一般安裝:資料資料夾在
C:\Users\你的帳號\AppData\Roaming\MetaQuotes\Terminal\一串亂碼\,裝了幾個券商的 MT5 就有幾個亂碼資料夾。 - 可攜模式(portable):用
terminal64.exe /portable啟動,資料資料夾就在安裝目錄裡面。我自己都用這個模式,MQL5 就在 MT5 旁邊,備份跟找檔案都方便。
打開 MetaEditor
在 MT5 按 F4,或主選單「工具 → MetaQuotes 語言編輯器」。MetaEditor 的畫面分三塊:左邊「導航」是 MQL5 資料夾的檔案樹,中間是編輯區,下面「工具箱」會顯示編譯結果跟錯誤訊息。
用精靈建立第一個 EA
- MetaEditor 點「檔案 → 新增」(
Ctrl+N),會跳出 MQL 精靈。 - 選「EA交易 (模板)」,下一步。
- 名稱填
Experts\HelloWorld,作者、連結隨意,參數這篇用不到,下一步。 - 後面幾頁問要不要加事件處理函數,全部不勾,直接完成。
精靈會產生一份骨架,裡面就是三個函數:OnInit()、OnDeinit()、OnTick()。EA 的一生就是這三個函數:掛上去跑一次 OnInit,之後每個報價跑一次 OnTick,被拿掉的時候跑一次 OnDeinit。
程式碼
把精靈產生的內容整份換成下面這段,存檔(Ctrl+S)。註解跟字串裡有中文沒關係,這篇的範例就是這樣直接編譯過的。
//+------------------------------------------------------------------+
//| HelloWorld.mq5 |
//| 冏掉的Alan羅 orzalanluo.com |
//+------------------------------------------------------------------+
#property copyright "orzalanluo.com"
#property link "https://orzalanluo.com"
#property version "1.00"
#property description "MT5 教學 01:第一個 EA,只印訊息、不下單"
int g_TickCount = 0; // 收到幾個 tick
//--- EA 掛上圖表時執行一次
int OnInit()
{
Print("Hello World! EA 啟動:", _Symbol, " ",
EnumToString(_Period));
return INIT_SUCCEEDED;
}
//--- EA 被移除、換週期、關程式時執行一次
void OnDeinit(const int reason)
{
Comment(""); // 清掉圖表左上角的文字
Print("EA 結束,原因代碼 = ", reason,
",共收到 ", g_TickCount, " 個 tick");
}
//--- 每來一個報價(tick)就執行一次
void OnTick()
{
g_TickCount++;
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
// 圖表左上角即時顯示,不用開日誌也看得到
Comment("Hello World!\n",
"Tick 數:", g_TickCount, "\n",
"Ask:", DoubleToString(ask, _Digits),
" Bid:", DoubleToString(bid, _Digits), "\n",
"時間:", TimeToString(TimeCurrent(),
TIME_DATE | TIME_SECONDS));
// 每 100 個 tick 才寫一行日誌,避免洗版
if(g_TickCount % 100 == 0)
Print("Tick #", g_TickCount,
" Ask=", DoubleToString(ask, _Digits),
" Bid=", DoubleToString(bid, _Digits));
}
//+------------------------------------------------------------------+逐段說明
#property 那幾行是程式的說明資訊,會顯示在 EA 的屬性視窗,跟執行邏輯無關。
g_TickCount 宣告在所有函數外面,是全域變數,EA 掛著的期間值會一直保留,所以能一直累加。我的習慣是全域變數加 g_ 前綴,一眼就知道它是誰。
OnInit() 只在 EA 載入時跑一次,適合做初始化。最後一定要回傳 INIT_SUCCEEDED,回傳別的值 MT5 會直接把 EA 卸掉。
OnDeinit(const int reason) 在 EA 被移除、換週期、關程式時跑一次,reason 會告訴你是哪一種,代碼表放在文末。這裡順手用 Comment("") 把圖表左上角的文字清掉,不然 EA 拿掉了字還留在那。
OnTick() 是主角,每來一個報價就執行一次。SymbolInfoDouble(_Symbol, SYMBOL_ASK) 拿目前圖表商品的 Ask 價,_Symbol、_Period、_Digits 這幾個底線開頭的是 MT5 幫你準備好的預定義變數,分別是商品名稱、週期、小數位數。
Comment() 會把文字寫在圖表左上角,即時更新,不用開日誌就看得到,除錯很好用。Print() 則是寫進「專家」日誌,可以留下紀錄。因為 EURUSD 一天有幾千個 tick,Print 每個 tick 都寫會洗版,所以用 % 100 每一百個才寫一行。
DoubleToString(ask, _Digits) 是把價格轉成固定小數位的字串。直接把 double 丟給 Print 也可以印,但有時會印出 1.0358600000000001 這種東西,轉一下比較好看。
編譯
在 MetaEditor 按 F7(或工具列的「編譯」)。下面工具箱的「錯誤」頁會顯示結果,看到 0 errors 就成功了:
'HelloWorld.mq5' HelloWorld.mq5 1 1
code generated 1 1
0 errors, 0 warnings, 1345 msec elapsed成功後同一個資料夾會多出 HelloWorld.ex5。.mq5 是你寫的原始碼,.ex5 是編譯出來給 MT5 執行的檔案,MT5 只認 .ex5。改了程式碼一定要重新編譯,不然圖表上跑的還是舊的。
如果有錯誤,工具箱會列出行號跟訊息,雙擊那一行會直接跳到出錯的位置。初學最常見的是漏分號、大括號沒成對,還有打到全形的標點符號(,、;「」),在程式碼裡全形符號一律是錯的,只能出現在字串跟註解裡。
掛到圖表上
- 回到 MT5,開一張圖表,例如 EURUSD H1。
- 按
Ctrl+N打開「導航」視窗,展開「EA交易」,應該會看到 HelloWorld。沒看到就在導航按右鍵「刷新」。 - 把 HelloWorld 拖到圖表上(或雙擊),會跳出屬性視窗。「一般」頁勾選「允許演算法交易」,按確定。這篇的 EA 不下單其實不勾也會跑,但養成習慣,之後的 EA 不勾就不能交易。
- 工具列上的「演算法交易」按鈕(
Ctrl+E)要是啟用(綠色)狀態,這是整個平台的總開關。
成功的話,圖表右上角會出現「HelloWorld」和一頂小帽子圖示,左上角開始跳 Comment 的文字,Tick 數會一直增加。帽子上如果有紅色叉叉,就是演算法交易沒開,回去檢查上面第 3、4 步。
日誌在下方「工具箱」(Ctrl+T)的「專家」頁,時間和來源(HelloWorld (EURUSD,H1))兩欄後面會看到這一行:
Hello World! EA 啟動:EURUSD PERIOD_H1沒有報價怎麼辦:用策略測試器
如果你是週末看這篇,掛上去只會看到 OnInit 那一行,Tick 數永遠是 0,因為休市沒有報價,OnTick 根本不會被呼叫。這不是程式壞了。這時候可以用策略測試器拿歷史資料餵給 EA,也是之後回測策略一定會用到的工具:
- MT5 按
Ctrl+R打開「策略測試」。 - EA 選 HelloWorld,商品 EURUSD,週期 H1,日期自己填 2025.01.02 到 2025.01.03,模式選「每個報價」。
- 按「開始」,幾秒就跑完。切到「日誌」頁看輸出。
我實際跑出來的結果是這樣,一天有 5706 個 tick:
2025.01.02 00:00:00 Hello World! EA 啟動:EURUSD PERIOD_H1
2025.01.02 00:33:30 Tick #100 Ask=1.03586 Bid=1.03546
2025.01.02 01:02:20 Tick #200 Ask=1.03516 Bid=1.03515
2025.01.02 01:27:20 Tick #300 Ask=1.03529 Bid=1.03527
...(中間略)
2025.01.02 23:33:20 Tick #5600 Ask=1.02632 Bid=1.02631
2025.01.02 23:58:20 Tick #5700 Ask=1.02678 Bid=1.02677
2025.01.02 23:59:59 EA 結束,原因代碼 = 1,共收到 5706 個 tick這也剛好說明了為什麼 Print 要每一百個 tick 才寫一行。
OnDeinit 的原因代碼
上面測試器結束時印出「原因代碼 = 1」。常見的幾個:
| 代碼 | 常數 | 意思 |
|---|---|---|
| 0 | REASON_PROGRAM | 程式自己呼叫 ExpertRemove() 結束 |
| 1 | REASON_REMOVE | 被從圖表移除(測試結束也算這個) |
| 2 | REASON_RECOMPILE | 重新編譯了,MT5 會自動重新載入 |
| 3 | REASON_CHARTCHANGE | 圖表換了商品或週期 |
| 4 | REASON_CHARTCLOSE | 圖表被關掉 |
| 5 | REASON_PARAMETERS | 使用者改了輸入參數 |
| 6 | REASON_ACCOUNT | 換了交易帳戶 |
| 8 | REASON_INITFAILED | OnInit 沒有回傳 INIT_SUCCEEDED |
| 9 | REASON_CLOSE | MT5 被關掉 |
其中 2 很實用:在 MetaEditor 按 F7 重新編譯,圖表上的 EA 會自動重跑一次 OnDeinit 再 OnInit,不用手動拿掉再掛回去。
練習
- 把 Print 的頻率改成每 500 個 tick 一行,重新編譯,觀察圖表上的 EA 有沒有自動重新載入。
- 在 Comment 裡多顯示一行點差:
ask - bid,再試著換算成點數(提示:除以_Point)。 - 把 EA 掛到 XAUUSD 跟 USDJPY 各一張圖,比較
_Digits印出來的價格小數位有什麼不同。
下一篇
環境有了、程式跑得起來,下一篇開始講 MQL5 語法:變數與型態、input 參數、if 判斷、迴圈、陣列。寫過 MT4 系列的人會發現九成一樣,我會把差異特別標出來。
本篇的 HelloWorld.mq5 可以在這裡下載:HelloWorld.mq5,放到 MQL5\Experts\ 底下,在 MetaEditor 打開按 F7 就能用。