Why Data Types Matter in EA Development
Every piece of data in an MQL4 program has a specific type. Understanding data types is the foundation of writing error-free EA code. Using the correct data type prevents compilation errors and ensures your EA calculates correctly.
Complete MQL4 Data Type Reference Table
| Data Type | Purpose | Value Range | Memory Size | Example |
|-----------|---------|-------------|-------------|---------|
| int | Integer numbers | -2,147,483,648 to 2,147,483,647 | 4 bytes | int magic = 12345; |
| double | Decimal numbers | ±1.7e-308 to ±1.7e+308 | 8 bytes | double price = 1.09250; |
| string | Text characters | Up to 2,147,483,647 characters | Variable | string symbol = "EURUSD"; |
| bool | Boolean logic | true or false (1 or 0) | 1 byte | bool isBuy = true; |
| datetime | Date and time | Jan 1, 1970 to Dec 31, 3000 | 8 bytes | datetime now = TimeCurrent(); |
| color | Color values | 0 to 16,777,215 (RGB) | 4 bytes | color clrRed = clrRed; |
1. Integer (int) - Whole Numbers
Integers are used for counting orders, magic numbers, slippage settings, and array indices.
```mql4
// Integer variable declarations
int magicNumber = 12345; // EA identifier
int slippage = 30; // Allowed slippage in points
int totalOrders = 0; // Order counter
int stopLossPoints = 50; // Stop loss in points
int takeProfitPoints = 100; // Take profit in points
// Integer arithmetic
int openOrders = OrdersTotal();
int pendingOrders = OrdersTotal() - openOrders;
int total = openOrders + pendingOrders;
// Integer best practices
// Use constants for fixed values
#define MAX_ORDERS 10
#define MIN_STOP_LOSS 20
if(openOrders < MAX_ORDERS) {
// Safe to open new order
}
```
2. Double - Decimal Numbers
Doubles handle all price values, stop loss/take profit distances, and indicator calculations.
```mql4
// Double variable declarations
double lotSize = 0.1; // Trading volume
double entryPrice = 0; // Order entry price
double stopLossPrice = 0; // Stop loss price
double takeProfitPrice = 0; // Take profit price
double accountBalance = AccountBalance();
// Risk-based lot size calculation
double CalculateLotSize(double riskPercent, double stopLossPoints) {
double riskAmount = AccountBalance() * riskPercent / 100;
double tickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
double lotSize = riskAmount / (stopLossPoints * tickValue);
// Normalize to step size
double stepSize = MarketInfo(Symbol(), MODE_LOTSTEP);
lotSize = MathFloor(lotSize / stepSize) * stepSize;
// Apply min/max limits
double minLot = MarketInfo(Symbol(), MODE_MINLOT);
double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);
lotSize = MathMax(minLot, MathMin(maxLot, lotSize));
return NormalizeDouble(lotSize, 2);
}
// Price normalization (CRITICAL for OrderSend)
double NormalizePrice(double price, string symbol) {
int digits = (int)MarketInfo(symbol, MODE_DIGITS);
return NormalizeDouble(price, digits);
}
```
3. String - Text Data
Strings store symbol names, file paths, and dynamic text for chart display.
```mql4
// String variable declarations
string symbolName = "EURUSD";
string logMessage = "";
string filePath = "C:\\MT4\\Files\\log.txt";
// String concatenation
string message = "Buy signal detected on " + symbolName + " at " + DoubleToString(entryPrice, 5);
// String utility functions
void WriteToLog(string text) {
string timestamp = TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES);
string logLine = "[" + timestamp + "] " + text;
Print(logLine);
}
// Extract currency pair parts
string baseCurrency = StringSubstr(symbolName, 0, 3); // "EUR"
string quoteCurrency = StringSubstr(symbolName, 3, 3); // "USD"
```
4. Boolean (bool) - True/False Logic
Booleans control trade conditions and state flags.
```mql4
// Boolean variable declarations
bool isNewBar = false;
bool hasOpenPosition = false;
bool allowTrading = true;
bool isBuySignal = false;
bool isSellSignal = false;
// Trading condition with boolean flags
void CheckTradeConditions() {
bool trendUp = iMA(NULL, 0, 20, 0, MODE_SMA, PRICE_CLOSE, 1) >
iMA(NULL, 0, 50, 0, MODE_SMA, PRICE_CLOSE, 1);
bool rsiOversold = iRSI(NULL, 0, 14, PRICE_CLOSE, 1) < 30;
bool noPosition = CountOrders(magicNumber) == 0;
if(trendUp && rsiOversold && noPosition && allowTrading) {
isBuySignal = true;
OpenBuyOrder();
}
}
// State flags for EA logic
static bool g_firstRun = true;
static bool g_tradeLock = false;
void OnTick() {
if(g_firstRun) {
Print("EA started first time on this chart");
g_firstRun = false;
}
if(g_tradeLock) {
Print("Trade locked - skipping this tick");
return;
}
}
```
5. Datetime - Time Management
Datetime variables handle all time-related operations including trade timing and bar detection.
```mql4
// Datetime variable declarations
datetime currentTime = TimeCurrent();
datetime lastTradeTime = 0;
datetime sessionStart = D'2024.01.15 08:00:00';
datetime expirationDate = D'2024.12.31 23:59:59';
// Time-based trade filtering
bool IsTradingHours() {
datetime now = TimeCurrent();
MqlDateTime timeStruct;
TimeToStruct(now, timeStruct);
int hour = timeStruct.hour;
int minute = timeStruct.min;
int dayOfWeek = timeStruct.day_of_week; // 0=Sunday, 6=Saturday
// Trading only Monday to Friday, 8:00 to 17:00
if(dayOfWeek >= 1 && dayOfWeek <= 5) {
if(hour >= 8 && hour < 17) {
return true;
}
// Allow 8:30 specifically
if(hour == 8 && minute >= 30) return true;
}
return false;
}
// Cooldown timer
bool IsCooldownExpired(int seconds) {
if(TimeCurrent() - lastTradeTime >= seconds) {
lastTradeTime = TimeCurrent();
return true;
}
return false;
}
// Get midnight timestamp
datetime GetMidnight() {
MqlDateTime tm;
TimeToStruct(TimeCurrent(), tm);
tm.hour = 0;
tm.min = 0;
tm.sec = 0;
return StructToTime(tm);
}
```
6. Color - Chart Visuals
Color variables enhance chart visualization for manual monitoring.
```mql4
// Predefined color constants
color buyArrowColor = clrGreen;
color sellArrowColor = clrRed;
color textColor = clrWhite;
color backgroundColor = clrBlack;
// RGB color creation
color customBlue = C'0,100,255';
color customOrange = 0x0000FFAA; // Hexadecimal format
// Drawing signals on chart
void DrawSignal(bool isBuy, double price, datetime time) {
string arrowName = "Signal_" + IntegerToString(time);
if(isBuy) {
ObjectCreate(0, arrowName, OBJ_ARROW_UP, 0, time, price);
ObjectSetInteger(0, arrowName, OBJPROP_COLOR, clrGreen);
} else {
ObjectCreate(0, arrowName, OBJ_ARROW_DOWN, 0, time, price);
ObjectSetInteger(0, arrowName, OBJPROP_COLOR, clrRed);
}
ObjectSetInteger(0, arrowName, OBJPROP_WIDTH, 2);
}
```
Variable Scope and Lifetime
```mql4
// GLOBAL scope - accessible everywhere, lifetime = entire EA runtime
double g_globalVariable = 100;
int g_tickCount = 0;
int OnInit() {
// LOCAL scope - only inside OnInit(), destroyed after function ends
int localCounter = 0;
localCounter++;
g_tickCount = 0;
return(INIT_SUCCEEDED);
}
void OnTick() {
// STATIC local - preserves value between function calls
static int staticCounter = 0;
staticCounter++;
// Regular local - reset to 0 each OnTick
int localCounter = 0;
localCounter++;
g_tickCount++; // Access global variable
Print("Static: ", staticCounter, " | Local: ", localCounter);
// Output: Static: 1,2,3... | Local: 1,1,1...
}
// Scope Hierarchy (from highest to lowest priority)
// 1. Local variables (inside function)
// 2. Function parameters
// 3. Global variables
```
Type Conversion (Casting)
```mql4
void TypeConversionExamples() {
// Implicit conversion (automatic)
double price = 1.09250;
int priceInt = price; // 1 (truncates decimal)
int points = 50;
double pointsDouble = points; // 50.0
// Explicit conversion (manual)
double precisePrice = 1.09250;
int normalizedPrice = (int)(precisePrice * 100000); // 109250
// String to number
string priceStr = "1.09250";
double priceFromString = StringToDouble(priceStr);
// Number to string
double accountBalance = AccountBalance();
string balanceStr = DoubleToString(accountBalance, 2);
string magicStr = IntegerToString(magicNumber);
// Datetime to string
datetime now = TimeCurrent();
string timeStr = TimeToString(now, TIME_DATE|TIME_MINUTES);
// String to datetime
string dateStr = "2024.01.15 14:30:00";
datetime parsedDate = StringToTime(dateStr);
}
```
Complete EA Template with Proper Data Types
```mql4
//+------------------------------------------------------------------+
//| DataTypesEA |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024"
#property version "1.00"
#property strict
// Input parameters
input double InpLotSize = 0.1; // Trading lot size
input int InpMagic = 12345; // EA magic number
input int InpSlippage = 30; // Slippage in points
input bool InpUseTimeFilter = true; // Enable time filter
input string InpSymbol = "EURUSD"; // Trading symbol
// Global variables
double g_spread;
int g_totalOrders;
bool g_initialized = false;
datetime g_lastTradeTime = 0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit() {
g_spread = MarketInfo(InpSymbol, MODE_SPREAD);
Print("EA initialized on ", InpSymbol, " with spread: ", g_spread);
g_initialized = true;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick() {
if(!g_initialized) return;
static datetime lastBarTime = 0;
if(Time[0] == lastBarTime) return;
lastBarTime = Time[0];
if(InpUseTimeFilter && !IsTradingHours()) return;
ExecuteStrategy();
}
//+------------------------------------------------------------------+
//| Strategy execution |
//+------------------------------------------------------------------+
void ExecuteStrategy() {
double maFast = iMA(InpSymbol, 0, 10, 0, MODE_SMA, PRICE_CLOSE, 1);
double maSlow = iMA(InpSymbol, 0, 30, 0, MODE_SMA, PRICE_CLOSE, 1);
if(maFast > maSlow && CountOrders() == 0) {
OpenBuy();
}
else if(maFast < maSlow && CountOrders() == 0) {
OpenSell();
}
}
```
Common Data Type Errors and Solutions
| Error | Cause | Solution |
|-------|-------|----------|
| "possible loss of data" | Assigning double to int | Use explicit cast: (int)variable |
| "string cannot be converted" | Mixing string and number | Use IntegerToString() or DoubleToString() |
| "undeclared identifier" | Variable not declared before use | Declare variable in correct scope |
| "true - cannot convert" | Using boolean in numeric context | Check logic expressions carefully |
| "'price' - not all control paths return" | Function missing return value | Add return statement for all paths |
Data Type Best Practices Checklist
Reference:
9. Next Step
Part 7 will explain Operators and Expressions in MQL4 – Arithmetic, comparison, logical, and assignment operators with practical EA examples and operator precedence rules.