Lấy thời gian hoặc giá tại các điểm đường thẳng được chỉ định
Nhiều đối tượng đồ họa bao gồm một hoặc nhiều đường thẳng. MQL5 cho phép bạn nội suy và ngoại suy các điểm trên những đường này và lấy một tọa độ khác từ một tọa độ đã biết, ví dụ, giá theo thời gian hoặc thời gian theo giá.
Nội suy luôn khả dụng: nó hoạt động "bên trong" đối tượng, tức là giữa các điểm neo. Ngoại suy bên ngoài một đối tượng chỉ có thể thực hiện nếu thuộc tính tia trong hướng tương ứng được bật cho nó (xem Thuộc tính tia cho các đối tượng có đường thẳng).
Hàm ObjectGetValueByTime
trả về giá trị giá cho thời gian được chỉ định. Hàm ObjectGetTimeByValue
trả về giá trị thời gian cho giá được chỉ định.
double ObjectGetValueByTime(long chartId, const string name, datetime time, int line)
datetime ObjectGetTimeByValue(long chartId, const string name, double value, int line)
Các tính toán được thực hiện cho một đối tượng có tên name
trên biểu đồ với chartId
. Các tham số time
và value
chỉ định một tọa độ đã biết để tính toán tọa độ chưa biết. Vì một đối tượng có thể có nhiều đường, sẽ có nhiều giá trị tương ứng với một tọa độ, do đó cần chỉ định số thứ tự của đường trong tham số line
.
Hàm trả về giá trị giá hoặc thời gian cho phép chiếu của điểm với tọa độ ban đầu được chỉ định so với đường.
Trong trường hợp xảy ra lỗi, hàm sẽ trả về 0, và mã lỗi sẽ được ghi vào _LastError
. Ví dụ, việc cố gắng ngoại suy giá trị đường với thuộc tính tia bị tắt sẽ tạo ra lỗi OBJECT_GETVALUE_FAILED (4205).
Các hàm này áp dụng cho các đối tượng sau:
- Trendline (OBJ_TREND)
- Trendline theo góc (OBJ_TRENDBYANGLE)
- Đường Gann (OBJ_GANNLINE)
- Kênh cách đều (OBJ_CHANNEL), 2 đường
- Kênh hồi quy tuyến tính (OBJ_REGRESSION); 3 đường
- Kênh độ lệch chuẩn (OBJ_STDDEVCHANNEL); 3 đường
- Đường mũi tên (OBJ_ARROWED_LINE)
Hãy kiểm tra hoạt động của hàm bằng một chỉ báo không dùng bộ đệm ObjectChannels.mq5
. Nó tạo ra hai đối tượng với kênh độ lệch chuẩn và kênh hồi quy tuyến tính, sau đó yêu cầu và hiển thị trong phần bình luận giá của các đường trên và dưới trên các thanh tương lai. Đối với kênh độ lệch chuẩn, thuộc tính OBJPROP_RAY_RIGHT được bật, nhưng đối với kênh hồi quy thì không (cố ý). Do đó, không có giá trị nào được nhận từ kênh thứ hai, và số không luôn được hiển thị trên màn hình cho nó.
Khi các thanh mới hình thành, các kênh sẽ tự động di chuyển sang phải. Độ dài của các kênh được đặt trong tham số đầu vào WorkPeriod
(mặc định là 10 thanh).
input int WorkPeriod = 10;
const string Prefix = "ObjChnl-";
const string ObjStdDev = Prefix + "StdDev";
const string ObjRegr = Prefix + "Regr";
void OnInit()
{
CreateObjects();
UpdateObjects();
}
2
3
4
5
6
7
8
9
10
11
Hàm CreateObjects
tạo 2 kênh và thực hiện các cài đặt ban đầu cho chúng.
void CreateObjects()
{
ObjectCreate(0, ObjStdDev, OBJ_STDDEVCHANNEL, 0, 0, 0);
ObjectCreate(0, ObjRegr, OBJ_REGRESSION, 0, 0, 0);
ObjectSetInteger(0, ObjStdDev, OBJPROP_COLOR, clrBlue);
ObjectSetInteger(0, ObjStdDev, OBJPROP_RAY_RIGHT, true);
ObjectSetInteger(0, ObjRegr, OBJPROP_COLOR, clrRed);
// NB: tia không được bật cho kênh hồi quy (cố ý)
}
2
3
4
5
6
7
8
9
Hàm UpdateObjects
di chuyển các kênh đến các thanh WorkPeriod
cuối cùng.
void UpdateObjects()
{
const datetime t0 = iTime(NULL, 0, WorkPeriod);
const datetime t1 = iTime(NULL, 0, 0);
// chúng ta không sử dụng ObjectMove vì các kênh hoạt động
// chỉ với tọa độ thời gian (giá được tính tự động)
ObjectSetInteger(0, ObjStdDev, OBJPROP_TIME, 0, t0);
ObjectSetInteger(0, ObjStdDev, OBJPROP_TIME, 1, t1);
ObjectSetInteger(0, ObjRegr, OBJPROP_TIME, 0, t0);
ObjectSetInteger(0, ObjRegr, OBJPROP_TIME, 1, t1);
}
2
3
4
5
6
7
8
9
10
11
12
Trong trình xử lý OnCalculate
, chúng ta cập nhật vị trí của các kênh trên các thanh mới, và trên mỗi lần nhảy giá, chúng ta gọi DisplayObjectData
để lấy ngoại suy giá và hiển thị nó dưới dạng bình luận.
int OnCalculate(const int rates_total,
const int prev_calculated,
const int begin,
const double &price[])
{
static datetime now = 0;
if(now != iTime(NULL, 0, 0))
{
UpdateObjects();
now = iTime(NULL, 0, 0);
}
DisplayObjectData();
return rates_total;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Trong hàm DisplayObjectData
, chúng ta sẽ tìm giá tại các điểm neo trên đường giữa (OBJPROP_PRICE). Ngoài ra, sử dụng ObjectGetValueByTime
, chúng ta sẽ yêu cầu giá trị giá cho các đường trên và dưới của kênh qua WorkPeriod
thanh trong tương lai.
void DisplayObjectData()
{
const double p0 = ObjectGetDouble(0, ObjStdDev, OBJPROP_PRICE, 0);
const double p1 = ObjectGetDouble(0, ObjStdDev, OBJPROP_PRICE, 1);
// các đẳng thức sau luôn đúng do thuật toán tính toán kênh:
// - các đường giữa của cả hai kênh là giống nhau,
// - các điểm neo luôn nằm trên đường giữa,
// ObjectGetValueByTime(0, ObjStdDev, iTime(NULL, 0, 0), 0) == p1
// ObjectGetValueByTime(0, ObjRegr, iTime(NULL, 0, 0), 0) == p1
// cố gắng ngoại suy giá tương lai từ các đường trên và dưới
const double d1 = ObjectGetValueByTime(0, ObjStdDev, iTime(NULL, 0, 0)
+ WorkPeriod * PeriodSeconds(), 1);
const double d2 = ObjectGetValueByTime(0, ObjStdDev, iTime(NULL, 0, 0)
+ WorkPeriod * PeriodSeconds(), 2);
const double r1 = ObjectGetValueByTime(0, ObjRegr, iTime(NULL, 0, 0)
+ WorkPeriod * PeriodSeconds(), 1);
const double r2 = ObjectGetValueByTime(0, ObjRegr, iTime(NULL, 0, 0)
+ WorkPeriod * PeriodSeconds(), 2);
// hiển thị tất cả giá nhận được trong một bình luận
Comment(StringFormat("%.*f %.*f\ndev: up=%.*f dn=%.*f\nreg: up=%.*f dn=%.*f",
_Digits, p0, _Digits, p1,
_Digits, d1, _Digits, d2,
_Digits, r1, _Digits, r2));
}
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
Điều quan trọng cần lưu ý là do thuộc tính tia không được bật cho kênh hồi quy, nó luôn trả về số không trong tương lai (mặc dù nếu chúng ta yêu cầu giá trong khoảng thời gian của kênh, chúng ta sẽ nhận được giá trị chính xác).
Kênh và giá trị giá tại các điểm của đường thẳng của chúng
Ở đây, đối với các kênh dài 10 thanh, việc ngoại suy cũng được thực hiện trên 10 thanh phía trước, điều này cho ra các giá trị tương lai được hiển thị trong dòng có "dev:", xấp xỉ tương ứng với biên phải của cửa sổ.