Tạo và xóa các ký hiệu tùy chỉnh
Hai hàm đầu tiên bạn cần để làm việc với các ký hiệu tùy chỉnh là CustomSymbolCreate
và CustomSymbolDelete
.
bool CustomSymbolCreate(const string name, const string path = "", const string origin = NULL)
Hàm này tạo một ký hiệu tùy chỉnh với tên được chỉ định (name
) trong nhóm được chỉ định (path
) và, nếu cần, với các thuộc tính của một ký hiệu mẫu — tên của nó có thể được chỉ định trong tham số origin
.
Tham số name
nên là một định danh đơn giản, không có phân cấp. Nếu cần, một hoặc nhiều cấp độ nhóm (thư mục con) cần thiết nên được chỉ định trong tham số path
, với ký tự phân cách là dấu gạch chéo ngược \
(dấu gạch chéo xuôi không được hỗ trợ ở đây, không giống như hệ thống tệp). Dấu gạch chéo ngược phải được nhân đôi trong chuỗi ký tự ("\").
Mặc định, nếu chuỗi path
rỗng ("" hoặc NULL), ký hiệu sẽ được tạo trực tiếp trong thư mục Custom
, thư mục này được cấp phát trong phân cấp chung của các ký hiệu cho các ký hiệu người dùng. Nếu path
được điền, nó sẽ được tạo bên trong thư mục Custom
đến độ sâu đầy đủ (nếu chưa có các thư mục tương ứng).
Tên của một ký hiệu, cũng như tên của một nhóm ở bất kỳ cấp độ nào, có thể chứa các chữ cái Latinh và số, không có dấu câu, khoảng trắng và ký tự đặc biệt. Ngoài ra, chỉ cho phép '.', '_', '&' và '#'.
Tên phải là duy nhất trong toàn bộ phân cấp ký hiệu, bất kể ký hiệu được tạo trong nhóm nào. Nếu một ký hiệu có cùng tên đã tồn tại, hàm sẽ trả về false
và sẽ đặt mã lỗi 5300 (ERR_NOT_CUSTOM_SYMBOL) hoặc 5304 (ERR_CUSTOM_SYMBOL_EXIST) trong _LastError
.
Lưu ý rằng nếu phần tử cuối cùng (hoặc thậm chí là duy nhất) của phân cấp trong chuỗi path
khớp chính xác với name
(phân biệt chữ hoa chữ thường), thì nó được coi là tên ký hiệu thuộc về đường dẫn và không phải là thư mục. Ví dụ, nếu tên và đường dẫn chứa các chuỗi "Example" và "MQL5Book\Example" tương ứng, thì ký hiệu "Example" sẽ được tạo trong thư mục "Custom\MQL5Book\". Đồng thời, nếu chúng ta đổi tên thành "example", chúng ta sẽ nhận được ký hiệu "example" trong thư mục "Custom\MQL5Book\Example".
Tính năng này có một hệ quả khác. Thuộc tính SYMBOL_PATH trả về đường dẫn cùng với tên ký hiệu ở cuối. Do đó, nếu chúng ta chuyển giá trị của nó mà không thay đổi từ một ký hiệu mẫu sang một ký hiệu mới được tạo, chúng ta sẽ nhận được hiệu ứng sau: một thư mục mang tên của ký hiệu cũ sẽ được tạo, bên trong đó sẽ xuất hiện một ký hiệu mới. Vì vậy, nếu bạn muốn tạo một ký hiệu tùy chỉnh trong cùng nhóm với ký hiệu gốc, bạn phải loại bỏ tên của ký hiệu gốc khỏi chuỗi thu được từ thuộc tính SYMBOL_PATH.
Chúng ta sẽ thể hiện tác dụng phụ của việc sao chép thuộc tính SYMBOL_PATH trong một ví dụ ở phần tiếp theo. Tuy nhiên, hiệu ứng này cũng có thể được sử dụng một cách tích cực. Đặc biệt, bằng cách tạo nhiều ký hiệu của nó dựa trên một ký hiệu gốc, việc sao chép SYMBOL_PATH sẽ đảm bảo rằng tất cả các ký hiệu mới được đặt trong thư mục mang tên của ký hiệu gốc, tức là nó sẽ nhóm các ký hiệu theo ký hiệu nguyên mẫu của chúng.
Thuộc tính SYMBOL_PATH cho các ký hiệu tùy chỉnh luôn bắt đầu bằng thư mục "Custom\" (tiền tố này được thêm tự động).
Độ dài tên bị giới hạn ở 31 ký tự. Khi vượt quá giới hạn, CustomSymbolCreate
sẽ trả về false
và đặt mã lỗi 5302 (ERR_CUSTOM_SYMBOL_NAME_LONG).
Độ dài tối đa của tham số path
là 127 ký tự, bao gồm "Custom\", các ký tự phân cách nhóm "\" và tên ký hiệu, nếu nó được chỉ định ở cuối.
Tham số origin
cho phép bạn tùy chọn chỉ định tên của ký hiệu mà từ đó các thuộc tính của ký hiệu tùy chỉnh được tạo sẽ được sao chép. Sau khi tạo một ký hiệu tùy chỉnh, bạn có thể thay đổi bất kỳ thuộc tính nào của nó thành giá trị mong muốn bằng cách sử dụng các hàm phù hợp (xem các hàm CustomSymbolSet
tại đây).
Nếu một ký hiệu không tồn tại được cung cấp làm tham số origin
, thì ký hiệu tùy chỉnh sẽ được tạo "trống", như thể tham số origin
không được chỉ định. Điều này sẽ gây ra lỗi 4301 (ERR_MARKET_UNKNOWN_SYMBOL).
Trong một ký hiệu mới được tạo "trống", tất cả các thuộc tính được đặt thành giá trị mặc định của chúng. Ví dụ, kích thước hợp đồng là 100000, số chữ số trong giá là 4, tính toán ký quỹ được thực hiện theo quy tắc Forex, và biểu đồ dựa trên giá Bid
.
Khi bạn chỉ định origin
, chỉ các cài đặt được chuyển từ ký hiệu này sang ký hiệu mới, nhưng không phải báo giá hoặc tick vì chúng phải được tạo riêng. Điều này sẽ được thảo luận trong các phần sau.
Việc tạo một ký hiệu không tự động thêm nó vào Market Watch
. Vì vậy, điều này phải được thực hiện rõ ràng (bằng tay hoặc lập trình). Nếu không có báo giá, cửa sổ biểu đồ sẽ trống.
bool CustomSymbolDelete(const string name)
Hàm này xóa một ký hiệu tùy chỉnh với tên được chỉ định. Không chỉ cài đặt bị xóa, mà tất cả dữ liệu về ký hiệu (báo giá và tick) cũng bị xóa. Đáng chú ý là lịch sử không bị xóa ngay lập tức, mà chỉ sau một khoảng trễ, điều này có thể là nguồn gốc của vấn đề nếu bạn định tái tạo một ký hiệu với cùng tên (chúng ta sẽ đề cập đến điểm này trong ví dụ của phần Thêm, thay thế và xóa báo giá).
Chỉ một ký hiệu tùy chỉnh mới có thể bị xóa. Ngoài ra, bạn không thể xóa một ký hiệu được chọn trong Market Watch
hoặc một ký hiệu đang có biểu đồ mở. Xin lưu ý rằng một ký hiệu cũng có thể được chọn ngầm, mà không hiển thị trong danh sách có thể nhìn thấy (trong trường hợp như vậy, thuộc tính SYMBOL_VISIBLE là false
, và thuộc tính SYMBOL_SELECT là true
). Ký hiệu như vậy trước tiên phải được "ẩn" bằng cách gọi SymbolSelect("name", false)
trước khi cố gắng xóa: nếu không, chúng ta sẽ nhận được lỗi CUSTOM_SYMBOL_SELECTED (5306).
Nếu việc xóa một ký hiệu để lại một thư mục trống (hoặc phân cấp thư mục), nó cũng sẽ bị xóa.
Ví dụ, hãy tạo một tập lệnh đơn giản CustomSymbolCreateDelete.mq5
. Trong các tham số đầu vào, bạn có thể chỉ định một tên, một đường dẫn và một ký hiệu mẫu.
input string CustomSymbol = "Dummy"; // Tên Ký hiệu Tùy chỉnh`
input string CustomPath = "MQL5Book\\Part7"; // Thư mục Ký hiệu Tùy chỉnh`
input string Origin;
2
3
Trong trình xử lý OnStart
, hãy kiểm tra xem đã có ký hiệu nào với tên đã cho chưa. Nếu chưa, thì sau khi có sự xác nhận từ người dùng, chúng ta sẽ tạo ký hiệu đó. Nếu ký hiệu đã có và đó là một ký hiệu tùy chỉnh, hãy xóa nó với sự cho phép của người dùng (điều này sẽ giúp việc dọn dẹp sau khi thử nghiệm kết thúc dễ dàng hơn).
void OnStart()
{`
bool custom = false;
if(!PRTF(SymbolExist(CustomSymbol, custom)))
{
if(IDYES == MessageBox("Create new custom symbol?", "Please, confirm", MB_YESNO))
{
PRTF(CustomSymbolCreate(CustomSymbol, CustomPath, Origin));
}
}
else
{
if(custom)
{
if(IDYES == MessageBox("Delete existing custom symbol?", "Please, confirm", MB_YESNO))
{
PRTF(CustomSymbolDelete(CustomSymbol));
}
}
else
{
Print("Can't delete non-custom symbol");
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Hai lần chạy liên tiếp với các tùy chọn mặc định nên dẫn đến các mục nhật ký sau.
SymbolExist(CustomSymbol,custom)=false / ok
Create new custom symbol?`
CustomSymbolCreate(CustomSymbol,CustomPath,Origin)=true / ok
SymbolExist(CustomSymbol,custom)=true / ok
Delete existing custom symbol?`
CustomSymbolDelete(CustomSymbol)=true / ok
```cpp
Giữa các lần chạy, bạn có thể mở hộp thoại ký hiệu trong terminal và kiểm tra xem ký hiệu tùy chỉnh tương ứng đã xuất hiện trong phân cấp ký hiệu chưa.
2
3
4
5
6
7
8
9