Sự kiện tham chiếu của chỉ báo và Expert Advisors: OnInit và OnDeinit
Trong các chương trình MQL tương tác — chỉ báo và Expert Advisors — môi trường tạo ra hai sự kiện để chuẩn bị cho việc khởi chạy (OnInit
) và dừng (OnDeinit
). Không có các sự kiện như vậy trong scripts và services vì chúng không chấp nhận các sự kiện không đồng bộ: sau khi quyền điều khiển được chuyển đến hàm xử lý sự kiện duy nhất của chúng là OnStart
và cho đến khi kết thúc công việc, ngữ cảnh thực thi của luồng script/service nằm trong mã của chương trình MQL. Ngược lại, đối với chỉ báo và Expert Advisors, quá trình làm việc bình thường giả định rằng môi trường sẽ liên tục gọi các hàm xử lý sự kiện cụ thể của chúng (chúng ta sẽ thảo luận về chúng trong các phần về chỉ báo và Expert Advisors), và mỗi lần, sau khi thực hiện các hành động cần thiết, các chương trình sẽ trả lại quyền điều khiển cho terminal để chờ đợi các sự kiện mới một cách nhàn rỗi.
int OnInit()
Hàm OnInit
là một hàm xử lý sự kiện cùng tên, được tạo ra sau khi tải một Expert Advisor hoặc chỉ báo. Hàm này chỉ có thể được định nghĩa khi cần thiết.
Hàm phải trả về một trong các giá trị của enum ENUM_INIT_RETCODE
.
Định danh | Mô tả |
---|---|
INIT_SUCCEEDED | Khởi tạo thành công, chương trình có thể tiếp tục thực thi; tương ứng với giá trị 0 |
INIT_FAILED | Khởi tạo không thành công, không thể tiếp tục thực thi do lỗi nghiêm trọng (ví dụ, không thể tạo tệp hoặc chỉ báo phụ trợ); giá trị 1 |
INIT_PARAMETERS_INCORRECT | Tập hợp tham số đầu vào không chính xác, việc thực thi chương trình là không thể |
INIT_AGENT_NOT_SUITABLE | Mã cụ thể để làm việc trong tester: vì một số lý do, tác nhân này không phù hợp để thử nghiệm (ví dụ, không đủ RAM, không hỗ trợ OpenCL, v.v.) |
Nếu OnInit
trả về bất kỳ mã trả về nào khác 0, điều này có nghĩa là khởi tạo không thành công, và sau đó sự kiện Deinit
được tạo ra, với mã lý do hủy khởi tạo là REASON_INITFAILED
(xem bên dưới).
Hàm OnInit
có thể được khai báo với kiểu kết quả là void
: trong trường hợp này, khởi tạo luôn được coi là thành công.
Trong hàm xử lý
OnInit
, điều quan trọng là phải kiểm tra xem tất cả thông tin môi trường cần thiết có sẵn hay không, và nếu không có, hãy hoãn các hành động chuẩn bị cho sự kiện tick hoặc timer tiếp theo. Vấn đề là khi terminal khởi động, sự kiệnOnInit
thường được kích hoạt trước khi kết nối với máy chủ được thiết lập, và do đó nhiều thuộc tính của công cụ tài chính và tài khoản giao dịch vẫn chưa được biết. Đặc biệt, giá trị của một pip của một ký hiệu cụ thể có thể được trả về là zero.
void OnDeinit(const int reason)
Hàm OnDeinit
(nếu được định nghĩa) được gọi khi Expert Advisor hoặc chỉ báo được hủy khởi tạo. Hàm này là tùy chọn.
Tham số reason
chứa mã lý do hủy khởi tạo. Các giá trị có thể được hiển thị trong bảng sau.
Hằng số | Giá trị | Mô tả |
---|---|---|
REASON_PROGRAM | 0 | Expert Advisor ngừng hoạt động bằng cách gọi hàm ExpertRemove |
REASON_REMOVE | 1 | Chương trình bị xóa khỏi biểu đồ |
REASON_RECOMPILE | 2 | Chương trình được biên dịch lại |
REASON_CHARTCHANGE | 3 | Ký hiệu hoặc chu kỳ biểu đồ thay đổi |
REASON_CHARTCLOSE | 4 | Biểu đồ bị đóng |
REASON_PARAMETERS | 5 | Tham số đầu vào thay đổi |
REASON_ACCOUNT | 6 | Một tài khoản khác đã được kích hoạt, hoặc đã xảy ra kết nối lại với máy chủ giao dịch do thay đổi cài đặt tài khoản |
REASON_TEMPLATE | 7 | Áp dụng một mẫu biểu đồ khác |
REASON_INITFAILED | 8 | Hàm xử lý OnInit trả về giá trị không null |
REASON_CLOSE | 9 | Terminal bị đóng |
Cùng mã này có thể được lấy ở bất kỳ đâu trong chương trình bằng cách sử dụng hàm UninitializeReason
nếu cờ dừng _StopFlag
được đặt trong chương trình MQL.
Tệp AllInOne.mqh
có lớp Finalizer
cho phép bạn "gắn" mã hủy khởi tạo trong hàm hủy thông qua lời gọi UninitializeReason
. Chúng ta phải nhận được cùng giá trị trong hàm xử lý OnDeinit
.
class Finalizer
{
static const Finalizer f;
public:
~Finalizer()
{
PRTF(EnumToString((ENUM_DEINIT_REASON)UninitializeReason()));
}
};
static const Finalizer Finalizer::f;
2
3
4
5
6
7
8
9
10
11
Để thuận tiện cho việc chuyển đổi mã thành biểu diễn chuỗi (tên của các lý do) bằng cách sử dụng EnumToString
, enum ENUM_DEINIT_REASON
với các hằng số từ bảng trên được mô tả trong tệp Uninit.mqh
. Nhật ký sẽ hiển thị các mục như:
OnDeinit DEINIT_REASON_REMOVE
EnumToString((ENUM_DEINIT_REASON)UninitializeReason())=DEINIT_REASON_REMOVE / ok
2
Khi bạn thay đổi ký hiệu hoặc khung thời gian của biểu đồ mà chỉ báo đang nằm, nó sẽ được dỡ bỏ và tải lại. Trong trường hợp này, trình tự kích hoạt sự kiện
OnDeinit
trong bản sao cũ vàOnInit
trong bản sao mới không được xác định. Điều này là do đặc thù của việc xử lý sự kiện không đồng bộ bởi terminal. Nói cách khác, có thể không hoàn toàn hợp lý rằng bản sao mới sẽ được tải và khởi tạo trước khi bản sao cũ được dỡ bỏ hoàn toàn. Nếu chỉ báo thực hiện một số điều chỉnh biểu đồ trongOnInit
(ví dụ, tạo một đối tượng đồ họa), thì không có biện pháp đặc biệt nào, bản sao đã dỡ bỏ có thể ngay lập tức "dọn dẹp" biểu đồ (xóa đối tượng, coi đó là của nó). Trong trường hợp cụ thể của các đối tượng đồ họa, có một giải pháp đặc biệt: các đối tượng có thể được đặt tên bao gồm tiền tố ký hiệu và khung thời gian (cũng như giá trị kiểm tra tổng của các biến đầu vào), nhưng trong trường hợp chung thì điều này sẽ không hiệu quả. Để có giải pháp phổ quát cho vấn đề này, một cơ chế đồng bộ hóa nào đó nên được triển khai, ví dụ, trên biến toàn cục hoặc tài nguyên.
Khi thử nghiệm các chỉ báo trong tester, các nhà phát triển MetaTrader 5 quyết định không tạo ra sự kiện OnDeinit
. Ý tưởng của họ là chỉ báo có thể tạo ra một số đối tượng đồ họa, mà nó thường xóa trong hàm xử lý OnDeinit
, nhưng người dùng muốn xem chúng sau khi thử nghiệm hoàn tất. Trên thực tế, tác giả của chương trình MQL có thể, nếu muốn, cung cấp hành vi tương tự và để lại các đối tượng với việc kiểm tra tích cực chế độ MQLInfoInteger(MQL_TESTER)
. Điều này kỳ lạ vì hàm xử lý OnDeinit
được gọi sau khi thử nghiệm Expert Advisor, và Expert Advisor cũng có thể xóa các đối tượng trong OnDeinit
. Bây giờ, chỉ đối với các chỉ báo, hóa ra hành vi thông thường của hàm xử lý OnDeinit
không thể được đảm bảo trong tester. Hơn nữa, việc kết thúc khác không được thực hiện, ví dụ, các hàm hủy của các đối tượng toàn cục không được gọi.
Do đó, nếu bạn cần thực hiện tính toán thống kê, lưu tệp, hoặc hành động khác sau khi chạy thử nghiệm mà ban đầu được dự định cho OnDeinit
của chỉ báo, bạn sẽ phải chuyển các thuật toán chỉ báo sang Expert Advisor.