Trang chủ Kiến thức Toán Tử So Sánh trong MQL5: ==, !=, <, >, <=, >=
Knowledge

Toán Tử So Sánh trong MQL5: ==, !=, <, >, <=, >=

14 tháng 11, 2025

Tìm hiểu cách sử dụng toán tử so sánh để kiểm tra điều kiện trong trading logic và risk management.

Các Toán Tử So Sánh

Toán tử so sánh được sử dụng để kiểm tra quan hệ giữa các giá trị, trả về true hoặc false. Chúng là nền tảng cho mọi điều kiện logic trong EA và indicators.

Toán Tử Bằng (==)

// So sánh integers
int a = 10;
int b = 10;
if(a == b) {
    Print("Equal");  // ✅ This will execute
}

// So sánh strings
string symbol = "EURUSD";
if(symbol == "EURUSD") {
    Print("Trading EURUSD");
}

// ⚠️ Cẩn thận với double comparison
double price1 = 0.1 + 0.2;  // 0.30000000000000004
double price2 = 0.3;
if(price1 == price2) {
    Print("Equal");  // ❌ Không execute (floating-point error)
}

// ✅ So sánh double đúng cách
double epsilon = 0.00001;
if(MathAbs(price1 - price2) < epsilon) {
    Print("Equal");  // ✅ This works
}

// So sánh enum values
ENUM_TIMEFRAMES period = PERIOD_H1;
if(period == PERIOD_H1) {
    Print("1 Hour timeframe");
}

Toán Tử Khác (!=)

// Not equal
int signal = 1;
if(signal != 0) {
    Print("Signal detected");
}

// String comparison
string symbol = "EURUSD";
if(symbol != "GBPUSD") {
    Print("Not trading GBPUSD");
}

// Kiểm tra new bar
static datetime lastBarTime = 0;
datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);
if(currentBarTime != lastBarTime) {
    Print("New bar!");
    lastBarTime = currentBarTime;
}

// Kiểm tra order không bị reject
ulong ticket = OrderSend(...);
if(ticket != 0) {
    Print("Order sent successfully");
}

Toán Tử Lớn Hơn (>) và Lớn Hơn Hoặc Bằng (>=)

// Greater than
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double minBalance = 1000.0;
if(balance > minBalance) {
    Print("Sufficient balance for trading");
}

// Greater than or equal
int totalOrders = PositionsTotal();
int maxOrders = 5;
if(totalOrders >= maxOrders) {
    Print("Max orders reached");
    return;  // Stop opening new orders
}

// RSI overbought
double rsi = iRSI(_Symbol, PERIOD_CURRENT, 14, PRICE_CLOSE);
if(rsi > 70) {
    Print("Overbought condition");
}

// Price above MA
double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double ma = iMA(_Symbol, PERIOD_CURRENT, 50, 0, MODE_SMA, PRICE_CLOSE);
if(price >= ma) {
    Print("Price above MA(50) - Bullish");
}

Toán Tử Nhỏ Hơn (<) và Nhỏ Hơn Hoặc Bằng (<=)

// Less than
double rsi = 25.5;
if(rsi < 30) {
    Print("Oversold condition");
}

// Less than or equal
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
int maxSpread = 20;  // 2 pips
if(spread <= maxSpread) {
    Print("Spread acceptable for trading");
} else {
    Print("Spread too high!");
}

// Stop loss distance check
double entryPrice = 1.12345;
double stopLoss = 1.12295;
double slDistance = MathAbs(entryPrice - stopLoss);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
double slPips = slDistance / point;

if(slPips < 20) {
    Print("Stop loss too tight!");
}

// Time check
MqlDateTime timeStruct;
TimeToStruct(TimeCurrent(), timeStruct);
if(timeStruct.hour <= 8) {
    Print("Asian session");
}

Kết Hợp Nhiều Điều Kiện với && và ||

// AND operator (&&) - tất cả phải true
double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double ma50 = iMA(_Symbol, PERIOD_CURRENT, 50, 0, MODE_SMA, PRICE_CLOSE);
double rsi = iRSI(_Symbol, PERIOD_CURRENT, 14, PRICE_CLOSE);

