程式交易教學

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

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



限時優惠代碼
在購買鈦金挑戰賽時輸入“TITANIUM30”,即獲得30%的折扣(優惠截止日期為2024年4月30日)。

優化了挑戰塞交易規則
無最低交易天數限制等優化了挑戰賽的交易規則。

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

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



【MQL編程基礎】|將ZigZag定義頭與肩並顯示買賣訊號的方法

1.登錄三個參數與兩個緩衝器

在本篇文章中,將利用稱為ZigZag的指標來定義頭與肩,並在頸線與突破的位置上,顯示買賣的箭頭訊號。ZigZag為MT4的標準配備,雖然亦可改造此原始檔案,但本次將使用iCustom函數來取得ZigZag的頂點資訊、從該數值定義頭與肩,並顯示買賣的訊號。

首先,在製作新檔案處選擇「自訂指標」,檔案名稱設定為「ZigZag_H_and_S」,參數為結合標準配備ZigZag的三個設定。第一個的名稱為「Depth」、預設值為「12」、第二個的名稱為「Deviation」、預設值為「5」、第三個的名稱為「Backstep」、預設值為「3」,接著點擊「下一步」。

自訂指標

在「自訂指標程式的事件處理常式」中,無需勾選「OnTimer」「OnChartEvent」即可進入下一步,並新增兩個緩衝器。買進訊號用的標籤設定為「UP」、樣式為「Arrow」、顏色為「Red」,另一個賣出訊號用的標籤設定為「DN」、樣式為「Arrow」、顏色為「DodgerBlue」。如此點擊「完成」便是雛形。

自訂指標程式的事件處理常式

2.變更緩衝器名稱並定義箭頭符號編碼

開啟檔案之後,先將買賣訊號的尺寸調大以利判別。將「#property indicator_width1」與「#property indicator_width2」的數值從「1」變為「5」。

#property indicator_width1 5

#property indicator_width2 5
另外,由於緩衝器的名稱過於冗長,可將「//— indicator buffers」的緩衝器名稱如此改變「UPBuffer」→「UP」、「DNBuffer」→「DN」,省略「Buffer」使其縮短(不縮短亦可)。

double UP[];

double DN[];
OnInit函數內的「//— indicator buffers mapping」緩衝器名稱也同樣如下進行變更。

SetIndexBuffer(0,UP);

SetIndexBuffer(1,DN);
其次,在「//— setting a code from the Wingdings charset as the property of PLOT_ARROW」定義箭頭符號的編碼。本次使用普通的箭頭,可如以下所示加以變更。233是向上箭頭、234則是向下箭頭的編碼。

SetIndexArrow(0,233);

SetIndexArrow(1,234);

3.回溯過去並搜尋ZigZag的點

在上述文章中,登錄了三個參數以及兩個緩衝器,並說明了如何定義箭頭符號的編碼。接下來,將在OnCalculate函數內製作主要迴路。

主要的迴路將從極限值開始計算至最新的K線。最低限度則是每次計算的K線,若極限值小於最低限度,則會就此設定為最低限度。

int limit = Bars – prev_calculated -1;

int min = 1;

if (limit < min) limit = min;

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

}
由於本次將搜尋ZigZag的模型,故最低限度會回溯至三個點,並從該處進行每一次計算。當一週計算結束之後, iCustom函數會搜尋ZigZag的點。需準備「count」來計算次數,當ZigZag數值並非「0」時,該處即是頂點,故會進行下一輪計算,而若其大於「3」以上,便會將該條列數值寫入最低限度。如此一來,就會在最低限度3點之前執行每一次的計算。

if (prev_calculated > 0) {

int count = 0;

for (int i = 1; i < Bars - 1; i++) {

double zz = iCustom(NULL, 0, “ZigZag”, Depth, Deviation, Backstep, 0, i);

if (zz != 0) count++;

if (count >= 3) {

min = i;

break;

}

}

}

4.將ZigZag 6個點的資訊儲存於序列中

接下來,與主要迴路相同,將以iCustom函數取得ZigZag資訊。本次為了判別頭與肩,必須記憶全部6個點,並定義K線編號與ZigZag數值,使其能夠分別儲存。其後會使用「ArrayInitialize」來重設序列、將最早找到的點作為第1點加以記憶。於此處回溯過去、搜尋剩餘的5點。逐一回溯、記憶,並在「n」為6的時候結束搜尋。

if (limit < min) limit = min;

double point[6];

int bar[6];

int n = 0;

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

double zz = iCustom(NULL, 0, “ZigZag”, Depth, Deviation, Backstep, 0, i);

if (zz != 0) {

ArrayInitialize(point, 0);

ArrayInitialize(bar, 0);

point[0] = zz;

bar[0] = i;

n = 1;

for (int j = i + 1; j < Bars - 1; j++) {

zz = iCustom(NULL, 0, “ZigZag”, Depth, Deviation, Backstep, 0, j);

if (zz != 0) {

point[n] = zz;

bar[n] = j;

n++;

}

if (n >= 6) break;

}

}

}

5.搜尋模型並顯示買賣訊號

在上述文章中,已將ZigZag 6個點的資訊儲存於序列中。其次,將針對圖表的形狀,組成模型搜尋迴路,以判別其為肩還是頭。此模型搜尋,只能在已儲存6個點的資訊之後方可執行。

