程式交易教學

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

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



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

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

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



製作依照方向改變顏色的移動平均線的自動交易程式

登錄三個緩衝器

在本章節當中,將說明如何製作依照方向改變顏色的移動平均線(MA:Moving Average)。首先介紹使用指標緩衝器的基本製作方式。

在製作新檔案時選擇「自訂指標」,並將檔案命名為「ColorfulMA_Normal」並新增參數。名稱設定為「PERIOD」、初始值為「5」。此處為了易於辨認MA的顏色變化,因故設定較為短暫的時間。

自訂指標

在「自訂指標程式的事件處理常式」中,無需勾選「OnTimer」「OnChartEvent」便點擊下一步。在「客製化指標的繪圖屬性」設定欄中,登錄含有MA數據的三個緩衝器。

●第一個是計算用的緩衝器,因此不會顯示。標籤設定為「MA」、顏色為「None」。
●第二個是上升用的緩衝器,標籤設定為「UP」、顏色為「Red」。
●第三個是下降用的緩衝器,標籤設定為「DN」、顏色為「DodgerBlue」。如此點擊「完成」即可呈現雛形。

三個緩衝器

計算MA並將數值匯入緩衝器

開啟新檔案時,將修正上方的屬性。由於「MA」的部分並不會如前文顯示,因此將樣式(type)從「DRAW_LINE」改變為「DRAW_NONE」。另外,為了使MA易於辨認,將「UP」與「DN」的寬度(width)從「1」變成「2」。

//--- plot MA

#property indicator_label1 “MA”

#property indicator_type1 DRAW_NONE

#property indicator_style1 STYLE_SOLID

#property indicator_width1 1

//--- plot UP

#property indicator_label2 “UP”

#property indicator_type2 DRAW_LINE

#property indicator_color2 clrRed

#property indicator_style2 STYLE_SOLID

#property indicator_width2 2

//--- plot DN

#property indicator_label3 “DN”

#property indicator_type3 DRAW_LINE

#property indicator_color3 clrDodgerBlue

#property indicator_style3 STYLE_SOLID

#property indicator_width3 2
接下來,在OnCalculate函數下方寫入MA的計算公式,並將MA的緩衝器如下列所示加以定義。樣式為簡單移動平均線,適用價格則是收盤價。

int limit = Bars - prev_calculated - 2;

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

MABuffer[i] = iMA(NULL, 0, PERIOD, 0, MODE_SMA, PRICE_CLOSE, i);
如此計算出的MA數值便會匯入於緩衝器中。

利用匯入的資訊顯示MA

接下來,將利用匯入緩衝器的資訊,以if文體組合成上升、下降的條件。

若比前1根K線有所上升,便在「UPBuffer」中輸入數值。若只有1將無法畫出線條,故此處的重點便是以「i+1」在1根K線之前輸入數值。與前1根K線相比,若並未出現上升,則在「DNBuffer」緩衝器中輸入數值。

if (MABuffer[i] > MABuffer[i + 1]) {

UPBuffer[i] = MABuffer[i];

UPBuffer[i + 1] = MABuffer[i + 1];

} else {

DNBuffer[i] = MABuffer[i];

DNBuffer[i + 1] = MABuffer[i + 1];

}
如此進行編譯並設定圖表,便會出現在向上時呈現紅色、向下時呈現藍色的MA。

向上紅色向下藍色

使用元件解決問題

目前已能夠顯示依方向改變顏色的移動平均線(MA:Moving Average)。但是,有些部分的 MA雖然呈現上升,卻沒有變為紅色。

移動平均線

造成此現象的原因在於前後皆為下降傾向。雖然實際上是上升,但由於前後皆為下降,因此數值被納入於下降用的緩衝器,進而使線條呈現下降的顏色。以下將介紹如何運用元件來解決此問題。

為了製作問題對策的指標,必須再度製作新檔案。

在製作新檔案時選擇「客製化指標」,並將檔案命名為「ColorfulMA」新增參數。與前一次相同,名稱設定為「PERIOD」、初始值為「5」。

