Học cách sử dụng for loop để duyệt mảng, xử lý bars, tính toán indicators và optimize performance.
for là vòng lặp phổ biến nhất trong MQL5, được sử dụng khi biết trước số lần lặp. Rất hữu ích cho việc duyệt mảng, xử lý historical bars, và tính toán indicators.
// Syntax: for(initialization; condition; increment)
// Simple counting loop
for(int i = 0; i < 10; i++) {
Print("Iteration: ", i); // 0, 1, 2, ..., 9
}
// Counting backward
for(int i = 10; i > 0; i--) {
Print("Countdown: ", i); // 10, 9, 8, ..., 1
}
// Increment by 2
for(int i = 0; i < 100; i += 2) {
Print("Even number: ", i); // 0, 2, 4, ..., 98
}
// Multiple variables (comma operator)
for(int i = 0, j = 10; i < 10; i++, j--) {
Print("i=", i, " j=", j);
}
// Array of prices
double prices[] = {1.12345, 1.12445, 1.12545, 1.12645, 1.12745};
// Loop through array
for(int i = 0; i < ArraySize(prices); i++) {
Print("Price[", i, "] = ", prices[i]);
}
// Calculate sum and average
double sum = 0;
for(int i = 0; i < ArraySize(prices); i++) {
sum += prices[i];
}
double average = sum / ArraySize(prices);
Print("Average price: ", average);
// Find maximum value
double maxPrice = prices[0];
for(int i = 1; i < ArraySize(prices); i++) {
if(prices[i] > maxPrice) {
maxPrice = prices[i];
}
}
Print("Maximum price: ", maxPrice);
// Find minimum with index
double minPrice = prices[0];
int minIndex = 0;
for(int i = 1; i < ArraySize(prices); i++) {
if(prices[i] < minPrice) {
minPrice = prices[i];
minIndex = i;
}
}
Print("Minimum price: ", minPrice, " at index: ", minIndex);
// Copy bar data
double high[], low[], close[];
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
ArraySetAsSeries(close, true);
int bars = 100;
CopyHigh(_Symbol, PERIOD_CURRENT, 0, bars, high);
CopyLow(_Symbol, PERIOD_CURRENT, 0, bars, low);
CopyClose(_Symbol, PERIOD_CURRENT, 0, bars, close);
// Loop through bars to calculate custom indicator
double indicator[];
ArrayResize(indicator, bars);
ArraySetAsSeries(indicator, true);
for(int i = 0; i < bars; i++) {
// Calculate true range
double tr = high[i] - low[i];
indicator[i] = tr;
}
// Calculate moving average of true range (ATR-like)
int period = 14;
double atr[];
ArrayResize(atr, bars);
ArraySetAsSeries(atr, true);
for(int i = 0; i < bars - period + 1; i++) {
double sum = 0;
for(int j = 0; j < period; j++) {
sum += indicator[i + j];
}
atr[i] = sum / period;
}
Print("ATR[0] = ", atr[0]);
// 2D array processing
double matrix[5][5];
// Fill matrix
for(int row = 0; row < 5; row++) {
for(int col = 0; col < 5; col++) {
matrix[row][col] = row * 10 + col;
}
}
// Print matrix
for(int row = 0; row < 5; row++) {
string rowStr = "";
for(int col = 0; col < 5; col++) {
rowStr += DoubleToString(matrix[row][col], 0) + " ";
}
Print("Row ", row, ": ", rowStr);
}
// Find pattern in bars
int signalCount = 0;
for(int i = 0; i < bars - 3; i++) {
// Check for 3 consecutive bullish candles
bool pattern = true;
for(int j = 0; j < 3; j++) {
if(close[i + j] <= close[i + j + 1]) {
pattern = false;
break;
}
}
if(pattern) {
signalCount++;
Print("Pattern found at bar: ", i);
}
}
// BREAK: Exit loop immediately
for(int i = 0; i < 100; i++) {
if(i == 50) {
Print("Breaking at: ", i);
break; // Stop loop
}
Print(i);
}
// Find first bullish candle
for(int i = 0; i < bars; i++) {
if(close[i] > close[i + 1]) {
Print("First bullish candle at bar: ", i);
break; // Found it, stop searching
}
}
// CONTINUE: Skip current iteration
for(int i = 0; i < 20; i++) {
if(i % 2 == 0) {
continue; // Skip even numbers
}
Print("Odd number: ", i);
}
// Process only closed positions
for(int i = PositionsTotal() - 1; i >= 0; i--) {
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue; // Skip if ticket invalid
double profit = PositionGetDouble(POSITION_PROFIT);
if(profit <= 0) continue; // Skip losing positions
Print("Profitable position: ", ticket, " Profit: $", profit);
}
// ❌ SLOW: Calculate ArraySize() every iteration
for(int i = 0; i < ArraySize(prices); i++) {
// Process prices[i]
}
// ✅ FAST: Cache array size
int size = ArraySize(prices);
for(int i = 0; i < size; i++) {
// Process prices[i]
}
// ❌ SLOW: Call function in condition
for(int i = 0; i < PositionsTotal(); i++) {
// PositionsTotal() called every iteration!
}
// ✅ FAST: Cache result
int total = PositionsTotal();
for(int i = 0; i < total; i++) {
// Much faster
}
// ❌ SLOW: Nested loops with large arrays
for(int i = 0; i < 1000; i++) {
for(int j = 0; j < 1000; j++) {
// 1,000,000 iterations!
}
}
// ✅ BETTER: Reduce iterations where possible
for(int i = 0; i < 1000; i++) {
for(int j = i + 1; j < 1000; j++) {
// ~500,000 iterations (half)
}
}
// Close all losing positions
void CloseLosingPositions() {
// ⚠️ Important: Loop backward when closing positions
// (closing changes array indices)
for(int i = PositionsTotal() - 1; i >= 0; i--) {
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
// Check if position belongs to this EA
long magic = PositionGetInteger(POSITION_MAGIC);
if(magic != EA_MAGIC) continue;
// Check profit
double profit = PositionGetDouble(POSITION_PROFIT);
if(profit >= 0) continue; // Skip profitable positions
// Close losing position
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.position = ticket;
request.symbol = PositionGetString(POSITION_SYMBOL);
request.volume = PositionGetDouble(POSITION_VOLUME);
request.type = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) ?
ORDER_TYPE_SELL : ORDER_TYPE_BUY;
request.price = (request.type == ORDER_TYPE_SELL) ?
SymbolInfoDouble(_Symbol, SYMBOL_BID) :
SymbolInfoDouble(_Symbol, SYMBOL_ASK);
request.deviation = 10;
if(OrderSend(request, result)) {
Print("Closed losing position #", ticket);
}
}
}
// Count orders by type
int CountOrdersByType(ENUM_ORDER_TYPE type) {
int count = 0;
int total = PositionsTotal();
for(int i = 0; i < total; i++) {
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetInteger(POSITION_TYPE) == type) {
count++;
}
}
return count;
}
// Calculate total profit
double CalculateTotalProfit() {
double totalProfit = 0;
int total = PositionsTotal();
for(int i = 0; i < total; i++) {
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
long magic = PositionGetInteger(POSITION_MAGIC);
if(magic != EA_MAGIC) continue;
totalProfit += PositionGetDouble(POSITION_PROFIT);
}
return totalProfit;
}
// ⚠️ DANGER: Infinite loop
for(int i = 0; i < 10; i--) { // Decrementing instead of incrementing!
// This will run forever!
}
// ✅ SAFE: Add safety counter
int maxIterations = 10000;
int counter = 0;
for(int i = 0; i < someCondition; i++) {
counter++;
if(counter > maxIterations) {
Print("Max iterations reached - breaking loop");
break;
}
// Your logic here
}
// ✅ SAFE: Use while with timeout
datetime startTime = GetTickCount();
int timeout = 1000; // 1 second
while(someCondition) {
if(GetTickCount() - startTime > timeout) {
Print("Timeout - breaking loop");
break;
}
// Your logic here
}
ArraySize() và PositionsTotal() trước loopi--break khi tìm thấy kết quảcontinue để skip invalid datai < size