Xóa đối tượng
API MQL5 cung cấp hai hàm để xóa đối tượng. Để xóa hàng loạt các đối tượng đáp ứng điều kiện về tiền tố trong tên, loại hoặc số cửa sổ phụ, hãy sử dụng ObjectsDeleteAll
. Nếu bạn cần chọn các đối tượng để xóa theo một số tiêu chí khác (ví dụ, theo tọa độ ngày giờ đã lỗi thời), hoặc nếu đó là một đối tượng đơn lẻ, hãy sử dụng hàm ObjectDelete
.
Hàm ObjectsDeleteAll
có hai dạng: có tham số cho tiền tố tên và không có.
int ObjectsDeleteAll(long chartId, int window = -1, int type = -1)
int ObjectsDeleteAll(long chartId, const string prefix, int window = -1, int type = -1)
2
Hàm xóa tất cả các đối tượng trên biểu đồ với chartId
được chỉ định, có tính đến cửa sổ phụ, loại và chuỗi con ban đầu trong tên.
Giá trị 0 trong tham số chartId
đại diện cho biểu đồ hiện tại, như thường lệ.
Giá trị mặc định (-1) trong các tham số window
và type
lần lượt xác định tất cả các cửa sổ phụ và tất cả các loại đối tượng.
Nếu tiền tố trống, các đối tượng có bất kỳ tên nào sẽ bị xóa.
Hàm được thực thi đồng bộ, tức là nó khóa chương trình MQL gọi cho đến khi hoàn thành và trả về số lượng đối tượng đã xóa. Vì hàm đợi thực thi tất cả các lệnh đã có trong hàng đợi biểu đồ trước khi gọi nó, hành động này có thể mất một chút thời gian.
bool ObjectDelete(long chartId, const string name)
Hàm xóa một đối tượng với tên được chỉ định trên biểu đồ với chartId
.
Không giống như ObjectsDeleteAll
, ObjectDelete
được thực thi không đồng bộ, tức là nó gửi một lệnh đến đồ họa để xóa đối tượng và ngay lập tức trả lại quyền điều khiển cho chương trình MQL. Kết quả true
cho biết lệnh đã được đặt thành công vào hàng đợi. Để kiểm tra kết quả thực thi, bạn có thể sử dụng hàm ObjectFind
hoặc bất kỳ hàm ObjectGet
nào, dùng để truy vấn thuộc tính của một đối tượng.
Ví dụ, hãy xem xét script ObjectCleanup1.mq5
. Nhiệm vụ của nó là xóa các đối tượng có tiền tố "của chúng ta", được tạo ra bởi script ObjectSimpleShowcase.mq5
từ phần trước.
Trong trường hợp đơn giản nhất, chúng ta có thể viết như sau:
#include "ObjectPrefix.mqh"
void OnStart()
{
const int n = ObjectsDeleteAll(0, ObjNamePrefix);
PrintFormat("%d objects deleted", n);
}
2
3
4
5
6
7
Nhưng để thêm sự đa dạng, chúng ta cũng có thể cung cấp tùy chọn xóa đối tượng bằng hàm ObjectDelete
thông qua nhiều lần gọi. Tất nhiên, cách tiếp cận này không có ý nghĩa khi ObjectsDeleteAll
đáp ứng mọi yêu cầu. Tuy nhiên, điều này không phải lúc nào cũng đúng: khi các đối tượng cần được chọn theo các điều kiện đặc biệt, tức là không chỉ theo tiền tố và loại, ObjectsDeleteAll
sẽ không còn hữu ích nữa.
Sau này, khi chúng ta làm quen với các hàm đọc thuộc tính của đối tượng, chúng ta sẽ hoàn thiện ví dụ này. Hiện tại, chúng ta sẽ chỉ giới thiệu một biến đầu vào để chuyển sang chế độ xóa "nâng cao" (UseCustomDeleteAll
).
#property script_show_inputs
input bool UseCustomDeleteAll = false;
2
Trong hàm OnStart
, tùy thuộc vào chế độ được chọn, chúng ta sẽ gọi ObjectsDeleteAll
tiêu chuẩn hoặc triển khai của riêng mình CustomDeleteAllObjects
.
void OnStart()
{
const int n = UseCustomDeleteAll ?
CustomDeleteAllObjects(0, ObjNamePrefix) :
ObjectsDeleteAll(0, ObjNamePrefix);
PrintFormat("%d objects deleted", n);
}
2
3
4
5
6
7
8
Hãy phác thảo hàm này trước, sau đó tinh chỉnh nó.
int CustomDeleteAllObjects(const long chart, const string prefix,
const int window = -1, const int type = -1)
{
int count = 0;
const int n = ObjectsTotal(chart, window, type);
// NB: lặp qua các đối tượng theo thứ tự ngược của danh sách biểu đồ nội bộ
// để giữ nguyên số thứ tự khi chúng ta di chuyển khỏi phần cuối
for(int i = n - 1; i >= 0; --i)
{
const string name = ObjectName(chart, i, window, type);
if(StringLen(prefix) == 0 || StringFind(name, prefix) == 0)
// các kiểm tra bổ sung mà ObjectsDeleteAll không cung cấp,
// ví dụ, theo tọa độ, màu sắc hoặc điểm neo
...
{
// gửi lệnh để xóa một đối tượng cụ thể
count += ObjectDelete(chart, name);
}
}
return count;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Ở đây chúng ta thấy một số tính năng mới sẽ được mô tả trong phần tiếp theo (ObjectsTotal
, ObjectName
). Ý nghĩa chung của chúng nên rõ ràng: hàm đầu tiên trả về chỉ số của các đối tượng trên biểu đồ, và hàm thứ hai trả về tên của đối tượng dưới chỉ số được chỉ định.
Cũng đáng chú ý rằng vòng lặp qua các đối tượng đi theo thứ tự giảm dần của chỉ số. Nếu chúng ta làm theo cách thông thường, việc xóa các đối tượng ở đầu danh sách sẽ dẫn đến vi phạm số thứ tự. Nghiêm túc mà nói, ngay cả vòng lặp hiện tại cũng không đảm bảo xóa hoàn toàn, giả sử một chương trình MQL khác bắt đầu thêm đối tượng song song với việc xóa của chúng ta. Thực tế, một đối tượng "ngoại lai" mới có thể được thêm vào đầu danh sách (nó được sắp xếp theo thứ tự bảng chữ cái của tên đối tượng) và tăng các chỉ số còn lại, đẩy đối tượng tiếp theo "của chúng ta" cần xóa ra ngoài chỉ số hiện tại i
. Càng nhiều đối tượng mới được thêm vào đầu, càng có khả năng bỏ sót việc xóa của mình.
Do đó, để cải thiện độ tin cậy, có thể sau vòng lặp kiểm tra rằng số lượng đối tượng còn lại bằng với sự khác biệt giữa số lượng ban đầu và số lượng đối tượng đã xóa. Mặc dù điều này không đảm bảo 100%, vì các chương trình khác có thể xóa đối tượng song song. Chúng ta sẽ để những chi tiết này cho việc tự nghiên cứu.
Trong triển khai hiện tại, script của chúng ta nên xóa tất cả các đối tượng có tiền tố "của chúng ta", bất kể chuyển đổi chế độ UseCustomDeleteAll
. Nhật ký nên hiển thị điều gì đó như sau:
ObjectSimpleShowcase (XAUUSD,H1) 14 objects of various types created
ObjectCleanup1 (XAUUSD,H1) 14 objects deleted
2
Hãy làm quen với các hàm ObjectsTotal
và ObjectName
mà chúng ta vừa sử dụng, sau đó quay lại phiên bản ObjectCleanup2.mq5
của script.