Summary: This comprehensive guide covers all MQL4 operators including arithmetic, comparison, logical, and assignment types. Learn operator precedence, expression evaluation, and practical EA coding examples with complete source code.




Why Operators Matter in EA Development
Operators are symbols that tell the compiler to perform specific mathematical, relational, or logical operations. Understanding operators is essential for creating trading conditions, calculating position sizes, and controlling EA logic flow.

Complete MQL4 Operator Reference Table
| Category | Operators | Purpose | Example |
|----------|-----------|---------|---------|
| Arithmetic | + - * / % | Basic math calculations | lotSize * price |
| Assignment | = += -= *= /= %= | Variable value assignment | total += 1 |
| Comparison | == != > < >= <= | Value comparison | price > maValue |
| Logical | && || ! | Boolean logic combinations | trendUp && rsiLow |
| Bitwise | & | ^ ~ << >> | Binary operations (advanced) | flags | mask |
| Ternary | ? : | Conditional assignment | isBuy ? 1 : -1 |

1. Arithmetic Operators - Basic Math Calculations
Arithmetic operators perform mathematical calculations on numeric values (int and double).
```mql4
// Arithmetic operators in EA calculations
double entryPrice = 1.09250;
double stopLoss = entryPrice - 0.0010; // Subtraction: 1.09150
double takeProfit = entryPrice + 0.0020; // Addition: 1.09450
double riskAmount = AccountBalance() * 0.02; // Multiplication: 2% risk
double lotSize = riskAmount / 1000; // Division
int remainder = 10 % 3; // Modulus: 1 (remainder of 10/3)

// Practical EA example - Position size calculator
double CalculatePositionSize(double riskPercent, double stopLossPoints) {
double accountEquity = AccountBalance();
double riskDollars = accountEquity * (riskPercent / 100);
double pointValue = MarketInfo(Symbol(), MODE_TICKVALUE);
double calculatedSize = riskDollars / (stopLossPoints * pointValue);

// Apply min/max and step rounding
double minLot = MarketInfo(Symbol(), MODE_MINLOT);
double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);
double stepSize = MarketInfo(Symbol(), MODE_LOTSTEP);

calculatedSize = MathFloor(calculatedSize / stepSize) * stepSize;
calculatedSize = MathMax(minLot, MathMin(maxLot, calculatedSize));

return NormalizeDouble(calculatedSize, 2);
}

// Dynamic stop loss calculation using arithmetic
double CalculateTrailingStop(double currentPrice, double entryPrice, int trailingPoints) {
double profitPoints = (currentPrice - entryPrice) / Point();
if(profitPoints > trailingPoints) {
return currentPrice - (trailingPoints * Point());
}
return 0;
}
```

2. Assignment Operators - Variable Value Setting
Assignment operators store values into variables. The simple assignment (=) is most common, while compound operators combine operation with assignment.
```mql4
// Basic assignment
int totalOrders = 0; // Initialize counter
double currentProfit = 0; // Initialize profit variable
string symbolName = "EURUSD"; // Initialize string

// Compound assignment operators
int orderCount = 5;
orderCount += 3; // Same as: orderCount = orderCount + 3 (result: 8)
orderCount -= 2; // Same as: orderCount = orderCount - 2 (result: 6)
orderCount *= 2; // Same as: orderCount = orderCount * 2 (result: 12)
orderCount /= 3; // Same as: orderCount = orderCount / 3 (result: 4)
orderCount %= 3; // Same as: orderCount = orderCount % 3 (result: 1)

// Practical EA example - Trade counter with compound assignment
int g_buyTrades = 0;
int g_sellTrades = 0;
int g_totalTrades = 0;

void UpdateTradeCounters(int orderType) {
if(orderType == OP_BUY) {
g_buyTrades++; // Increment buy counter
} else if(orderType == OP_SELL) {
g_sellTrades++; // Increment sell counter
}
g_totalTrades = g_buyTrades + g_sellTrades;
}

// Risk management with assignment operators
double g_dailyLoss = 0;
double g_maxDailyLoss = 1000;

void TrackDailyLoss(double lossAmount) {
g_dailyLoss += lossAmount; // Add to daily loss total
if(g_dailyLoss >= g_maxDailyLoss) {
Print("Daily loss limit reached. Closing all positions.");
CloseAllPositions();
}
}
```

