Hướng dẫn sử dụng while và do-while loops cho điều kiện không xác định trước, retry logic và event handling.
while và do-while là vòng lặp dựa trên điều kiện, chạy cho đến khi điều kiện trở thành false. Hữu ích khi không biết trước số lần lặp.
// Syntax: while(condition) { code }
// Basic while loop
int counter = 0;
while(counter < 10) {
Print("Counter: ", counter);
counter++;
}
// May not execute at all if condition is false
int value = 100;
while(value < 50) {
Print("This will never execute");
value++;
}
// Reading data until end
int index = 0;
double price = iClose(_Symbol, PERIOD_CURRENT, index);
while(price > 0) {
Print("Bar ", index, " Close: ", price);
index++;
if(index >= 100) break; // Safety limit
price = iClose(_Symbol, PERIOD_CURRENT, index);
}
// Syntax: do { code } while(condition);
// Always executes at least once
int counter = 0;
do {
Print("Counter: ", counter);
counter++;
} while(counter < 10);
// Executes once even if condition is false
int value = 100;
do {
Print("This executes once: ", value);
value++;
} while(value < 50); // false, but already executed once
// Practical: Retry logic
int retryCount = 0;
int maxRetries = 3;
bool success = false;
do {
success = TryToConnectToServer();
if(!success) {
Print("Retry ", retryCount + 1, " of ", maxRetries);
Sleep(1000); // Wait 1 second
}
retryCount++;
} while(!success && retryCount < maxRetries);
if(success) {
Print("Connected successfully");
} else {
Print("Failed after ", maxRetries, " attempts");
}
// Function to send order with retry logic
bool SendOrderWithRetry(ENUM_ORDER_TYPE type, double volume, double price,
double sl, double tp, string comment) {
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = volume;
request.type = type;
request.price = price;
request.sl = sl;
request.tp = tp;
request.deviation = 10;
request.magic = EA_MAGIC;
request.comment = comment;
int attempts = 0;
int maxAttempts = 3;
bool success = false;
do {
// Try to send order
success = OrderSend(request, result);
if(success) {
Print("Order sent successfully! Ticket: ", result.order);
return true;
} else {
Print("Order failed: ", result.retcode, " - ", result.comment);
// Check if error is recoverable
if(result.retcode == TRADE_RETCODE_REQUOTE) {
// Update price and retry
if(type == ORDER_TYPE_BUY) {
request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
} else {
request.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
}
Sleep(100); // Wait 100ms before retry
} else if(result.retcode == TRADE_RETCODE_PRICE_OFF) {
// Market closed or price invalid
Print("Market closed - cannot retry");
return false;
} else {
// Other errors - retry with delay
Sleep(500);
}
}
attempts++;
} while(!success && attempts < maxAttempts);
Print("Failed to send order after ", attempts, " attempts");
return false;
}
// Multiple conditions with AND
int bars = 0;
double totalVolume = 0;
while(bars < 100 && totalVolume < 1000.0) {
double volume = iVolume(_Symbol, PERIOD_CURRENT, bars);
totalVolume += volume;
bars++;
}
Print("Processed ", bars, " bars, Total volume: ", totalVolume);
// Multiple conditions with OR
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
int waitTime = 0;
int maxWaitTime = 60000; // 60 seconds
while(spread > 20 && waitTime < maxWaitTime) {
Sleep(1000); // Wait 1 second
waitTime += 1000;
spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
Print("Waiting for spread... Current: ", spread);
}
if(spread <= 20) {
Print("Spread acceptable - proceeding");
} else {
Print("Timeout - spread still too high");
}
// Intentional infinite loop with break conditions
void MonitorPositions() {
while(true) {
// Check if EA should stop
if(IsStopped()) {
Print("EA stopped - exiting monitor loop");
break;
}
// Check each position
for(int i = PositionsTotal() - 1; i >= 0; i--) {
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
// Check profit target
double profit = PositionGetDouble(POSITION_PROFIT);
if(profit >= 100.0) {
Print("Profit target reached - closing position");
ClosePosition(ticket);
}
// Check stop loss
if(profit <= -50.0) {
Print("Stop loss reached - closing position");
ClosePosition(ticket);
}
}
Sleep(100); // Check every 100ms
// Safety timeout
static datetime startTime = TimeCurrent();
if(TimeCurrent() - startTime > 3600) {
Print("Monitor timeout - 1 hour elapsed");
break;
}
}
}
// ⚠️ Use carefully - infinite loops can freeze EA!
// ✅ FOR: When you know the number of iterations
for(int i = 0; i < 100; i++) {
// Process 100 bars
}
// ✅ WHILE: When condition-based, unknown iterations
double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double targetPrice = 1.12000;
while(price < targetPrice) {
Sleep(1000);
price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
Print("Waiting for price to reach ", targetPrice);
}
// ✅ DO-WHILE: Need to execute at least once
do {
bool result = TrySendOrder();
if(result) break;
Sleep(1000);
} while(true); // Keep trying until success
// FOR equivalent is more readable for fixed iterations
for(int i = 0; i < 100; i++) {
// Clear what this does
}
// WHILE for condition-based is clearer
while(!OrderSendSuccessful() && !IsTimeout()) {
RetryOrder();
}
// Nested while for complex conditions
bool allPositionsClosed = false;
int maxWait = 10; // 10 seconds
int elapsed = 0;
while(!allPositionsClosed && elapsed < maxWait) {
allPositionsClosed = true;
int i = PositionsTotal() - 1;
while(i >= 0) {
ulong ticket = PositionGetTicket(i);
if(ticket > 0) {
allPositionsClosed = false;
ClosePosition(ticket);
}
i--;
}
if(!allPositionsClosed) {
Sleep(1000);
elapsed++;
}
}
if(allPositionsClosed) {
Print("All positions closed");
} else {
Print("Timeout - some positions still open");
}
Lỗi 1: Infinite loop without break
❌ while(true) {
// No break condition - loops forever!
}
✅ while(true) {
if(IsStopped()) break;
if(timeout) break;
}
Lỗi 2: Forgetting to update condition
❌ int i = 0;
while(i < 10) {
Print(i);
// Forgot i++ - infinite loop!
}
✅ int i = 0;
while(i < 10) {
Print(i);
i++;
}
Lỗi 3: Do-while semicolon
❌ do {
Print("Test");
} while(condition) // Missing semicolon!
✅ do {
Print("Test");
} while(condition); // Semicolon required
Sleep() trong loops để tránh CPU overload