本次將使用「OnChartEvent」。在「客製化指標的事件處理程序」畫面點選「OnChartEvent」,並在下一個畫面中登錄一個緩衝器。標籤設定為「MA」、顏色為「None」。如此點擊「完成」即可呈現雛形。

OnChartEvent

首先,將新檔案上方定義的「MA」樣式(type)從「DRAW_LINE」改變為「DRAW_NONE」。

//--- plot MA

#property indicator_label1 “MA”

#property indicator_type1 DRAW_NONE

#property indicator_style1 STYLE_SOLID

#property indicator_width1 1
至於MA的計算公式,則與先前製作的「ColorfulMA_Normal」相同,因此可將其複製並貼至OnCalculate的參數之下。

int limit = Bars - prev_calculated - 2;

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

MABuffer[i] = iMA(NULL, 0, PERIOD, 0, MODE_SMA, PRICE_CLOSE, i);

}

利用「MABuffer」數值決定顏色

此處將在「ChartEvent function」下方使用趨勢線,並製作繪製MA的程式。首先運用ObjectsDeleteAll函數記載重設元件的編碼。

void DrawMA()

{

ObjectsDeleteAll(0, “MA_”);

}
接下來,為了指定K線的搜尋範圍,應取得顯示於圖表中的K線資訊。

「CHART_FIRST_VISIBLE_BAR」會顯示圖表左邊的K線,若自該處減去顯示圖表所有K線數的「CHART_WIDTH_IN_BARS」,便會呈現右邊的數值。

若計算結果為負數,將會呈現「0」。

int barF = (int)ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR);

int barR = barF - (int)ChartGetInteger(0, CHART_WIDTH_IN_BARS);

if (barR < 0) barR = 0;
接著將使用得出的K線加以計算。如欲依照上升與下降來改變顏色,可利用「MABuffer」數值來決定。本次將顯示三種顏色,持平為「白」、上升為「紅」、下降為「藍」。

for (int i = barF; i > barR; i--) {

color clr = clrWhite;

if (MABuffer[i] > MABuffer[i + 1]) clr = clrRed;

else if (MABuffer[i] < MABuffer[i + 1]) clr = clrDodgerBlue;

}

使用趨勢線繪製MA

接下來將使用趨勢線來顯示MA。

從MQL4幫助檔中複製趨勢線的範例編碼加以使用。

在MQL4幫助檔的目錄中點選「Constants, Enumerations and Structures」→「Objects Constants」→「Object Types」,即可看見元件一覽。從中選擇「OBJ_TREND」,並將預先準備的「Create a trend line by the given coordinates」編碼複製貼上於檔案下方。

從「//--- set anchor points’ coordinates if they are not set」至「ResetLastError();」的4行以及「Print(__FUNCTION__,」「”: failed to create a trend line! Error code = “, GetLastError());」兩行皆無需使用,可予以刪除。

另外,如欲將線條加寬,可將上方的「// line width」從「width = 1」改成「width = 2」。由於無需進行選擇,故「// highlight to move」可從「selection = true」修改為「selection = false」。

//+------------------------------------------------------------------+

//| Create a trend line by the given coordinates |

//+------------------------------------------------------------------+

bool TrendCreate(const long chart_ID = 0, // chart’s ID

const string name = “TrendLine”, // line name

const int sub_window = 0, // subwindow index

datetime time1 = 0, // first point time

double price1 = 0, // first point price

datetime time2 = 0, // second point time

double price2 = 0, // second point price

const color clr = clrRed, // line color

const ENUM_LINE_STYLE style = STYLE_SOLID, // line style

const int width = 2, // line width

const bool back = false, // in the background

const bool selection = false, // highlight to move

const bool ray_right = false, // line’s continuation to the right

const bool hidden = true, // hidden in the object list

const long z_order = 0) // priority for mouse click

