Hàm xử lý sự kiện
Ngôn ngữ MQL5 cung cấp khả năng xử lý một số sự kiện được định nghĩa trước. Các hàm để xử lý những sự kiện này phải được định nghĩa trong chương trình MQL5; tên hàm, kiểu trả về, thành phần tham số (nếu có) và kiểu của chúng phải tuân thủ nghiêm ngặt mô tả của hàm xử lý sự kiện.
Bộ xử lý sự kiện của thiết bị đầu cuối khách hàng xác định các hàm xử lý sự kiện này hay sự kiện kia dựa trên kiểu giá trị trả về và kiểu tham số. Nếu các tham số khác, không tương ứng với mô tả dưới đây, được chỉ định cho hàm tương ứng, hoặc một kiểu trả về khác được chỉ định, hàm đó sẽ không được sử dụng làm bộ xử lý sự kiện.
OnStart
Hàm OnStart()
là bộ xử lý sự kiện Start, được tạo tự động chỉ dành cho việc chạy scripts. Nó phải có kiểu void
, không có tham số:
void OnStart();
Đối với hàm OnStart()
, kiểu trả về int
có thể được chỉ định.
OnInit
Hàm OnInit()
là bộ xử lý sự kiện Init. Nó phải có kiểu void
hoặc int
, không có tham số:
void OnInit();
Sự kiện Init được tạo ngay sau khi một Expert Advisor hoặc chỉ báo được tải xuống; sự kiện này không được tạo cho scripts. Hàm OnInit()
được sử dụng để khởi tạo. Nếu OnInit()
có kiểu giá trị trả về int
, mã trả về khác không biểu thị khởi tạo không thành công và tạo ra sự kiện Deinit với mã lý do hủy khởi tạo REASON_INITFAILED
.
Khi trả về INIT_FAILED
, EA bị buộc gỡ bỏ khỏi biểu đồ.
Khi trả về INIT_FAILED
, chỉ báo không bị gỡ khỏi biểu đồ. Chỉ báo còn lại trên biểu đồ không hoạt động — bộ xử lý sự kiện không được gọi trong chỉ báo.
Để tối ưu hóa các tham số đầu vào của Expert Advisor, nên sử dụng các giá trị của liệt kê ENUM_INIT_RETCODE làm mã trả về. Các giá trị này được sử dụng để tổ chức quá trình tối ưu hóa, bao gồm việc chọn tác nhân kiểm tra phù hợp nhất. Trong quá trình khởi tạo Expert Advisor trước khi bắt đầu kiểm tra, bạn có thể yêu cầu thông tin về cấu hình và tài nguyên của tác nhân (số lõi, lượng bộ nhớ trống, v.v.) bằng hàm TerminalInfoInteger(). Dựa trên thông tin thu được, bạn có thể cho phép sử dụng tác nhân kiểm tra này hoặc từ chối sử dụng nó trong quá trình tối ưu hóa Expert Advisor này.
ENUM_INIT_RETCODE
Định danh | Mô tả |
---|---|
INIT_SUCCEEDED | Khởi tạo thành công, việc kiểm tra Expert Advisor có thể tiếp tục. Mã này có ý nghĩa tương đương với giá trị null – Expert Advisor đã được khởi tạo thành công trong trình kiểm tra. |
INIT_FAILED | Khởi tạo thất bại; không có ý nghĩa trong việc tiếp tục kiểm tra do lỗi nghiêm trọng. Ví dụ, không thể tạo chỉ báo cần thiết cho hoạt động của Expert Advisor. Mã trả về này tương đương với giá trị khác không – khởi tạo Expert Advisor trong trình kiểm tra thất bại. |
INIT_PARAMETERS_INCORRECT | Giá trị này biểu thị tập hợp tham số đầu vào không chính xác. Chuỗi kết quả chứa mã trả về này được tô màu đỏ trong bảng tối ưu hóa chung. Việc kiểm tra cho tập hợp tham số đã cho của Expert Advisor sẽ không được thực hiện, tác nhân được tự do nhận nhiệm vụ mới. Khi nhận được giá trị này, trình kiểm tra chiến lược sẽ chắc chắn không chuyển nhiệm vụ này cho các tác nhân khác để thử lại. |
INIT_AGENT_NOT_SUITABLE | Không có lỗi trong quá trình khởi tạo, nhưng vì một lý do nào đó, tác nhân không phù hợp để kiểm tra. Ví dụ, không đủ bộ nhớ, không có hỗ trợ OpenCL, v.v. Sau khi trả về mã này, tác nhân sẽ không nhận nhiệm vụ cho đến khi kết thúc tối ưu hóa này. |
Hàm OnInit()
kiểu void
luôn biểu thị khởi tạo thành công.
OnDeinit
Hàm OnDeinit()
được gọi trong quá trình hủy khởi tạo và là bộ xử lý sự kiện Deinit. Nó phải được khai báo với kiểu void
và nên có một tham số kiểu const int
, chứa mã lý do hủy khởi tạo. Nếu một kiểu khác được khai báo, trình biên dịch sẽ tạo cảnh báo, nhưng hàm sẽ không được gọi. Đối với scripts, sự kiện Deinit không được tạo và do đó hàm OnDeinit()
không thể sử dụng trong scripts.
void OnDeinit(const int reason);
Sự kiện Deinit được tạo cho Expert Advisors và chỉ báo trong các trường hợp sau:
- Trước khi tái khởi tạo do thay đổi ký hiệu hoặc khoảng thời gian biểu đồ mà chương trình mql5 được gắn vào;
- Trước khi tái khởi tạo do thay đổi tham số đầu vào;
- Trước khi gỡ bỏ chương trình mql5.
OnTick
Sự kiện NewTick được tạo chỉ cho Expert Advisors khi nhận được một tick mới cho ký hiệu mà Expert Advisor được gắn vào biểu đồ. Việc định nghĩa hàm OnTick()
trong chỉ báo tùy chỉnh hoặc script là vô nghĩa, vì sự kiện NewTick không được tạo cho chúng.
Sự kiện Tick chỉ được tạo cho Expert Advisors, nhưng điều này không có nghĩa là Expert Advisors yêu cầu hàm OnTick()
, vì không chỉ sự kiện NewTick được tạo cho Expert Advisors, mà còn có các sự kiện Timer, BookEvent và ChartEvent. Nó phải được khai báo với kiểu void
, không có tham số:
void OnTick();
OnTimer
Hàm OnTimer()
được gọi khi sự kiện Timer xảy ra, được tạo bởi bộ đếm thời gian hệ thống chỉ cho Expert Advisors và chỉ báo - nó không thể sử dụng trong scripts. Tần suất xảy ra sự kiện được thiết lập khi đăng ký nhận thông báo về sự kiện này bằng hàm EventSetTimer().
Bạn có thể hủy đăng ký nhận sự kiện timer cho một Expert Advisor cụ thể bằng hàm EventKillTimer(). Hàm phải được định nghĩa với kiểu void
, không có tham số:
void OnTimer();
Nên gọi hàm EventSetTimer()
một lần trong hàm OnInit()
, và hàm EventKillTimer()
nên được gọi một lần trong OnDeinit()
.
Mỗi Expert Advisor, cũng như mỗi chỉ báo, hoạt động với bộ đếm thời gian riêng và chỉ nhận sự kiện từ nó. Ngay khi chương trình mql5 ngừng hoạt động, bộ đếm thời gian bị hủy bỏ buộc nếu nó đã được tạo nhưng chưa bị vô hiệu hóa bởi hàm EventKillTimer().
OnTrade
Hàm được gọi khi sự kiện Trade xảy ra, xuất hiện khi bạn thay đổi danh sách lệnh đã đặt và vị thế mở, lịch sử lệnh và lịch sử giao dịch. Khi thực hiện một hoạt động giao dịch (mở lệnh chờ, mở/đóng vị thế, đặt dừng, kích hoạt lệnh chờ, v.v.), lịch sử lệnh và giao dịch và/hoặc danh sách vị thế và lệnh hiện tại thay đổi tương ứng.
void OnTrade();
Người dùng phải tự triển khai trong mã việc kiểm tra trạng thái tài khoản giao dịch khi nhận được sự kiện như vậy (nếu điều này được yêu cầu bởi điều kiện chiến lược giao dịch). Nếu lệnh gọi hàm OrderSend()
đã hoàn thành thành công và trả về giá trị true
, điều này có nghĩa là máy chủ giao dịch đã đưa lệnh vào hàng đợi để thực hiện và gán một số vé cho nó. Ngay khi máy chủ xử lý lệnh này, sự kiện Trade sẽ được tạo. Và nếu người dùng nhớ giá trị vé, họ sẽ có thể tìm hiểu điều gì đã xảy ra với lệnh bằng cách sử dụng giá trị này trong quá trình xử lý sự kiện OnTrade()
.
OnTradeTransaction
Khi thực hiện một số hành động nhất định trên tài khoản giao dịch, trạng thái của nó thay đổi. Các hành động này bao gồm:
- Gửi yêu cầu giao dịch từ bất kỳ ứng dụng MQL5 nào trong thiết bị đầu cuối khách hàng bằng hàm OrderSend và OrderSendAsync và việc thực hiện tiếp theo của nó;
- Gửi yêu cầu giao dịch qua giao diện đồ họa của thiết bị đầu cuối và việc thực hiện tiếp theo của nó;
- Kích hoạt lệnh chờ và lệnh dừng trên máy chủ;
- Thực hiện các hoạt động ở phía máy chủ giao dịch.
Các giao dịch thương mại sau đây được thực hiện do các hành động này:
- Xử lý yêu cầu giao dịch;
- Thay đổi lệnh mở;
- Thay đổi lịch sử lệnh;
- Thay đổi lịch sử giao dịch;
- Thay đổi vị thế.
Ví dụ, khi gửi lệnh mua thị trường, nó được xử lý, một lệnh mua tương ứng được tạo cho tài khoản, sau đó lệnh được thực hiện và xóa khỏi danh sách các lệnh mở, rồi được thêm vào lịch sử lệnh, một giao dịch tương ứng được thêm vào lịch sử và một vị thế mới được tạo. Tất cả các hành động này là giao dịch thương mại. Sự xuất hiện của giao dịch như vậy tại thiết bị đầu cuối là sự kiện TradeTransaction. Nó gọi bộ xử lý OnTradeTransaction
void OnTradeTransaction(
const MqlTradeTransaction& trans, // cấu trúc giao dịch thương mại
const MqlTradeRequest& request, // cấu trúc yêu cầu
const MqlTradeResult& result // cấu trúc kết quả
);
2
3
4
5
Bộ xử lý chứa ba tham số:
- trans - tham số này nhận cấu trúc MqlTradeTransaction mô tả giao dịch thương mại được áp dụng cho tài khoản giao dịch;
- request - tham số này nhận cấu trúc MqlTradeRequest mô tả yêu cầu giao dịch;
- result - tham số này nhận cấu trúc MqlTradeResult mô tả kết quả thực hiện yêu cầu giao dịch.
Hai tham số cuối request và result chỉ được điền giá trị cho giao dịch loại TRADE_TRANSACTION_REQUEST, dữ liệu về giao dịch có thể nhận được từ tham số type
của biến trans. Lưu ý rằng trong trường hợp này, trường request_id
trong biến result chứa ID của yêu cầu giao dịch, sau khi thực hiện, giao dịch thương mại được mô tả trong biến trans đã được thực hiện. ID yêu cầu cho phép liên kết hành động đã thực hiện (gọi hàm OrderSend
hoặc OrderSendAsync
) với kết quả của hành động này được gửi đến OnTradeTransaction().
Một yêu cầu giao dịch được gửi thủ công từ thiết bị đầu cuối hoặc qua hàm OrderSend()/OrderSendAsync() có thể tạo ra một số giao dịch liên tiếp trên máy chủ giao dịch. Thứ tự ưu tiên của việc đến của các giao dịch này tại thiết bị đầu cuối không được đảm bảo. Do đó, bạn không nên mong đợi rằng một nhóm giao dịch sẽ đến sau nhóm khác khi phát triển thuật toán giao dịch của mình.
- Tất cả các loại giao dịch thương mại được mô tả trong liệt kê ENUM_TRADE_TRANSACTION_TYPE.
- Cấu trúc
MqlTradeTransaction
mô tả một giao dịch thương mại được điền theo cách khác nhau tùy thuộc vào loại giao dịch. Ví dụ, chỉ trườngtype
(loại giao dịch thương mại) phải được phân tích cho các giao dịch loạiTRADE_TRANSACTION_REQUEST
. Các tham số thứ hai và thứ ba của hàmOnTradeTransaction
(request
vàresult
) phải được phân tích để lấy dữ liệu bổ sung. Để biết thêm thông tin, xem "Cấu trúc của Giao dịch Thương mại". - Mô tả giao dịch thương mại không cung cấp tất cả thông tin có sẵn liên quan đến lệnh, giao dịch và vị thế (ví dụ, bình luận). Các hàm OrderGet*, HistoryOrderGet*, HistoryDealGet* và PositionGet* nên được sử dụng để lấy thông tin mở rộng.
Sau khi áp dụng các giao dịch thương mại cho tài khoản khách hàng, chúng được đặt liên tục vào hàng đợi giao dịch thương mại của thiết bị đầu cuối, từ đó chúng được gửi liên tục đến điểm vào OnTradeTransaction
theo thứ tự đến tại thiết bị đầu cuối.
Khi xử lý các giao dịch thương mại bởi Expert Advisor sử dụng bộ xử lý OnTradeTransaction
, thiết bị đầu cuối tiếp tục xử lý các giao dịch thương mại mới đến. Do đó, trạng thái của tài khoản giao dịch có thể thay đổi ngay cả trong quá trình hoạt động của OnTradeTransaction
. Ví dụ, trong khi chương trình MQL5 xử lý sự kiện thêm một lệnh mới, nó có thể được thực hiện, xóa khỏi danh sách các lệnh mở và chuyển vào lịch sử. Tiếp theo, ứng dụng sẽ được thông báo về các sự kiện này.
Độ dài hàng đợi giao dịch bao gồm 1024 phần tử. Nếu OnTradeTransaction
xử lý một giao dịch mới quá lâu, các giao dịch cũ trong hàng đợi có thể bị thay thế bởi các giao dịch mới hơn.
- Nói chung, không có tỷ lệ chính xác giữa số lần gọi
OnTrade
vàOnTradeTransaction
. Một lần gọiOnTrade
tương ứng với một hoặc nhiều lần gọiOnTradeTransaction
. OnTrade
được gọi sau các lần gọiOnTradeTransaction
tương ứng.
OnTester
Hàm OnTester()
là bộ xử lý của sự kiện Tester được tạo tự động sau khi kiểm tra lịch sử của Expert Advisor trên khoảng thời gian đã chọn kết thúc. Hàm phải được định nghĩa với kiểu double
, không có tham số:
double OnTester();
Hàm được gọi ngay trước khi gọi OnDeinit()
và có cùng kiểu giá trị trả về - double
. OnTester()
chỉ có thể được sử dụng trong việc kiểm tra Expert Advisors. Mục đích chính của nó là tính toán một giá trị nhất định được sử dụng làm tiêu chí tối đa tùy chỉnh trong tối ưu hóa di truyền của các tham số đầu vào.
Trong tối ưu hóa di truyền, sắp xếp giảm dần được áp dụng cho các kết quả trong một thế hệ. Tức là, từ quan điểm của tiêu chí tối ưu hóa, kết quả tốt nhất là những kết quả có giá trị lớn nhất (đối với tiêu chí tối đa tùy chỉnh, các giá trị được trả về bởi hàm OnTester
được tính đến). Trong cách sắp xếp này, các giá trị tệ nhất được đặt ở cuối và sau đó bị loại bỏ và không tham gia vào việc hình thành thế hệ tiếp theo.
OnTesterInit
Hàm được gọi trong EA khi sự kiện TesterInit xảy ra để thực hiện các hành động cần thiết trước khi tối ưu hóa trong trình kiểm tra chiến lược. Có hai kiểu hàm.
Phiên bản trả về kết quả
int OnTesterInit(void);
Giá trị trả về
Giá trị kiểu int, số không có nghĩa là khởi tạo thành công của EA được khởi chạy trên biểu đồ trước khi tối ưu hóa bắt đầu.
Việc gọi OnTesterInit()
trả về kết quả thực thi được khuyến nghị sử dụng vì nó không chỉ cho phép khởi tạo chương trình mà còn trả về mã lỗi trong trường hợp dừng tối ưu hóa sớm. Việc trả về bất kỳ giá trị nào khác INIT_SUCCEEDED
(0) có nghĩa là lỗi, không có tối ưu hóa nào được khởi chạy.
Phiên bản không trả về kết quả chỉ được giữ lại để tương thích với mã cũ. Không khuyến nghị sử dụng
void OnTesterInit(void);
Với sự bắt đầu của tối ưu hóa, một Expert Advisor có bộ xử lý OnTesterDeinit()
hoặc OnTesterPass()
được tự động tải trong một biểu đồ thiết bị đầu cuối riêng biệt với ký hiệu và khoảng thời gian được chỉ định trong trình kiểm tra, và nhận sự kiện TesterInit
. Hàm được sử dụng để khởi tạo Expert Advisor trước khi bắt đầu tối ưu hóa để tiếp tục xử lý kết quả tối ưu hóa.
OnTesterPass
Hàm OnTesterPass()
là bộ xử lý của sự kiện TesterPass được tạo tự động khi một khung được nhận trong quá trình tối ưu hóa Expert Advisor trong trình kiểm tra chiến lược. Hàm phải được định nghĩa với kiểu void
. Nó không có tham số:
void OnTesterPass();
Một Expert Advisor có bộ xử lý OnTesterPass()
được tự động tải trong một biểu đồ thiết bị đầu cuối riêng biệt với ký hiệu/khoảng thời gian được chỉ định để kiểm tra, và nhận các sự kiện TesterPass
khi một khung được nhận trong quá trình tối ưu hóa. Hàm được sử dụng để xử lý động kết quả tối ưu hóa "tại chỗ" mà không cần chờ đợi hoàn thành. Các khung được thêm bằng hàm FrameAdd(), có thể được gọi sau khi kết thúc một lần chạy trong bộ xử lý OnTester().
OnTesterDeinit
OnTesterDeinit()
là bộ xử lý của sự kiện TesterDeinit được tạo tự động sau khi tối ưu hóa Expert Advisor trong trình kiểm tra chiến lược kết thúc. Hàm phải được định nghĩa với kiểu void
. Nó không có tham số:
void OnTesterDeinit();
Một Expert Advisor có bộ xử lý TesterDeinit()
được tự động tải trên biểu đồ khi bắt đầu tối ưu hóa, và nhận TesterDeinit
sau khi hoàn thành. Hàm được sử dụng để xử lý cuối cùng tất cả kết quả tối ưu hóa.
OnBookEvent
Hàm OnBookEvent()
là bộ xử lý BookEvent. BookEvent
được tạo cho Expert Advisors và chỉ báo khi Độ sâu Thị trường thay đổi. Nó phải có kiểu void
và có một tham số kiểu string
:
void OnBookEvent (const string& symbol);
Để nhận sự kiện BookEvent
cho bất kỳ ký hiệu nào, bạn chỉ cần đăng ký trước để nhận các sự kiện này cho ký hiệu đó bằng hàm MarketBookAdd(). Để hủy đăng ký nhận sự kiện BookEvent
cho một ký hiệu cụ thể, gọi MarketBookRelease().
Không giống như các sự kiện khác, sự kiện BookEvent
được phát sóng. Điều này có nghĩa là nếu một Expert Advisor đăng ký nhận sự kiện BookEvent
bằng MarketBookAdd
, tất cả các Expert Advisors khác có bộ xử lý OnBookEvent()
sẽ nhận được sự kiện này. Do đó, cần phân tích tên của ký hiệu, được truyền đến bộ xử lý dưới dạng tham số const string& symbol
.
OnChartEvent
OnChartEvent()
là bộ xử lý của một nhóm sự kiện ChartEvent:
CHARTEVENT_KEYDOWN
— sự kiện nhấn phím, khi cửa sổ biểu đồ được tập trung;CHARTEVENT_MOUSE_MOVE
— sự kiện di chuyển chuột và nhấp chuột (nếu CHART_EVENT_MOUSE_MOVE=true được đặt cho biểu đồ);CHARTEVENT_OBJECT_CREATE
— sự kiện tạo đối tượng đồ họa (nếu CHART_EVENT_OBJECT_CREATE=true được đặt cho biểu đồ);CHARTEVENT_OBJECT_CHANGE
— sự kiện thay đổi thuộc tính đối tượng qua hộp thoại thuộc tính;CHARTEVENT_OBJECT_DELETE
— sự kiện xóa đối tượng đồ họa (nếu CHART_EVENT_OBJECT_DELETE=true được đặt cho biểu đồ);CHARTEVENT_CLICK
— sự kiện nhấp chuột trên biểu đồ;CHARTEVENT_OBJECT_CLICK
— sự kiện nhấp chuột vào đối tượng đồ họa thuộc về biểu đồ;CHARTEVENT_OBJECT_DRAG
— sự kiện di chuyển đối tượng đồ họa bằng chuột;CHARTEVENT_OBJECT_ENDEDIT
— sự kiện hoàn tất chỉnh sửa văn bản trong hộp nhập của đối tượng đồ họa LabelEdit;CHARTEVENT_CHART_CHANGE
— sự kiện thay đổi biểu đồ;CHARTEVENT_CUSTOM+n
— ID của sự kiện người dùng, trong đó n nằm trong khoảng từ 0 đến 65535.CHARTEVENT_CUSTOM_LAST
— ID chấp nhận được cuối cùng của sự kiện tùy chỉnh (CHARTEVENT_CUSTOM
+65535).
Hàm chỉ có thể được gọi trong Expert Advisors và chỉ báo. Hàm nên có kiểu void
với 4 tham số:
void OnChartEvent(const int id, // ID sự kiện
const long& lparam, // Tham số kiểu long của sự kiện
const double& dparam, // Tham số kiểu double của sự kiện
const string& sparam // Tham số kiểu string của sự kiện
);
2
3
4
5
Đối với mỗi loại sự kiện, các tham số đầu vào của hàm OnChartEvent()
có các giá trị xác định cần thiết để xử lý sự kiện này. Các sự kiện và giá trị được truyền qua các tham số này được liệt kê trong bảng dưới đây.
Sự kiện | Giá trị của tham số id | Giá trị của tham số lparam | Giá trị của tham số dparam | Giá trị của tham số sparam |
---|---|---|---|---|
Sự kiện nhấn phím | CHARTEVENT_KEYDOWN | mã của phím được nhấn | Số lần lặp lại (số lần nhấn phím được lặp lại do người dùng giữ phím) | Giá trị chuỗi của mặt nạ bit mô tả trạng thái các nút bàn phím |
Sự kiện chuột (nếu thuộc tính CHART_EVENT_MOUSE_MOVE=true được đặt cho biểu đồ) | CHARTEVENT_MOUSE_MOVE | tọa độ X | tọa độ Y | Giá trị chuỗi của mặt nạ bit mô tả trạng thái các nút chuột |
Sự kiện tạo đối tượng đồ họa (nếu CHART_EVENT_OBJECT_CREATE=true được đặt cho biểu đồ) | CHARTEVENT_OBJECT_CREATE | — | — | Tên của đối tượng đồ họa được tạo |
Sự kiện thay đổi thuộc tính đối tượng qua hộp thoại thuộc tính | CHARTEVENT_OBJECT_CHANGE | — | — | Tên của đối tượng đồ họa được sửa đổi |
Sự kiện xóa đối tượng đồ họa (nếu CHART_EVENT_OBJECT_DELETE=true được đặt cho biểu đồ) | CHARTEVENT_OBJECT_DELETE | — | — | Tên của đối tượng đồ họa bị xóa |
Sự kiện nhấp chuột trên biểu đồ | CHARTEVENT_CLICK | tọa độ X | tọa độ Y | — |
Sự kiện nhấp chuột vào đối tượng đồ họa thuộc về biểu đồ | CHARTEVENT_OBJECT_CLICK | tọa độ X | tọa độ Y | Tên của đối tượng đồ họa mà sự kiện xảy ra |
Sự kiện kéo đối tượng đồ họa bằng chuột | CHARTEVENT_OBJECT_DRAG | — | — | Tên của đối tượng đồ họa được di chuyển |
Sự kiện hoàn tất chỉnh sửa văn bản trong hộp nhập của đối tượng đồ họa LabelEdit | CHARTEVENT_OBJECT_ENDEDIT | — | — | Tên của đối tượng đồ họa LabelEdit mà việc chỉnh sửa văn bản đã hoàn tất |
Sự kiện thay đổi biểu đồ | CHARTEVENT_CHART_CHANGE | — | — | — |
ID của sự kiện người dùng dưới số N | CHARTEVENT_CUSTOM+N | Giá trị được đặt bởi hàm EventChartCustom() | Giá trị được đặt bởi hàm EventChartCustom() | Giá trị được đặt bởi hàm EventChartCustom() |
OnCalculate
Hàm OnCalculate()
chỉ được gọi trong các chỉ báo tùy chỉnh khi cần tính toán các giá trị chỉ báo bởi sự kiện Calculate. Điều này thường xảy ra khi nhận được một tick mới cho ký hiệu mà chỉ báo được tính toán. Chỉ báo này không cần phải được gắn vào bất kỳ biểu đồ giá nào của ký hiệu này.
Hàm OnCalculate()
phải có kiểu trả về int
. Có hai định nghĩa khả thi. Trong một chỉ báo, bạn không thể sử dụng cả hai phiên bản của hàm.
Dạng đầu tiên được thiết kế cho những chỉ báo có thể được tính toán trên một bộ đệm dữ liệu duy nhất. Ví dụ của chỉ báo như vậy là Đường Trung bình Di động Tùy chỉnh.
int OnCalculate (const int rates_total, // kích thước của mảng price[]
const int prev_calculated, // số thanh được xử lý trong lần gọi trước
const int begin, // nơi dữ liệu quan trọng bắt đầu từ
const double& price[] // mảng để tính toán
);
2
3
4
5
Như mảng price[]
, một chuỗi thời gian hoặc bộ đệm được tính toán của một chỉ báo nào đó có thể được truyền vào. Để xác định hướng lập chỉ mục trong mảng price[]
, gọi ArrayGetAsSeries(). Để không phụ thuộc vào các giá trị mặc định, bạn phải gọi hàm ArraySetAsSeries() một cách vô điều kiện cho những mảng được kỳ vọng làm việc với.
Chuỗi thời gian cần thiết hoặc một chỉ báo được sử dụng làm mảng price[]
có thể được người dùng chọn trong tab "Tham số" khi khởi động chỉ báo. Để làm điều này, bạn nên chỉ định mục cần thiết trong danh sách thả xuống của trường "Áp dụng cho".
Để nhận giá trị của chỉ báo tùy chỉnh từ các chương trình mql5 khác, hàm iCustom() được sử dụng, trả về tay cầm chỉ báo cho các hoạt động tiếp theo. Bạn cũng có thể chỉ định mảng price[]
thích hợp hoặc tay cầm của một chỉ báo khác. Tham số này nên được truyền cuối cùng trong danh sách các biến đầu vào của chỉ báo tùy chỉnh.
Ví dụ:
void OnStart()
{
//---
string terminal_path=TerminalInfoString(STATUS_TERMINAL_PATH);
int handle_customMA=iCustom(Symbol(),PERIOD_CURRENT, "Custom Moving Average",13,0, MODE_EMA,PRICE_TYPICAL);
if(handle_customMA>0)
Print("handle_customMA = ",handle_customMA);
else
Print("Cannot open or not EX5 file '"+terminal_path+"\\MQL5\\Indicators\\"+"Custom Moving Average.ex5'");
}
2
3
4
5
6
7
8
9
10
Trong ví dụ này, tham số cuối cùng được truyền là giá trị PRICE_TYPICAL
(từ liệt kê ENUM_APPLIED_PRICE), cho biết chỉ báo tùy chỉnh sẽ được xây dựng dựa trên giá điển hình thu được dưới dạng (High+Low+Close)/3. Nếu tham số này không được chỉ định, chỉ báo được xây dựng dựa trên giá trị PRICE_CLOSE
, tức là giá đóng cửa của mỗi thanh.
Một ví dụ khác cho thấy việc truyền tay cầm chỉ báo làm tham số cuối cùng để chỉ định mảng price[]
, được đưa ra trong mô tả của hàm iCustom().
Dạng thứ hai được thiết kế cho tất cả các chỉ báo khác, trong đó hơn một chuỗi thời gian được sử dụng để tính toán.
int OnCalculate (const int rates_total, // kích thước của chuỗi thời gian đầu vào
const int prev_calculated, // số thanh được xử lý trong lần gọi trước
const datetime& time[], // Thời gian
const double& open[], // Mở
const double& high[], // Cao
const double& low[], // Thấp
const double& close[], // Đóng
const long& tick_volume[], // Khối lượng Tick
const long& volume[], // Khối lượng Thực
const int& spread[] // Chênh lệch
);
2
3
4
5
6
7
8
9
10
11
Các tham số của open[]
, high[]
, low[]
và close[]
chứa các mảng với giá mở, giá cao và thấp và giá đóng của khung thời gian hiện tại. Tham số time[]
chứa một mảng với giá trị thời gian mở, tham số spread[]
có một mảng chứa lịch sử chênh lệch (nếu có chênh lệch nào được cung cấp cho chứng khoán được giao dịch). Các tham số của volume[]
và tick_volume[]
chứa lịch sử khối lượng giao dịch và khối lượng tick, tương ứng.
Để xác định hướng lập chỉ mục của time[]
, open[]
, high[]
, low[]
, close[]
, tick_volume[]
, volume[]
và spread[]
, gọi ArrayGetAsSeries(). Để không phụ thuộc vào các giá trị mặc định, bạn nên gọi hàm ArraySetAsSeries() một cách vô điều kiện cho những mảng được kỳ vọng làm việc với.
Tham số đầu tiên rates_total
chứa số lượng thanh, có sẵn cho chỉ báo để tính toán, và tương ứng với số lượng thanh có sẵn trong biểu đồ.
Chúng ta nên lưu ý mối liên hệ giữa giá trị trả về của OnCalculate()
và tham số đầu vào thứ hai prev_calculated
. Trong lần gọi hàm, tham số prev_calculated
chứa giá trị được trả về bởi OnCalculate()
trong lần gọi trước đó. Điều này cho phép các thuật toán kinh tế để tính toán chỉ báo tùy chỉnh nhằm tránh tính toán lặp lại cho những thanh không thay đổi kể từ lần chạy trước của hàm này.
Để làm điều này, thường đủ để trả về giá trị của tham số rates_total
, chứa số lượng thanh trong lần gọi hàm hiện tại. Nếu kể từ lần gọi cuối cùng của OnCalculate()
, dữ liệu giá đã thay đổi (lịch sử sâu hơn được tải xuống hoặc khoảng trống lịch sử được điền), giá trị của tham số đầu vào prev_calculated
sẽ được thiết bị đầu cuối đặt về số không.
Lưu ý: nếu OnCalculate
trả về số không, thì các giá trị chỉ báo không được hiển thị trong DataWindow của thiết bị đầu cuối khách hàng.
Để hiểu rõ hơn, sẽ hữu ích khi khởi động chỉ báo, mã của nó được đính kèm dưới đây.
Ví dụ Chỉ báo:
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
//---- plot Line
#property indicator_label1 "Line"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDarkBlue
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//--- indicator buffers
double LineBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,LineBuffer,INDICATOR_DATA);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime& time[],
const double& open[],
const double& high[],
const double& low[],
const double& close[],
const long& tick_volume[],
const long& volume[],
const int& spread[])
{
//--- Get the number of bars available for the current symbol and chart period
int bars=Bars(Symbol(),0);
Print("Bars = ",bars,", rates_total = ",rates_total,", prev_calculated = ",prev_calculated);
Print("time[0] = ",time[0]," time[rates_total-1] = ",time[rates_total-1]);
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
Xem thêm
Chạy Chương trình, Sự kiện Thiết bị Đầu cuối Khách hàng, Làm việc với Sự kiện