Trang chủ Kiến thức Câu Lệnh SWITCH-CASE trong MQL5: Multi-Way Branching
Knowledge

Câu Lệnh SWITCH-CASE trong MQL5: Multi-Way Branching

14 tháng 11, 2025

Học cách sử dụng switch-case để xử lý nhiều điều kiện rõ ràng hơn if-else chains trong trading logic.

SWITCH-CASE Statement

switch-case là cấu trúc điều khiển cho phép kiểm tra một biến với nhiều giá trị khác nhau. Rõ ràng và dễ đọc hơn chuỗi if-else dài.

Cú Pháp Cơ Bản

// Basic switch syntax
int signal = GetTradeSignal();

switch(signal) {
    case 1:
        Print("BUY signal");
        OpenBuyOrder();
        break;
    
    case -1:
        Print("SELL signal");
        OpenSellOrder();
        break;
    
    case 0:
        Print("No signal");
        break;
    
    default:
        Print("Unknown signal");
        break;
}

// ⚠️ break is crucial! Without it, execution "falls through"

Fall-Through Behavior

// Intentional fall-through (no break)
ENUM_DAY_OF_WEEK day = FRIDAY;

switch(day) {
    case MONDAY:
    case TUESDAY:
    case WEDNESDAY:
    case THURSDAY:
        Print("Weekday - Full trading");
        break;
    
    case FRIDAY:
        Print("Friday - Caution before weekend");
        // Fall through to weekend logic
    
    case SATURDAY:
    case SUNDAY:
        Print("Weekend/Friday - Reduce positions");
        CloseRiskyPositions();
        break;
    
    default:
        Print("Invalid day");
}

// ❌ Unintentional fall-through (forgot break)
int orderType = ORDER_TYPE_BUY;
switch(orderType) {
    case ORDER_TYPE_BUY:
        Print("Buy order");
        // Forgot break! Will also execute SELL code
    case ORDER_TYPE_SELL:
        Print("Sell order");
        break;
}

Switch với Enum Values

// Enum for trading signals
enum ENUM_TRADE_SIGNAL {
    SIGNAL_NONE = 0,
    SIGNAL_BUY_STRONG = 2,
    SIGNAL_BUY_WEAK = 1,
    SIGNAL_SELL_WEAK = -1,
    SIGNAL_SELL_STRONG = -2
};

ENUM_TRADE_SIGNAL signal = AnalyzeMarket();

switch(signal) {
    case SIGNAL_BUY_STRONG:
        Print("Strong buy signal - Full lot");
        OpenOrder(ORDER_TYPE_BUY, 0.1);
        break;
    
    case SIGNAL_BUY_WEAK:
        Print("Weak buy signal - Half lot");
        OpenOrder(ORDER_TYPE_BUY, 0.05);
        break;
    
    case SIGNAL_SELL_WEAK:
        Print("Weak sell signal - Half lot");
        OpenOrder(ORDER_TYPE_SELL, 0.05);
        break;
    
    case SIGNAL_SELL_STRONG:
        Print("Strong sell signal - Full lot");
        OpenOrder(ORDER_TYPE_SELL, 0.1);
        break;
    
    case SIGNAL_NONE:
        Print("No clear signal - Wait");
        break;
    
    default:
        Print("Unknown signal type");
}

Switch với Order Types

// Handle different order types
void ProcessOrder(ulong ticket) {
    if(!PositionSelectByTicket(ticket)) return;
    
    ENUM_ORDER_TYPE type = (ENUM_ORDER_TYPE)PositionGetInteger(POSITION_TYPE);
    double profit = PositionGetDouble(POSITION_PROFIT);
    double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
    double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT);
    
    switch(type) {
        case ORDER_TYPE_BUY:
            Print("Buy position: ", ticket);
            if(currentPrice >= openPrice + 100 * _Point) {
                Print("Moving to breakeven");
                ModifyStopLoss(ticket, openPrice);
            }
            break;
        
        case ORDER_TYPE_SELL:
            Print("Sell position: ", ticket);
            if(currentPrice <= openPrice - 100 * _Point) {
                Print("Moving to breakeven");
                ModifyStopLoss(ticket, openPrice);
            }
            break;
        
        default:
            Print("Unsupported order type: ", type);
    }
}

Switch vs If-Else Comparison

// ❌ Long if-else chain (harder to read)
int errorCode = GetLastError();