{

//--- create a trend line by the given coordinates

if(!ObjectCreate(chart_ID, name, OBJ_TREND, sub_window, time1, price1, time2, price2)) { return(false);

}

//--- set line color

ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr);

//--- set line display style

ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style);

//--- set line width

ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, width);

//--- display in the foreground (false) or background (true)

ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back);

//--- enable (true) or disable (false) the mode of moving the line by mouse

//--- when creating a graphical object using ObjectCreate function, the object cannot be

//--- highlighted and moved by default. Inside this method, selection parameter

//--- is true by default making it possible to highlight and move the object

ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection);

ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection);

//--- enable (true) or disable (false) the mode of continuation of the line’s display to the right

ObjectSetInteger(chart_ID, name, OBJPROP_RAY_RIGHT, ray_right);

//--- hide (true) or display (false) graphical object name in the object list

ObjectSetInteger(chart_ID, name, OBJPROP_HIDDEN, hidden);

//--- set the priority for receiving the event of a mouse click in the chart

ObjectSetInteger(chart_ID, name, OBJPROP_ZORDER, z_order);

//--- successful execution

return(true);

}

比較最初製作的MA與問題對策版MA

在DrawMA()的「else if (MABuffer[i] < MABuffer[i + 1]) clr = clrDodgerBlue;」下方叫出設定的TrendCreate。第1個時間點為「Time[i]」、價格為「MABuffer[i]」。第2個時間點與價格則分別加上1,設定為「Time[i+1]」、「MABuffer[i +1]」。

TrendCreate(0, “MA_” + (string)i, 0, Time[i], MABuffer[i], Time[i + 1], MABuffer[i + 1], clr);
最後在OnCalculate函數下方輸入製作的DrawMA()。

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 - 2;

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

MABuffer[i] = iMA(NULL, 0, PERIOD, 0, MODE_SMA, PRICE_CLOSE, i);

}

DrawMA();

//--- return value of prev_calculated for next call

return(rates_total);

}
另外,若希望在圖表出現變化時同步顯示,可在OnChartEvent函數中增加下列if文體。

if (id == CHARTEVENT_CHART_CHANGE) DrawMA();
如此進行編譯、設定圖表,並與最初的MA加以比較。畫面上方是最初製作的指標「ColorfulMA_Normal」、下方則是作為問題對策的指標「ColorfulMA」。在ColorfulMA中,可以見到前後皆為下降的上升部分也確實變成了紅色。

ColorfulMA

原始碼

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

ColorfulMA_Normal


//+------------------------------------------------------------------+

//| ColorfulMA_Normal.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 3

#property indicator_plots 3

//--- plot MA

#property indicator_label1 “MA”

#property indicator_type1 DRAW_NONE

#property indicator_style1 STYLE_SOLID

#property indicator_width1 1

//--- plot UP

#property indicator_label2 “UP”

#property indicator_type2 DRAW_LINE

#property indicator_color2 clrRed

#property indicator_style2 STYLE_SOLID

#property indicator_width2 2

//--- plot DN

#property indicator_label3 “DN”

#property indicator_type3 DRAW_LINE

#property indicator_color3 clrDodgerBlue

#property indicator_style3 STYLE_SOLID

#property indicator_width3 2

//--- input parameters

input int PERIOD = 5;

//--- indicator buffers

double MABuffer[];

double UPBuffer[];

double DNBuffer[];

//+------------------------------------------------------------------+

//| Custom indicator initialization function |

//+------------------------------------------------------------------+

int OnInit()

{

//--- indicator buffers mapping

SetIndexBuffer(0, MABuffer);

SetIndexBuffer(1, UPBuffer);

SetIndexBuffer(2, DNBuffer);

//---

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 - 2;

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

MABuffer[i] = iMA(NULL, 0, PERIOD, 0, MODE_SMA, PRICE_CLOSE, i);

if (MABuffer[i] > MABuffer[i + 1]) {

UPBuffer[i] = MABuffer[i];

UPBuffer[i + 1] = MABuffer[i + 1];

} else {

DNBuffer[i] = MABuffer[i];

DNBuffer[i + 1] = MABuffer[i + 1];

}

}

//--- return value of prev_calculated for next call

return(rates_total);

}

ColorfulMA


//+------------------------------------------------------------------+

//| ColorfulMA.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 1

#property indicator_plots 1

//--- plot MA

#property indicator_label1 “MA”

#property indicator_type1 DRAW_NONE

#property indicator_style1 STYLE_SOLID

#property indicator_width1 1

//--- input parameters

input int PERIOD = 5;

//--- indicator buffers

double MABuffer[];

//+------------------------------------------------------------------+

//| Custom indicator initialization function |

//+------------------------------------------------------------------+

int OnInit()

{

//--- indicator buffers mapping

SetIndexBuffer(0, MABuffer);

//---

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 - 2;

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

MABuffer[i] = iMA(NULL, 0, PERIOD, 0, MODE_SMA, PRICE_CLOSE, i);

}

DrawMA();

//--- return value of prev_calculated for next call

return(rates_total);

}

//+------------------------------------------------------------------+

//| ChartEvent function |

//+------------------------------------------------------------------+

void OnChartEvent(const int id,

const long &lparam,

const double &dparam,

const string &sparam)

{

//---

if (id == CHARTEVENT_CHART_CHANGE) DrawMA();

}

//+------------------------------------------------------------------+

//| ChartEvent function |

//+------------------------------------------------------------------+

void DrawMA()

{

ObjectsDeleteAll(0, “MA_”);

int barF = (int)ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR);

int barR = barF - (int)ChartGetInteger(0, CHART_WIDTH_IN_BARS);

if (barR < 0) barR = 0;

for (int i = barF; i > barR; i--) {

color clr = clrWhite;

if (MABuffer[i] > MABuffer[i + 1]) clr = clrRed;

else if (MABuffer[i] < MABuffer[i + 1]) clr = clrDodgerBlue;

TrendCreate(0, “MA_” + (string)i, 0, Time[i], MABuffer[i], Time[i + 1], MABuffer[i + 1], clr);

}

}

//+------------------------------------------------------------------+

//| Create a trend line by the given coordinates |

//+------------------------------------------------------------------+

bool TrendCreate(const long chart_ID = 0, // chart’s ID

const string name = “TrendLine”, // line name

const int sub_window = 0, // subwindow index

datetime time1 = 0, // first point time

double price1 = 0, // first point price

datetime time2 = 0, // second point time

double price2 = 0, // second point price

const color clr = clrRed, // line color

const ENUM_LINE_STYLE style = STYLE_SOLID, // line style

const int width = 2, // line width

const bool back = false, // in the background

const bool selection = false, // highlight to move

const bool ray_right = false, // line’s continuation to the right

const bool hidden = true, // hidden in the object list

const long z_order = 0) // priority for mouse click

{

//--- create a trend line by the given coordinates

if(!ObjectCreate(chart_ID, name, OBJ_TREND, sub_window, time1, price1, time2, price2)) {

return(false);

}

//--- set line color

ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr);

//--- set line display style

ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style);

//--- set line width

ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, width);

//--- display in the foreground (false) or background (true)

ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back);

//--- enable (true) or disable (false) the mode of moving the line by mouse

//--- when creating a graphical object using ObjectCreate function, the object cannot be

//--- highlighted and moved by default. Inside this method, selection parameter

//--- is true by default making it possible to highlight and move the object

ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection);

ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection);

//--- enable (true) or disable (false) the mode of continuation of the line’s display to the right

ObjectSetInteger(chart_ID, name, OBJPROP_RAY_RIGHT, ray_right);

//--- hide (true) or display (false) graphical object name in the object list

ObjectSetInteger(chart_ID, name, OBJPROP_HIDDEN, hidden);

//--- set the priority for receiving the event of a mouse click in the chart

ObjectSetInteger(chart_ID, name, OBJPROP_ZORDER, z_order);

//--- successful execution

return(true);

}

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

EA

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

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

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



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

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

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