Tìm giá trị tối đa và tối thiểu trong chuỗi thời gian
Trong nhóm các hàm làm việc với chuỗi thời gian của báo giá, có hai hàm cung cấp xử lý tổng hợp đơn giản nhất: tìm kiếm giá trị tối đa và tối thiểu của chuỗi trong một khoảng thời gian nhất định, lần lượt là iHighest
và iLowest
.
int iHighest(const string symbol, ENUM_TIMEFRAMES timeframe, ENUM_SERIESMODE type, int count = WHOLE_ARRAY, int offset = 0)
int iLowest(const string symbol, ENUM_TIMEFRAMES timeframe, ENUM_SERIESMODE type, int count = WHOLE_ARRAY, int offset = 0)
Các hàm trả về chỉ số của giá trị lớn nhất/nhỏ nhất cho một loại chuỗi thời gian cụ thể, được chỉ định bởi cặp tham số symbol/timeframe
, cũng như phần tử liệt kê ENUM_SERIESMODE (nó mô tả các trường báo giá đã quen thuộc với chúng ta).
Định danh | Mô tả |
---|---|
MODE_OPEN | Giá mở |
MODE_LOW | Giá thấp nhất |
MODE_HIGH | Giá cao nhất |
MODE_CLOSE | Giá đóng |
MODE_VOLUME | Khối lượng tick |
MODE_REAL_VOLUME | Khối lượng thực |
MODE_SPREAD | Chênh lệch giá |
Tham số offset
chỉ định chỉ số bắt đầu tìm kiếm. Việc đánh số được thực hiện như trong chuỗi thời gian, nghĩa là tăng offset
dẫn đến dịch chuyển về quá khứ, và chỉ số 0 có nghĩa là thanh hiện tại (đây là giá trị mặc định). Số lượng thanh được phân tích được chỉ định trong tham số count
(mặc định là WHOLE_ARRAY
).
Trong trường hợp xảy ra lỗi, các hàm trả về -1. Sử dụng GetLastError
để tìm mã lỗi.
Để minh họa cách hoạt động của một trong những hàm này (iHighest
), hãy sửa đổi ví dụ từ phần trước về việc ước lượng kích thước thực tế của chênh lệch giá theo thanh và so sánh kết quả. Tất nhiên, chúng phải khớp nhau. Phiên bản mới của script được đính kèm trong tệp SeriesSpreadHighest.mq5
.
Những thay đổi ảnh hưởng đến cấu trúc SpreadPerBar
và chu kỳ làm việc bên trong OnStart
.
Các trường đã được thêm vào cấu trúc để giúp hiểu cách hàm mới hoạt động. Do tính chất của thuật toán, chúng không bắt buộc.
struct SpreadPerBar
{
datetime time;
int spread;
int max; // thông qua chỉ số của thanh M1 với chênh lệch giá, giá trị tối đa
// trong số tất cả các thanh M1 trong thanh hiện tại của khung thời gian cao hơn
int num; // số lượng thanh M1 trong thanh hiện tại của khung thời gian cao hơn
int pos; // chỉ số ban đầu của thanh M1 trong thanh hiện tại của khung thời gian cao hơn
};
2
3
4
5
6
7
8
9
Các biến đổi chính ảnh hưởng đến OnStart
, nhưng chúng được giới hạn trong vòng lặp (tất cả các đoạn mã khác vẫn không thay đổi).
for(int i = 0; i < BarCount; ++i)
{
const datetime next = iTime(WorkSymbol, TimeFrame, i);
const datetime prev = iTime(WorkSymbol, TimeFrame, i + 1);
...
2
3
4
5
Các ranh giới của thanh hiện tại, prev
và next
, được xác định như trước đây. Tuy nhiên, thay vì sao chép các phần tử chuỗi thời gian giữa các nhãn này vào mảng riêng spreads
, và sau đó gọi ArrayMaximum
cho nó, chúng ta xác định các chỉ số và số lượng thanh M1 tạo thành thanh hiện tại của khung thời gian cao hơn. Điều này được thực hiện như sau.
Hàm iBarShift
cho phép tìm ra độ lệch (biến p
) trong lịch sử M1, nơi đặt ranh giới bên phải của thanh với thời gian next - 1
. Hàm Bars
tính toán số lượng thanh M1 (biến n
) nằm giữa prev
và next - 1
. Hai giá trị này trở thành tham số trong lời gọi hàm iHighest
để tìm giá trị tối đa của loại MODE_SPREAD
, trong số n
thanh M1, bắt đầu từ chỉ số p
. Nếu tối đa được tìm thấy mà không có vấn đề (m > -1
), chúng ta chỉ cần lấy giá trị tương ứng bằng iSpread
và đặt nó vào cấu trúc.
const int p = iBarShift(WorkSymbol, PERIOD_M1, next - 1);
const int n = Bars(WorkSymbol, PERIOD_M1, prev, next - 1);
const int m = iHighest(WorkSymbol, PERIOD_M1, MODE_SPREAD, n, p);
if(m > -1)
{
peaks[i].spread = iSpread(WorkSymbol, PERIOD_M1, m);
peaks[i].time = prev;
peaks[i].max = m;
peaks[i].num = n;
peaks[i].pos = p;
}
}
2
3
4
5
6
7
8
9
10
11
12
Khi xuất mảng kết quả ra nhật ký, giờ đây chúng ta sẽ thấy thêm các chỉ số của thanh M1, nơi thanh của khung thời gian cao hơn "bắt đầu" và nơi tìm thấy chênh lệch giá tối đa trong đó. Từ "bắt đầu" được đặt trong dấu ngoặc kép, vì khi các thanh M1 mới đến, các chỉ số này sẽ tăng lên, và "điểm bắt đầu" ảo của mỗi thanh sẽ dịch chuyển, mặc dù thời gian mở của các thanh lịch sử, tất nhiên, vẫn không đổi.
Maximal spreads per intraday bar
Processed 100 bars on EURUSD PERIOD_H1
[time] [spread] [max] [num] [pos]
[ 0] 2021.10.12 15:00 0 7 60 7
[ 1] 2021.10.12 14:00 1 89 60 67
[ 2] 2021.10.12 13:00 1 181 60 127
[ 3] 2021.10.12 12:00 1 213 60 187
[ 4] 2021.10.12 11:00 1 248 60 247
[ 5] 2021.10.12 10:00 0 307 60 307
[ 6] 2021.10.12 09:00 1 385 60 367
[ 7] 2021.10.12 08:00 2 469 60 427
[ 8] 2021.10.12 07:00 2 497 60 487
[ 9] 2021.10.12 06:00 1 550 60 547
[10] 2021.10.12 05:00 1 616 60 607
[11] 2021.10.12 04:00 1 678 60 667
[12] 2021.10.12 03:00 1 727 60 727
[13] 2021.10.12 02:00 4 820 60 787
[14] 2021.10.12 01:00 16 906 60 847
[15] 2021.10.12 00:00 65 956 60 907
[16] 2021.10.11 23:00 15 967 60 967
[17] 2021.10.11 22:00 2 1039 60 1027
[18] 2021.10.11 21:00 1 1090 60 1087
[19] 2021.10.11 20:00 1 1148 60 1147
[20] 2021.10.11 19:00 2 1210 60 1207
[21] 2021.10.11 18:00 1 1313 60 1267
[22] 2021.10.11 17:00 1 1345 60 1327
[23] 2021.10.11 16:00 1 1411 60 1387
[24] 2021.10.11 15:00 2 1461 60 1447
[25] 2021.10.11 14:00 1 1526 60 1507
...
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
Ví dụ, tại thời điểm script được khởi chạy, thanh với nhãn 2021.10.12 14:00 bắt đầu từ thanh M1 thứ 67 (tức là nó được mở cách đây 67 phút), và thanh M1 với chênh lệch giá tối đa bên trong thanh H1 này được tìm thấy dưới chỉ số 89. Rõ ràng, chỉ số này phải nhỏ hơn số của thanh M1 nơi thanh H1 trước đó bắt đầu: 2021.10.12 13:00 — nó được đánh dấu cách đây 127 phút. Trong thanh H1 này, lần lượt, chênh lệch giá tối đa cho chỉ số 181 được tìm thấy. Và điều này nhỏ hơn chỉ số 187 cho thanh cũ hơn 2021.10.12 12:00.
Các chỉ số trong cột pos
và max
liên tục tăng vì chúng ta duyệt qua các thanh theo thứ tự từ hiện tại đến quá khứ. Cột num
hầu như sẽ có giá trị 60 vì hầu hết các thanh H1 được tạo thành từ 60 thanh M1. Nhưng điều này không phải lúc nào cũng đúng. Ví dụ, dưới đây là các thanh hàng giờ chưa hoàn chỉnh, bao gồm ít phút hơn: điều này có thể là hậu quả của việc thị trường đóng cửa sớm do lịch nghỉ lễ, hoặc các khoảng trống thực sự trong hoạt động giao dịch (thiếu thanh khoản).
...
[38] 2021.10.11 01:00 20 2346 60 2287
[39] 2021.10.11 00:00 85 2404 58 2347
[40] 2021.10.08 23:00 15 2406 55 2405
[41] 2021.10.08 22:00 2 2463 60 2460
...
2
3
4
5
6