π’π Get Symbol Digits (GetSymbolDigits)ΒΆ
Sugar method: Returns the number of decimal places (precision) for a symbol.
API Information:
- Method:
sugar.GetSymbolDigits(symbol) - Timeout: 3 seconds
- Returns: Number of decimal digits
π Method SignatureΒΆ
π½ Input / β¬οΈ OutputΒΆ
| Input | Type | Description |
|---|---|---|
symbol |
string |
Trading symbol (e.g., "EURUSD") |
| Output | Type | Description |
|---|---|---|
int32 |
integer | Number of decimal places |
error |
error |
Error if symbol not found |
π¬ Just the EssentialsΒΆ
- What it is: Get the decimal precision used for price quotes.
- Why you need it: Price formatting, calculations, point size determination.
- Sanity check: EURUSD = 5 digits (1.10500), USDJPY = 3 digits (110.500).
π― When to UseΒΆ
β Price formatting - Display prices correctly
β Calculations - Determine point size
β Validation - Check price precision
β Rounding - Round prices to valid precision
π Usage ExamplesΒΆ
1) Basic usage - get digitsΒΆ
digits, err := sugar.GetSymbolDigits("EURUSD")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("EURUSD uses %d decimal places\n", digits)
// Calculate point size
pointSize := 1.0
for i := int32(0); i < digits; i++ {
pointSize /= 10.0
}
fmt.Printf("Point size: %.5f\n", pointSize)
2) Format price with correct precisionΒΆ
func FormatPrice(sugar *mt5.MT5Sugar, symbol string, price float64) string {
digits, err := sugar.GetSymbolDigits(symbol)
if err != nil {
return fmt.Sprintf("%.5f", price) // Default
}
format := fmt.Sprintf("%%.%df", digits)
return fmt.Sprintf(format, price)
}
// Usage:
price := 1.105003
formatted := FormatPrice(sugar, "EURUSD", price)
fmt.Printf("Price: %s\n", formatted) // "1.10500"
3) Round price to valid precisionΒΆ
func RoundToDigits(sugar *mt5.MT5Sugar, symbol string, price float64) (float64, error) {
digits, err := sugar.GetSymbolDigits(symbol)
if err != nil {
return 0, err
}
multiplier := math.Pow(10, float64(digits))
rounded := math.Round(price*multiplier) / multiplier
return rounded, nil
}
// Usage:
price := 1.1050033333
rounded, _ := RoundToDigits(sugar, "EURUSD", price)
fmt.Printf("Original: %.10f\n", price)
fmt.Printf("Rounded: %.5f\n", rounded) // 1.10500
4) Calculate point size from digitsΒΆ
digits, _ := sugar.GetSymbolDigits("EURUSD")
pointSize := math.Pow(10, -float64(digits))
fmt.Printf("Symbol: EURUSD\n")
fmt.Printf("Digits: %d\n", digits)
fmt.Printf("Point size: %.5f\n", pointSize)
// Calculate pip size (usually 10x point for 5-digit)
pipSize := pointSize * 10
fmt.Printf("Pip size: %.5f\n", pipSize)
5) Compare precision across symbolsΒΆ
symbols := []string{"EURUSD", "GBPUSD", "USDJPY", "XAUUSD", "BTCUSD"}
fmt.Println("Symbol Precision Comparison:")
fmt.Println("βββββββββββββββββββββββββββββββββββββββββ")
for _, symbol := range symbols {
digits, err := sugar.GetSymbolDigits(symbol)
if err != nil {
fmt.Printf("%-8s: Error - %v\n", symbol, err)
continue
}
pointSize := math.Pow(10, -float64(digits))
fmt.Printf("%-8s: %d digits (point: %.5f)\n",
symbol, digits, pointSize)
}
6) Validate price precisionΒΆ
func ValidatePricePrecision(sugar *mt5.MT5Sugar, symbol string, price float64) (bool, string) {
digits, err := sugar.GetSymbolDigits(symbol)
if err != nil {
return false, fmt.Sprintf("error: %v", err)
}
// Convert to string to count decimals
priceStr := fmt.Sprintf("%.10f", price)
parts := strings.Split(priceStr, ".")
if len(parts) != 2 {
return false, "invalid price format"
}
// Count actual decimal places (excluding trailing zeros)
decimals := strings.TrimRight(parts[1], "0")
actualDigits := len(decimals)
if actualDigits > int(digits) {
return false, fmt.Sprintf("price has %d decimals, max is %d",
actualDigits, digits)
}
return true, "valid precision"
}
// Usage:
price := 1.10500
valid, message := ValidatePricePrecision(sugar, "EURUSD", price)
if valid {
fmt.Printf("β
Price %f: %s\n", price, message)
} else {
fmt.Printf("β Price %f: %s\n", price, message)
}
7) Display price with symbol's precisionΒΆ
func DisplayPriceQuote(sugar *mt5.MT5Sugar, symbol string) {
digits, _ := sugar.GetSymbolDigits(symbol)
bid, _ := sugar.GetBid(symbol)
ask, _ := sugar.GetAsk(symbol)
format := fmt.Sprintf("%%.%df", digits)
fmt.Printf("Symbol: %s (%d digits)\n", symbol, digits)
fmt.Printf("Bid: %s\n", fmt.Sprintf(format, bid))
fmt.Printf("Ask: %s\n", fmt.Sprintf(format, ask))
}
// Usage:
DisplayPriceQuote(sugar, "EURUSD")
// Output:
// Symbol: EURUSD (5 digits)
// Bid: 1.10500
// Ask: 1.10502
8) Normalize price to symbol's precisionΒΆ
type PriceNormalizer struct {
Symbol string
Digits int32
Multiplier float64
}
func NewPriceNormalizer(sugar *mt5.MT5Sugar, symbol string) (*PriceNormalizer, error) {
digits, err := sugar.GetSymbolDigits(symbol)
if err != nil {
return nil, err
}
return &PriceNormalizer{
Symbol: symbol,
Digits: digits,
Multiplier: math.Pow(10, float64(digits)),
}, nil
}
func (pn *PriceNormalizer) Normalize(price float64) float64 {
return math.Round(price*pn.Multiplier) / pn.Multiplier
}
func (pn *PriceNormalizer) Format(price float64) string {
normalized := pn.Normalize(price)
format := fmt.Sprintf("%%.%df", pn.Digits)
return fmt.Sprintf(format, normalized)
}
func (pn *PriceNormalizer) GetPointSize() float64 {
return 1.0 / pn.Multiplier
}
// Usage:
normalizer, _ := NewPriceNormalizer(sugar, "EURUSD")
price := 1.1050033333
normalized := normalizer.Normalize(price)
formatted := normalizer.Format(price)
fmt.Printf("Original: %.10f\n", price)
fmt.Printf("Normalized: %.5f\n", normalized)
fmt.Printf("Formatted: %s\n", formatted)
fmt.Printf("Point size: %.5f\n", normalizer.GetPointSize())
9) Calculate price incrementsΒΆ
func CalculatePriceIncrements(sugar *mt5.MT5Sugar, symbol string, basePrice float64, steps int) {
digits, _ := sugar.GetSymbolDigits(symbol)
pointSize := math.Pow(10, -float64(digits))
fmt.Printf("Symbol: %s (%d digits)\n", symbol, digits)
fmt.Printf("Base price: %.*f\n", digits, basePrice)
fmt.Printf("Point size: %.5f\n\n", pointSize)
fmt.Println("Price increments:")
for i := -steps; i <= steps; i++ {
price := basePrice + (float64(i) * pointSize)
marker := " "
if i == 0 {
marker = "β"
}
fmt.Printf("%s %3d points: %.*f\n",
marker, i, digits, price)
}
}
// Usage:
CalculatePriceIncrements(sugar, "EURUSD", 1.10500, 5)
10) Advanced symbol precision managerΒΆ
type SymbolPrecisionManager struct {
cache map[string]int32
formatters map[string]string
}
func NewSymbolPrecisionManager() *SymbolPrecisionManager {
return &SymbolPrecisionManager{
cache: make(map[string]int32),
formatters: make(map[string]string),
}
}
func (spm *SymbolPrecisionManager) GetDigits(sugar *mt5.MT5Sugar, symbol string) (int32, error) {
// Check cache
if digits, exists := spm.cache[symbol]; exists {
return digits, nil
}
// Fetch from MT5
digits, err := sugar.GetSymbolDigits(symbol)
if err != nil {
return 0, err
}
// Cache
spm.cache[symbol] = digits
spm.formatters[symbol] = fmt.Sprintf("%%.%df", digits)
return digits, nil
}
func (spm *SymbolPrecisionManager) FormatPrice(sugar *mt5.MT5Sugar, symbol string, price float64) (string, error) {
digits, err := spm.GetDigits(sugar, symbol)
if err != nil {
return "", err
}
formatter := spm.formatters[symbol]
return fmt.Sprintf(formatter, price), nil
}
func (spm *SymbolPrecisionManager) NormalizePrice(sugar *mt5.MT5Sugar, symbol string, price float64) (float64, error) {
digits, err := spm.GetDigits(sugar, symbol)
if err != nil {
return 0, err
}
multiplier := math.Pow(10, float64(digits))
return math.Round(price*multiplier) / multiplier, nil
}
func (spm *SymbolPrecisionManager) GetPointSize(sugar *mt5.MT5Sugar, symbol string) (float64, error) {
digits, err := spm.GetDigits(sugar, symbol)
if err != nil {
return 0, err
}
return math.Pow(10, -float64(digits)), nil
}
func (spm *SymbolPrecisionManager) CalculatePipValue(
sugar *mt5.MT5Sugar,
symbol string,
volume float64,
) (float64, error) {
// Get symbol info for contract size
info, err := sugar.GetSymbolInfo(symbol)
if err != nil {
return 0, err
}
// Get point size
pointSize, err := spm.GetPointSize(sugar, symbol)
if err != nil {
return 0, err
}
// Pip = 10 points (for 5-digit broker)
pipSize := pointSize * 10
// Pip value = pip size Γ contract size Γ volume
pipValue := pipSize * info.ContractSize * volume
return pipValue, nil
}
func (spm *SymbolPrecisionManager) GenerateReport(sugar *mt5.MT5Sugar, symbols []string) {
fmt.Println("βββββββββββββββββββββββββββββββββββββββββ")
fmt.Println("β PRECISION ANALYSIS REPORT β")
fmt.Println("βββββββββββββββββββββββββββββββββββββββββ")
for _, symbol := range symbols {
digits, err := spm.GetDigits(sugar, symbol)
if err != nil {
fmt.Printf("%-8s: Error - %v\n", symbol, err)
continue
}
pointSize, _ := spm.GetPointSize(sugar, symbol)
pipValue, _ := spm.CalculatePipValue(sugar, symbol, 1.0)
fmt.Printf("\n%-8s:\n", symbol)
fmt.Printf(" Digits: %d\n", digits)
fmt.Printf(" Point: %.5f\n", pointSize)
fmt.Printf(" Pip value: $%.2f per lot\n", pipValue)
// Show example price
bid, _ := sugar.GetBid(symbol)
formatted, _ := spm.FormatPrice(sugar, symbol, bid)
fmt.Printf(" Example: %s\n", formatted)
}
}
// Usage:
manager := NewSymbolPrecisionManager()
// Format prices (cached for performance)
price1, _ := manager.FormatPrice(sugar, "EURUSD", 1.105003)
price2, _ := manager.FormatPrice(sugar, "USDJPY", 110.5033)
fmt.Printf("EURUSD: %s\n", price1) // 1.10500
fmt.Printf("USDJPY: %s\n", price2) // 110.503
// Normalize price
normalized, _ := manager.NormalizePrice(sugar, "EURUSD", 1.1050033)
fmt.Printf("Normalized: %.5f\n", normalized)
// Calculate pip value
pipValue, _ := manager.CalculatePipValue(sugar, "EURUSD", 1.0)
fmt.Printf("Pip value: $%.2f\n", pipValue)
// Generate report
symbols := []string{"EURUSD", "GBPUSD", "USDJPY", "XAUUSD"}
manager.GenerateReport(sugar, symbols)
π Related MethodsΒΆ
π¬ Symbol information:
GetSymbolInfo()- Gets Digits as part of full infoGetMinStopLevel()- Stop level in points
π¬ Price methods:
GetBid()/GetAsk()- Get current prices
β οΈ Common PitfallsΒΆ
1) Confusing digits with decimalsΒΆ
// β WRONG - digits = total decimal places
digits := 5
// For 1.10500: digits = 5 (all decimals)
// β
CORRECT - understand it's decimal precision
digits := 5
pointSize := math.Pow(10, -float64(digits)) // 0.00001
2) Not rounding pricesΒΆ
// β WRONG - using raw float
price := 1.1050033333
sugar.BuyMarket("EURUSD", 0.1) // Might fail!
// β
CORRECT - round to valid precision
digits, _ := sugar.GetSymbolDigits("EURUSD")
multiplier := math.Pow(10, float64(digits))
price = math.Round(price*multiplier) / multiplier
3) Hardcoding precisionΒΆ
// β WRONG - assuming 5 digits
price := fmt.Sprintf("%.5f", value)
// β
CORRECT - use actual digits
digits, _ := sugar.GetSymbolDigits(symbol)
format := fmt.Sprintf("%%.%df", digits)
price := fmt.Sprintf(format, value)
π Pro TipsΒΆ
-
Cache digits - Digits never change, safe to cache
-
Point size - Calculate as 10^(-digits)
-
Formatting - Use digits for display formatting
-
Validation - Round prices to symbol's precision
-
Pip = 10 points - For 5-digit brokers (EURUSD, GBPUSD)
π Common Digit ValuesΒΆ
Standard Forex (5 digits):
EURUSD, GBPUSD, etc. = 5 digits
- Example: 1.10500
- Point: 0.00001
- Pip: 0.0001 (10 points)
Yen pairs (3 digits):
USDJPY, EURJPY, etc. = 3 digits
- Example: 110.500
- Point: 0.001
- Pip: 0.01 (10 points)
Gold (2 digits):
XAUUSD = 2 digits
- Example: 1850.50
- Point: 0.01
- Pip: 0.10 (10 points)
Crypto (varies):
BTCUSD = 2 digits
- Example: 45000.50
- Point: 0.01
See also: GetSymbolInfo.md, GetMinStopLevel.md