Sửa đổi lệnh chờ
MetaTrader 5 cho phép bạn sửa đổi một số thuộc tính của lệnh chờ, bao gồm giá kích hoạt, mức bảo vệ và ngày hết hạn. Các thuộc tính chính như loại lệnh hoặc khối lượng không thể thay đổi. Trong những trường hợp như vậy, bạn nên xóa lệnh và thay thế bằng một lệnh khác. Trường hợp duy nhất mà loại lệnh có thể được thay đổi bởi chính máy chủ là khi lệnh dừng giới hạn được kích hoạt, lúc đó nó sẽ chuyển thành lệnh giới hạn tương ứng.
Việc sửa đổi lệnh theo chương trình được thực hiện bằng thao tác TRADE_ACTION_MODIFY
: hằng số này cần được ghi vào trường action
của cấu trúc MqlTradeRequest
trước khi gửi đến máy chủ bằng hàm OrderSend
hoặc OrderSendAsync
. Vé của lệnh được sửa đổi được chỉ định trong trường order
. Khi xem xét action
và order
, danh sách đầy đủ các trường bắt buộc cho thao tác này bao gồm:
action
order
price
type_time
(giá trị mặc định 0 tương ứng vớiORDER_TIME_GTC
)expiration
(mặc định 0, không quan trọng đối vớiORDER_TIME_GTC
)type_filling
(mặc định 0 tương ứng vớiORDER_FILLING_FOK
)stoplimit
(chỉ dành cho các lệnh loạiORDER_TYPE_BUY_STOP_LIMIT
vàORDER_TYPE_SELL_STOP_LIMIT
)
Các trường tùy chọn:
sl
tp
Nếu các mức bảo vệ đã được thiết lập cho lệnh, chúng nên được chỉ định để có thể lưu lại. Giá trị bằng 0 biểu thị việc xóa Stop Loss
và/hoặc Take Profit
.
Trong cấu trúc MqlTradeRequestSync
(MqlTradeSync.mqh
), việc thực hiện sửa đổi lệnh được đặt trong phương thức modify
.
struct MqlTradeRequestSync : public MqlTradeRequest
{
...
bool modify(const ulong ticket,
const double p, const double stop = 0, const double take = 0,
ENUM_ORDER_TYPE_TIME duration = ORDER_TIME_GTC, datetime until = 0,
const double origin = 0)
{
if(!OrderSelect(ticket)) return false;
action = TRADE_ACTION_MODIFY;
order = ticket;
// các trường sau cần thiết cho việc kiểm tra trong các hàm con
type = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
symbol = OrderGetString(ORDER_SYMBOL);
volume = OrderGetDouble(ORDER_VOLUME_CURRENT);
if(!setVolumePrices(volume, p, stop, take, origin)) return false;
if(!setExpiration(duration, until)) return false;
ZeroMemory(result);
return OrderSend(this, result);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Việc thực thi yêu cầu thực tế được thực hiện trong phương thức completed
, trong nhánh chuyên dụng của toán tử if
.
bool completed()
{
...
else if(action == TRADE_ACTION_MODIFY)
{
result.order = order;
result.bid = sl;
result.ask = tp;
result.price = price;
result.volume = stoplimit;
return result.modified(timeout);
}
...
}
2
3
4
5
6
7
8
9
10
11
12
13
14
Đối với cấu trúc MqlTradeResultSync
để biết các giá trị mới của thuộc tính của lệnh đã chỉnh sửa và có thể so sánh chúng với kết quả, chúng ta ghi chúng vào các trường trống (chúng không được máy chủ điền trong loại yêu cầu này). Tiếp theo trong phương thức modified
, cấu trúc kết quả chờ đợi việc áp dụng sửa đổi.
struct MqlTradeResultSync : public MqlTradeResult
{
...
bool modified(const ulong msc = 1000)
{
if(retcode != TRADE_RETCODE_DONE && retcode != TRADE_RETCODE_PLACED)
{
return false;
}
if(!wait(orderModified, msc))
{
Print("Order not found in environment: #" + (string)order);
return false;
}
return true;
}
static bool orderModified(MqlTradeResultSync &ref)
{
if(!(OrderSelect(ref.order) || HistoryOrderSelect(ref.order)))
{
Print("OrderSelect failed: #=" + (string)ref.order);
return false;
}
return TU::Equal(ref.bid, OrderGetDouble(ORDER_SL))
&& TU::Equal(ref.ask, OrderGetDouble(ORDER_TP))
&& TU::Equal(ref.price, OrderGetDouble(ORDER_PRICE_OPEN))
&& TU::Equal(ref.volume, OrderGetDouble(ORDER_PRICE_STOPLIMIT));
}
}
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
Ở đây, chúng ta thấy cách các thuộc tính của lệnh được đọc bằng hàm OrderGetDouble
và so sánh với các giá trị đã chỉ định. Tất cả điều này diễn ra theo quy trình quen thuộc, trong một vòng lặp bên trong hàm wait
, trong khoảng thời gian chờ nhất định của msc
(mặc định là 1000 mili giây).
Ví dụ, hãy sử dụng Expert Advisor PendingOrderModify.mq5
, trong khi kế thừa một số đoạn mã từ PendingOrderSend.mq5
. Đặc biệt, một tập hợp các tham số đầu vào và hàm PlaceOrder
để tạo lệnh mới. Nó được sử dụng khi khởi động lần đầu nếu không có lệnh nào cho tổ hợp ký hiệu và số Magic
đã cho, do đó đảm bảo rằng Expert Advisor có thứ gì đó để sửa đổi.
Cần một hàm mới để tìm lệnh phù hợp: GetMyOrder
. Nó rất giống với hàm GetMyPosition
, được sử dụng trong ví dụ với theo dõi vị thế (TrailingStop.mq5
) để tìm vị thế phù hợp. Mục đích của các hàm API MQL5 tích hợp được sử dụng bên trong GetMyOrder
nhìn chung nên rõ ràng từ tên của chúng, và mô tả kỹ thuật sẽ được trình bày trong các phần riêng biệt.
ulong GetMyOrder(const string name, const ulong magic)
{
for(int i = 0; i < OrdersTotal(); ++i)
{
ulong t = OrderGetTicket(i);
if(OrderGetInteger(ORDER_MAGIC) == magic
&& OrderGetString(ORDER_SYMBOL) == name)
{
return t;
}
}
return 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
Tham số đầu vào Distance2SLTP
giờ đây không còn. Thay vào đó, Expert Advisor mới sẽ tự động tính toán phạm vi giá hàng ngày và đặt các mức bảo vệ ở khoảng cách bằng một nửa phạm vi này. Vào đầu mỗi ngày, phạm vi và các mức mới trong các trường sl
và tp
sẽ được tính toán lại. Các yêu cầu sửa đổi lệnh sẽ được tạo dựa trên các giá trị mới.
Những lệnh chờ kích hoạt và chuyển thành vị thế sẽ được đóng khi đạt Stop Loss
hoặc Take Profit
. Thiết bị đầu cuối có thể thông báo cho chương trình MQL về việc kích hoạt các lệnh chờ và đóng các vị thế nếu bạn mô tả các trình xử lý sự kiện giao dịch trong đó. Điều này sẽ cho phép, ví dụ, tránh tạo lệnh mới nếu có vị thế đang mở. Tuy nhiên, chiến lược hiện tại cũng có thể được sử dụng. Vì vậy, chúng ta sẽ xử lý các sự kiện sau.
Logic chính của Expert Advisor được triển khai trong trình xử lý OnTick
.
void OnTick()
{
static datetime lastDay = 0;
static const uint DAYLONG = 60 * 60 * 24; // số giây trong một ngày
// loại bỏ phần "phân số", tức là thời gian
if(TimeTradeServer() / DAYLONG * DAYLONG == lastDay) return;
...
}
2
3
4
5
6
7
8
Hai dòng ở đầu hàm đảm bảo rằng thuật toán chạy một lần vào đầu mỗi ngày. Để làm điều này, chúng ta tính toán ngày hiện tại không có thời gian và so sánh nó với giá trị của biến lastDay
chứa ngày thành công cuối cùng. Tình trạng thành công hay lỗi tất nhiên trở nên rõ ràng vào cuối hàm, vì vậy chúng ta sẽ quay lại vấn đề này sau.
Tiếp theo, phạm vi giá cho ngày trước đó được tính toán.
const string symbol = StringLen(Symbol) == 0 ? _Symbol : Symbol;
const double range = iHigh(symbol, PERIOD_D1, 1) - iLow(symbol, PERIOD_D1, 1);
Print("Autodetected daily range: ", (float)range);
...
2
3
4
Tùy thuộc vào việc có lệnh hay không trong hàm GetMyOrder
, chúng ta sẽ tạo một lệnh mới qua PlaceOrder
hoặc chỉnh sửa lệnh hiện có bằng ModifyOrder
.
uint retcode = 0;
ulong ticket = GetMyOrder(symbol, Magic);
if(!ticket)
{
retcode = PlaceOrder((ENUM_ORDER_TYPE)Type, symbol, Volume,
range, Expiration, Until, Magic);
}
else
{
retcode = ModifyOrder(ticket, range, Expiration, Until);
}
...
2
3
4
5
6
7
8
9
10
11
12
Cả hai hàm, PlaceOrder
và ModifyOrder
, hoạt động dựa trên các tham số đầu vào của Expert Advisor và phạm vi giá tìm được. Chúng trả về trạng thái của yêu cầu, mà chúng ta sẽ cần phân tích để quyết định hành động nào sẽ thực hiện:
- Cập nhật biến
lastDay
nếu yêu cầu thành công (lệnh đã được cập nhật và Expert Advisor ngủ cho đến đầu ngày tiếp theo) - Giữ ngày cũ trong
lastDay
trong một thời gian để thử lại ở các lần tick tiếp theo nếu có vấn đề tạm thời (ví dụ, phiên giao dịch chưa bắt đầu) - Dừng Expert Advisor nếu phát hiện vấn đề nghiêm trọng (ví dụ, loại lệnh hoặc hướng giao dịch đã chọn không được phép trên ký hiệu)
...
if(/* phân tích retcode */)
{
lastDay = TimeTradeServer() / DAYLONG * DAYLONG;
}
}
2
3
4
5
6
Trong phần Đóng vị thế: toàn bộ và từng phần, chúng ta đã sử dụng một phân tích đơn giản hóa với macro IS_TANGIBLE cho câu trả lời theo dạng "có" và "không" để chỉ ra có lỗi hay không. Rõ ràng, cách tiếp cận này cần được cải thiện, và chúng ta sẽ quay lại vấn đề này sớm. Hiện tại, chúng ta sẽ tập trung vào chức năng chính của Expert Advisor.
Mã nguồn của hàm PlaceOrder
hầu như không thay đổi so với ví dụ trước. ModifyOrder
được hiển thị dưới đây.
Hãy nhớ rằng chúng ta đã xác định vị trí của các lệnh dựa trên phạm vi hàng ngày, áp dụng bảng hệ số. Nguyên tắc không thay đổi, tuy nhiên, vì giờ đây chúng ta có hai hàm làm việc với lệnh, PlaceOrder
và ModifyOrder
, bảng Coefficients
được đặt trong ngữ cảnh toàn cục. Chúng ta sẽ không lặp lại nó ở đây và sẽ đi thẳng đến hàm ModifyOrder
.
uint ModifyOrder(const ulong ticket, const double range,
ENUM_ORDER_TYPE_TIME expiration, datetime until)
{
// giá trị mặc định
const string symbol = OrderGetString(ORDER_SYMBOL);
const double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
...
}
2
3
4
5
6
7
8
Các mức giá được tính toán tùy thuộc vào loại lệnh và phạm vi được truyền vào.
const ENUM_ORDER_TYPE type = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
const double price = TU::GetCurrentPrice(type, symbol) + range * Coefficients[type];
// origin chỉ được điền cho các lệnh *_STOP_LIMIT
const bool stopLimit =
type == ORDER_TYPE_BUY_STOP_LIMIT ||
type == ORDER_TYPE_SELL_STOP_LIMIT;
const double origin = stopLimit ? TU::GetCurrentPrice(type, symbol) : 0;
TU::TradeDirection dir(type);
const int sltp = (int)(range / 2 / point);
const double stop = sltp == 0 ? 0 :
dir.negative(stopLimit ? origin : price, sltp * point);
const double take = sltp == 0 ? 0 :
dir.positive(stopLimit ? origin : price, sltp * point);
...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Sau khi tính toán tất cả các giá trị, chúng ta tạo một đối tượng của cấu trúc MqlTradeRequestSync
và thực thi yêu cầu.
MqlTradeRequestSync request(symbol);
ResetLastError();
// truyền dữ liệu cho các trường, gửi lệnh và chờ kết quả
if(request.modify(ticket, price, stop, take, expiration, until, origin)
&& request.completed())
{
Print("OK order modified: #=", ticket);
}
Print(TU::StringOf(request));
Print(TU::StringOf(request.result));
return request.result.retcode;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
Để phân tích retcode
mà chúng ta phải thực hiện trong khối gọi bên trong OnTick
, một cơ chế mới đã được phát triển bổ sung tệp TradeRetcode.mqh
. Tất cả mã trả về của máy chủ được chia thành nhiều nhóm "mức độ nghiêm trọng", được mô tả bởi các phần tử của liệt kê TRADE_RETCODE_SEVERITY
.
enum TRADE_RETCODE_SEVERITY
{
SEVERITY_UNDEFINED, // điều gì đó không chuẩn - chỉ xuất ra nhật ký
SEVERITY_NORMAL, // hoạt động bình thường
SEVERITY_RETRY, // thử cập nhật môi trường/giá lại (có thể nhiều lần)
SEVERITY_TRY_LATER, // cần đợi và thử lại
SEVERITY_REJECT, // yêu cầu bị từ chối, có lẽ(!) bạn có thể thử lại
//
SEVERITY_INVALID, // cần sửa yêu cầu
SEVERITY_LIMITS, // cần kiểm tra giới hạn và sửa yêu cầu
SEVERITY_PERMISSIONS, // yêu cầu thông báo người dùng và thay đổi cài đặt chương trình/terminal
SEVERITY_ERROR, // dừng, xuất thông tin ra nhật ký và cho người dùng
};
2
3
4
5
6
7
8
9
10
11
12
13
Nói một cách đơn giản, nửa đầu tương ứng với các lỗi có thể khắc phục: thường chỉ cần đợi một lúc và thử lại yêu cầu. Nửa sau yêu cầu bạn thay đổi nội dung yêu cầu, kiểm tra cài đặt tài khoản hoặc ký hiệu, quyền cho chương trình, và trong trường hợp xấu nhất, dừng giao dịch. Những ai muốn có thể vẽ một đường phân cách có điều kiện không phải sau SEVERITY_REJECT
, như hiện tại được đánh dấu trực quan, mà trước nó.
Việc chia tất cả mã thành các nhóm được thực hiện bởi hàm TradeCodeSeverity
(được đưa ra với các viết tắt).
TRADE_RETCODE_SEVERITY TradeCodeSeverity(const uint retcode)
{
static const TRADE_RETCODE_SEVERITY severities[] =
{
...
SEVERITY_RETRY, // REQUOTE (10004)
SEVERITY_UNDEFINED,
SEVERITY_REJECT, // REJECT (10006)
SEVERITY_NORMAL, // CANCEL (10007)
SEVERITY_NORMAL, // PLACED (10008)
SEVERITY_NORMAL, // DONE (10009)
SEVERITY_NORMAL, // DONE_PARTIAL (10010)
SEVERITY_ERROR, // ERROR (10011)
SEVERITY_RETRY, // TIMEOUT (10012)
SEVERITY_INVALID, // INVALID (10013)
SEVERITY_INVALID, // INVALID_VOLUME (10014)
SEVERITY_INVALID, // INVALID_PRICE (10015)
SEVERITY_INVALID, // INVALID_STOPS (10016)
SEVERITY_PERMISSIONS, // TRADE_DISABLED (10017)
SEVERITY_TRY_LATER, // MARKET_CLOSED (10018)
SEVERITY_LIMITS, // NO_MONEY (10019)
...
};
if(retcode == 0) return SEVERITY_NORMAL;
if(retcode < 10000 || retcode > HEDGE_PROHIBITED) return SEVERITY_UNDEFINED;
return severities[retcode - 10000];
}
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
Nhờ chức năng này, trình xử lý OnTick
có thể được bổ sung với xử lý lỗi "thông minh". Một biến tĩnh RetryFrequency
lưu trữ tần suất mà chương trình sẽ cố gắng lặp lại yêu cầu trong trường hợp xảy ra lỗi không nghiêm trọng. Lần cuối cùng thử nghiệm như vậy được thực hiện được lưu trong biến RetryRecordTime
.
void OnTick()
{
...
const static int DEFAULT_RETRY_TIMEOUT = 1; // giây
static int RetryFrequency = DEFAULT_RETRY_TIMEOUT;
static datetime RetryRecordTime = 0;
if(TimeTradeServer() - RetryRecordTime < RetryFrequency) return;
...
}
2
3
4
5
6
7
8
9
Khi hàm PlaceOrder
hoặc ModifyOrder
trả về giá trị của retcode
, chúng ta biết mức độ nghiêm trọng của nó và dựa trên mức độ nghiêm trọng, chúng ta chọn một trong ba lựa chọn: dừng Expert Advisor, chờ hết thời gian, hoặc hoạt động bình thường (đánh dấu việc sửa đổi lệnh thành công bằng ngày hiện tại trong lastDay
).
const TRADE_RETCODE_SEVERITY severity = TradeCodeSeverity(retcode);
if(severity >= SEVERITY_INVALID)
{
Alert("Can't place/modify pending order, EA is stopped");
RetryFrequency = INT_MAX;
}
else if(severity >= SEVERITY_RETRY)
{
RetryFrequency += (int)sqrt(RetryFrequency + 1);
RetryRecordTime = TimeTradeServer();
PrintFormat("Problems detected, waiting for better conditions "
"(timeout enlarged to %d seconds)",
RetryFrequency);
}
else
{
if(RetryFrequency > DEFAULT_RETRY_TIMEOUT)
{
RetryFrequency = DEFAULT_RETRY_TIMEOUT;
PrintFormat("Timeout restored to %d second", RetryFrequency);
}
lastDay = TimeTradeServer() / DAYLONG * DAYLONG;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Trong trường hợp xảy ra các vấn đề lặp lại được phân loại là có thể giải quyết, thời gian chờ RetryFrequency
tăng dần với mỗi lỗi tiếp theo nhưng được đặt lại về 1 giây khi yêu cầu được xử lý thành công.
Cần lưu ý rằng các phương thức của cấu trúc áp dụng MqlTradeRequestSync
kiểm tra rất nhiều tổ hợp tham số để đảm bảo tính đúng đắn và nếu phát hiện vấn đề, sẽ ngắt quá trình trước khi gọi SendRequest
. Hành vi này được bật theo mặc định, nhưng có thể bị vô hiệu hóa bằng cách định nghĩa một macro RETURN(X) trống trước chỉ thị #include
với MqlTradeSync.mqh
.
#define RETURN(X)
#include <MQL5Book/MqlTradeSync.mqh>
2
Với định nghĩa macro này, các kiểm tra sẽ chỉ in cảnh báo vào nhật ký nhưng sẽ tiếp tục thực thi các phương thức cho đến khi gọi SendRequest
.
Dù trong trường hợp nào, sau khi gọi một trong các phương thức của cấu trúc MqlTradeResultSync
, mã lỗi sẽ được thêm vào retcode
. Điều này sẽ được thực hiện bởi máy chủ hoặc bởi các thuật toán kiểm tra của cấu trúc MqlTradeRequestSync
(ở đây chúng ta tận dụng việc thể hiện MqlTradeResultSync
được bao gồm bên trong MqlTradeRequestSync
). Tôi không cung cấp ở đây mô tả về việc trả về mã lỗi và việc sử dụng macro RETURN trong các phương thức MqlTradeRequestSync
để giữ ngắn gọn. Những ai quan tâm có thể xem mã nguồn đầy đủ trong tệp MqlTradeSync.mqh
.
Hãy chạy Expert Advisor PendingOrderModify.mq5
trong bộ kiểm tra, với chế độ hình ảnh được bật, sử dụng dữ liệu của XAUUSD, H1 (chế độ tất cả tick hoặc tick thực). Với cài đặt mặc định, Expert Advisor sẽ đặt các lệnh loại ORDER_TYPE_BUY_STOP
với lô tối thiểu. Hãy đảm bảo từ nhật ký và lịch sử giao dịch rằng chương trình đặt các lệnh chờ và sửa đổi chúng vào đầu mỗi ngày.
2022.01.03 01:05:00 Autodetected daily range: 14.37
2022.01.03 01:05:00 buy stop 0.01 XAUUSD at 1845.73 sl: 1838.55 tp: 1852.91 (1830.63 / 1831.36)
2022.01.03 01:05:00 OK order placed: #=2
2022.01.03 01:05:00 TRADE_ACTION_PENDING, XAUUSD, ORDER_TYPE_BUY_STOP, V=0.01, ORDER_FILLING_FOK, »
» @ 1845.73, SL=1838.55, TP=1852.91, ORDER_TIME_GTC, M=1234567890
2022.01.03 01:05:00 DONE, #=2, V=0.01, Bid=1830.63, Ask=1831.36, Request executed
2022.01.04 01:05:00 Autodetected daily range: 33.5
2022.01.04 01:05:00 order modified [#2 buy stop 0.01 XAUUSD at 1836.56]
2022.01.04 01:05:00 OK order modified: #=2
2022.01.04 01:05:00 TRADE_ACTION_MODIFY, XAUUSD, ORDER_TYPE_BUY_STOP, V=0.01, ORDER_FILLING_FOK, »
2
3
4
5
6
7
8
9
10
Lệnh có thể được kích hoạt bất cứ lúc nào, sau đó vị thế được đóng sau một khoảng thời gian bởi Stop Loss
hoặc Take Profit
(như trong mã trên).
Trong một số trường hợp, có thể xảy ra tình huống khi vị thế vẫn tồn tại vào đầu ngày tiếp theo, và sau đó một lệnh mới sẽ được tạo thêm vào đó, như trong ảnh chụp màn hình dưới đây.
Expert Advisor với chiến lược giao dịch dựa trên lệnh chờ trong bộ kiểm tra
Lưu ý rằng do chúng ta yêu cầu báo giá của khung thời gian PERIOD_D1
để tính toán phạm vi hàng ngày, bộ kiểm tra hình ảnh mở biểu đồ tương ứng, ngoài biểu đồ làm việc hiện tại. Dịch vụ như vậy không chỉ hoạt động cho các khung thời gian khác với khung làm việc mà còn cho các ký hiệu khác. Điều này sẽ hữu ích, đặc biệt, khi phát triển Expert Advisor đa tiền tệ.
Để kiểm tra cách xử lý lỗi hoạt động, hãy thử vô hiệu hóa giao dịch cho Expert Advisor. Nhật ký sẽ chứa nội dung sau:
Autodetected daily range: 34.48
TRADE_ACTION_PENDING, XAUUSD, ORDER_TYPE_BUY_STOP, V=0.01, ORDER_FILLING_FOK, »
» @ 1975.73, SL=1958.49, TP=1992.97, ORDER_TIME_GTC, M=1234567890
CLIENT_DISABLES_AT, AutoTrading disabled by client
Alert: Can't place/modify pending order, EA is stopped
2
3
4
5
Lỗi này là nghiêm trọng, và Expert Advisor ngừng hoạt động.
Để thể hiện một trong những lỗi nhẹ hơn, chúng ta có thể sử dụng trình xử lý OnTimer
thay vì OnTick
. Sau đó, chạy cùng Expert Advisor trên các ký hiệu mà phiên giao dịch chỉ chiếm một phần trong ngày sẽ định kỳ tạo ra một chuỗi lỗi không nghiêm trọng về thị trường đóng cửa ("Market closed"). Trong trường hợp này, Expert Advisor sẽ tiếp tục cố gắng bắt đầu giao dịch, liên tục tăng thời gian chờ.
Điều này, đặc biệt, dễ kiểm tra trong bộ kiểm tra, cho phép thiết lập các phiên giao dịch tùy ý cho bất kỳ ký hiệu nào. Trên tab Settings
, bên phải danh sách thả xuống Delays
, có một nút mở hộp thoại Trade setup
. Ở đó, bạn nên bật tùy chọn Use your settings
và trên tab Trade
thêm ít nhất một bản ghi vào bảng Non-trading periods
.
Thiết lập các khoảng thời gian không giao dịch trong bộ kiểm tra
Lưu ý rằng các khoảng thời gian không giao dịch được thiết lập ở đây, không phải phiên giao dịch, tức là cài đặt này hoạt động ngược lại so với đặc điểm kỹ thuật của ký hiệu.
Nhiều lỗi tiềm ẩn liên quan đến hạn chế giao dịch có thể được loại bỏ bằng cách phân tích trước môi trường bằng một lớp như Permissions
được trình bày trong phần Hạn chế và quyền cho giao dịch tài khoản.