Lấy tick cuối cùng của một ký hiệu
Trong chương về chuỗi thời gian, trong phần Làm việc với mảng tick thực tế, chúng ta đã giới thiệu cấu trúc tích hợp MqlTick
chứa các trường với giá trị giá và khối lượng cho một ký hiệu cụ thể, được biết tại thời điểm mỗi thay đổi trong báo giá. Ở chế độ trực tuyến, một chương trình MQL có thể truy vấn giá và khối lượng nhận được cuối cùng bằng hàm SymbolInfoTick
sử dụng cùng cấu trúc này.
bool SymbolInfoTick(const string symbol, MqlTick &tick)
Đối với một ký hiệu với tên được đưa ra symbol
, hàm điền vào cấu trúc tick
được truyền bằng tham chiếu. Nếu thành công, nó trả về true
.
Như bạn đã biết, các chỉ báo và Expert Advisors được terminal tự động gọi khi có tick mới đến, nếu chúng chứa mô tả của các trình xử lý tương ứng OnCalculate
và OnTick
. Tuy nhiên, thông tin về ý nghĩa của thay đổi giá, khối lượng của giao dịch cuối cùng, và thời gian tạo tick không được chuyển trực tiếp đến các trình xử lý. Thông tin chi tiết hơn có thể được lấy bằng hàm SymbolInfoTick
.
Sự kiện tick chỉ được tạo ra cho ký hiệu của biểu đồ, và do đó chúng ta đã xem xét tùy chọn lấy sự kiện đa ký hiệu của riêng mình cho các tick dựa trên sự kiện tùy chỉnh. Trong trường hợp này, SymbolInfoTick
cho phép đọc thông tin về các tick trên các ký hiệu bên thứ ba khi nhận được thông báo.
Hãy lấy chỉ báo EventTickSpy.mq5
và chuyển đổi nó thành SymbolTickSpy.mq5
, nó sẽ yêu cầu cấu trúc MqlTick
cho ký hiệu tương ứng trên mỗi tick "đa tiền tệ" và sau đó tính toán và hiển thị tất cả các chênh lệch trên biểu đồ.
Hãy thêm một tham số đầu vào mới Index
. Nó sẽ cần thiết cho một cách gửi thông báo mới: chúng ta sẽ chỉ gửi chỉ số của ký hiệu đã thay đổi trong sự kiện người dùng (xem thêm ở phần sau).
#define TICKSPY 0xFEED // 65261
input string SymbolList =
"EURUSD,GBPUSD,XAUUSD,USDJPY,USDCHF"; // Danh sách ký hiệu, phân cách bằng dấu phẩy (ví dụ)
input ushort Message = TICKSPY; // ID thông điệp tùy chỉnh
input long Chart = 0; // ID biểu đồ nhận (không chỉnh sửa)
input int Index = 0; // Chỉ số trong danh sách ký hiệu (không chỉnh sửa)
2
3
4
5
6
7
Ngoài ra, chúng ta thêm mảng Spreads
để lưu trữ chênh lệch theo ký hiệu và biến SelfIndex
để ghi nhớ vị trí của ký hiệu biểu đồ hiện tại trong danh sách (nếu nó được bao gồm trong danh sách, điều này thường đúng). Biến sau cần thiết để gọi hàm xử lý tick mới của chúng ta từ OnCalculate
trong bản sao gốc của chỉ báo. Việc lấy một chỉ số sẵn có cho _Symbol
một cách rõ ràng và không gửi nó trong một sự kiện trở lại chính chúng ta là dễ dàng và chính xác hơn.
int Spreads[];
int SelfIndex = -1;
2
Các cấu trúc dữ liệu được giới thiệu được khởi tạo trong OnInit
. Nếu không, OnInit
vẫn không thay đổi, bao gồm việc khởi chạy các phiên bản phụ thuộc của chỉ báo trên các ký hiệu bên thứ ba (các dòng này được lược bỏ ở đây).
void OnInit()
{
...
const int n = StringSplit(SymbolList, ',', Symbols);
ArrayResize(Spreads, n);
for(int i = 0; i < n; ++i)
{
if(Symbols[i] != _Symbol)
{
...
}
else
{
SelfIndex = i;
}
Spreads[i] = 0;
}
...
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Trong trình xử lý OnCalculate
, chúng ta tạo một sự kiện tùy chỉnh trên mỗi tick nếu bản sao của chỉ báo hoạt động trên ký hiệu khác (đồng thời, ID của biểu đồ Chart
mà thông báo nên được gửi đến không bằng 0). Lưu ý rằng tham số duy nhất được điền trong sự kiện là lparam
, bằng với Index
(dparam
là 0, và sparam
là NULL). Nếu Chart
bằng 0, điều này có nghĩa là chúng ta đang ở bản sao chính của chỉ báo hoạt động trên ký hiệu biểu đồ _Symbol
, và nếu nó được tìm thấy trong danh sách ký hiệu đầu vào, chúng ta gọi trực tiếp OnSymbolTick
với chỉ số SelfIndex
tương ứng.
int OnCalculate(const int rates_total, const int prev_calculated, const int, const double &price[])
{
if(prev_calculated)
{
if(Chart > 0)
{
EventChartCustom(Chart, Message, Index, 0, NULL);
}
else if(SelfIndex > -1)
{
OnSymbolTick(SelfIndex);
}
}
return rates_total;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Trong phần nhận của thuật toán sự kiện trong OnChartEvent
, chúng ta cũng gọi OnSymbolTick
, nhưng lần này chúng ta lấy số ký hiệu từ danh sách trong lparam
(điều đã được gửi dưới dạng tham số Index
từ một bản sao khác của chỉ báo).
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
if(id == CHARTEVENT_CUSTOM + Message)
{
OnSymbolTick((int)lparam);
}
}
2
3
4
5
6
7
Hàm OnSymbolTick
yêu cầu thông tin tick đầy đủ bằng SymbolInfoTick
và tính toán chênh lệch dưới dạng hiệu số giữa giá Ask
và Bid
chia cho kích thước điểm (thuộc tính SYMBOL_POINT sẽ được thảo luận sau).
void OnSymbolTick(const int index)
{
const string symbol = Symbols[index];
MqlTick tick;
if(SymbolInfoTick(symbol, tick))
{
Spreads[index] = (int)MathRound((tick.ask - tick.bid)
/ SymbolInfoDouble(symbol, SYMBOL_POINT));
string message = "";
for(int i = 0; i < ArraySize(Spreads); ++i)
{
message += Symbols[i] + "=" + (string)Spreads[i] + "\n";
}
Comment(message);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Chênh lệch mới cập nhật ô tương ứng trong mảng Spreads
, sau đó toàn bộ mảng được hiển thị trên biểu đồ trong phần bình luận. Đây là cách nó trông như sau.
Chênh lệch hiện tại cho danh sách ký hiệu được yêu cầu
Bạn có thể so sánh trong thời gian thực sự tương ứng của thông tin trong phần bình luận và trong cửa sổ Market Watch
.