誠邀您參加全球知名外匯經紀商OANDA的自營交易(Prop Trader)
報名OANDA自營交易(Prop Trader),並通過我們的考核,您就可以使用OANDA提供的資金進行交易,獲得高達90%的交易利潤分成。
全面升級——更多功能、更大靈活性!
優化了“固定最大虧損”,“每日虧損限制”等。查看詳情全新「Boost」計劃
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另外,由於緩衝器的名稱過於冗長,可將「//— indicator buffers」的緩衝器名稱如此改變「UPBuffer」→「UP」、「DNBuffer」→「DN」,省略「Buffer」使其縮短(不縮短亦可)。
#property indicator_width2 5
double UP[];OnInit函數內的「//— indicator buffers mapping」緩衝器名稱也同樣如下進行變更。
double DN[];
SetIndexBuffer(0,UP);其次,在「//— setting a code from the Wingdings charset as the property of PLOT_ARROW」定義箭頭符號的編碼。本次使用普通的箭頭,可如以下所示加以變更。233是向上箭頭、234則是向下箭頭的編碼。
SetIndexBuffer(1,DN);
SetIndexArrow(0,233);
SetIndexArrow(1,234);
3.回溯過去並搜尋ZigZag的點
在上述文章中,登錄了三個參數以及兩個緩衝器,並說明了如何定義箭頭符號的編碼。接下來,將在OnCalculate函數內製作主要迴路。主要的迴路將從極限值開始計算至最新的K線。最低限度則是每次計算的K線,若極限值小於最低限度,則會就此設定為最低限度。
int limit = Bars – prev_calculated -1;由於本次將搜尋ZigZag的模型,故最低限度會回溯至三個點,並從該處進行每一次計算。當一週計算結束之後, iCustom函數會搜尋ZigZag的點。需準備「count」來計算次數,當ZigZag數值並非「0」時,該處即是頂點,故會進行下一輪計算,而若其大於「3」以上,便會將該條列數值寫入最低限度。如此一來,就會在最低限度3點之前執行每一次的計算。
int min = 1;
if (limit < min) limit = min;
for (int i = limit; i >= 0; i–) {
}
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點,故可視為頭與肩的模型成立。
當頭與肩的模型成立時,將從0點旁觀測前方的價格波動,若低於1點的低價,便會在該處顯示代表賣出訊號的向下箭頭,並結束迴路的處理,反之則會清空該數值。另外,當新的點出現時,也會在該處結束處理。
if (n >= 6) {以相同方式來增加買進符號的顯示條件。此處的0點為低價、同時2點小於0點、且2點亦小於4點、5點則大於3點、且5點大於1點,因此可視為逆向的頭與肩。
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點旁觀測前方的價格波動,若高於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自動程式交易的基本知識,以及在MT4/MT5平台上的安裝、參數設定方法、編碼等等內容。另外,對持有OANDA帳戶的客戶,還可以免費使用我們的獨有EA與指標工具。
誠邀您參加全球知名外匯經紀商OANDA的自營交易(Prop Trader)
報名OANDA自營交易(Prop Trader),並通過我們的考核,您就可以使用OANDA提供的資金進行交易,獲得高達90%的交易利潤分成。
全面升級——更多功能、更大靈活性!
優化了“固定最大虧損”,“每日虧損限制”等。查看詳情全新「Boost」計劃
500,000美元交易資金
您可以使用最高500,000美元的資金進行交易。
豐富的交易商品
您可以交易包括外匯、黃金、原油、股票指數等多種商品。