Các chỉ báo trong cửa sổ phụ riêng biệt: kích thước và mức độ
Cho đến nay, chúng ta đã giới hạn mình với các chỉ báo hoạt động trong cửa sổ biểu đồ chính, tức là chúng có chỉ thị #property indicator_chart_window
. Bây giờ là lúc để nghiên cứu các chỉ báo được đặt trong một cửa sổ phụ riêng biệt bên dưới biểu đồ giá. Hãy nhớ rằng chúng cần được khai báo với chỉ thị #property indicator_separate_window
.
Mọi thứ chúng ta đã học trước đây đều áp dụng cho các chỉ báo trong cửa sổ phụ, bao gồm việc mô tả và neo các bộ đệm, thiết lập kiểu và phong cách vẽ, đồng thời sử dụng cả dạng đầy đủ và rút gọn của OnCalculate
, tùy bạn chọn. Tuy nhiên, chúng cũng có một số đặc điểm và cài đặt bổ sung.
Vì cửa sổ phụ có thang giá trị riêng, MQL5 cho phép bạn đặt giá trị tối đa và tối thiểu cho nó (người dùng cũng có thể đặt các giới hạn tương tự trong hộp thoại cài đặt chỉ báo, trên tab Scale
). Điều này được thực hiện theo chương trình bằng hàm IndicatorSetDouble
với nguyên mẫu sau.
bool IndicatorSetDouble(ENUM_CUSTOMIND_PROPERTY_DOUBLE property, double value)
bool IndicatorSetDouble(ENUM_CUSTOMIND_PROPERTY_DOUBLE property, int modifier, double value)
Hàm này thiết lập giá trị thuộc tính kiểu double
cho một chỉ báo. Hai dạng được yêu cầu vì một số thuộc tính có thể có nhiều giá trị, đặc biệt là các mức ngang (sẽ được thảo luận sau). Các thuộc tính có sẵn được tập hợp trong liệt kê ENUM_CUSTOMIND_PROPERTY_DOUBLE
.
Định danh | Mô tả |
---|---|
INDICATOR_MINIMUM | Giá trị tối thiểu trên trục dọc |
INDICATOR_MAXIMUM | Giá trị tối đa trên trục dọc |
INDICATOR_LEVELVALUE | Giá trị mức ngang (số được đặt trong tham số modifier) |
Phạm vi thang cố định được sử dụng trong nhiều chỉ báo dao động, như WPR. Chúng ta sẽ xem một ví dụ với nó, bao gồm tất cả các hàm (thuộc tính) từ phần này.
Hàm trả về true
khi thành công và false
nếu không.
Ngoài việc kiểm soát thang giá trị, các chỉ báo trong cửa sổ phụ có thể, như chúng ta đã hiểu, có các mức ngang. Để thiết lập số lượng và thuộc tính của chúng, một hàm khác được sử dụng, IndicatorSetInteger
. Người dùng có thể thực hiện các hành động tương tự trong hộp thoại cài đặt chỉ báo trên tab Levels
.
bool IndicatorSetInteger(ENUM_CUSTOMIND_PROPERTY_INTEGER property, int value)
bool IndicatorSetInteger(ENUM_CUSTOMIND_PROPERTY_INTEGER property, int modifier, int value)
Hàm này cũng có hai dạng và cho phép bạn thiết lập giá trị thuộc tính kiểu int
hoặc tương đương (ví dụ, color
hoặc danh sách) cho chỉ báo. Các thuộc tính có sẵn được tập hợp trong liệt kê ENUM_CUSTOMIND_PROPERTY_INTEGER
. Ngoài các thuộc tính liên quan đến mức độ, nó còn chứa thuộc tính INDICATOR_DIGITS
, chung cho các chỉ báo thuộc bất kỳ loại nào: chúng ta sẽ xem xét nó trong phần tiếp theo.
Định danh | Mô tả |
---|---|
INDICATOR_DIGITS | Độ chính xác hiển thị giá trị chỉ báo (số chữ số sau dấu thập phân) |
INDICATOR_HEIGHT | Chiều cao cố định của cửa sổ chỉ báo tính bằng pixel (lệnh tiền xử lý #property indicator_height ) |
INDICATOR_LEVELS | Số lượng mức ngang trong cửa sổ chỉ báo |
INDICATOR_LEVELCOLOR | Màu sắc đường mức (kiểu color , tham số modifier đặt số mức) |
INDICATOR_LEVELSTYLE | Kiểu đường mức (kiểu ENUM_LINE_STYLE, tham số modifier đặt số mức) |
INDICATOR_LEVELWIDTH | Độ dày đường mức (1-5) (tham số modifier đặt số mức) |
Các mức có thể có nhãn văn bản. Để gán chúng, sử dụng hàm IndicatorSetString
.
bool IndicatorSetString(ENUM_CUSTOMIND_PROPERTY_STRING property, string value)
bool IndicatorSetString(ENUM_CUSTOMIND_PROPERTY_STRING property, int modifier, string value)
ENUM_CUSTOMIND_PROPERTY_STRING
chứa danh sách các tham số chuỗi của chỉ báo. Hãy chú ý đến thuộc tính INDICATOR_SHORTNAME
không liên quan đến mức độ: nó cũng chung cho tất cả các chỉ báo và sẽ được thảo luận trong phần tiếp theo.
Định danh | Mô tả |
---|---|
INDICATOR_SHORTNAME | Tiêu đề công khai của chỉ báo |
INDICATOR_LEVELTEXT | Mô tả của mức (số được chỉ định trong modifier) |
Tất cả các hàm đã đề cập cho các kiểu số int
và double
được nhân đôi bởi các chỉ thị đặc biệt (dưới đây là bảng tóm tắt).
Chỉ thị cho thuộc tính mức | Hàm tương tự | Kiểu thuộc tính | Mô tả |
---|---|---|---|
indicator_levelN | IndicatorSetDouble(INDICATOR_LEVELVALUE, N-1, value) | double | Giá trị cho mức ngang số N trên trục dọc |
indicator_levelcolor | IndicatorSetInteger(INDICATOR_LEVELCOLOR, N-1, color) | color | Màu sắc của các mức ngang (chỉ có thể đặt màu khác nhau bằng hàm) |
indicator_levelwidth | IndicatorSetInteger(INDICATOR_LEVELWIDTH, N-1, width) | int | Độ dày đường của các mức ngang tính bằng pixel (chỉ có thể đặt độ dày khác nhau bằng hàm) |
indicator_levelstyle | IndicatorSetInteger(INDICATOR_LEVELSTYLE, N-1, style) | ENUM_LINE_STYLE | Kiểu đường của các mức ngang (chỉ có thể đặt kiểu khác nhau bằng hàm) |
indicator_minimum | IndicatorSetDouble(INDICATOR_MINIMUM, minimum) | double | Giá trị tối thiểu cố định, giới hạn dưới của thang trên trục dọc |
indicator_maximum | IndicatorSetDouble(INDICATOR_MAXIMUM, maximum) | double | Giá trị tối đa cố định, giới hạn trên của thang trên trục dọc |
Lưu ý rằng việc đánh số các phiên bản thuộc tính (modifier) khi sử dụng chỉ thị #property
bắt đầu từ 1 (một), trong khi các hàm sử dụng đánh số từ 0 (không).
Một độc giả tinh ý sẽ nhận thấy rằng không có chỉ thị cho một số thuộc tính. Chúng bao gồm INDICATOR_LEVELTEXT
, INDICATOR_SHORTNAME
, INDICATOR_DIGITS
. Giả định rằng các thuộc tính này nên được điền động từ mã MQL, tùy thuộc vào các biến đầu vào và biểu đồ mà chỉ báo được đặt. INDICATOR_LEVELS
được thiết lập gián tiếp bằng cách chỉ định một số chỉ thị cho các mức.
Cuối cùng, đặc điểm nổi bật của các chỉ báo trong cửa sổ phụ là chương trình có thể "đóng băng" kích thước dọc của cửa sổ của nó.
Chỉ thị cho kích thước cửa sổ phụ | Hàm tương tự | Mô tả |
---|---|---|
indicator_height | IndicatorSetInteger(INDICATOR_HEIGHT, height) | Chiều cao cố định của cửa sổ phụ chỉ báo tính bằng pixel (người dùng sẽ không thể thay đổi chiều cao) |
Chiều cao cửa sổ phụ cố định thường chỉ được sử dụng cho các bảng điều khiển với các điều khiển (nút, cờ, trường nhập) được triển khai bằng đối tượng đồ họa.
Đáng tiếc, đối với các hàm thiết lập thuộc tính, không có các hàm ngược lại (IndicatorGetInteger
, IndicatorGetDouble
, IndicatorGetString
). Điều này, trong số các thứ khác, không cho phép, ví dụ, tìm số lượng và giá trị của các mức ngang nếu chúng đã bị người dùng thay đổi.
Ví dụ về làm việc với thang cố định và các mức, hãy xem xét chỉ báo IndWPR.mq5
. Trong đó, chúng ta sẽ sử dụng thuật toán WPR tiêu chuẩn: trên một số lượng thanh quá khứ nhất định (chu kỳ WPR), chúng ta sẽ tìm giá cao nhất H và thấp nhất L của giá (tức là phạm vi của nó). Sau đó, chúng ta tính tỷ lệ giữa chênh lệch giá hiện tại C và giá thấp L, C - L (hoặc chênh lệch -(H - C), với dấu trừ) so với toàn bộ phạm vi, và đưa mọi thứ vào phạm vi từ 0 đến -100. Đây là công thức chuẩn để tính WPR:
R% = (-(H — C) / (H — L)) * 100
Hãy thêm một số chỉ thị vào đầu mã nguồn. Ngoài thuộc tính vị trí chỉ báo trong cửa sổ riêng của nó, hãy đặt thang giá trị từ 0 đến -100.
#property indicator_separate_window
#property indicator_maximum 0.0
#property indicator_minimum -100.0
2
3
Một bộ đệm và một biểu đồ đường là đủ để lưu trữ giá trị và hiển thị chỉ báo.
#property indicator_buffers 1
#property indicator_plots 1
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDodgerBlue
2
3
4
Trong chỉ báo WPR, thường phân biệt hai mức: -20 và -80, làm ranh giới của vùng quá mua và quá bán, tương ứng. Hãy tạo một vài đường ngang cho chúng.
#property indicator_level1 -20.0
#property indicator_level2 -80.0
#property indicator_levelstyle STYLE_DOT
#property indicator_levelcolor clrSilver
#property indicator_levelwidth 1
2
3
4
5
Biến đầu vào duy nhất cho phép bạn đặt chu kỳ tính toán cho WPR.
input int WPRPeriod = 14; // Period
Mảng cho bộ đệm được khai báo ở cấp độ toàn cục và đăng ký với OnInit
.
double WPRBuffer[];
void OnInit()
{
// kiểm tra đầu vào đúng
if(WPRPeriod < 1)
{
Alert(StringFormat("Incorrect Period value (%d). Should be 1 or larger", WPRPeriod));
}
// liên kết mảng làm bộ đệm
SetIndexBuffer(0, WPRBuffer);
}
2
3
4
5
6
7
8
9
10
11
12
13
Trình xử lý OnInit
được mô tả với kiểu void
, ngụ ý rằng việc khởi tạo thành công. Tuy nhiên, nếu chu kỳ được đặt nhỏ hơn 1, nó sẽ không cho phép thực hiện tính toán và một cảnh báo được đưa ra cho người dùng.
Để đơn giản hóa tiêu đề hàm OnCalculate
, tệp tiêu đề IndCommon.mqh
đã được chuẩn bị cho các chỉ báo, với hai macro mô tả danh sách tham số tiêu chuẩn của cả hai dạng trình xử lý sự kiện.
#define ON_CALCULATE_STD_FULL_PARAM_LIST \
const int rates_total, \
const int prev_calculated, \
const datetime &time[], \
const double &open[], \
const double &high[], \
const double &low[], \
const double &close[], \
const long &tick_volume[], \
const long &volume[], \
const int &spread[]
#define ON_CALCULATE_STD_SHORT_PARAM_LIST \
const int rates_total, \
const int prev_calculated, \
const int begin, \
const double &data[]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Giờ đây, chúng ta có thể sử dụng định nghĩa ngắn gọn của OnCalculate
trong chỉ báo này và các chỉ báo khác (miễn là chúng ta hài lòng với các tên tham số được đề xuất trong macro).
#include <MQL5Book/IndCommon.mqh>
int OnCalculate(ON_CALCULATE_STD_FULL_PARAM_LIST)
{
if(rates_total < WPRPeriod || WPRPeriod < 1) return 0;
...
return rates_total;
}
2
3
4
5
6
7
8
Ở đầu OnCalculate
, chúng ta kiểm tra xem có thể tính toán bằng các giá trị hiện tại của WPRPeriod
và rates_total
hay không. Nếu không đủ dữ liệu hoặc chu kỳ quá ngắn, nó trả về 0, điều này sẽ để lại cửa sổ chỉ báo trống.
Tiếp theo, chúng ta điền vào vài thanh đầu tiên mà không thể tính WPR của chu kỳ đã cho bằng giá trị rỗng.
int OnCalculate(ON_CALCULATE_STD_FULL_PARAM_LIST)
{
...
if(prev_calculated == 0)
{
ArrayFill(WPRBuffer, 0, WPRPeriod - 1, EMPTY_VALUE);
}
...
}
2
3
4
5
6
7
8
9
Cuối cùng, chúng ta chạy các tính toán WPR và lưu trữ kết quả vào bộ đệm. Lưu ý rằng thanh cuối cùng được cập nhật trên mỗi tick: điều này đạt được bằng cách bắt đầu vòng lặp với prev_calculated - 1
.
int OnCalculate(ON_CALCULATE_STD_FULL_PARAM_LIST)
{
...
for(int i = fmax(prev_calculated - 1, WPRPeriod - 1);
i < rates_total && !IsStopped(); i++)
{
double max_high = high[fmax(ArrayMaximum(high, i - WPRPeriod + 1, WPRPeriod), 0)];
double min_low = low[fmax(ArrayMinimum(low, i - WPRPeriod + 1, WPRPeriod), 0)];
if(max_high != min_low)
{
WPRBuffer[i] = -(max_high - close[i]) * 100 / (max_high - min_low);
}
else
{
WPRBuffer[i] = WPRBuffer[i - 1];
}
}
return rates_total;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Các hàm ArrayMaximum
và ArrayMinimum
cho phép tìm kiếm chỉ số của giá cao nhất high
và thấp nhất low
.
Chỉ báo xuất hiện trong một cửa sổ riêng như sau.
WPR indicator
Trong các phần tiếp theo, chúng ta sẽ tiếp tục cải thiện chỉ báo này, dần dần thêm các thuộc tính thường dùng khác.