3. Comparison Operators - Trading Condition Testing
Comparison operators compare two values and return true or false. They are the foundation of all trading decisions.
```mql4
// Comparison operators in trading conditions
double currentPrice = Bid;
double maValue = iMA(NULL, 0, 20, 0, MODE_SMA, PRICE_CLOSE, 1);
double rsiValue = iRSI(NULL, 0, 14, PRICE_CLOSE, 1);

// Equality and inequality
if(currentPrice == maValue) { } // Equal to (rare in forex)
if(currentPrice != maValue) { } // Not equal to
if(rsiValue > 70) { } // Greater than (overbought)
if(rsiValue < 30) { } // Less than (oversold)
if(currentPrice >= maValue + 10*Point()) { } // Greater than or equal
if(currentPrice <= maValue - 10*Point()) { } // Less than or equal

// Practical EA example - Multi-condition trading signal
bool GenerateBuySignal() {
double maFast = iMA(NULL, 0, 10, 0, MODE_SMA, PRICE_CLOSE, 1);
double maSlow = iMA(NULL, 0, 30, 0, MODE_SMA, PRICE_CLOSE, 1);
double rsi = iRSI(NULL, 0, 14, PRICE_CLOSE, 1);
double close1 = iClose(NULL, 0, 1);
double close2 = iClose(NULL, 0, 2);

bool trendUp = maFast > maSlow;
bool oversold = rsi < 30;
bool bullishCandle = close1 > close2;

// Combine comparisons for signal
if(trendUp == true && oversold == true && bullishCandle == true) {
return true;
}
return false;
}

// Stop loss distance validation
bool IsStopLossValid(double stopLossPrice, int orderType) {
double currentPrice = (orderType == OP_BUY) ? Ask : Bid;
double minDistance = MarketInfo(Symbol(), MODE_STOPLEVEL) * Point();

if(orderType == OP_BUY) {
return (currentPrice - stopLossPrice) >= minDistance;
} else {
return (stopLossPrice - currentPrice) >= minDistance;
}
}
```

4. Logical Operators - Combining Trading Conditions
Logical operators combine multiple boolean expressions to create complex trading rules.
```mql4
// Logical operators: && (AND), || (OR), ! (NOT)

// AND operator (&&) - ALL conditions must be true
if(trendUp && rsiOversold && noPosition) {
OpenBuyOrder(); // Only executes if ALL three are true
}

// OR operator (||) - AT LEAST ONE condition must be true
if(priceAboveUpperBand || priceBelowLowerBand) {
Alert("Price touched Bollinger Band");
}

// NOT operator (!) - Reverses boolean value
if(!IsTradeAllowed()) {
Print("Trading is disabled");
return;
}

// Practical EA example - Comprehensive signal validation
bool ValidateTradeSignal(int signalType) {
// Check multiple conditions with logical operators
bool timeOk = IsTradingHours();
bool spreadOk = MarketInfo(Symbol(), MODE_SPREAD) < 30;
bool noExistingTrade = CountOrders(magicNumber) == 0;
bool balanceOk = AccountBalance() > 1000;
bool newsOk = !IsNewsTime(); // NOT operator example

// Combine all conditions
if(timeOk && spreadOk && noExistingTrade && balanceOk && newsOk) {
if(signalType == SIGNAL_BUY) {
bool buyConditions = CheckBuyConditions();
return buyConditions;
} else if(signalType == SIGNAL_SELL) {
bool sellConditions = CheckSellConditions();
return sellConditions;
}
}
return false;
}

// Complex entry logic with mixed operators
void CheckEntryConditions() {
double maFast = iMA(NULL, 0, 10, 0, MODE_SMA, PRICE_CLOSE, 1);
double maSlow = iMA(NULL, 0, 30, 0, MODE_SMA, PRICE_CLOSE, 1);
double rsi = iRSI(NULL, 0, 14, PRICE_CLOSE, 1);

bool buySignal = (maFast > maSlow) && (rsi < 30);
bool sellSignal = (maFast < maSlow) && (rsi > 70);
bool reversalSignal = (rsi < 25) || (rsi > 75);

if(buySignal && !HasBuyPosition()) {
OpenBuy();
} else if(sellSignal && !HasSellPosition()) {
OpenSell();
} else if(reversalSignal && !HasAnyPosition()) {
Print("Extreme RSI detected - monitoring for reversal");
}
}
```

