如何打造自己的第一支EA-MT4 EA語法教學(一)

MT4 是一套看盤兼交易的軟體,並附帶程式自動交易的功能,要想執行自動交易就得寫一支程式,告訴 MT4 何時該進場何時該出場,所以我們就來用「MQL4」這程式語言,照著我們的交易邏輯去寫出 EA。

在使用 MT4 前必須有交易商的帳號才可以免費使用 MT4,推薦大家使用 OANDA 安達,進入外匯市場的首選經紀商完整介紹!

點擊連結,開戶註冊 OANDA 安達,進入外匯市場!

Oanda 101203231041
Oanda 101203231042

如果還不熟悉 MT4 的基本用法,可以先參考以下文章!

一、打開 EA 編輯程式,並創建 EA 檔案

MT4 有內建一套程式碼編輯軟體「MetaEditor」,我們使用它來撰寫 EA。

首先打開 MT4,點擊下圖圈起來的圖示。

打開 EA 編輯程式,並創建 EA 檔案-1

打開來之後點擊文件>>新文件。

打開 EA 編輯程式,並創建 EA 檔案-2

選擇 EA 交易。

打開 EA 編輯程式,並創建 EA 檔案-3

接著幫我們的 EA 取一個名字,我這邊取作「第一支 EA」。

打開 EA 編輯程式,並創建 EA 檔案-4

接下來就一直按下一步,直到這個畫面:

打開 EA 編輯程式,並創建 EA 檔案-5

看到這個畫面先不要慌,讓我們一起來理解一下這些文字的作用。

二、理解EA框架

首先,這是一個MT4 EA專屬的程式碼框架,我們在這框架之下撰寫的EA才能正確執行,接下來我們來好好講解一下這個框架。

這份程式碼主要可以分成四大區塊,如下圖所示。

理解EA框架

第 1 個區塊:可以用來設定 EA 參數、變數、屬性或是宣告一些函式(function)供程式使用 。

第 2 個區塊:用來執行EA 初始化的區塊 。

第 3 個區塊:當 EA 從執行狀態下被移除時會執行的區塊 。

第 4 個區塊:當 MT4 接受到新的報價時就會執行該區塊內的程式碼,所以我們的交易邏輯主要會是寫在這裡。

點擊連結,開戶註冊 OANDA 安達,進入外匯市場!

Oanda 101203231041
Oanda 101203231042

三、MQL4基本語法要素

每一種語言,都由不同的基本詞彙構成。而在 MT4 的 MQL4 當中,基本的程式碼分為以下幾種要素(在編輯器中為了讓使用者方便識別,預設會用不同的顏色呈現):

