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 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.
// 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"
// 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;
}
// 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");
}
// 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);
}
}
// ❌ 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");
}
// 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";
}
}
// 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;
}
}
// ✅ 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;
}
default casebreak sau mỗi case (trừ khi muốn fall-through)