// Buy signal: Price > MA50 AND RSI < 70
if(price > ma50 && rsi < 70) {
    Print("Buy signal confirmed");
}

// OR operator (||) - ít nhất một true
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
int totalOrders = PositionsTotal();

// Skip trading if spread too high OR max orders reached
if(spread > 30 || totalOrders >= 5) {
    Print("Cannot trade");
    return;
}

// Complex conditions
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double equity = AccountInfoDouble(ACCOUNT_EQUITY);
double drawdownPercent = (balance - equity) / balance * 100.0;

// Stop trading if drawdown > 10% OR balance < $500
if(drawdownPercent > 10.0 || balance < 500.0) {
    Print("Risk limits exceeded!");
    CloseAllPositions();
}

Ứng Dụng Thực Tế: Trading Filters

// 1. Spread Filter
bool IsSpreadAcceptable() {
    int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
    int maxSpread = 20;  // 2 pips for EURUSD
    return (spread <= maxSpread);
}

// 2. Time Filter
bool IsTradingTime() {
    MqlDateTime timeStruct;
    TimeToStruct(TimeCurrent(), timeStruct);
    
    // Monday to Friday
    if(timeStruct.day_of_week < 1 || timeStruct.day_of_week > 5)
        return false;
    
    // 8:00 AM to 5:00 PM
    if(timeStruct.hour < 8 || timeStruct.hour >= 17)
        return false;
    
    return true;
}

// 3. Risk Filter
bool IsRiskAcceptable() {
    double balance = AccountInfoDouble(ACCOUNT_BALANCE);
    double equity = AccountInfoDouble(ACCOUNT_EQUITY);
    
    // Floating loss percentage
    double floatingLossPercent = (balance - equity) / balance * 100.0;
    
    // Max 5% floating loss
    if(floatingLossPercent > 5.0)
        return false;
    
    // Min balance $1000
    if(balance < 1000.0)
        return false;
    
    return true;
}

// 4. Combine All Filters
void OnTick() {
    if(!IsSpreadAcceptable()) {
        Print("Spread too high");
        return;
    }
    
    if(!IsTradingTime()) {
        Print("Outside trading hours");
        return;
    }
    
    if(!IsRiskAcceptable()) {
        Print("Risk limits exceeded");
        return;
    }
    
    // All filters passed - proceed with trading logic
    int signal = CheckTradingSignal();
    if(signal != 0) {
        OpenTrade(signal);
    }
}

So Sánh Chuỗi (String Comparison)

// Case-sensitive comparison
string symbol = "EURUSD";
if(symbol == "eurusd") {
    Print("Match");  // ❌ Không match (case-sensitive)
}

// Case-insensitive comparison
string symbol2 = "EURUSD";
string test = "eurusd";
StringToUpper(test);  // Convert to "EURUSD"
if(symbol2 == test) {
    Print("Match");  // ✅ Now matches
}

// StringCompare function
int result = StringCompare(symbol, "EURUSD");
// result = 0: equal
// result < 0: symbol < "EURUSD"
// result > 0: symbol > "EURUSD"

if(result == 0) {
    Print("Strings are equal");
}

// Check if symbol contains substring
string majorPairs = "EURUSD,GBPUSD,USDJPY,USDCHF";
if(StringFind(majorPairs, symbol) >= 0) {
    Print("Symbol is a major pair");
}

Best Practices

  • ✅ Dùng MathAbs(a - b) < epsilon để so sánh double
  • ✅ Kiểm tra giá trị trước khi so sánh (avoid NULL/uninitialized)
  • ✅ Sử dụng () để nhóm điều kiện phức tạp
  • ✅ Tách logic thành các hàm filter riêng biệt
  • ⛔ Không dùng == trực tiếp với double
  • ⛔ Tránh quá nhiều điều kiện lồng nhau (nested if)

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

  1. Viết hàm kiểm tra: Price trong khoảng ±50 pips của MA(50)?
  2. Tạo filter: Chỉ trade khi RSI trong vùng 40-60 (neutral zone)
  3. Viết logic: Close tất cả positions nếu drawdown > 10%

Tài Liệu Tham Khảo