程式碼 說明
標點符號 程式碼中通常會包含標點符號,絕大多數程式碼都是使用半形符號。舉個例子來說,在 MQL4 要結束一行程式碼要使用分號「 」,預設為黑色
內建保留字 組成策略的基礎要素,在 MQL4 中已經建立好常用的,內建字是無法被更改的,大致如下:
( 1 ) 資料型別(intdoublestringbooldatetimecolorvoid 等)
( 2 ) 訪問規範(const 等)
( 3 ) 記憶體類別(exturninputstatic 等)
( 4 ) 運算符(ifelseforwhileswtichbreak 等)
( 5 ) 其他類型(truefalsethis#defined#property#include等)
預設為藍色紅色
運算符 基本的數學運算、邏輯運算
( 1 ) 數學運算(加+、減–、乘*、除/)
( 2 ) 邏輯運算(大於>大於等於>=小於<小於等於<=等於==不等於!=
預設為黑色
文字串、數字 只要使用雙引號「“文字”」夾住的都是文字,預設為淺綠色
常數 一些值固定不變的常數,通常以大寫英文字與底線(_)命名,例如:
( 1 ) 訂單類型(OP_BUYOP_SELL 等)
( 2 ) 價格類型(PRICE_CLOSEPRICE_OPEN 等)
( 3 ) 其他類型(MODE_UPPERMODE_MAIN 等)
預設為紅色
EA的參數 預設為棕色
變數 預設為黑色
函式 自訂函式或是內建函式,例如:
( 1 ) 訂單函式(OrdersTotal()OrderSend()、OrderProfit() 等)預設為紫色
( 2 ) 通用函式(Print()Alert()等)預設為紫色
( 3 ) 指標函式(iMA()iMACD()、iBands() 等)預設為淺綠色
內建變數 在 MQL4 中已經建立好常用的,內建字是無法被更改的,內建字包含以下幾種:
( 1 ) 報價相關字(BidAskDigits 等)
( 2 ) K 棒相關字(OpenHighLowClose等)
預設桃紅色
註解 用於註記或是說明程式碼用途的文字,不會被EA執行。
( 1 ) 單行註解,以「//」開頭
( 2 ) 多行註解,以「/*」開頭,「*/」結尾
預設為灰色

四、語法講解

我們先來看個完整範例:

MT4 EA 語法講解-1

接下來我們逐一區塊來講解:

首先是4~15行

MT4 EA 語法講解-2

1. EA屬性宣告

#property 開頭,用來宣告 EA 的一些屬性,如:作者、網站連結、版本號等。

2. EA參數 / 變數宣告

講參數前我們先來理解一下變數,變數是用來記錄EA執行時需要的一些數值,而在宣告變數前要先宣告其「形態」。

基本的型態有以下這些:

  • 整數型態(int):正負整數,如 0、1、3、-4、-100
  • 實數型態(double):正負小數點,如 0.0、1.0、3.14、-4.25、-10.99
  • 布林型態(bool):只有兩種,真(true)或假(false)
  • 字符串型態(string):用2個雙引號包起來的文字,如 “ea”、”我的EA”、”000000”

當我們在宣告變數時會先宣告型態,然後接一個空格,再寫上變數名稱,如上圖程式碼的第 14 行:
int bars = 0// 用於紀錄圖表K棒數量

這裡的 int 就是在宣告整數型態的變數,而 bars 則為變數名稱,
在這我們還使用「=」將其初始值設為 0
最後接上「;」就完成變數的宣告了,
後面灰色字的部分則為註解,EA並不會去讀取並執行。

接下來我們來講參數,以 inputextern 開頭,用來宣告 EA 的一些可調整參數,也能視為一種變數。

但是用input做開頭的參數只能在掛載 EA 時去修改它的值,而 extern 開頭的則可以在程式碼內去修改值。

值得注意的是在參數後面接的單行註解會在 MT4 的 EA 參數設定畫面顯示。

  • 沒加註解:
MT4 的 EA 參數設定畫面-沒加註解
  • 有加註解:
MT4 的 EA 參數設定畫面-有加註解

3. EA初始化

MT4 EA初始化

OnInit() 這個函式內執行 EA 初始化的程式碼,這裡我們將上面宣告的 bars 變數的值設為 EA 掛的圖表的 K棒數量,Bars 為內建保留字,會返回 EA 掛的圖表的 K棒數量。

4. EA移除時執行

MT4 EA 移除時執行

當 EA 被移除時會執行 OnDeinit() 這個函式內的程式碼,這裡我們使用內建的函式 Alert() ,發出警示提醒我們 EA 已被移除。

5. 接收到新報價

MT4 接收到新報價

當 EA 接收到新報價時就會執行 OnTick() 這個函式內的程式碼,這裡我們來寫上進出場邏輯,我們的邏輯如下:

  1. K 棒收定時執行進出場判斷
  2. 收盤價大於 MA 進多單
  3. 收盤價小於 MA 平倉多單

第 46 行
第一步,我們要先知道進來 OnTick ()的當下是否為 K 棒收定,所以我們第 46 行使用 if 這個條件判斷式,當 if 後面小括號內的條件式都為 true 時就執行大括號內的程式碼,bars != Bars 的意思是 bars 的值不等於 EA 掛的圖表的K棒數量。

我們在 EA初始化時有執行 bars = Bars,而當新報價進來時發現 bars != Bars 這就意味著有新的 K棒出現了,上一根 K棒為收定狀態,此時就滿足了我們第一個條件「K 棒收定時執行進出場判斷」。

第 47 行
我們又再次執行 bars = Bars 以同步 EA 紀錄的K棒數量,避免下一個報價進來,而 K棒卻還不是收定狀態時執行第 46 行後的程式碼。

48~50 行為進場條件判斷
一樣使用 if 來做判斷,EA 沒有訂單且最新收定的 K棒收盤價大於當下 MA值,這裡的 Close[1]意思是圖表由右往左數第 2 根 K棒的收盤價,而第一根 K 棒的收盤價就是 Close[0],由此可知越新的 K 棒它的序號是越小的,並且是從 0 開始。

接下來我們來看一下
iMA(Symbol(), PERIOD_CURRENT, maPeriod, 0, MODE_SMA, PRICE_CLOSE, 0)

iMA()是一個內建的指標函式,透過傳入不同的參數獲取不同狀況下 MA 的值
iMA()參數如下:

  1. 貨幣兌名稱:這裡傳入 Symbol(),是內建函式,為當前 EA 掛的圖表的貨幣兌名稱
  2. 套用時間周期: 這裡傳入 PERIOD_CURRENT,是內建常數,為當前 EA 掛的圖表的時間周期
  3. MA 時間周期參數:這裡傳入 maPeriod,為我們在一開始宣告的EA參數
  4. MA 偏移量參數: 這裡傳入 0
  5. MA 移動平均算法參數:這裡傳入 MODE_SMA,是內建常數,表示使用簡單移動平均算法
  6. MA 套用價格參數: 這裡傳入 PRICE_CLOSE,是內建常數,表示使用收盤價來做 MA 運算
  7. K 棒序號:這裡傳入 0,表示取得最新一根 K棒的 MA值

當 48 行滿足條件時執行 49 行的進場語法 OrderSend(Symbol(), OP_BUY, lots, Ask, 3, 0, 0)
OrderSend() 是一個內建的下單語法,下單成功會回傳訂單編號,若失敗則會回傳 -1,我們用 ticket 這個變數來記錄,


OrderSend() 參數如下:

  1. 貨幣兌名稱:這裡傳入 Symbol() , 是內建函式,為當前 EA 掛的圖表的貨幣兌名稱
  2. 下單類型:這裡傳入 OP_BUY, 是內建常數,為一般多單類型
  3. 下單手數:這裡傳入 lots,為我們在一開始宣告的 EA 參數
  4. 進場價格:這裡傳入 Ask,是內建保留字,為賣價,由於我們要下的是市價多單於是這裡要給賣價
  5. 容許的滑點:這裡傳入 3,表示允許訂單在進場價格+-3點內成交
  6. 停損價格:我們這裡不做停損的設置,故填入 0
  7. 停利價格:同上

第 51~56 行為出場條件判斷
當 EA 有訂單且最新收定的 K 棒收盤價小於 MA 時,執行平倉語法 OrderClose(ticket, lots, Bid, 3) 。

OrderClose() 是一個內建的平倉語法,平倉成功會回傳 true,若失敗則會回傳 false,我們宣告 result 這個變數來暫時紀錄平倉結果,若為 true 則將 ticket 變數紀錄的訂單編號歸零。

OrderClose()參數如下:

  1. 訂單編號:這裡傳入 ticket
  2. 平倉手數:這裡傳入 lots,為我們在一開始宣告的EA參數
  3. 平倉價格:這裡傳入 Bid,是內建保留字,為買價,由於我們要平倉的是多單於是這裡要給買價
  4. 容許的滑點:這裡傳入3,表示允許訂單在平倉價格 +-3 點內成交

以上就是我們一隻包含參數設置、指標運用、進出場語法的 EA。在這裡我們先粗略的體驗一下 EA 撰寫的方式,下一篇文章 我們再來詳細的解說 MQL4 的語法,感謝大家的閱讀。

MT4 EA 語法教學系列:


量化通粉絲社群,一起討論程式交易!

加入LINE匿名群組量化通QuantPass」無壓力討論與分享!

追蹤量化通的粉絲專頁量化通QuantPass」即時獲取實用的資源!

程式交易課程推薦
📣 MT4 程式交易系列線上課程,手把手開始用程式交易打造自己的被動收入!

Marco
Marco

8年經驗法人級EA開發者,已開發過至少百隻EA、腳本、外部套件等相關MT4/MT5程式,期間曾開發過跨交易所/經紀商對沖避險EA、動態權重馬丁策略、多商品網格策略、也專門開發設計各式網站、金流電商等,將程式與交易視為志業,持續精進自己的人。

文章: 5

4 則留言

  1. 你好,找到這教學, 非常實用有用!想請教, mt4能否用在掃描一堆資產那一隻符合我的技術指標?例如我想在小時圖找出所有rsi少於30的, 請問這個能否做到? 非常多謝你😃

    • 可以的,只要先抓出所有商品的symbol name再一個個帶入指標計算即可
      下面是抓出所有商品symbol name的語法

      int total = SymbolsTotal(false);
      for(int i = 0; i < total; i++) {
      string symbolName = SymbolName(i, false);
      Print(symbolName);
      }

  2. 你好
    我按照你的範例打上去後,出現了
    ‘}’ – semicolon expected A2.mq4 44 10
    ‘}’ – semicolon expected A2.mq4 67 10
    ‘result’ – variable already defined A2.mq4 73 16
    ‘}’ – unexpected end of program A2.mq4 80 3
    四個錯誤,我改來改去越改錯越多,請問問題出在哪裡了QQ

    void OnTick()
    {
    //—
    if (bars != Bars)
    {
    bars = Bars;
    //如果EA沒有訂單且K棒收盤大於MA

    if (ticket iMA(Symbol(), PERIOD_CURRENT, maPeriod, 0, MODE_SMA, PRICE_CLOSE, 0))

    //則執行進場動作,進多單並記錄訂單編號

    ticket = OrderSend(Symbol(), OP_BUY, lots, Ask,3, 100, 0)
    }

    {
    if (ticket > 0 && Close[1] < iMA(Symbol(), PERIOD_CURRENT, maPeriod, 0, MODE_SMA, PRICE_CLOSE, 0))
    //市價平倉多單

    bool result = OrderClose(ticket, lots, Bid, 3);
    if(result == true) //如果平倉成功
    {
    ticket = 0;
    } //訂單歸零
    }
    {
    if (bars != Bars)
    {
    bars = Bars;
    //如果EA沒有訂單且K棒收盤大於MA

    if (ticket <= 0 && Close[1] < iMA(Symbol(), PERIOD_CURRENT, maPeriod, 0, MODE_SMA, PRICE_CLOSE, 0))

    //則執行進場動作,進多單並記錄訂單編號

    ticket = OrderSend(Symbol(), OP_SELL, lots, Bid,3, 100, 0)
    }

    {
    if (ticket < 0 && Close[1] < iMA(Symbol(), PERIOD_CURRENT, maPeriod, 0, MODE_SMA, PRICE_CLOSE, 0))
    //市價平倉多單

    bool result = OrderClose(ticket, lots, Ask, 3);
    if(result == true) //如果平倉成功
    {
    ticket = 0;
    } //訂單歸零
    }
    }
    }
    //+——————————————————————+

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *