誠邀您參加全球知名外匯經紀商OANDA的自營交易(Prop Trader)
報名OANDA自營交易(Prop Trader),並通過我們的考核,您就可以使用OANDA提供的資金進行交易,獲得高達90%的交易利潤分成。
優化了挑戰塞交易規則
無最低交易天數限制等優化了挑戰賽的交易規則。
500,000美元交易資金
您可以使用最高500,000美元的資金進行交易。
豐富的交易商品
您可以交易包括外匯、黃金、原油、股票指數等多種商品。
利用EDIT物件繪製週間計算表格的方法說明
製作指定為「年」的方格
在「EDIT物件的參數定義・設定方法」中,說明了在製作新檔案時,該如何透過EDIT物件的參數來定義表格位置。參考文章:EDIT物件的參數定義・設定方法
接下來,將針對OnInit函數中顯示表格橫向位置的X,從第1列開始依序進行定義。
第1列維持「POSX」;第2列中,則將第1列的寬度(WIDTH_TITLE)添加至POSX;第3列中,則將WIDTH_DATA添加至第2列的x[1];在第4列,則添加WIDTH_DATA至第3列的x[2]。
int x[4];其次,在第1列使用EditCreate製作指定為「年」的方格。X的位置為「x[0]」,Y的位置維持「POSY」;由於是第1列,故寬度為「WIDTH_TITLE」、高度為共用的「HEIGHT」。初始值為「2020」,而結尾則使用「false」以利進行編輯。
x[0] = POSX;
x[1] = x[0] + WIDTH_TITLE;
x[2] = x[1] + WIDTH_DATA;
x[3] = x[2] + WIDTH_DATA;
EditCreate(“Year”, x[0], POSY, WIDTH_TITLE, HEIGHT, “2020”, false);EditCreate參數「ability to edit」的預設為「false」,此處將變更為「true」,藉此讓此方格之外的部分無法編輯。
read_only = true, // ability to edit在此狀態下,如欲一概刪除後續的物件,可在檔案上方的屬性內容「#property indicator_chart_window」之下,使用「#define」來定義「PREFIX」。
#define PREFIX MQLInfoString(MQL_PROGRAM_NAME) + “_”PREFIX代表接頭辭的意義,能夠從圖表中刪除以指定文字列開頭的物件;由於每次的物件開頭都要加上PREFIX,因此可在檔案下方「Create Edit object」的參數指定之下,寫入下列公式。
name = PREFIX + name;但是,在 EditCreate括號內的「object name」編碼中,含有阻止更改變數數值的「const」;此處將不加以替換,而是刪除「const string」中的「const」。
bool EditCreate(string name = “Edit”, // object name如此進行編譯並設定圖表,便完成了一個可供編輯的EDIT。
新增陽線、陰線、十字線的方格
接下來,將在寫有2020的方格旁,製作陽線、陰線、十字線的方格。陽線的X位置設定為「x[1]」、寬度為「WIDTH_DATA」、顏色為「Red」;陰線的X位置為「x[2]」、寬度為「WIDTH_DATA」、顏色為「Blue」;十字線的X位置為「x[3]」、寬度為「WIDTH_DATA」、顏色為「Yellow」。EditCreate(“Up”, x[1], POSY, WIDTH_DATA, HEIGHT, “陽線”, true, clrRed);其次,於「Custom indicator initialization function」下方設定「Custom indicator deinit function」,寫入下列使用OnDeinit函數的公式。
EditCreate(“Down”, x[2], POSY, WIDTH_DATA, HEIGHT, “陰線”, true, clrDodgerBlue);
EditCreate(“Cross”, x[3], POSY, WIDTH_DATA, HEIGHT, “十字線”, true, clrYellow);
void OnDeinit(const int reason)有了此公式後,一旦變更參數、進行編譯、或是從圖表中刪除指標,便會刪除所有包含此「PREFIX」的物件。如此進行編譯後,即可新增陽線、陰線、十字線的方格
{
if (reason == REASON_PARAMETERS || reason == REASON_RECOMPILE || reason == REASON_REMOVE)
ObjectsDeleteAll(0, PREFIX);
}
新增週一~週五的表格
本次將在下方新增週間表格。先新增週一~週五的5行,縱向位置設定為POSY+高度(HEIGHT)×「i+1」。for (int i = 0; i < 5; i++) {製作物件的順序將從星期開始,其次為陽線、陰線、十字線的計算結果。橫向位置及寬度皆與年的方格相同,縱向位置則替換為「y」。陽線、陰線、十字線的文字內容將在其後匯入計算數據,故此處留白;文字顏色則保留預設值的白色。
int y = POSY + HEIGHT * (i + 1);
EditCreate(“DOW” + (string)i, x[0], y, WIDTH_TITLE, HEIGHT, dow);但是,星期的部分還需進行其他定義;屆時使用的是枚舉值「ENUM_DAY_OF_WEEK」,藉以依序顯示0(週日)~6(週六)的週間數值。
EditCreate(“Up” + (string)i, x[1], y, WIDTH_DATA, HEIGHT, “”);
EditCreate(“Down” + (string)i, x[2], y, WIDTH_DATA, HEIGHT, “”);
EditCreate(“Cross” + (string)i, x[3], y, WIDTH_DATA, HEIGHT, “”);
以for文體指定的「i」為0~4,若在此處加上1,便正好符合週間數量,並變更成了週間的枚舉值。使用「EnumToString」將此更改的部分變成週間名稱;週間名稱僅需開頭3個文字即可辨認,因此設定為僅顯示文字開頭的3個文字。
string dow = StringSubstr(EnumToString((ENUM_DAY_OF_WEEK)(i + 1)), 0, 3);如此便完成了表格部分;若在編譯後設定表格,即可顯示加上週間行數的表格。
依週間計算陽線、陰線、十字線的顯示方式
此處製作的函數「Calc」,將依照週一~週五來計算陽線、陰線、十字線的數量。首先應設定搜尋的範圍,故將讀取顯示「年」的文字;接下來,使用將文字列變更為時間的StringToTime函數,藉以改變成開始的時間。由於外匯市場於1月1日休市,因此開始時間點若設定為「1月2日00:00」便不會出錯。
string year = ObjectGetString(0, PREFIX + “Year”, OBJPROP_TEXT);接著要使用「iBarShift」函數,藉以將時間改為顯示中的時間週期K線數量。參數方面,可指定顯示中的貨幣對與時間週期,並以下列公式定義開始搜尋的K線。
datetime timeStart = StringToTime(year + “.01.02 00:00”);
int iStart = iBarShift(NULL, 0, timeStart);若該K線的年份比所設定的年份更小,便不會進行以上處理;若更大則會就此結束。另外,若該條列的週間為週日或週六,亦不會進行以上處理。
其次,將在for文體上定義依照條列計算陽線或陰線的序列。若為陽線就計算「up」,陰線則為「down」;當兩者皆無時,則計算「cross」。週一的數字雖為1,但在排列上應設定為0號,因此使用「-1」。如此即可個別納入數據。
int up[5] = {0, 0, 0, 0, 0}, down[5] = {0, 0, 0, 0, 0}, cross[5] = {0, 0, 0, 0, 0};接下來,為了將納入的數據寫入已存在的表格文字資訊中,將添加以下公式。
for (int i = iStart; i >= 0; i–) {
if (TimeYear(Time[i]) < (int)year) continue;
if (TimeYear(Time[i]) > (int)year) break;
int dow = TimeDayOfWeek(Time[i]);
if (dow == SUNDAY || dow == SATURDAY) continue;
if (Close[i] > Open[i]) up[dow – 1]++;
else if (Close[i] < Open[i]) down[dow - 1]++;
else cross[dow – 1]++;
}
for (int i = 0; i < 5; i++) {將此Calc函數置於「OnCalculate」之下進行編譯,便會顯示陽線、陰線、十字線的條數。
ObjectSetString(0, PREFIX + “Up” + (string)i, OBJPROP_TEXT, (string)up[i]);
ObjectSetString(0, PREFIX + “Down” + (string)i, OBJPROP_TEXT, (string)down[i]);
ObjectSetString(0, PREFIX + “Cross” + (string)i, OBJPROP_TEXT, (string)cross[i]);
}
顯示陽線、陰線、十字線的佔比
作為補充資訊,可在條數後方顯示陽線、陰線、十字線的佔比。將計算出的陽線、陰線、十字線數量,個別除以總線條數量以得出佔比,再乘以100使其以百分比來呈現。此處的陽線、陰線、十字線總數若非為0,便將計算結果以括號包圍,顯示至小數點以下1位數。
for (int i = 0; i < 5; i++) {添加上列編碼並進行編譯,即可在條列數的後方顯示佔比。
int total = up[i] + down[i] + cross[i];
string ratioUP = “-“, ratioDown = “-“, ratioCross = “-“;
if (total != 0) {
ratioUP = “(” + DoubleToString(100.0 * up[i] / total, 1) + “%)”;
ratioDown = “(” + DoubleToString(100.0 * down[i] / total, 1) + “%)”;
ratioCross = “(” + DoubleToString(100.0 * cross[i] / total, 1) + “%)”;
}
ObjectSetString(0, PREFIX + “Up” + (string)i, OBJPROP_TEXT, (string)up[i] + ratioUP);
ObjectSetString(0, PREFIX + “Down” + (string)i, OBJPROP_TEXT, (string)down[i] + ratioDown);
ObjectSetString(0, PREFIX + “Cross” + (string)i, OBJPROP_TEXT, (string)cross[i] + ratioCross);
}
另外,由於本次是以週間來計算、不需採用週以外的計算處理,因此需要新增條件,以利處理日線以下的時間週期。在第一個for文體上新增下列的if文體。
if (_Period <= PERIOD_D1) {最後將使用「CHARTEVENT_OBJECT_ENDEDIT」,以利在編輯EDIT物件的年份方格時,運用Calc函數來反映數值。另外,當年份編輯中輸入無意義數值時,可新增回復處理動作,將讀取文字變更為整數型。若年份數值比MT4適用的最古老年份「1970」更小、抑或比目前年份更大,便會自動帶入今年的數值。
if (id == CHARTEVENT_OBJECT_ENDEDIT) {如此進行編譯後,一旦輸入小於 1970、或是無意義的數據,就會轉變為今年的年份。如此即是完成。
if (sparam == PREFIX + “Year”) {
string year = ObjectGetString(0, sparam, OBJPROP_TEXT);
string text = (string)(int)year;
if ((int)year < 1970 || (int)year > Year()) text = (string)Year();
ObjectSetString(0, sparam, OBJPROP_TEXT, text);
Calc();
}
}
↓
原始碼
本次製作的原始碼如以下所示。//+——————————————————————+
//| UpDownTable_DOW.mq4 |
//| Copyright 2021, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+——————————————————————+
#property copyright “Copyright 2021, MetaQuotes Software Corp.”
#property link “https://www.mql5.com”
#property version “1.00”
#property strict
#property indicator_chart_window
#define PREFIX MQLInfoString(MQL_PROGRAM_NAME) + “_”
//— input parameters
input int POSX = 0;
input int POSY = 15;
input int WIDTH_TITLE = 80;
input int WIDTH_DATA = 150;
input int HEIGHT = 30;
//+——————————————————————+
//| Custom indicator initialization function |
//+——————————————————————+
int OnInit()
{
//— indicator buffers mapping
int x[4];
x[0] = POSX;
x[1] = x[0] + WIDTH_TITLE;
x[2] = x[1] + WIDTH_DATA;
x[3] = x[2] + WIDTH_DATA;
EditCreate(“Year”, x[0], POSY, WIDTH_TITLE, HEIGHT, “2020”, false);
EditCreate(“Up”, x[1], POSY, WIDTH_DATA, HEIGHT, “陽線”, true, clrRed);
EditCreate(“Down”, x[2], POSY, WIDTH_DATA, HEIGHT, “陰線”, true, clrDodgerBlue);
EditCreate(“Cross”, x[3], POSY, WIDTH_DATA, HEIGHT, “十字線”, true, clrYellow);
for (int i = 0; i < 5; i++) {
int y = POSY + HEIGHT * (i + 1);
string dow = StringSubstr(EnumToString((ENUM_DAY_OF_WEEK)(i + 1)), 0, 3);
EditCreate(“DOW” + (string)i, x[0], y, WIDTH_TITLE, HEIGHT, dow);
EditCreate(“Up” + (string)i, x[1], y, WIDTH_DATA, HEIGHT, “”);
EditCreate(“Down” + (string)i, x[2], y, WIDTH_DATA, HEIGHT, “”);
EditCreate(“Cross” + (string)i, x[3], y, WIDTH_DATA, HEIGHT, “”);
}
//—
return(INIT_SUCCEEDED);
}
//+——————————————————————+
//| Custom indicator deinit function |
//+——————————————————————+
void OnDeinit(const int reason)
{
if (reason == REASON_PARAMETERS || reason == REASON_RECOMPILE || reason == REASON_REMOVE)
ObjectsDeleteAll(0, PREFIX);
}
//+——————————————————————+
//| 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[])
{
//—
Calc();
//— 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_OBJECT_ENDEDIT) {
if (sparam == PREFIX + “Year”) {
string year = ObjectGetString(0, sparam, OBJPROP_TEXT);
string text = (string)(int)year;
if ((int)year < 1970 || (int)year > Year()) text = (string)Year();
ObjectSetString(0, sparam, OBJPROP_TEXT, text);
Calc();
}
}
}
//+——————————————————————+
//| Calculate function |
//+——————————————————————+
void Calc()
{
string year = ObjectGetString(0, PREFIX + “Year”, OBJPROP_TEXT);
datetime timeStart = StringToTime(year + “.01.02 00:00”);
int iStart = iBarShift(NULL, 0, timeStart);
int up[5] = {0, 0, 0, 0, 0}, down[5] = {0, 0, 0, 0, 0}, cross[5] = {0, 0, 0, 0, 0};
if (_Period <= PERIOD_D1) {
for (int i = iStart; i >= 0; i–) {
if (TimeYear(Time[i]) < (int)year) continue;
if (TimeYear(Time[i]) > (int)year) break;
int dow = TimeDayOfWeek(Time[i]);
if (dow == SUNDAY || dow == SATURDAY) continue;
if (Close[i] > Open[i]) up[dow – 1]++;
else if (Close[i] < Open[i]) down[dow - 1]++;
else cross[dow – 1]++;
}
}
for (int i = 0; i < 5; i++) {
int total = up[i] + down[i] + cross[i];
string ratioUP = “-“, ratioDown = “-“, ratioCross = “-“;
if (total != 0) {
ratioUP = “(” + DoubleToString(100.0 * up[i] / total, 1) + “%)”;
ratioDown = “(” + DoubleToString(100.0 * down[i] / total, 1) + “%)”;
ratioCross = “(” + DoubleToString(100.0 * cross[i] / total, 1) + “%)”;
}
ObjectSetString(0, PREFIX + “Up” + (string)i, OBJPROP_TEXT, (string)up[i] + ratioUP);
ObjectSetString(0, PREFIX + “Down” + (string)i, OBJPROP_TEXT, (string)down[i] + ratioDown);
ObjectSetString(0, PREFIX + “Cross” + (string)i, OBJPROP_TEXT, (string)cross[i] + ratioCross);
}
}
//+——————————————————————+
//| Create Edit object |
//+——————————————————————+
bool EditCreate(string name = “Edit”, // object name
const int x = 0, // X coordinate
const int y = 0, // Y coordinate
const int width = 50, // width
const int height = 18, // height
const string text = “Text”, // text
const bool read_only = true, // ability to edit
const color clr = clrWhite, // text color
const color back_clr = clrBlack, // background color
const color border_clr = clrWhite, // border color
const long chart_ID = 0, // chart’s ID
const int sub_window = 0, // subwindow index
const string font = “メイリオ”, // font
const int font_size = 14, // font size
const ENUM_ALIGN_MODE align = ALIGN_CENTER, // alignment type
const ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER, // chart corner for anchoring
const bool back = false, // in the background
const bool selection = false, // highlight to move
const bool hidden = true, // hidden in the object list
const long z_order = 0) // priority for mouse click
{
name = PREFIX + name;
//— reset the error value
ResetLastError();
//— create edit field
if(!ObjectCreate(chart_ID, name, OBJ_EDIT, sub_window, 0, 0)) {
Print(__FUNCTION__,
“: failed to create \”Edit\” object! Error code = “, GetLastError());
return(false);
}
//— set object coordinates
ObjectSetInteger(chart_ID, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(chart_ID, name, OBJPROP_YDISTANCE, y);
//— set object size
ObjectSetInteger(chart_ID, name, OBJPROP_XSIZE, width);
ObjectSetInteger(chart_ID, name, OBJPROP_YSIZE, height);
//— set the text
ObjectSetString(chart_ID, name, OBJPROP_TEXT, text);
//— set text font
ObjectSetString(chart_ID, name, OBJPROP_FONT, font);
//— set font size
ObjectSetInteger(chart_ID, name, OBJPROP_FONTSIZE, font_size);
//— set the type of text alignment in the object
ObjectSetInteger(chart_ID, name, OBJPROP_ALIGN, align);
//— enable (true) or cancel (false) read-only mode
ObjectSetInteger(chart_ID, name, OBJPROP_READONLY, read_only);
//— set the chart’s corner, relative to which object coordinates are defined
ObjectSetInteger(chart_ID, name, OBJPROP_CORNER, corner);
//— set text color
ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr);
//— set background color
ObjectSetInteger(chart_ID, name, OBJPROP_BGCOLOR, back_clr);
//— set border color
ObjectSetInteger(chart_ID, name, OBJPROP_BORDER_COLOR, border_clr);
//— 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 label by mouse
ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection);
ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection);
//— 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自動程式交易的基本知識,以及在MT4/MT5平台上的安裝、參數設定方法、編碼等等內容。另外,對持有OANDA帳戶的客戶,還可以免費使用我們的獨有EA與指標工具。
誠邀您參加全球知名外匯經紀商OANDA的自營交易(Prop Trader)
報名OANDA自營交易(Prop Trader),並通過我們的考核,您就可以使用OANDA提供的資金進行交易,獲得高達90%的交易利潤分成。
優化了挑戰塞交易規則
無最低交易天數限制等優化了挑戰賽的交易規則。
500,000美元交易資金
您可以使用最高500,000美元的資金進行交易。
豐富的交易商品
您可以交易包括外匯、黃金、原油、股票指數等多種商品。