106 lines
3.1 KiB
Plaintext
106 lines
3.1 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| Utilities.mqh - Helper utility functions |
|
|
//| Price normalization, lot normalization, etc. |
|
|
//+------------------------------------------------------------------+
|
|
|
|
#ifndef __UTILITIES_MQH__
|
|
#define __UTILITIES_MQH__
|
|
|
|
class CUtilities
|
|
{
|
|
public:
|
|
// Normalize price to bid/ask
|
|
static double NormalizePrice(const string symbol, double price)
|
|
{
|
|
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
|
|
int digits = GetDigits(symbol);
|
|
return NormalizeDouble(price, digits);
|
|
}
|
|
|
|
// Normalize lot size to contract size step
|
|
static double NormalizeLot(const string symbol, double lot)
|
|
{
|
|
double min_lot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
|
|
double max_lot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
|
|
double lot_step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
|
|
|
|
// Guard against invalid broker volume data
|
|
if(min_lot <= 0.0 || max_lot <= 0.0 || lot_step <= 0.0 || max_lot < min_lot)
|
|
return 0.0;
|
|
|
|
// Compute precision from volume step
|
|
int precision = 0;
|
|
double s = lot_step;
|
|
const double eps = 1e-9;
|
|
while(MathAbs(MathRound(s) - s) > eps && precision < 8)
|
|
{
|
|
s *= 10.0;
|
|
precision++;
|
|
}
|
|
|
|
// Round down to nearest step
|
|
double normalized = MathFloor(lot / lot_step) * lot_step;
|
|
normalized = NormalizeDouble(normalized, precision);
|
|
|
|
// If normalized is below minimum, indicate invalid by returning 0.0
|
|
if(normalized < min_lot)
|
|
return 0.0;
|
|
|
|
// Clamp to maximum allowed (rounded down to step)
|
|
if(normalized > max_lot)
|
|
{
|
|
normalized = MathFloor(max_lot / lot_step) * lot_step;
|
|
normalized = NormalizeDouble(normalized, precision);
|
|
if(normalized < min_lot)
|
|
return 0.0;
|
|
}
|
|
|
|
return normalized;
|
|
}
|
|
|
|
// Convert points to price distance
|
|
static double PointsToPrice(const string symbol, int points)
|
|
{
|
|
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
|
|
return (double)points * point;
|
|
}
|
|
|
|
// Convert price distance to points
|
|
static int PriceToPoints(const string symbol, double price_distance)
|
|
{
|
|
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
|
|
return (int)(price_distance / point);
|
|
}
|
|
|
|
// Get point value
|
|
static double GetPoint(const string symbol)
|
|
{
|
|
return SymbolInfoDouble(symbol, SYMBOL_POINT);
|
|
}
|
|
|
|
// Get digits
|
|
static int GetDigits(const string symbol)
|
|
{
|
|
long digits = SymbolInfoInteger(symbol, SYMBOL_DIGITS);
|
|
if(digits < 0)
|
|
digits = 0;
|
|
if(digits > 255)
|
|
digits = 255;
|
|
return (int)digits;
|
|
}
|
|
|
|
// Safe double comparison with precision
|
|
static bool DoubleEquals(double a, double b, double tolerance = 0.00001)
|
|
{
|
|
return MathAbs(a - b) < tolerance;
|
|
}
|
|
|
|
// Get contract size (lot multiplier)
|
|
static double GetContractSize(const string symbol)
|
|
{
|
|
return SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE);
|
|
}
|
|
};
|
|
|
|
#endif //__UTILITIES_MQH__
|