5. Ternary Operator (? :) - Conditional Assignment
The ternary operator provides a compact way to write if-else assignments.
```mql4
// Syntax: condition ? value_if_true : value_if_false

// Basic ternary usage
int direction = (maFast > maSlow) ? 1 : -1; // 1 for buy, -1 for sell
double lotSize = (accountBalance > 10000) ? 0.1 : 0.05;
string signal = (rsi < 30) ? "BUY" : "WAIT";

// Practical EA example - Dynamic parameter selection
double GetDynamicStopLoss() {
double volatility = iATR(NULL, 0, 14, 1);
double baseStop = 50 * Point();

// Use ternary for volatility adjustment
return (volatility > 0.0020) ? baseStop * 2 : baseStop;
}

// Entry price determination with ternary
double GetEntryPrice(int orderType) {
return (orderType == OP_BUY) ? Ask : Bid;
}

// Order type string conversion
string OrderTypeToString(int orderType) {
return (orderType == OP_BUY) ? "BUY" :
(orderType == OP_SELL) ? "SELL" :
(orderType == OP_BUYLIMIT) ? "BUY LIMIT" :
(orderType == OP_SELLLIMIT) ? "SELL LIMIT" : "UNKNOWN";
}

// Risk-based lot size with multiple conditions
double GetRiskLotSize(double riskPercent) {
double balance = AccountBalance();
double riskAmount = balance * riskPercent / 100;
double baseLot = riskAmount / 10000;

// Nested ternary (use sparingly - can reduce readability)
double lotSize = (balance > 50000) ? baseLot * 1.5 :
(balance > 20000) ? baseLot * 1.2 :
(balance > 5000) ? baseLot : baseLot * 0.5;

return NormalizeDouble(lotSize, 2);
}
```

6. Operator Precedence - Which Operation Runs First
Operator precedence determines the order of evaluation in complex expressions.
```mql4
// Operator precedence table (highest to lowest)
// 1. () parentheses
// 2. ! - + (unary operators)
// 3. * / %
// 4. + -
// 5. < > <= >=
// 6. == !=
// 7. &&
// 8. ||
// 9. = += -= (assignment)

// Precedence examples
double result = 5 + 3 * 2; // Multiplication first: 5 + 6 = 11
double result2 = (5 + 3) * 2; // Parentheses first: 8 * 2 = 16

bool condition = a > b && c < d || e == f;
// Evaluated as: ((a > b) && (c < d)) || (e == f)

// Practical EA example - Proper precedence usage
bool GenerateSignal() {
double maFast = iMA(NULL, 0, 10, 0, MODE_SMA, PRICE_CLOSE, 1);
double maSlow = iMA(NULL, 0, 30, 0, MODE_SMA, PRICE_CLOSE, 1);
double rsi = iRSI(NULL, 0, 14, PRICE_CLOSE, 1);
int totalOrders = CountOrders(magicNumber);

// Without parentheses - unclear intention
// bool buy = maFast > maSlow && rsi < 30 || totalOrders == 0;

// With parentheses - clear and correct
bool buy = (maFast > maSlow) && (rsi < 30) && (totalOrders == 0);
bool sell = (maFast < maSlow) && (rsi > 70) && (totalOrders == 0);

return buy || sell;
}

// Complex calculation with precedence
double CalculateRiskRewardRatio() {
double entry = 1.09250;
double stopLoss = 1.09150;
double takeProfit = 1.09450;

// Risk = entry - stopLoss, Reward = takeProfit - entry
// Division happens before subtraction without parentheses
double ratio = (takeProfit - entry) / (entry - stopLoss);

return NormalizeDouble(ratio, 2);
}
```

