程式交易教學

誠邀您參加全球知名外匯經紀商OANDA的自營交易(Prop Trader)

報名OANDA自營交易(Prop Trader),並通過我們的考核,您就可以使用OANDA提供的資金進行交易,獲得高達90%的交易利潤分成。



全面升級——更多功能、更大靈活性!
優化了“固定最大虧損”,“每日虧損限制”等。查看詳情全新「Boost」計劃

500,000美元交易資金
您可以使用最高500,000美元的資金進行交易。

豐富的交易商品
您可以交易包括外匯、黃金、原油、股票指數等多種商品。



【MQL編程基礎】|以不同方式比較多週期框架移動平均線(MA)的方法

1.在製作新檔案時增加參數與緩衝

在本篇文章中,將說明如何以不同方式比較多週期框架移動平均線(MA)。本次將透過以下四個方式來比較多週期框架MA。

    ①僅利用上一級別時間週期的MA數值。使用iBarShift函數,依照上一級別時間週期的數值顯示階梯狀的多週期框架。

    ②連結上述①中所製作的MA確定點。也就是所謂平滑化圖形。

    ③將MA週期乘以上一級別時間週期比率的偽多週期框架方式。舉例來說,若上一級別時間週期為1小時週期,顯示的時間週期則是15分鐘週期,則因1小時週期為60分鐘,故可知是15分鐘週期的4倍。將1小時週期中的20週期MA在15分鐘圖表中顯示時,該週期便會變成4倍的80MA。

    ④針對已確定的K線,使用上一級別時間週期的收盤價,至於尚未確定的最新K線,則採用顯示中的K線收盤價,屬於複合式的方法。(此④可呈現出最貼近實際的顯示內容)
首先,在製作新檔案處選擇「自訂指標」,檔案名稱設定為「MTF_MA_test」並新增為參數。本次的MA週期名稱登錄為「PERIOD」、類型為「int」、初始數值為「20」。

自訂指標

在「自訂指標程式的事件處理常式」畫面中,無需勾選「OnTimer」或「OnChartEvent」即可進入下一步,並在「客製化指標的繪圖屬性」畫面欄位中,新增MA用的四個緩衝。

第一個的標籤登錄為「MA0」、顏色為「White」,第二個的標籤為「MA1」、顏色為「Magenta」,第三個的標籤為「MA2」、顏色為「DodgerBlue」,第四個的標籤為「MA3」、顏色為「YellowGreen」,如此點擊「完成」即是雛形。

顏色

2.變更MA的線條種類,並指定時間週期

接下來,將透過檔案上方的屬性,變更MA0、MA1、MA2的線條種類。MA0設定為「STYLE_DOT」、MA1為「STYLE_DASH」、MA2則是「STYLE_DASHDOT」。

關於MA1,繪圖類型應從「DRAW_LINE」更改為「DRAW_SECTION」。若維持原本的LINE,只要刪除中間點的數值,便會無法連接線條,改成SECTION之後即能以直線連接多點。

//— plot MA0

#property indicator_style1 STYLE_DOT

//— plot MA1

#property indicator_type2 DRAW_SECTION

#property indicator_style2 STYLE_DASH

//— plot MA2

#property indicator_style3 STYLE_DASHDOT
另外,由於緩衝名稱過於冗長,因此以「MA0Buffer」→「MA0」的方式省略「Buffer」。

double MA0[];

double MA1[];

double MA2[];

double MA3[];
針對OnInit函數中「//— indicator buffers mapping」的緩衝名稱,也同樣如以下所示將之縮短。

SetIndexBuffer(0,MA0);

SetIndexBuffer(1,MA1);

SetIndexBuffer(2,MA2);

SetIndexBuffer(3,MA3);
其次,要新增指定時間週期的參數。本次使用的是列舉型的「ENUM_TIMEFRAMES」,指定為1小時週期。在「//— input parameters」下方添加以下編碼。

input ENUM_TIMEFRAMES TF = PERIOD_H1;

3.顯示階梯狀的多週期框架MA

