Quản lý chỉ báo trên biểu đồ
Như chúng ta đã tìm hiểu, biểu đồ là môi trường thực thi và trực quan hóa cho các chỉ báo. Mối liên kết chặt chẽ của chúng được xác nhận thêm thông qua một nhóm các hàm tích hợp sẵn cung cấp khả năng kiểm soát các chỉ báo trên biểu đồ. Trong một trong những chương trước, chúng ta đã hoàn thành tổng quan về các tính năng này. Bây giờ chúng ta sẵn sàng xem xét chi tiết sau khi làm quen với các biểu đồ.
Tất cả các hàm đều có điểm chung là hai tham số đầu tiên được thống nhất: đó là định danh biểu đồ (chartId
) và số cửa sổ (window
). Giá trị bằng 0 của các tham số lần lượt biểu thị biểu đồ hiện tại và cửa sổ chính.
int ChartIndicatorsTotal(long chartId, int window)
Hàm trả về số lượng tất cả các chỉ báo được gắn vào cửa sổ biểu đồ được chỉ định. Nó có thể được sử dụng để liệt kê tất cả các chỉ báo gắn với một biểu đồ nhất định. Số lượng tất cả các cửa sổ biểu đồ có thể được lấy từ thuộc tính CHART_WINDOWS_TOTAL bằng cách sử dụng hàm ChartGetInteger
.
string ChartIndicatorName(long chartId, int window, int index)
Hàm trả về tên ngắn của chỉ báo theo index
trong danh sách các chỉ báo nằm trong cửa sổ biểu đồ được chỉ định. Tên ngắn là tên được chỉ định trong thuộc tính INDICATOR_SHORTNAME bởi hàm IndicatorSetString
(nếu không được đặt, thì mặc định nó bằng tên tệp chỉ báo).
int ChartIndicatorGet(long chartId, int window, const string shortname)
Hàm trả về tay cầm của chỉ báo với tên ngắn được chỉ định trong cửa sổ biểu đồ cụ thể. Có thể nói rằng việc xác định chỉ báo trong hàm ChartIndicatorGet
được thực hiện chính xác bằng tên ngắn, và do đó nên tạo tên ngắn sao cho chứa giá trị của tất cả các tham số đầu vào. Nếu điều này không thể thực hiện vì lý do nào đó, có một cách khác để xác định một phiên bản chỉ báo thông qua danh sách các tham số của nó, có thể lấy được bằng hàm IndicatorParameters
dựa trên một mô tả đã cho.
Việc lấy tay cầm từ hàm ChartIndicatorGet
làm tăng bộ đếm nội bộ sử dụng chỉ báo này. Hệ thống thực thi terminal giữ tất cả các chỉ báo được tải mà bộ đếm lớn hơn 0. Do đó, một chỉ báo không còn cần thiết phải được giải phóng rõ ràng bằng cách gọi IndicatorRelease
. Nếu không, chỉ báo sẽ vẫn nhàn rỗi và tiêu tốn tài nguyên.
bool ChartIndicatorAdd(long chartId, int window, int handle)
Hàm thêm một chỉ báo với mô tả được truyền trong tham số cuối cùng vào cửa sổ biểu đồ được chỉ định. Chỉ báo và biểu đồ phải có cùng kết hợp biểu tượng và khung thời gian. Nếu không, lỗi ERR_CHART_INDICATOR_CANNOT_ADD (4114) sẽ xảy ra.
Để thêm một chỉ báo vào một cửa sổ mới, tham số window
phải lớn hơn chỉ số của cửa sổ hiện có cuối cùng một đơn vị, tức là bằng với thuộc tính CHART_WINDOWS_TOTAL nhận được qua lời gọi ChartGetInteger
. Nếu giá trị tham số vượt quá giá trị của ChartGetInteger(ID,CHART_WINDOWS_TOTAL)
, một cửa sổ mới và chỉ báo sẽ không được tạo.
Nếu một chỉ báo được thêm vào cửa sổ biểu đồ chính, vốn nên được vẽ trong một cửa sổ phụ riêng biệt (ví dụ, iMACD tích hợp hoặc một chỉ báo tùy chỉnh với thuộc tính được chỉ định
#property indicator_separate_window
), thì chỉ báo đó có thể dường như không hiển thị, mặc dù nó sẽ có mặt trong danh sách các chỉ báo. Điều này thường có nghĩa là giá trị của chỉ báo này không nằm trong phạm vi hiển thị của biểu đồ giá. Giá trị của chỉ báo "ẩn" như vậy có thể được quan sát trongData window
và đọc bằng các hàm từ các chương trình MQL khác.
Việc thêm một chỉ báo vào biểu đồ làm tăng bộ đếm nội bộ sử dụng nó do liên kết với biểu đồ. Nếu chương trình MQL giữ mô tả của nó và nó không còn cần thiết, thì nên xóa nó bằng cách gọi IndicatorRelease
. Điều này sẽ thực sự giảm bộ đếm, nhưng chỉ báo sẽ vẫn trên biểu đồ.
bool ChartIndicatorDelete(long chartId, int window, const string shortname)
Hàm xóa chỉ báo với tên ngắn được chỉ định khỏi cửa sổ có số window
trên biểu đồ với chartId
. Nếu có nhiều chỉ báo cùng tên ngắn trong cửa sổ phụ biểu đồ được chỉ định, chỉ báo đầu tiên theo thứ tự sẽ bị xóa.
Nếu các chỉ báo khác được tính toán bằng giá trị của chỉ báo bị xóa trên cùng biểu đồ, chúng cũng sẽ bị xóa.
Việc xóa một chỉ báo khỏi biểu đồ không có nghĩa là phần tính toán của nó cũng sẽ bị xóa khỏi bộ nhớ terminal nếu mô tả vẫn còn trong chương trình MQL. Để giải phóng tay cầm chỉ báo, sử dụng hàm IndicatorRelease
.
Hàm ChartWindowFind
trả về số của cửa sổ phụ nơi chỉ báo được đặt. Có 2 dạng được thiết kế để tìm kiếm chỉ báo hiện tại trên biểu đồ của nó hoặc một chỉ báo với tên ngắn đã cho trên một biểu đồ bất kỳ với định danh chartId
.
int ChartWindowFind()
int ChartWindowFind(long chartId, string shortname)
Dạng thứ hai có thể được sử dụng trong các script và Expert Advisors.
Là ví dụ đầu tiên thể hiện các hàm này, hãy xem xét phiên bản đầy đủ của script ChartList.mq5
. Chúng ta đã tạo và dần dần cải tiến nó trong các phần trước, cho đến phần Lấy số lượng và khả năng hiển thị của các cửa sổ/cửa sổ phụ. So với ChartList4.mq5
được trình bày ở đó, chúng ta sẽ thêm các biến đầu vào để có thể liệt kê chỉ các biểu đồ có chương trình MQL và ngăn chặn hiển thị các cửa sổ ẩn.
input bool IncludeEmptyCharts = true;
input bool IncludeHiddenWindows = true;
2
Với giá trị mặc định (true
), tham số IncludeEmptyCharts
chỉ thị bao gồm tất cả các biểu đồ vào danh sách, kể cả các biểu đồ trống. Tham số IncludeHiddenWindows
đặt hiển thị các cửa sổ ẩn theo mặc định. Các cài đặt này tương ứng với logic kịch bản trước đó ChartListN
.
Để tính toán tổng số chỉ báo và chỉ báo trong các cửa sổ phụ, chúng ta định nghĩa các biến indicators
và subs
.
void ChartList()
{
...
int indicators = 0, subs = 0;
...
2
3
4
5
Vòng lặp làm việc qua các cửa sổ của biểu đồ hiện tại đã trải qua những thay đổi lớn.
void ChartList()
{
...
for(int i = 0; i < win; i++)
{
const bool visible = ChartGetInteger(id, CHART_WINDOW_IS_VISIBLE, i);
if(!visible && !IncludeHiddenWindows) continue;
if(!visible)
{
Print(" ", i, "/Hidden");
}
const int n = ChartIndicatorsTotal(id, i);
for(int k = 0; k < n; k++)
{
if(temp == 0)
{
Print(header);
}
Print(" ", i, "/", k, " [I] ", ChartIndicatorName(id, i, k));
indicators++;
if(i > 0) subs++;
temp++;
}
}
...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Ở đây chúng ta đã thêm các lời gọi ChartIndicatorsTotal
và ChartIndicatorName
. Bây giờ danh sách sẽ đề cập đến các chương trình MQL của tất cả các loại: [E] — Expert Advisors, [S] — scripts, [I] — indicators.
Dưới đây là ví dụ về các mục nhật ký được tạo bởi script cho cài đặt mặc định.
Chart List
N, ID, Symbol, TF, #subwindows, *active, Windows handle
0 132358585987782873 EURUSD M15 #1 133538
1/0 [I] ATR(11)
1 132360375330772909 EURUSD D1 133514
2 132544239145024745 EURUSD M15 * 395646
[S] ChartList
3 132544239145024732 USDRUB D1 395688
4 132544239145024744 EURUSD H1 #2 active 2361730
1/0 [I] %R(14)
2/Hidden
2/0 [I] Momentum(15)
5 132544239145024746 EURUSD H1 133584
Total chart number: 6, with MQL-programs: 3
Experts: 0, Scripts: 1, Indicators: 3 (main: 0 / sub: 3)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Nếu đặt cả hai tham số đầu vào thành false
, chúng ta nhận được danh sách rút gọn.
Chart List
N, ID, Symbol, TF, #subwindows, *active, Windows handle
0 132358585987782873 EURUSD M15 #1 133538
1/0 [I] ATR(11)
2 132544239145024745 EURUSD M15 * active 395646
[S] ChartList
4 132544239145024744 EURUSD H1 #2 2361730
1/0 [I] %R(14)
Total chart number: 6, with MQL-programs: 3
Experts: 0, Scripts: 1, Indicators: 2 (main: 0 / sub: 2)
2
3
4
5
6
7
8
9
10
Là ví dụ thứ hai, hãy xem xét một script thú vị ChartIndicatorMove.mq5
.
Khi chạy nhiều chỉ báo trên một biểu đồ, chúng ta thường có thể cần thay đổi thứ tự của các chỉ báo. MetaTrader 5 không có công cụ tích hợp cho việc này, buộc bạn phải xóa một số chỉ báo và thêm lại chúng, trong khi điều quan trọng là lưu và khôi phục các cài đặt. Script ChartIndicatorMove.mq5
cung cấp tùy chọn để tự động hóa quy trình này. Cần lưu ý rằng script chỉ chuyển các chỉ báo: nếu bạn cần thay đổi thứ tự của các cửa sổ phụ cùng với các đối tượng đồ họa (nếu chúng ở bên trong), thì bạn nên sử dụng mẫu tpl.
Cơ sở hoạt động của ChartIndicatorMove.mq5
như sau. Khi script được áp dụng cho một biểu đồ, nó xác định vào cửa sổ/cửa sổ phụ nào nó đã được thêm, và bắt đầu liệt kê các chỉ báo được tìm thấy ở đó cho người dùng với yêu cầu xác nhận chuyển. Người dùng có thể đồng ý, hoặc tiếp tục liệt kê.
Hướng di chuyển, lên hoặc xuống, được đặt trong biến đầu vào MoveDirection
. Liệt kê DIRECTION sẽ mô tả nó.
#property script_show_inputs
enum DIRECTION
{
Up = -1,
Down = +1,
};
input DIRECTION MoveDirection = Up;
2
3
4
5
6
7
8
9
Để chuyển chỉ báo không phải sang cửa sổ phụ bên cạnh mà sang cửa sổ tiếp theo, tức là thực sự hoán đổi các cửa sổ phụ với các chỉ báo (thường được yêu cầu), chúng ta giới thiệu biến đầu vào jumpover
.
input bool JumpOver = true;
Vòng lặp qua các chỉ báo của cửa sổ mục tiêu thu được từ ChartWindowOnDropped
bắt đầu trong OnStart
.
void OnStart()
{
const int w = ChartWindowOnDropped();
if(w == 0 && MoveDirection == Up)
{
Alert("Can't move up from window at index 0");
return;
}
const int n = ChartIndicatorsTotal(0, w);
for(int i = 0; i < n; ++i)
{
...
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
Bên trong vòng lặp, chúng ta xác định tên của chỉ báo tiếp theo, hiển thị thông báo cho người dùng, và di chuyển chỉ báo từ cửa sổ này sang cửa sổ khác bằng một chuỗi các thao tác sau:
- Lấy tay cầm bằng cách gọi
ChartIndicatorGet
. - Thêm nó vào cửa sổ phía trên hoặc dưới cửa sổ hiện tại qua
ChartIndicatorAdd
, theo hướng đã chọn, và khi di chuyển xuống, một cửa sổ phụ mới có thể được tạo tự động. - Xóa chỉ báo khỏi cửa sổ trước đó bằng
ChartIndicatorDelete
. - Giải phóng mô tả, vì chúng ta không còn cần nó trong chương trình.
...
const string name = ChartIndicatorName(0, w, i);
const string caption = EnumToString(MoveDirection);
const int button = MessageBox("Move '" + name + "' " + caption + "?",
caption, MB_YESNOCANCEL);
if(button == IDCANCEL) break;
if(button == IDYES)
{
const int h = ChartIndicatorGet(0, w, name);
ChartIndicatorAdd(0, w + MoveDirection, h);
ChartIndicatorDelete(0, w, name);
IndicatorRelease(h);
break;
}
...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Hình ảnh sau cho thấy kết quả của việc hoán đổi các cửa sổ phụ với các chỉ báo WPR
và Momentum
. Script được khởi chạy bằng cách thả nó vào cửa sổ phụ trên cùng với chỉ báo WPR
, hướng di chuyển được chọn là xuống (Down
), nhảy (JumpOver
) được bật theo mặc định.
Hoán đổi chỉ báo trong các cửa sổ phụ
Xin lưu ý rằng nếu bạn di chuyển chỉ báo từ cửa sổ phụ sang cửa sổ chính, các biểu đồ của nó rất có thể sẽ không hiển thị do các giá trị vượt ra ngoài phạm vi giá hiển thị. Nếu điều này xảy ra do nhầm lẫn, bạn có thể sử dụng script để chuyển chỉ báo trở lại cửa sổ phụ.