Xóa lệnh chờ
Việc xóa một lệnh chờ được thực hiện ở cấp độ chương trình bằng thao tác TRADE_ACTION_REMOVE
: hằng số này cần được gán cho trường action
của cấu trúc MqlTradeRequest
trước khi gọi một trong các phiên bản của hàm OrderSend
. Trường duy nhất cần thiết ngoài action
là order
để chỉ định vé của lệnh cần xóa.
Phương thức remove
trong cấu trúc ứng dụng MqlTradeRequestSync
từ tệp MqlTradeSync.mqh
khá đơn giản.
struct MqlTradeRequestSync : public MqlTradeRequest
{
...
bool remove(const ulong ticket)
{
if(!OrderSelect(ticket)) return false;
action = TRADE_ACTION_REMOVE;
order = ticket;
ZeroMemory(result);
return OrderSend(this, result);
}
}
2
3
4
5
6
7
8
9
10
11
12
Việc kiểm tra thực tế xóa lệnh được thực hiện theo cách truyền thống trong phương thức completed
.
bool completed()
{
...
else if(action == TRADE_ACTION_REMOVE)
{
result.order = order;
return result.removed(timeout);
}
...
}
2
3
4
5
6
7
8
9
10
Việc chờ đợi việc xóa thực sự của lệnh được thực hiện trong phương thức removed
của cấu trúc MqlTradeResultSync
.
struct MqlTradeResultSync : public MqlTradeResult
{
...
bool removed(const ulong msc = 1000)
{
if(retcode != TRADE_RETCODE_DONE)
{
return false;
}
if(!wait(orderRemoved, msc))
{
Print("Order removal timeout: #=" + (string)order);
return false;
}
return true;
}
static bool orderRemoved(MqlTradeResultSync &ref)
{
return !OrderSelect(ref.order) && HistoryOrderSelect(ref.order);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Ví dụ về Expert Advisor (PendingOrderDelete.mq5
) thể hiện việc xóa một lệnh sẽ được xây dựng hầu như hoàn toàn dựa trên PendingOrderSend.mq5
. Điều này là do việc đảm bảo sự tồn tại của một lệnh trước khi xóa sẽ dễ dàng hơn. Do đó, ngay sau khi khởi động, Expert Advisor sẽ tạo một lệnh mới với các tham số đã chỉ định. Sau đó, lệnh sẽ được xóa trong trình xử lý OnDeinit
. Nếu bạn thay đổi các tham số đầu vào của Expert Advisor, ký hiệu hoặc khung thời gian biểu đồ, lệnh cũ cũng sẽ bị xóa và một lệnh mới sẽ được tạo.
Biến toàn cục OwnOrder
đã được thêm vào để lưu trữ vé của lệnh. Nó được điền vào kết quả của lời gọi PlaceOrder
(bản thân hàm này không thay đổi).
ulong OwnOrder = 0;
void OnTimer()
{
// thực thi mã một lần cho các tham số hiện tại
EventKillTimer();
const string symbol = StringLen(Symbol) == 0 ? _Symbol : Symbol;
OwnOrder = PlaceOrder((ENUM_ORDER_TYPE)Type, symbol, Volume,
Distance2SLTP, Expiration, Until, Magic, Comment);
}
2
3
4
5
6
7
8
9
10
11
Đây là hàm xóa đơn giản RemoveOrder
, tạo đối tượng request
và lần lượt gọi các phương thức remove
và completed
cho nó.
void OnDeinit(const int)
{
if(OwnOrder != 0)
{
RemoveOrder(OwnOrder);
}
}
void RemoveOrder(const ulong ticket)
{
MqlTradeRequestSync request;
if(request.remove(ticket) && request.completed())
{
Print("OK order removed");
}
Print(TU::StringOf(request));
Print(TU::StringOf(request.result));
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Nhật ký sau đây hiển thị các mục xuất hiện do việc đặt Expert Advisor trên biểu đồ EURUSD, sau đó ký hiệu được chuyển sang XAUUSD, và sau đó Expert Advisor bị xóa.
(EURUSD,H1) Autodetected daily range: 0.0094
(EURUSD,H1) OK order placed: #=1284920879
(EURUSD,H1) TRADE_ACTION_PENDING, EURUSD, ORDER_TYPE_BUY_STOP, V=0.01, ORDER_FILLING_FOK, »
» @ 1.11011, ORDER_TIME_GTC, M=1234567890
(EURUSD,H1) DONE, #=1284920879, V=0.01, Request executed, Req=1
(EURUSD,H1) OK order removed
(EURUSD,H1) TRADE_ACTION_REMOVE, EURUSD, ORDER_TYPE_BUY, ORDER_FILLING_FOK, #=1284920879
(EURUSD,H1) DONE, #=1284920879, Request executed, Req=2
(XAUUSD,H1) Autodetected daily range: 47.45
(XAUUSD,H1) OK order placed: #=1284921672
(XAUUSD,H1) TRADE_ACTION_PENDING, XAUUSD, ORDER_TYPE_BUY_STOP, V=0.01, ORDER_FILLING_FOK, »
2
3
4
5
6
7
8
9
10
11
Chúng ta sẽ xem xét một ví dụ khác về việc xóa lệnh để thực hiện chiến lược "One Cancel Other" (OCO) trong phần sự kiện OnTrade
.