Trang chủ Kiến thức Vòng Lặp WHILE và DO-WHILE trong MQL5
Knowledge

Vòng Lặp WHILE và DO-WHILE trong MQL5

14 tháng 11, 2025

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 Loops

whiledo-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.

WHILE Loop: Kiểm Tra Trước Khi Thực Thi

// 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);
}

DO-WHILE Loop: Thực Thi Ít Nhất Một Lần

// 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");
}

Ứng Dụng: Retry Order Send

// 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;
}

While với Multiple Conditions

// 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");
}

Infinite Loop với Break

// 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!

While vs For: Khi Nào Dùng Cái Nào?

// ✅ 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 Loops

// 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");
}

Common Mistakes

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

Best Practices

  • ✅ Luôn có break condition cho infinite loops
  • ✅ Sử dụng timeout protection
  • ✅ Prefer FOR khi biết số lần lặp
  • ✅ Use DO-WHILE cho retry logic
  • ✅ Add Sleep() trong loops để tránh CPU overload
  • ⛔ Tránh infinite loops không có exit condition
  • ⛔ Không quên update loop variable

Bài Tập Thực Hành

  1. Viết while loop chờ spread < 15 pips (max 30 seconds)
  2. Tạo do-while retry logic cho OrderSend (max 5 attempts)
  3. Implement monitor loop check positions mỗi 5 giây

Tài Liệu Tham Khảo