在上述內容中,變更了MA的線條種類並縮短緩衝名稱,也新增了能夠指定時間週期的參數。接下來,將在OnCalculate函數內製作主要迴路,並顯示多週期框架MA。

本次將上一級別時間週期設定為1小時,一旦顯示的圖表大於1小時週期,便會就此結束處理動作。將計算週期的最大值定義為「limit」、最小值為「min」。當limit小於min時,會繼續計算至 min,且每次至少會計算至等同於上一時間週期的數量。

if (_Period > TF) return 0;

int limit = Bars – prev_calculated -2;

int min = PeriodSeconds(TF) / PeriodSeconds();

if (limit < min) limit = min;
接下來,將自定義的limit至最新K線為止進行計算。以「iBarShift」取得與上一時間週期相應的K線編號,並藉此顯示多週期框架MA。

for (int i = limit; i >= 0; i–) {

int bar = iBarShift(NULL, TF, Time[i]);

MA0[i] = iMA(NULL, TF, PERIOD, 0, MODE_SMA, PRICE_CLOSE, bar);

}
如此進行編譯並設定圖表,便會見到多週期框架MA呈現階梯狀。

MA呈現階梯狀

4.連接MA0確定點,顯示平滑化圖形的多週期框架MA

接下來,將連接階梯狀多週期框架MA的確定點,並顯示平滑化圖形的MA。直到中途的處理方式都與MA0相同,其後則在前一根K線的位置,顯示相應的上一級別時間週期編號,若當前K線所見的前一根K線等同於上一級別時間週期,便將前一K線數值留為空白。如此一來,尚未完成的數值就會消失,僅剩下確定的點。

MA1[i] = iMA(NULL, TF, PERIOD, 0, MODE_SMA, PRICE_CLOSE, bar);

int barPre = iBarShift(NULL, TF, Time[i + 1]);

if (bar == barPre) MA1[i + 1] = EMPTY_VALUE;
如此進行編譯,即可追加顯示只連接MA0確定點的多週期框架MA。

多週期框架MA

5.顯示偽多週期框架MA

本次會將MA週期乘以上一級別時間週期的比率,顯示出偽多週期框架MA。因希望計算目前的時間週期,因此時間週期設定為「0」,將週期乘以上一級別時間週期的比率,設定為「PERIOD * min」。本次顯示MA的時間週期為15分鐘,而上一時間週期為1小時,因此min=4,也就是週期會變成4倍。

MA2[i] = iMA(NULL, 0, PERIOD * min, 0, MODE_SMA, PRICE_CLOSE, i);
如此進行編譯,便會追加顯示水藍色的偽多週期框架MA。其動作會稍微慢於平滑化的MA1。

偽多週期框架MA

6.顯示復合式的多週期框架MA

在上一章節中,利用上一級別時間週期的MA數值,顯示出階梯狀的多週期框架MA、以及連接該確定點的平滑化圖形多週期框架MA,並將週期乘以上一級別時間週期的比率,顯示出偽多週期框架MA等3種方式。最後,將顯示復合式的多週期框架MA。

此復合式多週期框架MA的計算方式中,會針對已確定的K線,使用上一級別時間週期的收盤價,至於尚未確定的最新K線,則採用顯示中的K線收盤價。首先定義能合併計算收盤價的「sum」變數,從1開始至PERIOD為止,一併計算19條上一級別時間週期的收盤價。其得出的總計數字,會加上顯示中的時間週期收盤價,最後再除以PERIOD。

double sum = 0;

for (int j = 1; j < PERIOD; j++) {

sum += iClose(NULL, TF, bar + j);

}

MA3[i] = (sum + Close[i]) / PERIOD;
如此進行編譯,便會追加顯示綠色的複合式多週期框架MA。

複合式多週期框架MA

比起平滑化的線條,利用實際的上一級別時間週期數值,謹慎計算而得出的複合式多週期框架MA,更能夠描繪出近似於階梯狀線條的軌跡。從這樣的結果來看,可知一旦將MA平滑化,便會與實際的數值出現較大落差。

