Hướng dẫn sử dụng kiểu double để xử lý giá cả, volume, và các phép tính thập phân chính xác trong trading.
double là kiểu dữ liệu floating-point 64-bit trong MQL5, có độ chính xác khoảng 15-17 chữ số thập phân. Đây là kiểu dữ liệu quan trọng nhất trong trading vì hầu hết giá cả, volume, và indicator values đều là số thực.
// Giá cả
double askPrice = 1.12345;
double bidPrice = 1.12340;
// Volume và lot size
double volume = 0.01;
double maxLot = 100.0;
// Indicator values
double maValue = 1.12300;
double rsiValue = 65.75;
// Percentage và ratios
double riskPercent = 2.0;
double rewardRatio = 3.0;
// Lấy số digits của symbol
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
Print("Digits: ", digits); // Ví dụ: 5 (cho EURUSD)
// Normalize giá theo digits
double price = 1.123456789;
double normalizedPrice = NormalizeDouble(price, digits);
Print("Normalized: ", normalizedPrice); // 1.12346
// Point value (thường = 0.00001 cho 5-digit broker)
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
Print("Point: ", point); // 0.00001
❌ SAI: So sánh trực tiếp
double a = 0.1 + 0.2; // = 0.30000000000000004
double b = 0.3;
if(a == b) // FALSE! (floating-point error)
Print("Equal");
✅ ĐÚNG: So sánh với epsilon
double a = 0.1 + 0.2;
double b = 0.3;
double epsilon = 0.00001; // Độ sai số cho phép
if(MathAbs(a - b) < epsilon)
Print("Equal"); // TRUE
// Tính lot size dựa trên risk management
double accountBalance = AccountInfoDouble(ACCOUNT_BALANCE);
double riskPercent = 2.0; // 2%
int stopLossPips = 50;
double pipValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
double riskAmount = accountBalance * riskPercent / 100.0;
double lotSize = riskAmount / (stopLossPips * pipValue);
lotSize = NormalizeDouble(lotSize, 2); // 0.01, 0.1, 1.0, etc.
// Kiểm tra lot size với giới hạn
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
if(lotSize < minLot) lotSize = minLot;
if(lotSize > maxLot) lotSize = maxLot;
// Tính profit/loss tiềm năng
double entryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double takeProfitPrice = entryPrice + 100 * point;
double potentialProfit = (takeProfitPrice - entryPrice) / point * lotSize * pipValue;
Print("Potential Profit: $", NormalizeDouble(potentialProfit, 2));
double value = -123.456;
// Giá trị tuyệt đối
double absolute = MathAbs(value); // 123.456
// Làm tròn
double rounded = MathRound(value); // -123
double ceil = MathCeil(value); // -123
double floor = MathFloor(value); // -124
// Min/Max
double min = MathMin(100.5, 200.3); // 100.5
double max = MathMax(100.5, 200.3); // 200.3
// Căn bậc hai và lũy thừa
double sqrt = MathSqrt(16.0); // 4.0
double power = MathPow(2.0, 3.0); // 8.0
// Lấy giá hiện tại
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double spread = ask - bid;
int spreadPips = (int)((spread / point) + 0.5);
// Copy price data
double high[], low[], close[];
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
ArraySetAsSeries(close, true);
CopyHigh(_Symbol, PERIOD_CURRENT, 0, 100, high);
CopyLow(_Symbol, PERIOD_CURRENT, 0, 100, low);
CopyClose(_Symbol, PERIOD_CURRENT, 0, 100, close);
// Tính average true range
double atr = 0;
for(int i = 1; i < 14; i++) {
double trueRange = MathMax(high[i], close[i-1]) - MathMin(low[i], close[i-1]);
atr += trueRange;
}
atr = atr / 14.0;
Print("ATR(14): ", NormalizeDouble(atr, digits));
NormalizeDouble() trước khi gửi order==if(divisor > 0.0001)SymbolInfoDouble() để lấy thông tin symbolif(price == 0), dùng if(price < 0.000001)