Complete EA Template Using All Operator Types
```mql4
//+------------------------------------------------------------------+
//| OperatorsEA.mq4|
//+------------------------------------------------------------------+
#property copyright "Copyright 2024"
#property version "1.00"
#property strict

input double InpLotSize = 0.1;
input int InpMagic = 12345;
input int InpRiskPercent = 2;
input int InpMaxDailyLoss = 500;

double g_dailyLoss = 0;
int g_todayTrades = 0;
datetime g_lastReset = 0;

//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit() {
g_lastReset = GetMidnight();
Print("EA initialized with risk management");
return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick() {
static datetime lastBarTime = 0;
if(Time[0] == lastBarTime) return;
lastBarTime = Time[0];

ResetDailyIfNeeded();

if(IsTradeAllowed() && !IsMaxDailyLossReached()) {
EvaluateAndTrade();
}
}

//+------------------------------------------------------------------+
//| Reset daily counters |
//+------------------------------------------------------------------+
void ResetDailyIfNeeded() {
datetime midnight = GetMidnight();
if(midnight != g_lastReset) {
g_dailyLoss = 0;
g_todayTrades = 0;
g_lastReset = midnight;
Print("Daily counters reset");
}
}

//+------------------------------------------------------------------+
//| Main trading logic with operators |
//+------------------------------------------------------------------+
void EvaluateAndTrade() {
double maFast = iMA(NULL, 0, 10, 0, MODE_SMA, PRICE_CLOSE, 1);
double maSlow = iMA(NULL, 0, 30, 0, MODE_SMA, PRICE_CLOSE, 1);
double rsi = iRSI(NULL, 0, 14, PRICE_CLOSE, 1);
int orderCount = CountOrders(InpMagic);

// Compound assignment and comparison operators
bool trendUp = maFast > maSlow;
bool trendDown = maFast < maSlow;
bool oversold = rsi < 30;
bool overbought = rsi > 70;
bool canTrade = (orderCount == 0) && (g_todayTrades < 5);

// Logical operators combining conditions
if(trendUp && oversold && canTrade) {
double dynamicLot = CalculateLotSize(InpRiskPercent, 50);
OpenOrder(OP_BUY, dynamicLot);
g_todayTrades++; // Increment operator
}
else if(trendDown && overbought && canTrade) {
double dynamicLot = CalculateLotSize(InpRiskPercent, 50);
OpenOrder(OP_SELL, dynamicLot);
g_todayTrades++;
}
}

//+------------------------------------------------------------------+
//| Calculate lot size using arithmetic operators |
//+------------------------------------------------------------------+
double CalculateLotSize(int riskPercent, int stopPoints) {
double riskAmount = AccountBalance() * (riskPercent / 100.0);
double pointValue = MarketInfo(Symbol(), MODE_TICKVALUE);
double rawLot = riskAmount / (stopPoints * pointValue);

double stepSize = MarketInfo(Symbol(), MODE_LOTSTEP);
double minLot = MarketInfo(Symbol(), MODE_MINLOT);
double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);

// Compound assignment and ternary operator
rawLot = MathFloor(rawLot / stepSize) * stepSize;
rawLot = (rawLot < minLot) ? minLot : (rawLot > maxLot) ? maxLot : rawLot;

return NormalizeDouble(rawLot, 2);
}

//+------------------------------------------------------------------+
//| Check if daily loss limit reached |
//+------------------------------------------------------------------+
bool IsMaxDailyLossReached() {
return g_dailyLoss >= InpMaxDailyLoss;
}
```

Operator Best Practices Checklist
  • [ ] Use parentheses to make complex expressions readable

  • [ ] Avoid nested ternary operators (use if-else instead)

  • [ ] Use compound assignments (+=, -=) for counters and accumulators

  • [ ] Always use parentheses when mixing && and || operators

  • [ ] Compare floating point numbers with caution (use NormalizeDouble)

  • [ ] Use comparison operators with Point() for price differences

  • [ ] Prefer positive logic (!false) over negative logic when possible


  • Reference:
  • MetaQuotes Ltd. "MQL4 Documentation - Operators" (2024)

  • Elder, Alexander. "Trading for a Living" (1993)


  • 9. Next Step
    Part 8 will explain Conditional Statements (if/else/switch) in MQL4 – Complete guide to controlling EA trading logic flow with if, else if, else, and switch statements including practical trading examples.