誠邀您參加全球知名外匯經紀商OANDA的自營交易(Prop Trader)
報名OANDA自營交易(Prop Trader),並通過我們的考核,您就可以使用OANDA提供的資金進行交易,獲得高達90%的交易利潤分成。
優化了挑戰塞交易規則
無最低交易天數限制等優化了挑戰賽的交易規則。
500,000美元交易資金
您可以使用最高500,000美元的資金進行交易。
豐富的交易商品
您可以交易包括外匯、黃金、原油、股票指數等多種商品。
【MQL編程基礎】|將ZigZag按道氏理論分色顯示的方法
1.開啟ZigZag編碼並命名保存
在本篇文章中,將介紹將ZigZag按道氏理論分色顯示的方法。ZigZag 是MT4標準配備的指標,能以直線顯示頂底,為相當便利的工具。
本次將山峰高點與山谷低點一同上揚的波形定義為上升趨勢,一同下降的波形則定義為下跌趨勢,並以顏色區分顯示。
此處將不會從頭製作程式,而是使用ZigZag改造而成。首先在圖表上設定ZigZag。為了顯示更多ZigZag的頂底,故將參數的Depth數值設定為「5」。
為了改造ZigZag的程式,在MT4導覽中的「ZigZag」上點擊右鍵,再點擊「修改」並開啟檔案。
其次,點擊MetaEditor的「文件」→「另存為」、將名稱變更為「Colorful_ZigZag」加以保存。
2.新增上升趨勢用與下跌趨勢用的緩衝器
以新名稱保存之後,就要來改造編碼。首先新增三個緩衝器。在檔案上方的屬性中,將「#property indicator_buffers」的「1」變更為「3」、並於其下新增「#property indicator_color2」與「#property indicator_color3」。第一個設定為白色、第二個為紅色、第三個則是藍色。另外,也在此處指定線條的寬度。第一條線為細線、第二條與第三條則使用粗線以便目視。#property indicator_buffers 3接著,在「double ExtLowBuffer[];」下方添加上升趨勢用與下跌趨勢用的緩衝器。
#property indicator_color1 clrWhite
#property indicator_color2 clrRed
#property indicator_color3 clrDodgerBlue
#property indicator_width1 1
#property indicator_width2 3
#property indicator_width3 3
double UP[], DN[];同時,將OnInit函數內的「//— 2 additional buffers」緩衝器數量從「3」添加至「5」。
IndicatorBuffers(5);其次,在第2個「//—- indicator buffers」新增「UP」、第3個新增「DN」,將編號做出區隔。
SetIndexBuffer(0,ExtZigzagBuffer);另外,因本次使用「DRAW_LINE」來繪製線條,故應在「//—- drawing settings」的「SetIndexStyle(0, DRAW_SECTION);」下方添加下列2行。
SetIndexBuffer(1,UP);
SetIndexBuffer(2,DN);
SetIndexBuffer(3,ExtHighBuffer);
SetIndexBuffer(4,ExtLowBuffer);
SetIndexStyle(1, DRAW_LINE);如此便完成了基礎檔案的準備。其他部分則可直接沿用,並在必要時添加迴路。
SetIndexStyle(2, DRAW_LINE);
3.準備四組序列並儲存資訊
前文沿用了ZigZag的程式,並新增了上升趨勢用與下跌趨勢用的緩衝器。接下來,將針對上升線與下降線,新增以不同顏色顯示的迴路。首先將定義計算的範圍,本次為了判別高價與低價的上移、下移模式,需再次計算直至找到ZigZag的四個點。在ZigZag的緩衝器「ExtZigzagBuffer」並非「0」的狀況下進行計算,當計算達到「4」時則結束搜尋。將該條列儲存為最小計算範圍,並除去for文體。
limit = Bars – prev_calculated – 1;其次,至該儲存的數值為止,重複進行最低限度的計算。由於需記憶ZigZag四個點的數值、以及K線編號的數值,因此應準備四組序列。當找到點的時候,在第一個序列寫入該資訊,並將計算作為「1」。
int min = 0;
int count = 0;
for (i = 0; i < Bars - 1; i++) {
if (ExtZigzagBuffer[i] != 0) count++;
if (count >= 4) {
min = i;
break;
}
}
if (limit < min) limit = min;本次將從找到的「i」的前1條列,回溯過去的所有序列進行搜尋。當「j」的條列並非「0」時,即可儲存第二個序列之後的點,並在計算達到4以上時結束。如此便在序列bar[]與zz[]儲存四個ZigZag的頂點資訊。
int bar[4];
double zz[4];
for (i = limit; i >= 0; i–) {
if (ExtZigzagBuffer[i] != 0) {
bar[0] = i;
zz[0] = ExtZigzagBuffer[i];
count = 1;
}
}
for (int j = i + 1; j < Bars - 1; j++) {另外,為了在每一次都能重設四個序列,需將能透過指定數值將序列初始化的「ArrayInitialize」寫入於「for (i = limit; i >= 0; i–) {」之下。
if (ExtZigzagBuffer[j] != 0) {
bar[count] = j;
zz[count] = ExtZigzagBuffer[j];
count++;
if (count >= 4) break;
}
}
ArrayInitialize(bar, -1);
ArrayInitialize(zz, 0);
4.搜尋價格波動模型並判別趨勢
接下來,在搜尋完序列之後,若最後一個條列為「-1」,便需使用「continue」以停止後續處理。if (bar[3] == -1) continue;此後續處理,意即搜尋高價與低價的上移、下移判別模型。如以下畫面所示,0點為高價、且0點大於2點、1點又大於3點,高價與低價一同上揚,因此可視為上升趨勢。
以相同的思考方式,當0點為低價、同時0點小於2點、1點又小於3點時,便是高價與低價一併下降,因此可視為下跌趨勢。關於線條的繪製,本次將在此另外製作名為「DrawLine」的函數。
if (zz[0] == High[i] && zz[0] > zz[2] && zz[1] > zz[3]) {
DrawLine(UP, bar, zz);
} else if (zz[0] == Low[i] && zz[0] < zz[2] && zz[1] < zz[3]) {
DrawLine(DN, bar, zz);
}
5.因應價格波動模型繪製不同線條
在上述文章中,說明了如何搜尋判別上升趨勢與下跌趨勢的價格波動模型、製作名為「DrawLine」的函數、以及執行線條的繪製處理。接下來,將說明此DrawLine的處理過程。在檔案下方設置「Draw line function」,並於此處新增編碼。具體來說,即是叫出緩衝器序列與K線編號資訊,並進行線條的繪製。在MT4中,參數只能以「引用傳遞」的方式在數組中傳遞,因此需要在各個序列的前方添加「&」。
void DrawLine(double &array[], int &bar[], double &zz[])本次要在一次設定當中繪製「上升・下降・上升」或是「下降・上升・下降」等3條線,故必須將for文體重複3次。為了能夠在一定期間內分別繪製,此處的關鍵在於,不使用指定分離兩點並劃出一條直線的「DRAW_SECTION」指標,而是使用「DRAW_LINE」。在繪製線條時,Draw_Line能夠1個點1個點地依序繪製,並將其連接為1條直線。因此,首先需將bar[i+1減去bar[i]求出有哪些點。其後需使用除法,而若點的數量n為「0」,便不會執行處理動作。
for (int i = 0; i < 3; i++) {為了顯示每1個點的價格變化,需算出整體數值的範圍,並以n進行除算。此處可利用「pitch」,從 0至n號為止,依照每1個點畫出線條。將「bar[i]」作為起始點來依序新增「j」。
int n = bar[i + 1] – bar[i];
if (n == 0) continue;
double pitch = (zz[i + 1] – zz[i]) / n;如此進行編譯並設定圖表,便可見到上升趨勢為紅色、下跌趨勢為藍色,實現了ZigZag的顏色區分。
for (int j = 0; j <= n; j++) {
array[bar[i] + j] = zz[i] + pitch * j;
}
6.原始碼
本次製作的原始碼如以下所示。//+——————————————————————+
//| Colorful_ZigZag.mq4 |
//| Copyright 2006-2014, MetaQuotes Software Corp. |
//| http://www.mql4.com |
//+——————————————————————+
#property copyright “2006-2014, MetaQuotes Software Corp.”
#property link “http://www.mql4.com”
#property strict
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 clrWhite
#property indicator_color2 clrRed
#property indicator_color3 clrDodgerBlue
#property indicator_width1 1
#property indicator_width2 3
#property indicator_width3 3
//—- indicator parameters
input int InpDepth = 12; // Depth
input int InpDeviation = 5; // Deviation
input int InpBackstep = 3; // Backstep
//—- indicator buffers
double ExtZigzagBuffer[];
double ExtHighBuffer[];
double ExtLowBuffer[];
double UP[], DN[];
//— globals
int ExtLevel = 3; // recounting’s depth of extremums
//+——————————————————————+
//| Custom indicator initialization function |
//+——————————————————————+
int OnInit()
{
if(InpBackstep >= InpDepth) {
Print(“Backstep cannot be greater or equal to Depth”);
return(INIT_FAILED);
}
//— 2 additional buffers
IndicatorBuffers(5);
//—- drawing settings
SetIndexStyle(0, DRAW_SECTION);
SetIndexStyle(1, DRAW_LINE);
SetIndexStyle(2, DRAW_LINE);
//—- indicator buffers
SetIndexBuffer(0, ExtZigzagBuffer);
SetIndexBuffer(1, UP);
SetIndexBuffer(2, DN);
SetIndexBuffer(3, ExtHighBuffer);
SetIndexBuffer(4, ExtLowBuffer);
SetIndexEmptyValue(0, 0.0);
//—- indicator short name
IndicatorShortName(“ZigZag(” + string(InpDepth) + “,” + string(InpDeviation) + “,” + string(InpBackstep) + “)”);
//—- initialization done
return(INIT_SUCCEEDED);
}
//+——————————————————————+
//| |
//+——————————————————————+
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 i, limit, counterZ, whatlookfor = 0;
int back, pos, lasthighpos = 0, lastlowpos = 0;
double extremum;
double curlow = 0.0, curhigh = 0.0, lasthigh = 0.0, lastlow = 0.0;
//— check for history and inputs
if(rates_total < InpDepth || InpBackstep >= InpDepth)
return(0);
//— first calculations
if(prev_calculated == 0)
limit = InitializeAll();
else {
//— find first extremum in the depth ExtLevel or 100 last bars
i = counterZ = 0;
while(counterZ < ExtLevel && i < 100) {
if(ExtZigzagBuffer[i] != 0.0)
counterZ++;
i++;
}
//— no extremum found – recounting all from begin
if(counterZ == 0)
limit = InitializeAll();
else {
//— set start position to found extremum position
limit = i – 1;
//— what kind of extremum?
if(ExtLowBuffer[i] != 0.0) {
//— low extremum
curlow = ExtLowBuffer[i];
//— will look for the next high extremum
whatlookfor = 1;
} else {
//— high extremum
curhigh = ExtHighBuffer[i];
//— will look for the next low extremum
whatlookfor = -1;
}
//— clear the rest data
for(i = limit – 1; i >= 0; i–) {
ExtZigzagBuffer[i] = 0.0;
ExtLowBuffer[i] = 0.0;
ExtHighBuffer[i] = 0.0;
}
}
}
//— main loop
for(i = limit; i >= 0; i–) {
//— find lowest low in depth of bars
extremum = low[iLowest(NULL, 0, MODE_LOW, InpDepth, i)];
//— this lowest has been found previously
if(extremum == lastlow)
extremum = 0.0;
else {
//— new last low
lastlow = extremum;
//— discard extremum if current low is too high
if(low[i] – extremum > InpDeviation * Point)
extremum = 0.0;
else {
//— clear previous extremums in backstep bars
for(back = 1; back <= InpBackstep; back++) {
pos = i + back;
if(ExtLowBuffer[pos] != 0 && ExtLowBuffer[pos] > extremum)
ExtLowBuffer[pos] = 0.0;
}
}
}
//— found extremum is current low
if(low[i] == extremum)
ExtLowBuffer[i] = extremum;
else
ExtLowBuffer[i] = 0.0;
//— find highest high in depth of bars
extremum = high[iHighest(NULL, 0, MODE_HIGH, InpDepth, i)];
//— this highest has been found previously
if(extremum == lasthigh)
extremum = 0.0;
else {
//— new last high
lasthigh = extremum;
//— discard extremum if current high is too low
if(extremum – high[i] > InpDeviation * Point)
extremum = 0.0;
else {
//— clear previous extremums in backstep bars
for(back = 1; back <= InpBackstep; back++) {
pos = i + back;
if(ExtHighBuffer[pos] != 0 && ExtHighBuffer[pos] < extremum)
ExtHighBuffer[pos] = 0.0;
}
}
}
//— found extremum is current high
if(high[i] == extremum)
ExtHighBuffer[i] = extremum;
else
ExtHighBuffer[i] = 0.0;
}
//— final cutting
if(whatlookfor == 0) {
lastlow = 0.0;
lasthigh = 0.0;
} else {
lastlow = curlow;
lasthigh = curhigh;
}
for(i = limit; i >= 0; i–) {
switch(whatlookfor) {
case 0: // look for peak or lawn
if(lastlow == 0.0 && lasthigh == 0.0) {
if(ExtHighBuffer[i] != 0.0) {
lasthigh = High[i];
lasthighpos = i;
whatlookfor = -1;
ExtZigzagBuffer[i] = lasthigh;
}
if(ExtLowBuffer[i] != 0.0) {
lastlow = Low[i];
lastlowpos = i;
whatlookfor = 1;
ExtZigzagBuffer[i] = lastlow;
}
}
break;
case 1: // look for peak
if(ExtLowBuffer[i] != 0.0 && ExtLowBuffer[i] < lastlow && ExtHighBuffer[i] == 0.0) {
ExtZigzagBuffer[lastlowpos] = 0.0;
lastlowpos = i;
lastlow = ExtLowBuffer[i];
ExtZigzagBuffer[i] = lastlow;
}
if(ExtHighBuffer[i] != 0.0 && ExtLowBuffer[i] == 0.0) {
lasthigh = ExtHighBuffer[i];
lasthighpos = i;
ExtZigzagBuffer[i] = lasthigh;
whatlookfor = -1;
}
break;
case -1: // look for lawn
if(ExtHighBuffer[i] != 0.0 && ExtHighBuffer[i] > lasthigh && ExtLowBuffer[i] == 0.0) {
ExtZigzagBuffer[lasthighpos] = 0.0;
lasthighpos = i;
lasthigh = ExtHighBuffer[i];
ExtZigzagBuffer[i] = lasthigh;
}
if(ExtLowBuffer[i] != 0.0 && ExtHighBuffer[i] == 0.0) {
lastlow = ExtLowBuffer[i];
lastlowpos = i;
ExtZigzagBuffer[i] = lastlow;
whatlookfor = 1;
}
break;
}
}
//— 色分け
limit = Bars – prev_calculated – 1;
int min = 0;
int count = 0;
for (i = 0; i < Bars - 1; i++) {
if (ExtZigzagBuffer[i] != 0) count++;
if (count >= 4) {
min = i;
break;
}
}
if (limit < min) limit = min;
int bar[4];
double zz[4];
for (i = limit; i >= 0; i–) {
ArrayInitialize(bar, -1);
ArrayInitialize(zz, 0);
if (ExtZigzagBuffer[i] != 0) {
bar[0] = i;
zz[0] = ExtZigzagBuffer[i];
count = 1;
for (int j = i + 1; j < Bars - 1; j++) {
if (ExtZigzagBuffer[j] != 0) {
bar[count] = j;
zz[count] = ExtZigzagBuffer[j];
count++;
if (count >= 4) break;
}
}
if (bar[3] == -1) continue;
if (zz[0] == High[i] && zz[0] > zz[2] && zz[1] > zz[3]) {
DrawLine(UP, bar, zz);
} else if (zz[0] == Low[i] && zz[0] < zz[2] && zz[1] < zz[3]) {
DrawLine(DN, bar, zz);
}
}
}
//— done
return(rates_total);
}
//+——————————————————————+
//| |
//+——————————————————————+
int InitializeAll() {
ArrayInitialize(ExtZigzagBuffer, 0.0);
ArrayInitialize(ExtHighBuffer, 0.0);
ArrayInitialize(ExtLowBuffer, 0.0);
//— first counting position
return(Bars – InpDepth);
}
//+——————————————————————+
//| Draw line function |
//+——————————————————————+
void DrawLine(double & array[], int &bar[], double & zz[])
{
for (int i = 0; i < 3; i++) {
int n = bar[i + 1] – bar[i];
if (n == 0) continue;
double pitch = (zz[i + 1] – zz[i]) / n;
for (int j = 0; j <= n; j++) {
array[bar[i] + j] = zz[i] + pitch * j;
}
}
}
將EA自動程式交易應用於外匯與差價合約交易中
我們以圖文形式詳細介紹有關EA自動程式交易的基本知識,以及在MT4/MT5平台上的安裝、參數設定方法、編碼等等內容。另外,對持有OANDA帳戶的客戶,還可以免費使用我們的獨有EA與指標工具。
誠邀您參加全球知名外匯經紀商OANDA的自營交易(Prop Trader)
報名OANDA自營交易(Prop Trader),並通過我們的考核,您就可以使用OANDA提供的資金進行交易,獲得高達90%的交易利潤分成。
優化了挑戰塞交易規則
無最低交易天數限制等優化了挑戰賽的交易規則。
500,000美元交易資金
您可以使用最高500,000美元的資金進行交易。
豐富的交易商品
您可以交易包括外匯、黃金、原油、股票指數等多種商品。