Đọc bản ghi sự kiện theo ID
Biết được lịch trình sự kiện trong tương lai gần, các nhà giao dịch có thể điều chỉnh robot của họ cho phù hợp. Không có hàm hoặc sự kiện nào trong API lịch (ở đây "sự kiện" được hiểu là các hàm xử lý thông tin tài chính mới như OnCalendar
, tương tự với OnTick
) để tự động theo dõi các bản tin. Thuật toán phải tự thực hiện việc này với bất kỳ tần suất nào được chọn. Cụ thể, bạn có thể tìm ra định danh của sự kiện mong muốn bằng một trong những hàm đã thảo luận trước đó (ví dụ: CalendarValueHistoryByEvent
, CalendarValueHistory
) và sau đó gọi CalendarValueById
để lấy trạng thái hiện tại của các trường trong cấu trúc MqlCalendarValue
.
bool CalendarValueById(ulong id, MqlCalendarValue &value)
Hàm này điền vào cấu trúc được truyền bằng tham chiếu với thông tin hiện tại về một sự kiện cụ thể.
Kết quả của hàm biểu thị dấu hiệu thành công (true
) hoặc lỗi (false
).
Hãy tạo một chỉ báo không bộ đệm đơn giản CalendarRecordById.mq5
, sẽ tìm trong tương lai sự kiện gần nhất với loại "chỉ số tài chính" (tức là một chỉ số số) và sẽ thăm dò trạng thái của nó theo bộ đếm thời gian. Khi tin tức được công bố, dữ liệu sẽ thay đổi (giá trị "thực tế" của chỉ số sẽ được biết), và chỉ báo sẽ hiển thị cảnh báo.
Tần suất thăm dò lịch được đặt trong biến đầu vào.
input uint TimerSeconds = 5;
Chúng ta chạy bộ đếm thời gian trong OnInit
.
void OnInit()
{
EventSetTimer(TimerSeconds);
}
2
3
4
Để xuất mô tả sự kiện ra nhật ký một cách thuận tiện, chúng ta sử dụng cấu trúc MqlCalendarRecord
mà chúng ta đã biết từ ví dụ với kịch bản CalendarForDates.mq5
.
Để lưu trữ trạng thái ban đầu của thông tin tin tức, chúng ta mô tả cấu trúc track
.
MqlCalendarValue track;
Khi cấu trúc trống (và có "0" trong trường id
), chương trình phải truy vấn các sự kiện sắp tới và tìm trong số đó sự kiện gần nhất với loại CALENDAR_TYPE_INDICATOR và giá trị hiện tại chưa được biết.
void OnTimer()
{
if(!track.id)
{
MqlCalendarValue values[];
if(PRTF(CalendarValueHistory(values, TimeCurrent(), TimeCurrent() + DAY_LONG * 3)))
{
for(int i = 0; i < ArraySize(values); ++i)
{
MqlCalendarEvent event;
CalendarEventById(values[i].event_id, event);
if(event.type == CALENDAR_TYPE_INDICATOR && !values[i].HasActualValue())
{
track = values[i];
PrintFormat("Started monitoring %lld", track.id);
StructPrint(MqlCalendarRecord(track), ARRAYPRINT_HEADER);
return;
}
}
}
}
...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Sự kiện được tìm thấy sẽ được sao chép vào track
và xuất ra nhật ký. Sau đó, mỗi lần gọi OnTimer
sẽ quy về việc lấy thông tin cập nhật về sự kiện vào cấu trúc update
, được truyền vào CalendarValueById
với định danh track.id
. Tiếp theo, cấu trúc gốc và cấu trúc mới được so sánh bằng hàm phụ trợ StructCompare
(dựa trên StructToCharArray
và ArrayCompare
, xem mã nguồn đầy đủ). Bất kỳ sự khác biệt nào cũng khiến trạng thái mới được in ra (dự báo có thể đã thay đổi), và nếu giá trị hiện tại xuất hiện, bộ đếm thời gian sẽ dừng lại. Để bắt đầu chờ tin tức tiếp theo, chỉ báo này cần được khởi tạo lại: đây là để trình diễn, và để kiểm soát tình hình theo danh sách tin tức, chúng ta sẽ phát triển một lớp bộ lọc thực tế hơn sau này.
else
{
MqlCalendarValue update;
if(CalendarValueById(track.id, update))
{
if(fabs(StructCompare(track, update)) == 1)
{
Alert(StringFormat("News %lld changed", track.id));
PrintFormat("New state of %lld", track.id);
StructPrint(MqlCalendarRecord(update), ARRAYPRINT_HEADER);
if(update.HasActualValue())
{
Print("Timer stopped");
EventKillTimer();
}
else
{
track = update;
}
}
}
if(TimeCurrent() <= track.time)
{
Comment("Forthcoming event time: ", track.time,
", remaining: ", Timing::stringify((uint)(track.time - TimeCurrent())));
}
else
{
Comment("Forthcoming event time: ", track.time,
", late for: ", Timing::stringify((uint)(TimeCurrent() - track.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
Trong khi chờ sự kiện, chỉ báo hiển thị một bình luận với thời gian dự kiến của bản tin và còn lại bao nhiêu thời gian trước đó (hoặc độ trễ là bao nhiêu).
Bình luận về việc chờ đợi hoặc trễ hẹn cho tin tức tiếp theo
Điều quan trọng cần lưu ý là tin tức có thể được công bố sớm hơn hoặc muộn hơn một chút so với ngày đã định. Điều này tạo ra một số vấn đề khi kiểm tra các chiến lược tin tức trên lịch sử, vì thời gian cập nhật các mục lịch trong terminal và qua API MQL5 không được cung cấp. Chúng ta sẽ cố gắng giải quyết vấn đề này một phần trong phần tiếp theo.
Dưới đây là các đoạn trích từ nhật ký đầu ra do chỉ báo tạo ra với một khoảng cách:
CalendarValueHistory(values,TimeCurrent(),TimeCurrent()+(60*60*24)*3)=186 / ok
Started monitoring 156045
[id] [event_id] [time] [period] [revision] »
156045 840020013 2022.06.27 15:30:00 2022.05.01 00:00:00 0 »
» [actual_value] [prev_value] [revised_prev_value] [forecast_value] [impact_type] »
» -9223372036854775808 400000 -9223372036854775808 0 0 »
» [importance] [name] [currency] [code] [actual] [previous] [revised] [forecast]
» "Medium" "Durable Goods Orders m/m" "USD" "US" nan 0.40000 nan 0.00000
...
Alert: News 156045 changed
New state of 156045
[id] [event_id] [time] [period] [revision] »
156045 840020013 2022.06.27 15:30:00 2022.05.01 00:00:00 0 »
» [actual_value] [prev_value] [revised_prev_value] [forecast_value] [impact_type] »
» 700000 400000 -9223372036854775808 0 1 »
» [importance] [name] [currency] [code] [actual] [previous] [revised] [forecast]
» "Medium" "Durable Goods Orders m/m" "USD" "US" 0.70000 0.40000 nan 0.00000
Timer stopped
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Tin tức được cập nhật có giá trị actual_value
.
Để không phải chờ quá lâu trong quá trình kiểm tra, nên chạy chỉ báo này trong giờ làm việc của các thị trường chính, khi mật độ phát hành tin tức cao.
Hàm CalendarValueById
không phải là duy nhất, và có lẽ không phải là linh hoạt nhất, để theo dõi các thay đổi trong lịch. Chúng ta sẽ xem xét một vài cách tiếp cận khác trong các phần tiếp theo.