Chuyển đổi tọa độ màn hình sang thời gian/giá và ngược lại
Sự tồn tại của các nguyên tắc khác nhau để đo lường không gian làm việc của biểu đồ dẫn đến nhu cầu tính toán lại các đơn vị đo lường giữa chúng. Có hai hàm để thực hiện điều này.
bool ChartTimePriceToXY(long chartId, int window, datetime time, double price, int &x, int &y)
bool ChartXYToTimePrice(long chartId, int x, int y, int &window, datetime &time, double &price)
Hàm ChartTimePriceToXY
chuyển đổi tọa độ biểu đồ từ biểu diễn thời gian/giá (time/price
) sang tọa độ X và Y tính bằng pixel (x/y
). Hàm ChartXYToTimePrice
thực hiện thao tác ngược lại: nó chuyển đổi tọa độ X và Y thành giá trị thời gian và giá.
Cả hai hàm đều yêu cầu chỉ định ID biểu đồ trong tham số đầu tiên chartId
. Ngoài ra, số của cửa sổ phụ window
được truyền vào ChartTimePriceToXY
(nó phải nằm trong số lượng cửa sổ). Nếu có nhiều cửa sổ phụ, mỗi cửa sổ có chuỗi thời gian riêng và thang dọc (được gọi một cách có điều kiện là "giá" với tham số price
).
Tham số window
là đầu ra trong hàm ChartXYToTimePrice
. Hàm này điền tham số này cùng với time
và price
. Điều này là do tọa độ pixel là chung cho toàn bộ màn hình, và gốc x/y
có thể rơi vào bất kỳ cửa sổ phụ nào.
Thời gian, giá và tọa độ màn hình
Các hàm trả về true
khi hoàn thành thành công.
Lưu ý rằng khu vực hình chữ nhật hiển thị tương ứng với báo giá hoặc tọa độ màn hình bị giới hạn trong cả hai hệ tọa độ. Do đó, có thể xảy ra tình huống khi với dữ liệu ban đầu cụ thể, thời gian, giá hoặc pixel nhận được sẽ nằm ngoài khu vực hiển thị. Đặc biệt, giá trị âm cũng có thể được nhận. Chúng ta sẽ xem xét một ví dụ tính toán lại tương tác trong chương về sự kiện trên biểu đồ.
Trong phần trước, chúng ta đã thấy cách tìm ra vị trí khởi chạy một chương trình MQL. Mặc dù về mặt vật lý chỉ có một điểm thả cuối cùng, biểu diễn của nó trong tọa độ báo giá và màn hình thường chứa sai số tính toán. Hai hàm mới để chuyển đổi pixel thành giá/thời gian và ngược lại sẽ giúp chúng ta xác nhận điều này.
Script đã sửa đổi được gọi là ChartXY.mq5
. Nó có thể được chia thành 3 giai đoạn. Ở giai đoạn đầu tiên, chúng ta suy ra tọa độ của điểm thả, như trước đây.
void OnStart()
{
const int w1 = PRTF(ChartWindowOnDropped());
const datetime t1 = PRTF(ChartTimeOnDropped());
const double p1 = PRTF(ChartPriceOnDropped());
const int x1 = PRTF(ChartXOnDropped());
const int y1 = PRTF(ChartYOnDropped());
...
2
3
4
5
6
7
8
Ở giai đoạn thứ hai, chúng ta cố gắng chuyển đổi tọa độ màn hình x1
và y1
trong thời gian (t2
) và giá (p2
), và so sánh chúng với những giá trị thu được từ các hàm OnDropped
ở trên.
int w2;
datetime t2;
double p2;
PRTF(ChartXYToTimePrice(0, x1, y1, w2, t2, p2));
Print(w2, " ", p2, " ", t2);
PRTF(w1 == w2 && t1 == t2 && p1 == p2);
...
2
3
4
5
6
7
Sau đó, chúng ta thực hiện chuyển đổi ngược: sử dụng tọa độ báo giá thu được t1
và p1
để tính toán tọa độ màn hình - x2
và y2
và cũng so sánh với giá trị ban đầu x1
và y1
.
int x2, y2;
PRTF(ChartTimePriceToXY(0, w1, t1, p1, x2, y2));
Print(x2, " ", y2);
PRTF(x1 == x2 && y1 == y2);
...
2
3
4
5
Như chúng ta sẽ thấy sau trong nhật ký ví dụ, tất cả các kiểm tra trên sẽ thất bại (sẽ có sai lệch nhỏ trong các giá trị). Vì vậy, chúng ta cần bước thứ ba.
Hãy tính toán lại tọa độ màn hình và báo giá với hậu tố 2 trong tên biến và lưu chúng vào các biến với hậu tố mới 3. Sau đó, chúng ta so sánh tất cả các giá trị từ giai đoạn đầu tiên và thứ ba với nhau.
int w3;
datetime t3;
double p3;
PRTF(ChartXYToTimePrice(0, x2, y2, w3, t3, p3));
Print(w3, " ", p3, " ", t3);
PRTF(w1 == w3 && t1 == t3 && p1 == p3);
int x3, y3;
PRTF(ChartTimePriceToXY(0, w2, t2, p2, x3, y3));
Print(x3, " ", y3);
PRTF(x1 == x3 && y1 == y3);
}
2
3
4
5
6
7
8
9
10
11
12
Hãy chạy script trên biểu đồ XAUUSD, H1. Dưới đây là dữ liệu điểm ban đầu.
ChartWindowOnDropped()=0 / ok
ChartTimeOnDropped()=2021.11.22 18:00:00 / ok
ChartPriceOnDropped()=1797.7 / ok
ChartXOnDropped()=234 / ok
ChartYOnDropped()=280 / ok
2
3
4
5
Chuyển đổi pixel sang báo giá cho kết quả sau.
ChartXYToTimePrice(0,x1,y1,w2,t2,p2)=true / ok
0 1797.16 2021.11.22 18:30:00
w1==w2&&t1==t2&&p1==p2=false / ok
2
3
Có sự khác biệt ở cả thời gian và giá. Tính toán ngược lại cũng không hoàn hảo về độ chính xác.
ChartTimePriceToXY(0,w1,t1,p1,x2,y2)=true / ok
232 278
x1==x2&&y1==y2=false / ok
2
3
Mất độ chính xác xảy ra do lượng tử hóa các giá trị trên các trục theo đơn vị đo lường, đặc biệt là pixel và điểm.
Cuối cùng, bước cuối cùng chứng minh rằng các sai số thu được ở trên không phải là hiện tượng của hàm, vì tính toán vòng tròn dẫn đến kết quả ban đầu.
ChartXYToTimePrice(0,x2,y2,w3,t3,p3)=true / ok
0 1797.7 2021.11.22 18:00:00
w1==w3&&t1==t3&&p1==p3=true / ok
ChartTimePriceToXY(0,w2,t2,p2,x3,y3)=true / ok
234 280
x1==x3&&y1==y3=true / ok
2
3
4
5
6
Trong mã giả, điều này có thể được biểu diễn bằng các đẳng thức sau:
ChartTimePriceToXY(ChartXYToTimePrice(XY)) = XY
ChartXYToTimePrice(ChartTimePriceToXY(TP)) = TP
2
Áp dụng hàm ChartTimePriceToXY
vào kết quả làm việc của ChartXYToTimePrice
sẽ cho tọa độ ban đầu. Điều tương tự cũng đúng cho các chuyển đổi theo hướng ngược lại: áp dụng ChartXYToTimePrice
vào kết quả của ChartTimePriceToXY
sẽ cho sự khớp.
Do đó, cần cân nhắc kỹ lưỡng khi triển khai các thuật toán sử dụng hàm tính toán lại nếu chúng có yêu cầu cao về độ chính xác.
Một ví dụ khác về việc sử dụng ChartWindowOnDropped
sẽ được đưa ra trong script ChartIndicatorMove.mq5
trong phần Quản lý chỉ báo trên biểu đồ.