Thiết kế các chương trình MQL thuộc nhiều loại khác nhau
Loại chương trình là một thuộc tính cơ bản trong MQL5. Khác với C++ hoặc các ngôn ngữ lập trình đa năng khác, nơi bất kỳ chương trình nào cũng có thể được phát triển theo hướng tùy ý, chẳng hạn như thêm giao diện đồ họa hoặc tải dữ liệu từ máy chủ qua mạng, các chương trình MQL được chia thành các nhóm nhất định theo mục đích của chúng. Ví dụ, phân tích chuỗi thời gian kỹ thuật với khả năng trực quan hóa được thực hiện qua các chỉ báo, nhưng chúng không thể giao dịch. Ngược lại, các hàm API giao dịch có sẵn cho Expert Advisors, nhưng chúng thiếu bộ đệm chỉ báo (mảng để vẽ đường).
Do đó, khi giải quyết một vấn đề ứng dụng cụ thể, nhà phát triển nên chia nhỏ nó thành các phần, và chức năng của mỗi phần nên phù hợp với chuyên môn của một loại riêng biệt. Tất nhiên, trong các trường hợp đơn giản, một chương trình MQL duy nhất là đủ, nhưng đôi khi giải pháp kỹ thuật tối ưu không rõ ràng. Ví dụ, bạn sẽ triển khai việc vẽ biểu đồ Renko như thế nào: dưới dạng chỉ báo, dưới dạng custom symbol được tạo bởi service, hay là các tính toán cụ thể trực tiếp trong Expert Advisor giao dịch? Tất cả các lựa chọn đều khả thi.
Loại chương trình MQL được đặc trưng bởi một số yếu tố.
Thứ nhất, mỗi loại chương trình có một thư mục riêng trong thư mục làm việc MQL5. Chúng ta đã đề cập đến điều này trong phần giới thiệu của Phần 1 và liệt kê các thư mục. Vì vậy, đối với chỉ báo, Expert Advisors, scripts và services, các thư mục được chỉ định lần lượt là Indicators
, Experts
, Scripts
và Services
. Thư mục con Libraries
được dành riêng cho các thư viện trong thư mục MQL5. Trong mỗi thư mục này, bạn có thể tổ chức một cây các thư mục lồng nhau với cấu hình tùy ý.
Tệp nhị phân (chương trình hoàn chỉnh với phần mở rộng ex5
) — là kết quả của việc biên dịch tệp mq5 — được tạo trong cùng thư mục với tệp nguồn mq5. Tuy nhiên, chúng ta cũng nên đề cập đến các dự án trong MetaEditor (tệp với phần mở rộng mqproj
), mà chúng ta sẽ phân tích trong chương Dự án. Khi một dự án được phát triển, sản phẩm hoàn chỉnh được tạo trong một thư mục bên cạnh dự án. Khi tạo một chương trình từ MQL5 Wizard trong MetaEditor (lệnh File -> New
), tệp nguồn được đặt mặc định trong thư mục tương ứng với loại chương trình. Nếu bạn vô tình sao chép một chương trình vào sai thư mục, không có gì nghiêm trọng sẽ xảy ra: nó sẽ không biến, ví dụ, từ Expert Advisor thành chỉ báo, hoặc ngược lại. Nó có thể được di chuyển đến vị trí mong muốn trực tiếp trong trình chỉnh sửa, bên trong cửa sổ Navigator
, hoặc trong trình quản lý tệp bên ngoài. Trong Navigator
, mỗi loại chương trình được hiển thị với một biểu tượng đặc biệt.
Vị trí của một chương trình trong thư mục MQL5 trong một thư mục con dành riêng cho một loại cụ thể không xác định loại của chương trình MQL này. Loại được xác định dựa trên nội dung của tệp thực thi, mà đến lượt nó, được trình biên dịch hình thành từ các chỉ thị thuộc tính và câu lệnh trong mã nguồn.
Hệ thống phân cấp thư mục theo loại chương trình được sử dụng để thuận tiện. Nên tuân thủ nó, trừ khi đó là một nhóm các dự án liên quan (với các chương trình thuộc các loại khác nhau), việc lưu trữ chúng trong một thư mục riêng sẽ hợp lý hơn.
Thứ hai, mỗi loại chương trình được đặc trưng bởi sự hỗ trợ cho một tập hợp sự kiện hệ thống cụ thể, hạn chế, kích hoạt chương trình. Chúng ta sẽ xem Tổng quan về các hàm xử lý sự kiện trong một phần riêng biệt. Để nhận các sự kiện của một loại cụ thể trong một chương trình, cần mô tả một hàm xử lý với nguyên mẫu được định nghĩa trước (tên, danh sách tham số, giá trị trả về).
Ví dụ, chúng ta đã thấy rằng trong scripts và services, công việc bắt đầu trong hàm OnStart
, và vì nó là hàm duy nhất ở đó, nó có thể được gọi là "điểm vào chính" mà qua đó terminal chuyển quyền điều khiển sang mã ứng dụng. Trong các loại chương trình khác, tình hình có phần phức tạp hơn. Nói chung, chúng ta lưu ý rằng một loại chương trình được đặc trưng bởi một tập hợp các hàm xử lý nhất định, một số trong đó có thể là bắt buộc và một số là tùy chọn (nhưng đồng thời không được chấp nhận cho các loại chương trình khác). Đặc biệt, một chỉ báo yêu cầu hàm OnCalculate
(không có nó, chỉ báo sẽ không biên dịch và trình biên dịch sẽ tạo ra lỗi). Tuy nhiên, hàm này không được sử dụng trong Expert Advisors.
Thứ ba, một số loại chương trình yêu cầu các chỉ thị #property
đặc biệt. Trong chương Thuộc tính chung của chương trình, chúng ta đã thấy các chỉ thị có thể được sử dụng trong tất cả các loại chương trình. Tuy nhiên, còn có các chỉ thị chuyên biệt khác. Ví dụ, trong các nhiệm vụ với services mà chúng ta đã đề cập, chúng ta đã gặp chỉ thị #property service
, biến chương trình thành một service. Nếu không có nó, ngay cả việc đặt chương trình trong thư mục Services
cũng sẽ không cho phép nó chạy trong nền.
Tương tự, chỉ thị #property library
đóng vai trò quyết định trong việc tạo thư viện. Tất cả các thuộc tính chỉ thị như vậy sẽ được thảo luận trong các phần dành cho các loại chương trình tương ứng.
Sự kết hợp của các chỉ thị và hàm xử lý sự kiện được xem xét khi xác định loại chương trình MQL theo thứ tự sau (từ trên xuống dưới cho đến khi khớp đầu tiên):
- chỉ báo: sự hiện diện của hàm xử lý
OnCalculate
- thư viện:
#property library
- script: sự hiện diện của hàm xử lý
OnStart
và không có#property service
- service: sự hiện diện của hàm xử lý
OnStart
và#property service
- Expert Advisor: sự hiện diện của bất kỳ hàm xử lý nào khác
Một ví dụ về ảnh hưởng của các thuộc tính này đến trình biên dịch sẽ được đưa ra trong phần Tổng quan về các hàm xử lý sự kiện.
Đối với tất cả các điểm trên, cần xem xét thêm một điểm nữa. Loại chương trình được xác định bởi mô-đun biên dịch chính: tệp có phần mở rộng mq5, nơi các nguồn khác từ các thư mục khác có thể được bao gồm bằng chỉ thị
#include
. Tất cả các hàm được bao gồm theo cách này được xem xét ở cùng cấp độ với những hàm có mặt trực tiếp trong tệp mq5 chính.Mặt khác, các chỉ thị
#property
chỉ có hiệu lực khi được đặt trong tệp mq5 chính được biên dịch. Nếu các chỉ thị xuất hiện trong các tệp được bao gồm trong chương trình bằng#include
, chúng sẽ bị bỏ qua.
Tệp mq5 chính không cần phải chứa các hàm xử lý sự kiện theo nghĩa đen. Hoàn toàn có thể chấp nhận được việc đặt một phần hoặc toàn bộ thuật toán trong các tệp tiêu đề mqh và sau đó bao gồm chúng trong một hoặc nhiều chương trình. Ví dụ, chúng ta có thể triển khai hàm xử lý OnStart
với một tập hợp các hành động hữu ích trong một tệp mqh và sử dụng nó qua #include
bên trong hai chương trình riêng biệt: một script và một service.
Trong khi đó, hãy lưu ý rằng sự hiện diện của các hàm xử lý sự kiện chung không phải là động cơ duy nhất để tách các đoạn thuật toán chung vào một tệp tiêu đề. Bạn có thể sử dụng cùng một công thức tính toán, ví dụ, trong một chỉ báo và trong một Expert Advisor, để lại các hàm xử lý sự kiện của chúng trong các mô-đun chương trình chính.
Mặc dù thường được gọi là tệp tiêu đề và đặt phần mở rộng
mqh
cho các tệp bao gồm, nhưng điều này không cần thiết về mặt kỹ thuật. Hoàn toàn có thể chấp nhận được (mặc dù không khuyến khích) bao gồm một tệp mq5 khác hoặc, ví dụ, một tệp txt trong một tệp mq5. Chúng có thể chứa một số mã cũ hoặc, giả sử, khởi tạo một số mảng với các hằng số. Việc bao gồm một tệp mq5 khác không làm nó trở thành tệp chính.Bạn nên đảm bảo rằng chỉ các hàm xử lý sự kiện đặc trưng cho loại chương trình cụ thể mới được đưa vào chương trình, và không có bản sao nào trong số chúng (như bạn biết, các hàm được xác định bởi sự kết hợp của tên và danh sách tham số: nạp chồng hàm chỉ được phép với tập hợp tham số khác nhau). Điều này thường được đạt được bằng cách sử dụng các chỉ thị tiền xử lý khác nhau. Ví dụ, bằng cách định nghĩa macro
#define OnStart OnStartPrevious
trước khi bao gồm một tệp script mq5 của bên thứ ba trong một số chương trình của chúng ta, chúng ta sẽ thực sự biến hàmOnStart
được mô tả trong đó thànhOnStartPrevious
, và chúng ta có thể gọi nó như bình thường từ các hàm xử lý sự kiện của riêng mình.Tuy nhiên, cách tiếp cận này chỉ có ý nghĩa trong các trường hợp đặc biệt khi mã nguồn của tệp mq5 được bao gồm không thể sửa đổi vì một lý do nào đó, đặc biệt là khi nó không thể được cấu trúc với việc chọn lọc các thuật toán quan tâm thành các hàm hoặc lớp trong các tệp tiêu đề riêng biệt.
Theo nguyên tắc tương tác với người dùng, các chương trình MQL có thể được chia thành các chương trình tương tác và tiện ích.
Các chương trình tương tác — chỉ báo và Expert Advisors — có thể xử lý sự kiện, xảy ra trong môi trường phần mềm để đáp ứng các hành động của người dùng, chẳng hạn như nhấn nút trên bàn phím, di chuyển chuột, thay đổi kích thước cửa sổ, cũng như nhiều sự kiện khác, ví dụ, liên quan đến việc nhận dữ liệu báo giá hoặc hành động của bộ đếm thời gian.
Các chương trình tiện ích — services và scripts — chỉ dựa vào các biến đầu vào được thiết lập tại thời điểm khởi chạy và không phản hồi các sự kiện trong hệ thống.
Ngoài tất cả các loại chương trình là thư viện. Chúng luôn được thực thi như một phần của một loại chương trình MQL khác (một trong bốn loại chính), và do đó không có bất kỳ đặc điểm hay hành vi đặc trưng nào. Đặc biệt, chúng không thể nhận trực tiếp sự kiện từ terminal và không có luồng riêng (xem phần tiếp theo). Cùng một thư viện có thể được kết nối với nhiều chương trình, và điều này xảy ra một cách động tại thời điểm khởi chạy của mỗi chương trình cha. Trong phần về thư viện, chúng ta sẽ tìm hiểu cách mô tả API xuất khẩu của thư viện và nhập nó vào chương trình cha.