I am creating a trading EA based on the martingale method. However, the following order is not being calculated according to martingale to offset the loss from the previous order. I would greatly appreciate your help, as there seems to be an error in my EA. Thanks !
//+------------------------------------------------------------------+//| CustomSellSignal.mq5 |//| Tên của bạn |//| Công ty của bạn |//+------------------------------------------------------------------+#property copyright"Tên của bạn"#property link"Trang web của bạn"#property version"1.02"#property strict// Tham số đầu vàoinputint sma_length = 12; // Chu kỳ của Đường Trung Bình Đơn Giản (SMA)inputint max_bars_before_cancel = 5; // Số lượng nến trước khi hủy lệnhinputdouble martingale_multiplier = 2; // Hệ số martingaleulong last_order_ticket = 0; // Số hiệu của lệnh gần nhất// Khai báo handle của chỉ báo đường trung bìnhint sma_handle;
// Khai báo các biến chứa dữ liệu nếndouble n1_open, n1_close, n1_low, n1_high;
double n2_low, n2_close, n2_open, n2_high;
double n3_low, n3_close, n3_open, n3_high;
double n4_low, n4_close, n4_open, n4_high;
double n5_low, n5_close, n5_open, n5_high;
// Khai báo các biến cho giao dịchdouble entry_level, stop_loss_level, take_profit_level;
bool condition_sell;
// Khai báo yêu cầu và kết quả giao dịchMqlTradeRequest request;
MqlTradeResult result;
// Khai báo mảng để theo dõi các lệnh chờdatetime order_placed_time[];
ulong order_ticket[];
int order_placed_bar_index[];
//+------------------------------------------------------------------+//| Hàm khởi tạo Expert Advisor |//+------------------------------------------------------------------+intOnInit()
{
// Tạo chỉ báo đường trung bình
sma_handle = iMA(NULL, 0, sma_length, 0, MODE_SMA, PRICE_CLOSE);
if (sma_handle == INVALID_HANDLE)
{
Print("Không thể tạo handle cho chỉ báo SMA");
returnINIT_FAILED;
}
// Khởi tạo các mảngArraySetAsSeries(order_placed_time, true);
ArraySetAsSeries(order_ticket, true);
ArraySetAsSeries(order_placed_bar_index, true);
returnINIT_SUCCEEDED;
}
//+------------------------------------------------------------------+//| Hàm hủy Expert Advisor |//+------------------------------------------------------------------+voidOnDeinit(constint reason)
{
// Giải phóng handle của chỉ báo đường trung bìnhIndicatorRelease(sma_handle);
}
// Biến cờ để kiểm tra xem lệnh đã được đặt hay chưabool order_placed = false;
datetime last_time = 0; // Theo dõi thời gian của nến cuối// Khai báo biến toàn cục cho rủi ro và số tiền thua lỗdouble risk_amount = 10.0; // Khởi tạo với giá trị mặc địnhdouble last_loss_amount = 0; // Biến lưu số tiền thua lỗ// Khai báo biến toàn cục để theo dõi số lần lệnh thuaint loss_streak = 0;
// Biến lưu trữ tổng số tiền lỗ trước đódouble total_loss = 0.0; // Khởi tạo với giá trị // Hàm tính toán risk_amountvoid CalculateRiskAmount()
{
// Chọn toàn bộ lịch sửif (HistorySelect(0, TimeCurrent()))
{
int closedOrdersCount = HistoryOrdersTotal();
Print("Số lệnh đã đóng: ", closedOrdersCount);
if (closedOrdersCount > 0)
{
if (HistoryOrderSelect(closedOrdersCount - 1))
{
double last_order_profit = HistoryDealGetDouble(HistoryOrderGetInteger(closedOrdersCount - 0, ORDER_TICKET), DEAL_PROFIT);
Print("Lợi nhuận lệnh gần nhất: ", last_order_profit);
if (last_order_profit < 0)
{
// Lệnh thua
last_loss_amount = MathAbs(last_order_profit);
risk_amount = last_loss_amount * martingale_multiplier; // Áp dụng martingale
loss_streak++; // Tăng số lần thuaPrint("Cập nhật risk_amount: ", risk_amount, " với martingale_multiplier: ", martingale_multiplier);
}
else
{
// Lệnh thắng
risk_amount = 10; // Reset về 10 USD
loss_streak = 0; // Reset số lần thuaPrint("Reset risk_amount về 10");
}
}
}
else
{
Print("Không có lệnh nào đã đóng trong lịch sử.");
}
}
}
//+------------------------------------------------------------------+//| Hàm thực thi lệnh theo từng tick |//+------------------------------------------------------------------+voidOnTick()
{
// Gọi hàm cập nhật risk_amount
CalculateRiskAmount();
// Kiểm tra xem có đủ số lượng nến để tính toán hay khôngint bars = iBars(NULL, 0);
if (bars < sma_length + max_bars_before_cancel + 1)
{
return;
}
// Lấy thời gian của nến hiện tạidatetime current_time = iTime(NULL, 0, 0);
// Kiểm tra xem nến mới đã bắt đầu hay chưaif (current_time != last_time)
{
last_time = current_time;
order_placed = false; // Đặt lại cờ khi bắt đầu nến mới
}
// Lấy dữ liệu của các nến
n1_open = iOpen(NULL, 0, 1);
n1_close = iClose(NULL, 0, 1);
n1_low = iLow(NULL, 0, 1);
n1_high = iHigh(NULL, 0, 1);
n2_low = iLow(NULL, 0, 2);
n2_close = iClose(NULL, 0, 2);
n2_open = iOpen(NULL, 0, 2);
n2_high = iHigh(NULL, 0, 2);
n3_low = iLow(NULL, 0, 3);
n3_close = iClose(NULL, 0, 3);
n3_open = iOpen(NULL, 0, 3);
n3_high = iHigh(NULL, 0, 3);
n4_low = iLow(NULL, 0, 4);
n4_close = iClose(NULL, 0, 4);
n4_open = iOpen(NULL, 0, 4);
n4_high = iHigh(NULL, 0, 4);
n5_low = iLow(NULL, 0, 5);
n5_close = iClose(NULL, 0, 5);
n5_open = iOpen(NULL, 0, 5);
n5_high = iHigh(NULL, 0, 5);
// Tính toán SMAdouble sma_buffer[];
if (CopyBuffer(sma_handle, 0, 0, sma_length + 1, sma_buffer) <= 0)
{
Print("Không thể lấy dữ liệu SMA");
return;
}
double sma_current = sma_buffer[0];
double sma_previous = sma_buffer[1];
bool price_trend_down = sma_current < sma_previous;
// Định nghĩa điều kiện bán
condition_sell = price_trend_down &&
n1_close < n1_open && n1_high < n2_high &&
n2_close > n2_open && n2_high < n3_high &&
n3_close < n3_open &&
n4_close < n4_open;
// Nếu có điều kiện bán và chưa có lệnh nào được đặtif (condition_sell && !order_placed)
{
// Tính toán mức vào lệnh, dừng lỗ và chốt lời
entry_level = (n1_high + n1_low) / 2;
stop_loss_level = n2_high + 2; // Cài đặt mức dừng lỗ ban đầu
take_profit_level = entry_level - (stop_loss_level - entry_level);
// Tính toán khoảng cách dừng lỗdouble stop_loss_distance = MathAbs(stop_loss_level - entry_level);
// Tính khối lượng giao dịchdouble lot_size_calculated = risk_amount / stop_loss_distance / 50; // Đảm bảo lot size được tính toán// Gửi lệnh bán giới hạnZeroMemory(request);
request.action = TRADE_ACTION_PENDING;
request.symbol = Symbol();
request.volume = NormalizeDouble(lot_size_calculated, 2);
request.type = ORDER_TYPE_SELL_LIMIT;
request.price = NormalizeDouble(entry_level, _Digits);
request.sl = NormalizeDouble(stop_loss_level, _Digits);
request.tp = NormalizeDouble(take_profit_level, _Digits);
request.deviation = 3;
request.magic = 0;
request.comment = "Sell Limit Order";
request.type_filling = ORDER_FILLING_FOK;
// Gửi lệnh bán giới hạnif (!OrderSend(request, result))
{
Print("Không thể gửi lệnh bán giới hạn: ", result.retcode);
}
else
{
Print("Lệnh bán giới hạn được gửi thành công. Số hiệu: ", result.order);
order_placed = true; // Đặt cờ đã đặt lệnh// Lưu số hiệu lệnh, thời gian và chỉ số nếnArrayResize(order_ticket, ArraySize(order_ticket) + 1);
ArrayResize(order_placed_time, ArraySize(order_placed_time) + 1);
ArrayResize(order_placed_bar_index, ArraySize(order_placed_bar_index) + 1);
order_ticket[ArraySize(order_ticket) - 1] = result.order;
order_placed_time[ArraySize(order_placed_time) - 1] = current_time;
order_placed_bar_index[ArraySize(order_placed_bar_index) - 1] = iBarShift(NULL, 0, current_time, false);
}
}
// Kiểm tra và hủy các đơn hàng nếu cầnfor (int i = 0; i < ArraySize(order_ticket); i++)
{
if (order_ticket[i] != 0)
{
// Kiểm tra trạng thái của đơn hàngif (OrderSelect(order_ticket[i]))
{
if (OrderGetInteger(ORDER_STATE) == ORDER_STATE_CANCELED)
{
// Đặt lại ticket nếu đơn hàng bị hủy
order_ticket[i] = 0;
order_placed_time[i] = 0;
order_placed_bar_index[i] = 0;
}
elseif (OrderGetInteger(ORDER_STATE) == ORDER_STATE_FILLED)
{
// Nếu lệnh đã được thực hiện, cập nhật last_order_ticket
last_order_ticket = order_ticket[i];
order_placed = false; // Đặt lại cờ khi có lệnh đã được thực hiện
}
}
}
}
}
I am creating a trading EA based on the martingale method. However, the following order is not being calculated according to martingale to offset the loss from the previous order. I would greatly appreciate your help, as there seems to be an error in my EA. Thanks !