7.原始碼

本次製作的原始碼如以下所示。

//+——————————————————————+

//| MTF_MA_test.mq4 |

//| Copyright 2022, MetaQuotes Software Corp. |

//| https://www.mql5.com |

//+——————————————————————+

#property copyright “Copyright 2022, MetaQuotes Software Corp.”

#property link “https://www.mql5.com”

#property version “1.00”

#property strict

#property indicator_chart_window

#property indicator_buffers 4

#property indicator_plots 4

//— plot MA0

#property indicator_label1 “MA0”

#property indicator_type1 DRAW_LINE

#property indicator_color1 clrWhite

#property indicator_style1 STYLE_DOT

#property indicator_width1 1

//— plot MA1

#property indicator_label2 “MA1”

#property indicator_type2 DRAW_SECTION

#property indicator_color2 clrFuchsia

#property indicator_style2 STYLE_DASH

#property indicator_width2 1

//— plot MA2

#property indicator_label3 “MA2”

#property indicator_type3 DRAW_LINE

#property indicator_color3 clrDodgerBlue

#property indicator_style3 STYLE_DASHDOT

#property indicator_width3 1

//— plot MA3

#property indicator_label4 “MA3”

#property indicator_type4 DRAW_LINE

#property indicator_color4 clrYellowGreen

#property indicator_style4 STYLE_SOLID

#property indicator_width4 1

//— input parameters

input ENUM_TIMEFRAMES TF = PERIOD_H1;

input int PERIOD = 20;

//— indicator buffers

double MA0[];

double MA1[];

double MA2[];

double MA3[];

//+——————————————————————+

//| Custom indicator initialization function |

//+——————————————————————+

int OnInit()

{

//— indicator buffers mapping

SetIndexBuffer(0, MA0);

SetIndexBuffer(1, MA1);

SetIndexBuffer(2, MA2);

SetIndexBuffer(3, MA3);

//—

return(INIT_SUCCEEDED);

}

//+——————————————————————+

//| Custom indicator iteration function |

//+——————————————————————+

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[])

{

//—

if (_Period > TF) return 0;

int limit = Bars – prev_calculated – 2;

int min = PeriodSeconds(TF) / PeriodSeconds();

if (limit < min) limit = min;

for (int i = limit; i >= 0; i–) {

int bar = iBarShift(NULL, TF, Time[i]);

MA0[i] = iMA(NULL, TF, PERIOD, 0, MODE_SMA, PRICE_CLOSE, bar);

MA1[i] = iMA(NULL, TF, PERIOD, 0, MODE_SMA, PRICE_CLOSE, bar);

int barPre = iBarShift(NULL, TF, Time[i + 1]);

if (bar == barPre) MA1[i + 1] = EMPTY_VALUE;

MA2[i] = iMA(NULL, 0, PERIOD * min, 0, MODE_SMA, PRICE_CLOSE, i);

double sum = 0;

for (int j = 1; j < PERIOD; j++) {

sum += iClose(NULL, TF, bar + j);

}

MA3[i] = (sum + Close[i]) / PERIOD;

}

//— return value of prev_calculated for next call

return(rates_total);

}

將EA自動程式交易應用於外匯與差價合約交易中

EA

我們以圖文形式詳細介紹有關EA自動程式交易的基本知識,以及在MT4/MT5平台上的安裝、參數設定方法、編碼等等內容。另外,對持有OANDA帳戶的客戶,還可以免費使用我們的獨有EA與指標工具。

誠邀您參加全球知名外匯經紀商OANDA的自營交易(Prop Trader)

報名OANDA自營交易(Prop Trader),並通過我們的考核,您就可以使用OANDA提供的資金進行交易,獲得高達90%的交易利潤分成。



全面升級——更多功能、更大靈活性!
優化了“固定最大虧損”,“每日虧損限制”等。查看詳情全新「Boost」計劃

500,000美元交易資金
您可以使用最高500,000美元的資金進行交易。

豐富的交易商品
您可以交易包括外匯、黃金、原油、股票指數等多種商品。