Khả năng hiển thị của các đối tượng trong ngữ cảnh khung thời gian
Người dùng MetaTrader 5 biết về tab Hiển thị trong hộp thoại thuộc tính đối tượng, nơi bạn có thể sử dụng các công tắc để chọn khung thời gian mà đối tượng sẽ được hiển thị và khung thời gian mà nó sẽ bị ẩn. Đặc biệt, bạn có thể tạm thời ẩn hoàn toàn đối tượng trên tất cả các khung thời gian.
MQL5 có một thuộc tính chương trình tương tự, OBJPROP_TIMEFRAMES
, kiểm soát khả năng hiển thị của đối tượng trên một khung thời gian. Giá trị của thuộc tính này có thể là bất kỳ tổ hợp nào của các cờ số nguyên đặc biệt: mỗi cờ (hằng số) chứa một bit tương ứng với một khung thời gian (xem bảng). Để đặt/lấy thuộc tính OBJPROP_TIMEFRAMES
, hãy sử dụng các hàm ObjectSetInteger
/ObjectGetInteger
.
Hằng số | Giá trị | Khả năng hiển thị trong khung thời gian |
---|---|---|
OBJ_NO_PERIODS | 0 | Đối tượng bị ẩn trên tất cả các khung thời gian |
OBJ_PERIOD_M1 | 0x00000001 | M1 |
OBJ_PERIOD_M2 | 0x00000002 | M2 |
OBJ_PERIOD_M3 | 0x00000004 | M3 |
OBJ_PERIOD_M4 | 0x00000008 | M4 |
OBJ_PERIOD_M5 | 0x00000010 | M5 |
OBJ_PERIOD_M6 | 0x00000020 | M6 |
OBJ_PERIOD_M10 | 0x00000040 | M10 |
OBJ_PERIOD_M12 | 0x00000080 | M12 |
OBJ_PERIOD_M15 | 0x00000100 | M15 |
OBJ_PERIOD_M20 | 0x00000200 | M20 |
OBJ_PERIOD_M30 | 0x00000400 | M30 |
OBJ_PERIOD_H1 | 0x00000800 | H1 |
OBJ_PERIOD_H2 | 0x00001000 | H2 |
OBJ_PERIOD_H3 | 0x00002000 | H3 |
OBJ_PERIOD_H4 | 0x00004000 | H4 |
OBJ_PERIOD_H6 | 0x00008000 | H6 |
OBJ_PERIOD_H8 | 0x00010000 | H8 |
OBJ_PERIOD_H12 | 0x00020000 | H12 |
OBJ_PERIOD_D1 | 0x00040000 | D1 |
OBJ_PERIOD_W1 | 0x00080000 | W1 |
OBJ_PERIOD_MN1 | 0x00100000 | MN1 |
OBJ_ALL_PERIODS | 0x001fffff | Tất cả các khung thời gian |
Các cờ có thể được kết hợp bằng toán tử OR bitwise (|
), ví dụ, sự chồng lấp của các cờ OBJ_PERIOD_M15 | OBJ_PERIOD_H4
có nghĩa là đối tượng sẽ hiển thị trên khung thời gian 15 phút và 4 giờ.
Lưu ý rằng mỗi cờ có thể được tạo bằng cách dịch chuyển 1 sang trái theo số bit bằng với số thứ tự của hằng số trong bảng. Điều này giúp dễ dàng tạo cờ động khi thuật toán hoạt động trên nhiều khung thời gian thay vì một khung cụ thể.
Chúng ta sẽ sử dụng tính năng này trong script thử nghiệm ObjectTimeframes.mq5
. Nhiệm vụ của nó là tạo nhiều nhãn văn bản lớn trên biểu đồ với tên của các khung thời gian, và mỗi tiêu đề chỉ hiển thị trong khung thời gian tương ứng. Ví dụ, nhãn lớn "D1" chỉ hiển thị trên biểu đồ ngày, và khi chuyển sang H4, chúng ta sẽ thấy "H4".
Để lấy tên ngắn của khung thời gian, không có tiền tố PERIOD_
, một hàm phụ trợ đơn giản được triển khai.
string GetPeriodName(const int tf)
{
const static int PERIOD_ = StringLen("PERIOD_");
return StringSubstr(EnumToString((ENUM_TIMEFRAMES)tf), PERIOD_);
}
2
3
4
5
Để lấy danh sách tất cả các khung thời gian từ liệt kê ENUM_TIMEFRAMES
, chúng ta sẽ sử dụng hàm EnumToArray
đã được trình bày trong phần về chuyển đổi liệt kê.
#include "ObjectPrefix.mqh"
#include <MQL5Book/EnumToArray.mqh>
void OnStart()
{
ENUM_TIMEFRAMES tf = 0;
int values[];
const int n = EnumToArray(tf, values, 0, USHORT_MAX);
...
}
2
3
4
5
6
7
8
9
10
Tất cả các nhãn sẽ được hiển thị ở giữa cửa sổ tại thời điểm script khởi chạy. Việc thay đổi kích thước cửa sổ sau khi script kết thúc sẽ khiến các chú thích đã tạo không còn ở giữa nữa. Đây là hệ quả của việc MQL5 chỉ hỗ trợ neo vào các góc của cửa sổ, không phải ở giữa. Nếu bạn muốn tự động duy trì vị trí của các đối tượng, bạn nên triển khai một thuật toán tương tự trong chỉ báo và phản hồi các sự kiện thay đổi kích thước cửa sổ. Ngoài ra, chúng ta có thể hiển thị nhãn ở một góc, ví dụ, góc dưới bên phải.
const int centerX = (int)ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) / 2;
const int centerY = (int)ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS) / 2;
...
2
3
Trong vòng lặp qua các khung thời gian, chúng ta tạo một đối tượng OBJ_LABEL
cho mỗi khung, và đặt nó ở giữa cửa sổ với neo ở trung tâm của đối tượng.
for(int i = 1; i < n; ++i)
{
// tạo và thiết lập nhãn văn bản cho mỗi khung thời gian
const string name = ObjNamePrefix + (string)i;
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, centerX);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, centerY);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_CENTER);
...
}
2
3
4
5
6
7
8
9
10
Tiếp theo, chúng ta đặt văn bản (tên của khung thời gian), kích thước phông chữ lớn, màu xám và thuộc tính hiển thị ở nền.
ObjectSetString(0, name, OBJPROP_TEXT, GetPeriodName(values[i]));
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fmin(centerY, centerX));
ObjectSetInteger(0, name, OBJPROP_COLOR, clrLightGray);
ObjectSetInteger(0, name, OBJPROP_BACK, true);
...
2
3
4
5
Cuối cùng, chúng ta tạo cờ khả năng hiển thị chính xác cho khung thời gian thứ i
và ghi nó vào thuộc tính OBJPROP_TIMEFRAMES
.
const int flag = 1 << (i - 1);
ObjectSetInteger(0, name, OBJPROP_TIMEFRAMES, flag);
}
2
3
Xem điều gì đã xảy ra trên biểu đồ khi chuyển đổi khung thời gian.
Nhãn với tên khung thời gian
Nếu bạn mở hộp thoại Object List
và bật All
đối tượng trong danh sách,很容易 kiểm tra rằng có các nhãn được tạo cho tất cả các khung thời gian và kiểm tra cờ khả năng hiển thị của chúng.
Để xóa các đối tượng, bạn có thể chạy script ObjectCleanup1.mq5
.