首先是賣出訊號的顯示條件。如下方畫面所示,0點為高點,同時2點大於0點、2點又大於4點、5點則小於3點、且5點亦小於1點,故可視為頭與肩的模型成立。

ZigZag 6個點

當頭與肩的模型成立時,將從0點旁觀測前方的價格波動,若低於1點的低價,便會在該處顯示代表賣出訊號的向下箭頭,並結束迴路的處理,反之則會清空該數值。另外,當新的點出現時,也會在該處結束處理。

if (n >= 6) {

if (point[0] == High[bar[0]] && point[2] > point[0] && point[2] > point[4] && point[5] < point[3] && point[5] < point[1]) {

for (int k = i – 1; k >= 0; k–) {

if (Low[k] < point[1]) {

DN[k] = High[k];

break;

} else DN[k] = EMPTY_VALUE;

zz = iCustom(NULL, 0, “ZigZag”, Depth, Deviation, Backstep, 0, k);

if (zz != 0) break;

}

}

}
以相同方式來增加買進符號的顯示條件。此處的0點為低價、同時2點小於0點、且2點亦小於4點、5點則大於3點、且5點大於1點,因此可視為逆向的頭與肩。

逆向的頭與肩成立時,將從0點旁觀測前方的價格波動,若高於1點的高價,便會在該處顯示代表買進訊號的向上箭頭,並結束迴路的處理,反之則會清空該數值。另外,當新的點出現時,也會在該處結束處理。

if (point[0] == Low[bar[0]] && point[2] < point[0] && point[2] < point[4] && point[5] > point[3] && point[5] > point[1]) {

for (int k = i – 1; k >= 0; k–) {

if (High[k] > point[1]) {

UP[k] = Low[k];

break;

} else UP[k] = EMPTY_VALUE;

zz = iCustom(NULL, 0, “ZigZag”, Depth, Deviation, Backstep, 0, k);

if (zz != 0) break;

}

}
如此進行編譯並設定圖表,便會依照指定的條件,以箭頭顯示買賣訊號。

箭頭顯示買賣訊號

6.原始碼

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

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

//| ZigZag_H_and_S.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 2

#property indicator_plots 2

//— plot UP

#property indicator_label1 “UP”

#property indicator_type1 DRAW_ARROW

#property indicator_color1 clrRed

#property indicator_style1 STYLE_SOLID

#property indicator_width1 5

//— plot DN

#property indicator_label2 “DN”

#property indicator_type2 DRAW_ARROW

#property indicator_color2 clrDodgerBlue

#property indicator_style2 STYLE_SOLID

#property indicator_width2 5

//— input parameters

input int Depth = 12;

input int Deviation = 5;

input int Backstep = 3;

//— indicator buffers

double UP[];

double DN[];

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

//| Custom indicator initialization function |

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

int OnInit()

{

//— indicator buffers mapping

SetIndexBuffer(0, UP);

SetIndexBuffer(1, DN);

//— setting a code from the Wingdings charset as the property of PLOT_ARROW

SetIndexArrow(0, 233);

SetIndexArrow(1, 234);

//—

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

{

//—

int limit = Bars – prev_calculated – 1;

int min = 1;

if (prev_calculated > 0) {

int count = 0;

for (int i = 1; i < Bars - 1; i++) {

double zz = iCustom(NULL, 0, “ZigZag”, Depth, Deviation, Backstep, 0, i);

if (zz != 0) count++;

if (count >= 3) {

min = i;

break;

}

}

}

if (limit < min) limit = min;

double point[6];

int bar[6];

int n = 0;

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

double zz = iCustom(NULL, 0, “ZigZag”, Depth, Deviation, Backstep, 0, i);

if (zz != 0) {

ArrayInitialize(point, 0);

ArrayInitialize(bar, 0);

point[0] = zz;

bar[0] = i;

n = 1;

for (int j = i + 1; j < Bars - 1; j++) {

zz = iCustom(NULL, 0, “ZigZag”, Depth, Deviation, Backstep, 0, j);

if (zz != 0) {

point[n] = zz;

bar[n] = j;

n++;

}

if (n >= 6) break;

}

if (n >= 6) {

if (point[0] == High[bar[0]] && point[2] > point[0] && point[2] > point[4] && point[5] < point[3] && point[5] < point[1]) {

for (int k = i – 1; k >= 0; k–) {

if (Low[k] < point[1]) {

DN[k] = High[k];

break;

} else DN[k] = EMPTY_VALUE;

zz = iCustom(NULL, 0, “ZigZag”, Depth, Deviation, Backstep, 0, k);

if (zz != 0) break;

}

}

if (point[0] == Low[bar[0]] && point[2] < point[0] && point[2] < point[4] && point[5] > point[3] && point[5] > point[1]) {

for (int k = i – 1; k >= 0; k–) {

if (High[k] > point[1]) {

UP[k] = Low[k];

break;

} else UP[k] = EMPTY_VALUE;

zz = iCustom(NULL, 0, “ZigZag”, Depth, Deviation, Backstep, 0, k);

if (zz != 0) break;

}

}

}

}

}

//— 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提供的資金進行交易,獲得高達80%的交易利潤分成。



限時優惠代碼
在購買鈦金挑戰賽時輸入“TITANIUM30”,即獲得30%的折扣(優惠截止日期為2024年4月30日)。

優化了挑戰塞交易規則
無最低交易天數限制等優化了挑戰賽的交易規則。

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

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