Tìm chỉ số thanh theo thời gian (iBarShift)
Hàm iBarShift
cung cấp số thứ tự của thanh tương ứng với thời gian được chỉ định. Trong trường hợp này, việc đánh số các thanh luôn được hiểu theo kiểu chuỗi thời gian, tức là chỉ số 0 tương ứng với thanh bên phải nhất, mới nhất, và các giá trị tăng dần khi di chuyển từ phải sang trái (vào quá khứ).
int iBarShift(const string symbol, ENUM_TIMEFRAMES timeframe, datetime time, bool exact = false)
Hàm trả về chỉ số của thanh trong chuỗi thời gian cho cặp tham số symbol/timeframe
được chỉ định, mà giá trị của tham số time
rơi vào. Mỗi thanh được đặc trưng bởi thời gian mở và thời lượng chung cho tất cả các thanh trong chuỗi, tức là một chu kỳ. Ví dụ, trên khung thời gian giờ, một thanh được đánh dấu với thời gian mở là 13:00 kéo dài từ 13:00:00 đến 13:59:59 (bao gồm cả phút và giây cuối cùng).
Nếu không có thanh nào cho thời gian được chỉ định (ví dụ, thời gian rơi vào giờ hoặc ngày không giao dịch), thì hàm sẽ hoạt động khác nhau tùy thuộc vào tham số exact: nếu exact = true
, hàm sẽ trả về -1; nếu exact = false
, nó sẽ trả về chỉ số của thanh gần nhất có thời gian mở nhỏ hơn thời gian được chỉ định. Trong trường hợp không có thanh như vậy, tức là không có lịch sử trước thời gian được chỉ định, hàm sẽ trả về -1. Nhưng có một chi tiết cần lưu ý ở đây.
Chú ý! Nếu hàm
iBarShift
trả về một số thứ tự thanh cụ thể, tức là một giá trị khác -1, điều này không có nghĩa là lần truy cập chuỗi thời gian tiếp theo bằng chỉ số này sẽ có thể lấy được giá hoặc các đặc tính khác của thanh này. Đặc biệt, điều này có thể xảy ra nếu chỉ số của thanh được yêu cầu vượt quá giới hạn thanh trong cửa sổ terminal (TerminalInfoInteger(TERMINAL_MAXBARS)
). Điều này có thể xảy ra khi các thanh mới được hình thành: sau đó các thanh cũ hơn có thể vượt quá giới hạn sang bên trái và nằm ngoài cửa sổ hiển thị, mặc dù về mặt danh nghĩa chúng có thể vẫn còn trong bộ nhớ một thời gian. Nhà phát triển nên luôn kiểm tra các tình huống như vậy.
Hãy kiểm tra hiệu suất của các hàm Bars/iBars
(xem phần trước) và iBarShift
bằng cách sử dụng script SeriesBars.mq5
.
void OnStart()
{
const datetime target = PRTF(ChartTimeOnDropped());
PRTF(iBarShift(NULL, 0, target));
PRTF(iBarShift(NULL, 0, target, true));
PRTF(iBarShift(NULL, 0, TimeCurrent()));
PRTF(Bars(NULL, 0, target, TimeCurrent()));
PRTF(Bars(NULL, 0, TimeCurrent(), target));
PRTF(iBars(NULL, 0));
PRTF(Bars(NULL, 0));
PRTF(Bars(NULL, 0, 0, TimeCurrent()));
PRTF(Bars(NULL, 0, TimeCurrent(), TimeCurrent()));
}
2
3
4
5
6
7
8
9
10
11
12
13
Ở đây, chúng ta gặp một hàm chưa quen thuộc khác là ChartTimeOnDropped
(chúng ta sẽ mô tả nó sau): nó trả về thời gian của một thanh cụ thể (trong biểu đồ đang hoạt động) mà script từ Navigator
đã được kéo và thả bằng chuột. Trước tiên, hãy kéo script vào khu vực của biểu đồ nơi có báo giá.
Các mục sau sẽ được tạo trong nhật ký (các số sẽ khác nhau, tùy thuộc vào cài đặt, hành động của bạn và thời gian hiện tại):
ChartTimeOnDropped()=2021.10.01 09:00:00 / ok
iBarShift(NULL,0,target)=125 / ok
iBarShift(NULL,0,target,true)=125 / ok
iBarShift(NULL,0,TimeCurrent())=0 / ok
Bars(NULL,0,target,TimeCurrent())=126 / ok
Bars(NULL,0,TimeCurrent(),target)=126 / ok
iBars(NULL,0)=10004 / ok
Bars(NULL,0)=10004 / ok
Bars(NULL,0,0,TimeCurrent())=10004 / ok
Bars(NULL,0,TimeCurrent(),TimeCurrent())=0 / ok
2
3
4
5
6
7
8
9
10
Trong trường hợp này, script đã được kéo đến một thanh có thời gian 2021.10.01 09:00 (khung thời gian giờ được sử dụng). Theo iBarShift
, thời gian này tương ứng với thanh số 125.
Số lượng thanh từ thanh dưới chuột đến thanh cuối cùng (thời gian hiện tại) là 126. Điều này phù hợp với số thanh 125 vì việc đánh số bắt đầu từ 0.
Tổng số thanh trên biểu đồ, thu được theo các cách khác nhau (iBars
, Bars
không có phạm vi ngày, và Bars
với phạm vi đầy đủ từ 0 đến thời điểm hiện tại TimeCurrent
), bằng 10004. Cài đặt terminal có giới hạn là 10000 nhưng thêm 4 thanh giờ đã được hình thành trong phiên.
Số thứ tự của thanh mà thời gian hiện tại rơi vào iBarShift(..., TimeCurrent())
luôn là 0 đối với một ký hiệu và khung thời gian hiện có, với điều kiện exact = false
. Nếu exact = true
, thì đôi khi chúng ta có thể nhận được -1 vì thời gian máy chủ tăng lên khi các tick của tất cả các công cụ thị trường đến, và ký hiệu hiện tại có thể tạm thời không được giao dịch. Khi đó, thời gian máy chủ có thể vượt trước hơn một thanh, và đối với TimeCurrent
không có thanh mới nào để khớp chính xác.
Nếu chúng ta kéo và thả script vào khu vực trống bên phải của thanh cuối cùng hiện tại (tức là vào tương lai), chúng ta sẽ nhận được kết quả như sau:
ChartTimeOnDropped()=2021.10.09 02:30:00 / ok
iBarShift(NULL,0,target)=0 / ok
iBarShift(NULL,0,target,true)=-1 / ok
Bars(NULL,0,target,TimeCurrent())=0 / ok
Bars(NULL,0,TimeCurrent(),target)=0 / ok
iBars(NULL,0)=10004 / ok
Bars(NULL,0)=10004 / ok
Bars(NULL,0,0,TimeCurrent())=10004 / ok
Bars(NULL,0,TimeCurrent(),TimeCurrent())=0 / ok
2
3
4
5
6
7
8
9
Hàm iBarShift
trong chế độ tìm kiếm bất kỳ thanh trước đó (exact = false
) trả về 0 vì thanh hiện tại là gần nhất với tương lai. Tuy nhiên, tìm kiếm chính xác (exact = true
) cho kết quả -1. Ngoài ra, các hàm Bars
đếm số thanh trong phạm vi từ thời gian hiện tại đến "mục tiêu" tương lai hiện trả về 0 (chưa có thanh nào ở đó).
Hàm iBarShift
đặc biệt hữu ích cho việc viết các chương trình MQL đa tiền tệ. Thường xuyên, lịch trình giao dịch cho các công cụ tài chính khác nhau không trùng nhau, vì vậy đối với một thời gian cụ thể, một thanh có thể tồn tại trên một ký hiệu nhưng không tồn tại trên ký hiệu khác. Sử dụng hàm iBarShift
trong chế độ tìm kiếm thanh gần nhất (trước đó), bạn luôn có thể lấy chỉ số thanh với giá có liên quan cho các ký hiệu khác nhau tại cùng một thời điểm. Thông thường, ngay cả đối với các ký hiệu Forex, chỉ số của các thanh lịch sử cho cùng một thời gian có thể khác nhau.
Ví dụ, các lệnh sau sẽ ghi lại số lượng thanh và số thứ tự của chúng khác nhau trong cùng một phạm vi ngày cho ba ký hiệu: EURUSD, XAUUSD, USDRUB trên khung thời gian một giờ (máy chủ MQ Demo):
PRTF(Bars("EURUSD", PERIOD_H1, D'2021.05.01', D'2021.09.01')); // 2087
PRTF(Bars("XAUUSD", PERIOD_H1, D'2021.05.01', D'2021.09.01')); // 1991
PRTF(Bars("USDRUB", PERIOD_H1, D'2021.05.01', D'2021.09.01')); // 694
PRTF(iBarShift("EURUSD", PERIOD_H1, D'2021.09.01')); // 671
PRTF(iBarShift("XAUUSD", PERIOD_H1, D'2021.09.01')); // 638
PRTF(iBarShift("USDRUB", PERIOD_H1, D'2021.09.01')); // 224
2
3
4
5
6