Lấy danh sách các vị thế
Trong nhiều ví dụ về Expert Advisors, chúng ta đã sử dụng các hàm API MQL5 được thiết kế để phân tích các vị thế giao dịch đang mở. Phần này trình bày mô tả chính thức của chúng.
Điều quan trọng cần lưu ý là các hàm thuộc nhóm này không thể tạo, sửa đổi hoặc xóa vị thế. Như chúng ta đã thấy trước đó, tất cả các hành động như vậy được thực hiện gián tiếp thông qua việc gửi lệnh. Nếu chúng được thực thi thành công, các giao dịch sẽ được thực hiện, kết quả là các vị thế được hình thành.
Một đặc điểm khác là các hàm chỉ áp dụng cho các vị thế trực tuyến. Để khôi phục lịch sử các vị thế, cần phân tích lịch sử giao dịch.
Hàm PositionsTotal
cho phép bạn tìm ra tổng số vị thế đang mở trên tài khoản (cho tất cả các công cụ tài chính).
int PositionsTotal()
Với cách tính toán vị thế theo kiểu netting (ACCOUNT_MARGIN_MODE_RETAIL_NETTING và ACCOUNT_MARGIN_MODE_EXCHANGE), chỉ có thể có một vị thế cho mỗi ký hiệu tại bất kỳ thời điểm nào. Vị thế này có thể là kết quả của một hoặc nhiều giao dịch.
Với cách biểu diễn vị thế độc lập (ACCOUNT_MARGIN_MODE_RETAIL_HEDGING), nhiều vị thế có thể được mở đồng thời cho mỗi ký hiệu, bao gồm cả các vị thế đa hướng. Mỗi giao dịch tham gia thị trường tạo ra một vị thế riêng biệt, vì vậy việc thực thi từng bước một phần của một lệnh có thể tạo ra nhiều vị thế.
Hàm PositionGetSymbol
trả về ký hiệu của một vị thế theo số thứ tự của nó.
string PositionGetSymbol(int index)
Chỉ số phải nằm trong khoảng từ 0 đến N-1, trong đó N là giá trị nhận được từ lời gọi trước của PositionsTotal
. Thứ tự các vị thế không được quy định.
Nếu không tìm thấy vị thế, một chuỗi rỗng sẽ được trả về, và mã lỗi sẽ có sẵn trong _LastError
.
Ví dụ về việc sử dụng hai hàm này đã được cung cấp trong một số Expert Advisors thử nghiệm (TrailingStop.mq5, TradeCloseBy.mq5, và các ví dụ khác) trong các hàm có tên GetMyPosition/GetMyPositions
.
Một vị thế đang mở được đặc trưng bởi một vé duy nhất, là số phân biệt nó với các vị thế khác, nhưng có thể thay đổi trong suốt vòng đời của nó trong một số trường hợp, chẳng hạn như đảo ngược vị thế trong chế độ netting bởi một giao dịch, hoặc do các hoạt động dịch vụ trên máy chủ (mở lại để tính phí swap, thanh toán bù trừ).
Để lấy vé của một vị thế theo số thứ tự của nó, chúng ta sử dụng hàm PositionGetTicket
.
ulong PositionGetTicket(int index)
Ngoài ra, hàm này đánh dấu một vị thế trong môi trường giao dịch của terminal, sau đó cho phép bạn đọc các thuộc tính của nó bằng một nhóm các hàm đặc biệt PositionGet. Nói cách khác, tương tự như với lệnh, terminal duy trì một bộ nhớ đệm nội bộ cho mỗi chương trình MQL để lưu trữ các thuộc tính của một vị thế. Để đánh dấu một vị thế, ngoài PositionGetTicket
, còn có hai hàm: PositionSelect
và PositionSelectByTicket
mà chúng ta sẽ thảo luận dưới đây.
Trong trường hợp xảy ra lỗi, hàm PositionGetTicket
sẽ trả về 0.
Vé không nên nhầm lẫn với định danh được gán cho mỗi vị thế và không bao giờ thay đổi. Chính các định danh được sử dụng để liên kết các vị thế với lệnh và giao dịch. Chúng ta sẽ nói về điều này sau một chút.
Vé cần thiết để thực hiện các yêu cầu liên quan đến vị thế: vé được chỉ định trong các trường
position
vàposition_by
của cấu trúcMqlTradeRequest
. Ngoài ra, bằng cách lưu vé vào một biến, chương trình sau đó có thể chọn một vị thế cụ thể bằng hàmPositionSelectByTicket
(xem dưới đây) và làm việc với nó mà không cần liệt kê lại các vị thế trong vòng lặp.
Khi một vị thế bị đảo ngược trên tài khoản netting, POSITION_TICKET được thay đổi thành vé của lệnh đã khởi tạo hoạt động này. Tuy nhiên, vị thế như vậy vẫn có thể được theo dõi bằng ID. Việc đảo ngược vị thế không được hỗ trợ trong chế độ hedging.
bool PositionSelect(const string symbol)
Hàm này chọn một vị thế đang mở theo tên của công cụ tài chính.
Với cách biểu diễn vị thế độc lập (ACCOUNT_MARGIN_MODE_RETAIL_HEDGING), có thể có nhiều vị thế đang mở cho mỗi ký hiệu cùng một lúc. Trong trường hợp này, PositionSelect
sẽ chọn vị thế có vé nhỏ nhất.
Kết quả trả về báo hiệu việc thực thi hàm thành công (true
) hay không thành công (false
).
Việc các thuộc tính của vị thế được chọn được lưu trong bộ nhớ đệm có nghĩa là vị thế đó có thể không còn tồn tại nữa, hoặc nó có thể đã thay đổi nếu chương trình đọc các thuộc tính của nó sau một khoảng thời gian. Nên gọi hàm PositionSelect
ngay trước khi truy cập dữ liệu.
bool PositionSelectByTicket(ulong ticket)
Hàm này chọn một vị thế đang mở để làm việc tiếp theo dựa trên vé được chỉ định.
Chúng ta sẽ xem xét các ví dụ sử dụng các hàm này sau khi nghiên cứu thuộc tính và các hàm liên quan PositionGet.
Khi xây dựng các thuật toán sử dụng PositionsTotal
, OrdersTotal
, và các hàm tương tự, cần tính đến các nguyên tắc không đồng bộ của hoạt động terminal. Chúng ta đã đề cập đến chủ đề này khi viết các lớp MqlTradeSync.mqh
và triển khai việc chờ kết quả thực thi từ các yêu cầu giao dịch. Tuy nhiên, việc chờ đợi này không phải lúc nào cũng có thể thực hiện ở phía máy khách. Đặc biệt, nếu chúng ta đặt một lệnh chờ, thì việc chuyển đổi của nó thành lệnh thị trường và thực thi tiếp theo sẽ diễn ra trên máy chủ. Tại thời điểm này, lệnh có thể không còn được liệt kê trong số các lệnh đang hoạt động (OrdersTotal
sẽ trả về 0), nhưng vị thế vẫn chưa được hiển thị (PositionsTotal
cũng bằng 0). Do đó, một chương trình MQL có điều kiện đặt lệnh khi không có vị thế có thể vô tình khởi tạo một lệnh mới, dẫn đến việc vị thế cuối cùng sẽ tăng gấp đôi.
Để giải quyết vấn đề này, một chương trình MQL phải phân tích môi trường giao dịch sâu hơn là chỉ kiểm tra số lượng lệnh và vị thế cùng một lúc. Ví dụ, bạn có thể giữ một bản chụp trạng thái đúng cuối cùng của môi trường giao dịch và không cho phép bất kỳ thực thể nào biến mất mà không có xác nhận nào đó. Chỉ sau đó, một lệnh mới có thể được hình thành. Do đó, một lệnh chỉ có thể bị xóa cùng với sự thay đổi vị thế (tạo, đóng) hoặc được chuyển vào lịch sử với trạng thái hủy. Một trong những giải pháp khả thi được đề xuất dưới dạng lớp TradeGuard
trong tệp TradeGuard.mqh
. Cuốn sách cũng bao gồm kịch bản demo TradeGuardExample.mq5
mà bạn có thể nghiên cứu thêm.