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

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

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


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

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

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

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

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

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

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

選擇 EA 交易。

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

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

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

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

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

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

Mt4 101209161710
Mt4 101209161711

二、理解EA框架

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

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

理解EA框架

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

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

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

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

三、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 的語法,感謝大家的閱讀。


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

加入LINE社群量化交易討論群」無壓力討論與分享!

加入臉書社團「程式交易 Taiwan」即時獲取實用的資源!

Marco
Marco

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

文章: 5

6 則留言

  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;
    } //訂單歸零
    }
    }
    }
    //+——————————————————————+

發佈留言

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