程式交易教學

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

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



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

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

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

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



【MQL編程基礎】|將ZigZag按道氏理論分色顯示的方法

1.開啟ZigZag編碼並命名保存

在本篇文章中,將介紹將ZigZag按道氏理論分色顯示的方法。

ZigZag 是MT4標準配備的指標,能以直線顯示頂底,為相當便利的工具。

本次將山峰高點與山谷低點一同上揚的波形定義為上升趨勢,一同下降的波形則定義為下跌趨勢,並以顏色區分顯示。

此處將不會從頭製作程式,而是使用ZigZag改造而成。首先在圖表上設定ZigZag。為了顯示更多ZigZag的頂底,故將參數的Depth數值設定為「5」。

ZigZag

為了改造ZigZag的程式,在MT4導覽中的「ZigZag」上點擊右鍵,再點擊「修改」並開啟檔案。

ZigZag

其次,點擊MetaEditor的「文件」→「另存為」、將名稱變更為「Colorful_ZigZag」加以保存。

2.新增上升趨勢用與下跌趨勢用的緩衝器

以新名稱保存之後,就要來改造編碼。首先新增三個緩衝器。在檔案上方的屬性中,將「#property indicator_buffers」的「1」變更為「3」、並於其下新增「#property indicator_color2」與「#property indicator_color3」。第一個設定為白色、第二個為紅色、第三個則是藍色。另外,也在此處指定線條的寬度。第一條線為細線、第二條與第三條則使用粗線以便目視。

#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
接著,在「double ExtLowBuffer[];」下方添加上升趨勢用與下跌趨勢用的緩衝器。

double UP[], DN[];
同時,將OnInit函數內的「//— 2 additional buffers」緩衝器數量從「3」添加至「5」。

IndicatorBuffers(5);
其次,在第2個「//—- indicator buffers」新增「UP」、第3個新增「DN」,將編號做出區隔。

SetIndexBuffer(0,ExtZigzagBuffer);

SetIndexBuffer(1,UP);

SetIndexBuffer(2,DN);

SetIndexBuffer(3,ExtHighBuffer);

SetIndexBuffer(4,ExtLowBuffer);
另外,因本次使用「DRAW_LINE」來繪製線條,故應在「//—- drawing settings」的「SetIndexStyle(0, DRAW_SECTION);」下方添加下列2行。

SetIndexStyle(1, DRAW_LINE);

SetIndexStyle(2, DRAW_LINE);
如此便完成了基礎檔案的準備。其他部分則可直接沿用,並在必要時添加迴路。

3.準備四組序列並儲存資訊

前文沿用了ZigZag的程式,並新增了上升趨勢用與下跌趨勢用的緩衝器。接下來,將針對上升線與下降線,新增以不同顏色顯示的迴路。

首先將定義計算的範圍,本次為了判別高價與低價的上移、下移模式,需再次計算直至找到ZigZag的四個點。在ZigZag的緩衝器「ExtZigzagBuffer」並非「0」的狀況下進行計算,當計算達到「4」時則結束搜尋。將該條列儲存為最小計算範圍,並除去for文體。

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;

}

}
其次,至該儲存的數值為止,重複進行最低限度的計算。由於需記憶ZigZag四個點的數值、以及K線編號的數值,因此應準備四組序列。當找到點的時候,在第一個序列寫入該資訊,並將計算作為「1」。

if (limit < min) limit = min;

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;

}

}
本次將從找到的「i」的前1條列,回溯過去的所有序列進行搜尋。當「j」的條列並非「0」時,即可儲存第二個序列之後的點,並在計算達到4以上時結束。如此便在序列bar[]與zz[]儲存四個ZigZag的頂點資訊。

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;

}

}
另外,為了在每一次都能重設四個序列,需將能透過指定數值將序列初始化的「ArrayInitialize」寫入於「for (i = limit; i >= 0; i–) {」之下。

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++) {

int n = bar[i + 1] – bar[i];

if (n == 0) continue;
為了顯示每1個點的價格變化,需算出整體數值的範圍,並以n進行除算。此處可利用「pitch」,從 0至n號為止,依照每1個點畫出線條。將「bar[i]」作為起始點來依序新增「j」。

double pitch = (zz[i + 1] – zz[i]) / n;

for (int j = 0; j <= n; j++) {

array[bar[i] + j] = zz[i] + pitch * j;

}
如此進行編譯並設定圖表,便可見到上升趨勢為紅色、下跌趨勢為藍色,實現了ZigZag的顏色區分。

ZigZag的顏色區分

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

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

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

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



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

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

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

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