Hướng dẫn chi tiết về hàm OrderSend() để thực hiện các lệnh giao dịch, từ cơ bản đến nâng cao với ví dụ thực tế.
Hàm OrderSend() là một trong những hàm quan trọng nhất trong MQL5, được sử dụng để gửi các yêu cầu giao dịch đến máy chủ giao dịch. Đây là hàm cốt lõi mà mọi Expert Advisor đều cần sử dụng để mở, đóng hoặc sửa đổi các vị thế giao dịch.
bool OrderSend(
MqlTradeRequest& request, // cấu trúc yêu cầu
MqlTradeResult& result // cấu trúc kết quả
);
Để sử dụng OrderSend(), bạn cần khởi tạo cấu trúc MqlTradeRequest với các thông tin sau:
//+------------------------------------------------------------------+
//| Mở lệnh Buy với Stop Loss và Take Profit |
//+------------------------------------------------------------------+
bool OpenBuyPosition(string symbol, double volume, double sl_points, double tp_points)
{
MqlTradeRequest request;
MqlTradeResult result;
// Reset cấu trúc
ZeroMemory(request);
ZeroMemory(result);
// Lấy thông tin symbol
double ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
int digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
// Tính toán SL và TP
double sl = NormalizeDouble(ask - sl_points * point, digits);
double tp = NormalizeDouble(ask + tp_points * point, digits);
// Thiết lập yêu cầu
request.action = TRADE_ACTION_DEAL; // Giao dịch ngay
request.symbol = symbol; // Symbol
request.volume = volume; // Khối lượng
request.type = ORDER_TYPE_BUY; // Lệnh Buy
request.price = ask; // Giá Ask hiện tại
request.sl = sl; // Stop Loss
request.tp = tp; // Take Profit
request.deviation = 10; // Độ trượt giá cho phép (points)
request.magic = 123456; // Magic number
request.comment = "Buy Order"; // Comment
request.type_filling = ORDER_FILLING_FOK; // Fill or Kill
// Gửi lệnh
if(!OrderSend(request, result))
{
Print("OrderSend error: ", GetLastError());
Print("Result retcode: ", result.retcode);
return false;
}
// Kiểm tra kết quả
if(result.retcode == TRADE_RETCODE_DONE ||
result.retcode == TRADE_RETCODE_PLACED)
{
Print("Buy order opened successfully!");
Print("Order ticket: ", result.order);
Print("Volume: ", result.volume);
Print("Price: ", result.price);
return true;
}
else
{
Print("Order failed! Return code: ", result.retcode);
return false;
}
}
//+------------------------------------------------------------------+
//| Sử dụng trong OnTick() |
//+------------------------------------------------------------------+
void OnTick()
{
static bool position_opened = false;
if(!position_opened)
{
if(OpenBuyPosition(_Symbol, 0.1, 500, 1000))
{
position_opened = true;
}
}
}
//+------------------------------------------------------------------+
//| Mở lệnh Sell với quản lý rủi ro |
//+------------------------------------------------------------------+
bool OpenSellPosition(string symbol, double volume)
{
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
ZeroMemory(result);
double bid = SymbolInfoDouble(symbol, SYMBOL_BID);
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
int digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
// SL và TP tính toán dựa trên ATR
double sl = NormalizeDouble(bid + 500 * point, digits);
double tp = NormalizeDouble(bid - 1000 * point, digits);
request.action = TRADE_ACTION_DEAL;
request.symbol = symbol;
request.volume = volume;
request.type = ORDER_TYPE_SELL;
request.price = bid;
request.sl = sl;
request.tp = tp;
request.deviation = 10;
request.magic = 123456;
request.comment = "Sell Order";
request.type_filling = ORDER_FILLING_FOK;
if(!OrderSend(request, result))
{
Print("OrderSend error: ", GetLastError());
return false;
}
if(result.retcode == TRADE_RETCODE_DONE)
{
Print("Sell order opened at price: ", result.price);
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Đặt lệnh Buy Stop |
//+------------------------------------------------------------------+
bool PlaceBuyStopOrder(string symbol, double volume, double entry_price)
{
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
ZeroMemory(result);
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
int digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
// Tính SL và TP từ entry price
double sl = NormalizeDouble(entry_price - 500 * point, digits);
double tp = NormalizeDouble(entry_price + 1000 * point, digits);
request.action = TRADE_ACTION_PENDING; // Lệnh chờ
request.symbol = symbol;
request.volume = volume;
request.type = ORDER_TYPE_BUY_STOP; // Buy Stop
request.price = NormalizeDouble(entry_price, digits);
request.sl = sl;
request.tp = tp;
request.magic = 123456;
request.comment = "Buy Stop Order";
request.type_time = ORDER_TIME_GTC; // Good Till Cancel
request.type_filling = ORDER_FILLING_RETURN;
if(!OrderSend(request, result))
{
Print("Failed to place Buy Stop: ", GetLastError());
return false;
}
if(result.retcode == TRADE_RETCODE_DONE ||
result.retcode == TRADE_RETCODE_PLACED)
{
Print("Buy Stop placed successfully at: ", entry_price);
Print("Order ticket: ", result.order);
return true;
}
return false;
}
| Mã Lỗi | Tên | Mô Tả | Giải Pháp |
|---|---|---|---|
| 10004 | TRADE_RETCODE_REQUOTE | Giá đã thay đổi | Thử lại với giá mới |
| 10006 | TRADE_RETCODE_REJECT | Yêu cầu bị từ chối | Kiểm tra thông số giao dịch |
| 10013 | TRADE_RETCODE_INVALID_VOLUME | Khối lượng không hợp lệ | Điều chỉnh volume theo bội số lot step |
| 10014 | TRADE_RETCODE_INVALID_PRICE | Giá không hợp lệ | Normalize giá theo digits |
| 10015 | TRADE_RETCODE_INVALID_STOPS | SL/TP không hợp lệ | Kiểm tra SYMBOL_TRADE_STOPS_LEVEL |
//+------------------------------------------------------------------+
//| Kiểm tra điều kiện trước khi OrderSend |
//+------------------------------------------------------------------+
bool CheckTradeConditions(string symbol)
{
// Kiểm tra trading allowed
if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
{
Print("Trading not allowed in terminal");
return false;
}
// Kiểm tra expert advisor allowed
if(!MQLInfoInteger(MQL_TRADE_ALLOWED))
{
Print("EA trading not allowed");
return false;
}
// Kiểm tra symbol trading allowed
if(!SymbolInfoInteger(symbol, SYMBOL_TRADE_MODE))
{
Print("Trading disabled for symbol: ", symbol);
return false;
}
// Kiểm tra đủ margin
double free_margin = AccountInfoDouble(ACCOUNT_MARGIN_FREE);
if(free_margin < 100) // Minimum margin requirement
{
Print("Not enough free margin: ", free_margin);
return false;
}
return true;
}
OrderSend() là hàm nền tảng trong giao dịch tự động với MQL5. Hiểu rõ cách sử dụng đúng hàm này, kết hợp với xử lý lỗi hợp lý và kiểm tra điều kiện kỹ lưỡng sẽ giúp EA của bạn hoạt động ổn định và hiệu quả.
Lưu ý quan trọng: Luôn test EA trên tài khoản demo trước khi sử dụng với tài khoản thật. OrderSend() trực tiếp tác động đến tài khoản giao dịch của bạn.