Hôm nay, tôi sẽ hướng dẫn bạn các kiến thức cơ bản về viết bot giao dịch forex trên nền tảng MetaTrader 5 (MT5).
Kiến thức cơ bản về lập trình viết bot MT5
MT5 sử dụng ngôn ngữ lập trình MQL5 (MetaQuotes Language 5) để phát triển bot giao dịch tự động (còn gọi là Expert Advisors). Dưới đây là các kiến thức cơ bản cần biết:
1. Cài đặt môi trường phát triển
- Tải và cài đặt MT5
- Sử dụng MetaEditor (tích hợp sẵn trong MT5) để viết code
- Quen thuộc với các thư viện MQL5
2. Cấu trúc cơ bản của một EA (Expert Advisor)
- Hàm OnInit(): Khởi tạo EA
- Hàm OnDeinit(): Dọn dẹp khi EA dừng
- Hàm OnTick(): Thực thi mỗi khi có tick mới (biến động giá)
3. Các kiến thức quan trọng khác
- Làm việc với biến và dữ liệu
- Xử lý các lệnh giao dịch
- Quản lý rủi ro và vốn
- Tiếp cận dữ liệu thị trường (giá, khối lượng, chỉ báo)
Ví dụ về bot giao dịch đơn giản
//+------------------------------------------------------------------+
//| SimpleForexTrader.mq5 |
//| Bot Giao Dịch Forex Đơn Giản |
//+------------------------------------------------------------------+
#property copyright "Forex Bot Example"
#property link ""
#property version "1.00"
#property strict
// Định nghĩa các tham số đầu vào
input double LotSize = 0.01; // Khối lượng giao dịch
input int StopLoss = 100; // Điểm dừng lỗ (tính bằng điểm)
input int TakeProfit = 200; // Điểm chốt lời (tính bằng điểm)
input int MAPeriod1 = 20; // Chu kỳ đường MA nhanh
input int MAPeriod2 = 50; // Chu kỳ đường MA chậm
// Định nghĩa các handle cho chỉ báo
int ma_handle_fast;
int ma_handle_slow;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Khởi tạo các chỉ báo
ma_handle_fast = iMA(_Symbol, PERIOD_CURRENT, MAPeriod1, 0, MODE_SMA, PRICE_CLOSE);
ma_handle_slow = iMA(_Symbol, PERIOD_CURRENT, MAPeriod2, 0, MODE_SMA, PRICE_CLOSE);
if(ma_handle_fast == INVALID_HANDLE || ma_handle_slow == INVALID_HANDLE)
{
Print("Lỗi khi khởi tạo chỉ báo MA: ", GetLastError());
return(INIT_FAILED);
}
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Giải phóng các handle
IndicatorRelease(ma_handle_fast);
IndicatorRelease(ma_handle_slow);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Kiểm tra xem đã có đủ dữ liệu cho các chỉ báo chưa
if(BarsCalculated(ma_handle_fast) < 2 || BarsCalculated(ma_handle_slow) < 2)
return;
// Mảng lưu giá trị của các đường MA
double ma_fast_values[];
double ma_slow_values[];
// Thiết lập kích thước mảng và sắp xếp
ArraySetAsSeries(ma_fast_values, true);
ArraySetAsSeries(ma_slow_values, true);
// Lấy giá trị của các chỉ báo
if(CopyBuffer(ma_handle_fast, 0, 0, 3, ma_fast_values) <= 0 ||
CopyBuffer(ma_handle_slow, 0, 0, 3, ma_slow_values) <= 0)
{
Print("Lỗi khi sao chép dữ liệu chỉ báo: ", GetLastError());
return;
}
// Kiểm tra điều kiện giao nhau của các đường MA
bool buy_signal = (ma_fast_values[1] <= ma_slow_values[1]) && (ma_fast_values[0] > ma_slow_values[0]);
bool sell_signal = (ma_fast_values[1] >= ma_slow_values[1]) && (ma_fast_values[0] < ma_slow_values[0]);
// Kiểm tra xem đã có vị thế mở hay chưa
if(PositionsTotal() == 0)
{
// Nếu có tín hiệu mua
if(buy_signal)
{
OpenBuyOrder();
}
// Nếu có tín hiệu bán
else if(sell_signal)
{
OpenSellOrder();
}
}
}
//+------------------------------------------------------------------+
//| Mở lệnh mua |
//+------------------------------------------------------------------+
void OpenBuyOrder()
{
double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double sl = price - StopLoss * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
double tp = price + TakeProfit * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
MqlTradeRequest trade_request;
MqlTradeResult trade_result;
ZeroMemory(trade_request);
trade_request.action = TRADE_ACTION_DEAL;
trade_request.symbol = _Symbol;
trade_request.volume = LotSize;
trade_request.type = ORDER_TYPE_BUY;
trade_request.price = price;
trade_request.sl = sl;
trade_request.tp = tp;
trade_request.deviation = 5;
trade_request.type_filling = ORDER_FILLING_FOK;
trade_request.magic = 123456; // Mã định danh cho EA
if(!OrderSend(trade_request, trade_result))
Print("Lỗi mở lệnh mua: ", GetLastError());
else
Print("Lệnh mua đã được mở: ", trade_result.order);
}
//+------------------------------------------------------------------+
//| Mở lệnh bán |
//+------------------------------------------------------------------+
void OpenSellOrder()
{
double price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double sl = price + StopLoss * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
double tp = price - TakeProfit * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
MqlTradeRequest trade_request;
MqlTradeResult trade_result;
ZeroMemory(trade_request);
trade_request.action = TRADE_ACTION_DEAL;
trade_request.symbol = _Symbol;
trade_request.volume = LotSize;
trade_request.type = ORDER_TYPE_SELL;
trade_request.price = price;
trade_request.sl = sl;
trade_request.tp = tp;
trade_request.deviation = 5;
trade_request.type_filling = ORDER_FILLING_FOK;
trade_request.magic = 123456; // Mã định danh cho EA
if(!OrderSend(trade_request, trade_result))
Print("Lỗi mở lệnh bán: ", GetLastError());
else
Print("Lệnh bán đã được mở: ", trade_result.order);
}
Giải thích các luồng của bot
Bot trên hoạt động theo một chiến lược giao dịch đơn giản dựa trên giao cắt của 2 đường trung bình động (Moving Average):
- Luồng khởi tạo (OnInit):
- Đăng ký và khởi tạo các chỉ báo (2 đường MA)
- Kiểm tra xem các chỉ báo có được khởi tạo thành công không
- Luồng xử lý dữ liệu (OnTick):
- Được gọi mỗi khi có biến động giá (tick)
- Lấy dữ liệu của các đường MA
- Kiểm tra điều kiện giao cắt (tín hiệu giao dịch)
- Kiểm tra các vị thế hiện tại
- Thực hiện mở lệnh nếu có tín hiệu và chưa có vị thế nào đang mở
- Luồng kết thúc (OnDeinit):
- Giải phóng tài nguyên (các handle chỉ báo)
- Dọn dẹp khi EA dừng hoạt động
- Luồng giao dịch:
- Hàm OpenBuyOrder(): Mở lệnh mua với stop loss và take profit
- Hàm OpenSellOrder(): Mở lệnh bán với stop loss và take profit
Cách test bot
- Test trên dữ liệu lịch sử (Backtesting):
- Mở MT5 > Nhấn F6 hoặc Menu > View > Strategy Tester
- Chọn EA cần test
- Cài đặt các tham số (cặp tiền, khung thời gian, khoảng thời gian test)
- Chọn mô hình test (thường là "Every tick" cho độ chính xác cao nhất)
- Nhấn "Start" để bắt đầu test
- Tối ưu hóa tham số:
- Trong Strategy Tester, nhấn vào tab "Optimization"
- Thiết lập các tham số cần tối ưu hóa
- Chọn tiêu chí tối ưu (lợi nhuận, tỉ lệ thắng/thua, v.v.)
- Chạy quá trình tối ưu hóa
- Test trên tài khoản demo:
- Biên dịch EA và đặt vào thư mục Experts
- Mở biểu đồ của cặp tiền bạn muốn giao dịch
- Kéo EA từ Navigator vào biểu đồ
- Cài đặt các tham số và nhấn "OK"
- Kích hoạt Auto Trading bằng cách nhấn vào nút với biểu tượng "đèn giao thông" trên thanh công cụ
- Giám sát và phân tích:
- Theo dõi nhật ký giao dịch trong tab "Experts"
- Theo dõi kết quả trong tab "Toolbox > Trade"
- Phân tích hiệu suất EA và điều chỉnh nếu cần
💡
Lời khuyên khi phát triển bot
- Luôn bắt đầu với chiến lược đơn giản và cải thiện dần
- Test kỹ trên dữ liệu lịch sử trước khi chạy thực tế
- Luôn sử dụng quản lý vốn và rủi ro thích hợp
- Đừng quá tin vào kết quả backtesting, thị trường luôn biến động
- Bắt đầu với tài khoản demo, sau đó chuyển sang tài khoản thật với khối lượng nhỏ