Alert
Hiển thị một thông báo trong một cửa sổ riêng.
void Alert(
argument, // giá trị đầu tiên
... // các giá trị khác
);
2
3
4
Tham số
argument
[truyền vào] Bất kỳ giá trị nào được phân tách bằng dấu phẩy. Để chia thông tin đầu ra thành nhiều dòng, bạn có thể sử dụng ký tự xuống dòng \n
hoặc \r\n
. Số lượng tham số không thể vượt quá 64.
Giá trị trả về
Không có giá trị trả về.
Ghi chú
Mảng không thể được truyền vào hàm Alert()
. Mảng cần được xuất từng phần tử. Dữ liệu kiểu double
được xuất với 8 chữ số sau dấu thập phân, dữ liệu kiểu float
được hiển thị với 5 chữ số sau dấu thập phân. Để xuất số thực với độ chính xác khác hoặc ở định dạng khoa học, hãy sử dụng hàm DoubleToString()
.
Dữ liệu kiểu bool
được xuất dưới dạng chuỗi true
hoặc false
. Ngày tháng được xuất dưới dạng YYYY.MM.DD HH:MI:SS. Để hiển thị ngày ở định dạng khác, sử dụng hàm TimeToString()
. Dữ liệu kiểu màu được xuất dưới dạng chuỗi R,G,B hoặc tên màu, nếu màu đó có trong tập hợp màu.
Hàm Alert()
không hoạt động trong Bộ Kiểm Tra Chiến Lược.
Ví dụ:
//--- enums
enum ENUM_INTERSECT_DIRECTION
{
INTERSECT_DIRECTION_NONE= 0, // không giao nhau
INTERSECT_DIRECTION_UP = 1, // giao nhau hướng lên
INTERSECT_DIRECTION_DOWN=-1, // giao nhau hướng xuống
};
//--- input parameters
input uint InpPeriod = 10; // Chu kỳ MA
input int InpShift = 0; // Dịch chuyển MA
input ENUM_MA_METHOD InpMethod = MODE_SMA; // Phương pháp MA
input ENUM_APPLIED_PRICE InpPrice = PRICE_CLOSE; // Giá áp dụng MA
//--- global variables
int ExtMaHandle;
int ExtMaPeriod;
double ExtData[2];
MqlRates ExtRates[2];
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- chu kỳ để tính trung bình động sẽ bằng giá trị mặc định (10) nếu tham số đầu vào chỉ định là 0
ExtMaPeriod=int(InpPeriod<1 ? 10 : InpPeriod);
//--- tạo một tay cầm cho chỉ báo Trung bình Động với các tham số được chỉ định
ExtMaHandle=iMA(Symbol(),PERIOD_CURRENT,ExtMaPeriod,InpShift,InpMethod,InpPrice);
ResetLastError();
if(ExtMaHandle==INVALID_HANDLE)
{
PrintFormat("Không thể tạo tay cầm iMA(). Mã lỗi: %d",GetLastError());
return(INIT_FAILED);
}
//--- lấy thời gian cập nhật giá cuối cùng
datetime tick_time=TickTime();
//--- lấy dữ liệu trung bình động và dữ liệu giá từ hai thanh cuối cùng
if(GetData(ExtMaHandle,ExtData,ExtRates) && tick_time!=0)
{
//--- nếu giá nằm trên MA
if(ExtRates[1].close>ExtData[1])
{
//--- tạo văn bản thông báo và hiển thị Alert
string message=StringFormat("Thời gian thanh: %s. Giá nằm trên trung bình động",TimeToString(ExtRates[1].time));
Alert(message+" tại "+TimeToString(tick_time,TIME_DATE|TIME_MINUTES|TIME_SECONDS));
/*
Kết quả:
Alert: Thời gian thanh: 2024.02.16 18:00. Giá nằm trên trung bình động tại 2024.02.16 18:47:43
*/
}
else
{
//--- nếu giá nằm dưới MA
if(ExtRates[1].close<ExtData[1])
{
//--- tạo văn bản thông báo và hiển thị Alert
string message=StringFormat("Thời gian thanh: %s. Giá nằm dưới trung bình động.",TimeToString(ExtRates[1].time));
Alert(message+" tại "+TimeToString(tick_time,TIME_DATE|TIME_MINUTES|TIME_SECONDS));
/*
Kết quả:
Alert: Thời gian thanh: 2024.02.16 19:00. Giá nằm dưới trung bình động tại 2024.02.16 19:33:14
*/
}
else
{
//--- tạo văn bản thông báo và hiển thị Alert
string message=StringFormat("Thời gian thanh: %s. Giá và trung bình động bằng nhau.",TimeToString(ExtRates[1].time));
Alert(message+" tại "+TimeToString(tick_time,TIME_DATE|TIME_MINUTES|TIME_SECONDS));
/*
Kết quả:
Alert: Thời gian thanh: 2024.02.16 20:00. Giá và trung bình động bằng nhau tại 2024.02.16 20:12:22
*/
}
}
}
//--- thành công
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
ResetLastError();
//--- lấy dữ liệu trung bình động và dữ liệu giá từ hai thanh cuối cùng
if(!GetData(ExtMaHandle,ExtData,ExtRates))
return;
//--- lấy hướng giao nhau của giá với trung bình động trên thanh hiện tại
ENUM_INTERSECT_DIRECTION intersect=GetIntersectDirection(ExtData,ExtRates);
//--- biến để lưu thông báo trước đó
static string message_prev="";
//--- nếu giá đã giao nhau với trung bình động trên thanh hiện tại theo hướng lên
if(intersect==INTERSECT_DIRECTION_UP)
{
//--- lấy thời gian tick mà giao nhau xảy ra
datetime tick_time=TickTime();
if(tick_time==0)
return;
//--- tạo văn bản thông báo
string message=StringFormat("Thời gian thanh: %s. Giá đã giao nhau với MA từ dưới lên trên",TimeToString(ExtRates[1].time));
//--- nếu thông báo trước đó không bằng thông báo hiện tại, hiển thị Alert với thông báo và thời gian tick
if(message!=message_prev)
{
Alert(message+" tại "+TimeToString(tick_time,TIME_DATE|TIME_MINUTES|TIME_SECONDS));
message_prev=message;
/*
Kết quả:
Alert: Thời gian thanh: 2024.02.16 09:00. Giá đã giao nhau với MA từ dưới lên trên tại 2024.02.16 09:20:35
*/
}
}
//--- nếu giá đã giao nhau với trung bình động trên thanh hiện tại theo hướng xuống
if(intersect==INTERSECT_DIRECTION_DOWN)
{
//--- lấy thời gian tick mà giao nhau xảy ra
datetime tick_time=TickTime();
if(tick_time==0)
return;
//--- tạo văn bản thông báo
string message=StringFormat("Thời gian thanh: %s. Giá đã giao nhau với MA từ trên xuống dưới",TimeToString(ExtRates[1].time));
//--- nếu thông báo trước đó không bằng thông báo hiện tại, hiển thị Alert với thông báo và thời gian tick
if(message!=message_prev)
{
Alert(message+" tại "+TimeToString(tick_time,TIME_DATE|TIME_MINUTES|TIME_SECONDS));
message_prev=message;
/*
Kết quả:
Alert: Thời gian thanh: 2024.02.16 10:00. Giá đã giao nhau với MA từ trên xuống dưới tại 2024.02.16 10:42:15
*/
}
}
}
//+------------------------------------------------------------------+
//| Get price and moving average data into arrays |
//+------------------------------------------------------------------+
bool GetData(int handle,double &ma_data[],MqlRates &price_data[])
{
ResetLastError();
//--- lấy dữ liệu trung bình động từ hai thanh cuối cùng
if(CopyBuffer(handle,0,0,2,ma_data)!=2)
{
PrintFormat("CopyBuffer() thất bại. Mã lỗi: %d",GetLastError());
return(false);
}
//--- lấy dữ liệu giá cho hai thanh cuối cùng
if(CopyRates(Symbol(),PERIOD_CURRENT,0,2,price_data)!=2)
{
PrintFormat("CopyRates() thất bại. Mã lỗi: %d",GetLastError());
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
//| Return the direction of the price crossing the moving average |
//+------------------------------------------------------------------+
ENUM_INTERSECT_DIRECTION GetIntersectDirection(double &ma_data[],MqlRates &price_data[])
{
double ma0=ma_data[1];
double ma1=ma_data[0];
double close0=price_data[1].close;
double close1=price_data[0].close;
if(close1<=ma1 && close0>ma0)
return(INTERSECT_DIRECTION_UP);
else
{
if(close1>=ma1 && close0<ma0)
return(INTERSECT_DIRECTION_DOWN);
else
return(INTERSECT_DIRECTION_NONE);
}
}
//+------------------------------------------------------------------+
//| Return the tick time in seconds |
//+------------------------------------------------------------------+
datetime TickTime()
{
MqlTick tick={};
ResetLastError();
if(!SymbolInfoTick(Symbol(),tick))
{
PrintFormat("SymbolInfoTick() thất bại. Mã lỗi: %d",GetLastError());
return(0);
}
return(tick.time);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195