if(errorCode == ERR_INVALID_STOPS) {
    Print("Invalid stops");
} else if(errorCode == ERR_INVALID_TRADE_VOLUME) {
    Print("Invalid volume");
} else if(errorCode == ERR_MARKET_CLOSED) {
    Print("Market closed");
} else if(errorCode == ERR_NOT_ENOUGH_MONEY) {
    Print("Not enough money");
} else if(errorCode == ERR_TRADE_TIMEOUT) {
    Print("Trade timeout");
} else {
    Print("Unknown error");
}

// ✅ Switch-case (cleaner, more readable)
switch(errorCode) {
    case ERR_INVALID_STOPS:
        Print("Invalid stops");
        break;
    
    case ERR_INVALID_TRADE_VOLUME:
        Print("Invalid volume");
        break;
    
    case ERR_MARKET_CLOSED:
        Print("Market closed");
        break;
    
    case ERR_NOT_ENOUGH_MONEY:
        Print("Not enough money");
        break;
    
    case ERR_TRADE_TIMEOUT:
        Print("Trade timeout");
        break;
    
    default:
        Print("Unknown error");
}

Ứng Dụng Thực Tế: Timeframe Handler

// Get bars per day based on timeframe
int GetBarsPerDay(ENUM_TIMEFRAMES period) {
    switch(period) {
        case PERIOD_M1:  return 1440;  // 24*60
        case PERIOD_M5:  return 288;   // 24*12
        case PERIOD_M15: return 96;    // 24*4
        case PERIOD_M30: return 48;    // 24*2
        case PERIOD_H1:  return 24;
        case PERIOD_H4:  return 6;
        case PERIOD_D1:  return 1;
        case PERIOD_W1:  return 1;     // Approximate
        case PERIOD_MN1: return 1;     // Approximate
        default:
            Print("Unknown timeframe");
            return 0;
    }
}

// Get timeframe name
string GetTimeframeName(ENUM_TIMEFRAMES period) {
    switch(period) {
        case PERIOD_M1:  return "M1";
        case PERIOD_M5:  return "M5";
        case PERIOD_M15: return "M15";
        case PERIOD_M30: return "M30";
        case PERIOD_H1:  return "H1";
        case PERIOD_H4:  return "H4";
        case PERIOD_D1:  return "D1";
        case PERIOD_W1:  return "W1";
        case PERIOD_MN1: return "MN1";
        default:         return "Unknown";
    }
}

Switch with Multiple Cases (Grouping)

// Group similar cases
void HandleTradingHour(int hour) {
    switch(hour) {
        // Asian session
        case 0:
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
        case 6:
        case 7:
        case 8:
            Print("Asian session - Low volatility strategy");
            UseRangeStrategy();
            break;
        
        // European session
        case 9:
        case 10:
        case 11:
        case 12:
        case 13:
        case 14:
        case 15:
        case 16:
            Print("European session - Breakout strategy");
            UseBreakoutStrategy();
            break;
        
        // US session
        case 17:
        case 18:
        case 19:
        case 20:
        case 21:
            Print("US session - Trend following");
            UseTrendStrategy();
            break;
        
        // Late night
        default:
            Print("Low liquidity - No trading");
            break;
    }
}

Limitations of Switch

// ✅ Switch works with: int, char, enum
int value = 10;
switch(value) { /* OK */ }

// ❌ Switch does NOT work with: double, string, bool
double price = 1.12345;
switch(price) {  // COMPILE ERROR!
    case 1.12345: break;
}

// ❌ Switch does NOT support ranges
int spread = 25;
switch(spread) {
    case 0-10:  // ERROR! Not valid syntax
        Print("Low spread");
        break;
}

// ✅ Use if-else for ranges
if(spread >= 0 && spread <= 10) {
    Print("Low spread");
} else if(spread > 10 && spread <= 20) {
    Print("Medium spread");
} else {
    Print("High spread");
}

// ❌ Switch does NOT support expressions in cases
int ma = 100;
switch(price) {
    case ma + 10:  // ERROR! Case must be constant
        break;
}

Best Practices

  • ✅ Luôn có default case
  • ✅ Luôn dùng break sau mỗi case (trừ khi muốn fall-through)
  • ✅ Sử dụng switch cho enum values
  • ✅ Group similar cases lại với nhau
  • ✅ Prefer switch cho >= 3 điều kiện rời rạc
  • ⛔ Không dùng switch với double/string
  • ⛔ Tránh quá nhiều cases (>20) - consider refactoring

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

  1. Viết switch xử lý 5 order errors khác nhau với retry logic
  2. Tạo timeframe selector: M1-D1 với different indicator parameters
  3. Implement session handler: Asian/European/US với strategies khác nhau

Tài Liệu Tham Khảo