MT5Service - Symbol Methods (Mid-Level API)ΒΆ
13 methods for working with symbols and their parameters with clean Go types
π§© API Layer: MID-LEVEL - wrappers over MT5Account with convenient DTO structures
Implementation:
These methods are implemented in examples/mt5/MT5Service.go, which wraps package/Helpers/MT5Account.go low-level API with convenient helpers for ease of use.
Demo files:
examples/demos/service/04_service_demo.go- comprehensive examples of all service wrapper methodsexamples/demos/service/05_service_streaming.go- streaming methods examples
π― Why These Methods ExistΒΆ
Problem: In MT5Account, to get symbol parameters you need to make multiple calls:
// Low-level (MT5Account) - 3 calls for 3 parameters:
bidData, _ := account.SymbolInfoDouble(ctx, &pb.SymbolInfoDoubleRequest{
Symbol: "EURUSD",
Type: pb.SymbolInfoDoubleProperty_SYMBOL_BID,
})
bid := bidData.Value // β unpacking
askData, _ := account.SymbolInfoDouble(ctx, &pb.SymbolInfoDoubleRequest{
Symbol: "EURUSD",
Type: pb.SymbolInfoDoubleProperty_SYMBOL_ASK,
})
ask := askData.Value // β unpacking
digitsData, _ := account.SymbolInfoInteger(ctx, &pb.SymbolInfoIntegerRequest{
Symbol: "EURUSD",
Type: pb.SymbolInfoIntegerProperty_SYMBOL_DIGITS,
})
digits := digitsData.Value // β unpacking
Solution: MT5Service provides direct methods and batch operations:
// Mid-level (MT5Service) - 1 call for all parameters:
symbols, _, _ := service.GetSymbolParamsMany(ctx, nil, nil, nil, nil)
for _, s := range symbols {
fmt.Printf("%s: Bid=%.5f, Ask=%.5f, Digits=%d\n",
s.Name, s.Bid, s.Ask, s.Digits)
}
Advantages:
- β One GetSymbolParamsMany call instead of 10+ SymbolInfo* calls
- β Returns clean Go types (float64, int64, string)
- β SymbolTick with time.Time (not Unix timestamp)
- β SessionTime with time.Time (not protobuf Timestamp)
- β Automatic timestamp conversion
π All 13 MethodsΒΆ
| Method | Returns | Low-Level Equivalent |
|---|---|---|
GetSymbolsTotal(ctx, selectedOnly) |
int32 |
SymbolsTotal(ctx, req) + .Total |
SymbolExist(ctx, symbol) |
(bool, bool) |
SymbolExist(ctx, req) + .Exists, .IsCustom |
GetSymbolName(ctx, index, selectedOnly) |
string |
SymbolName(ctx, req) + .Name |
SymbolSelect(ctx, symbol, select_) |
bool |
SymbolSelect(ctx, req) + .Success |
IsSymbolSynchronized(ctx, symbol) |
bool |
SymbolIsSynchronized(ctx, req) + .Synchronized |
GetSymbolDouble(ctx, symbol, property) |
float64 |
SymbolInfoDouble(ctx, req) + .Value |
GetSymbolInteger(ctx, symbol, property) |
int64 |
SymbolInfoInteger(ctx, req) + .Value |
GetSymbolString(ctx, symbol, property) |
string |
SymbolInfoString(ctx, req) + .Value |
GetSymbolMarginRate(ctx, symbol, orderType) |
*SymbolMarginRate |
SymbolInfoMarginRate(ctx, req) + unpacking |
GetSymbolTick(ctx, symbol) |
*SymbolTick |
SymbolInfoTick(ctx, req) + time.Time conversion |
GetSymbolSessionQuote(ctx, symbol, day, idx) |
*SessionTime |
SymbolInfoSessionQuote(ctx, req) + .AsTime() |
GetSymbolSessionTrade(ctx, symbol, day, idx) |
*SessionTime |
SymbolInfoSessionTrade(ctx, req) + .AsTime() |
GetSymbolParamsMany(ctx, name, sort, page, perPage) |
[]SymbolParams |
SymbolParamsMany(ctx, req) + unpacking |
π¦ DTO StructuresΒΆ
SymbolParamsΒΆ
type SymbolParams struct {
Name string // Symbol name (EURUSD, GBPUSD, etc.)
Bid float64 // Current Bid price
Ask float64 // Current Ask price
Last float64 // Last deal price
Point float64 // Point size (minimal price change)
Digits int32 // Number of decimal places
Spread int32 // Current spread in points
VolumeMin float64 // Minimum volume for trading
VolumeMax float64 // Maximum volume for trading
VolumeStep float64 // Volume step
TradeTickSize float64 // Trade tick size
TradeTickValue float64 // Trade tick value
TradeContractSize float64 // Contract size
SwapLong float64 // Swap for long positions
SwapShort float64 // Swap for short positions
MarginInitial float64 // Initial margin requirement
MarginMaintenance float64 // Maintenance margin requirement
}
Advantage: All important symbol parameters in one structure.
SymbolTickΒΆ
type SymbolTick struct {
Time time.Time // Tick time (already converted from Unix)
Bid float64 // Current Bid price
Ask float64 // Current Ask price
Last float64 // Last deal price
Volume uint64 // Tick volume
TimeMS int64 // Tick time in milliseconds
Flags uint32 // Tick flags
VolumeReal float64 // Tick volume with decimal precision
}
Advantage: Time is already time.Time, no manual conversion from Unix timestamp needed.
SymbolMarginRateΒΆ
type SymbolMarginRate struct {
InitialMarginRate float64 // Initial margin rate
MaintenanceMarginRate float64 // Maintenance margin rate
}
SessionTimeΒΆ
type SessionTime struct {
From time.Time // Session start time (already converted)
To time.Time // Session end time (already converted)
}
Advantage: From/To are already time.Time, no .AsTime() calls needed.
π Method SignaturesΒΆ
1) GetSymbolsTotalΒΆ
Returns the number of available symbols.
selectedOnly=true- only symbols in Market WatchselectedOnly=false- all symbols
2) SymbolExistΒΆ
Checks if a symbol exists in the terminal.
Returns: (exists, isCustom, error)
3) GetSymbolNameΒΆ
func (s *MT5Service) GetSymbolName(
ctx context.Context,
index int32,
selectedOnly bool,
) (string, error)
Gets symbol name by index.
4) SymbolSelectΒΆ
func (s *MT5Service) SymbolSelect(
ctx context.Context,
symbol string,
select_ bool,
) (bool, error)
Adds/removes a symbol to/from Market Watch.
select_=true- addselect_=false- remove
5) IsSymbolSynchronizedΒΆ
Checks if symbol data is synchronized with the server.
6-8) GetSymbolDouble / GetSymbolInteger / GetSymbolStringΒΆ
func (s *MT5Service) GetSymbolDouble(
ctx context.Context,
symbol string,
property pb.SymbolInfoDoubleProperty,
) (float64, error)
func (s *MT5Service) GetSymbolInteger(
ctx context.Context,
symbol string,
property pb.SymbolInfoIntegerProperty,
) (int64, error)
func (s *MT5Service) GetSymbolString(
ctx context.Context,
symbol string,
property pb.SymbolInfoStringProperty,
) (string, error)
Get a single symbol property by ID.
Available Double properties:
SYMBOL_BID- Bid priceSYMBOL_ASK- Ask priceSYMBOL_POINT- point sizeSYMBOL_VOLUME_MIN- minimum volumeSYMBOL_VOLUME_MAX- maximum volume
Available Integer properties:
SYMBOL_DIGITS- number of decimal placesSYMBOL_SPREAD- spread in pointsSYMBOL_TRADE_MODE- trading mode
Available String properties:
SYMBOL_DESCRIPTION- symbol descriptionSYMBOL_PATH- path in symbols tree
9) GetSymbolMarginRateΒΆ
func (s *MT5Service) GetSymbolMarginRate(
ctx context.Context,
symbol string,
orderType pb.ENUM_ORDER_TYPE,
) (*SymbolMarginRate, error)
Gets margin rates for a symbol and order type.
10) GetSymbolTickΒΆ
Gets the last tick for a symbol.
Advantage: Time is already time.Time, no manual conversion needed.
11-12) GetSymbolSessionQuote / GetSymbolSessionTradeΒΆ
func (s *MT5Service) GetSymbolSessionQuote(
ctx context.Context,
symbol string,
dayOfWeek pb.DayOfWeek,
sessionIndex uint32,
) (*SessionTime, error)
func (s *MT5Service) GetSymbolSessionTrade(
ctx context.Context,
symbol string,
dayOfWeek pb.DayOfWeek,
sessionIndex uint32,
) (*SessionTime, error)
Get trading/quote session times.
Advantage: From/To are already time.Time, no .AsTime() calls needed.
13) GetSymbolParamsManyΒΆ
func (s *MT5Service) GetSymbolParamsMany(
ctx context.Context,
symbolName *string,
sortType *pb.AH_SYMBOL_PARAMS_MANY_SORT_TYPE,
pageNumber *int32,
itemsPerPage *int32,
) ([]SymbolParams, int32, error)
RECOMMENDED method - gets parameters for multiple symbols in one call.
Returns: (symbols []SymbolParams, total int32, error)
Parameters (all optional):
symbolName- name filter (nil = all symbols)sortType- sort type (nil = default)pageNumber- page number (nil = 1)itemsPerPage- items per page (nil = all)
π‘ Usage ExamplesΒΆ
Example 1: Getting Current Price (Bid/Ask)ΒΆ
// β BEFORE (MT5Account) - 2 calls, 6 lines:
bidReq := &pb.SymbolInfoDoubleRequest{
Symbol: "EURUSD",
Type: pb.SymbolInfoDoubleProperty_SYMBOL_BID,
}
bidData, _ := account.SymbolInfoDouble(ctx, bidReq)
bid := bidData.Value
askReq := &pb.SymbolInfoDoubleRequest{
Symbol: "EURUSD",
Type: pb.SymbolInfoDoubleProperty_SYMBOL_ASK,
}
askData, _ := account.SymbolInfoDouble(ctx, askReq)
ask := askData.Value
fmt.Printf("EURUSD: Bid=%.5f, Ask=%.5f\n", bid, ask)
// β
AFTER (MT5Service) - 1 GetSymbolTick call, 3 lines:
tick, _ := service.GetSymbolTick(ctx, "EURUSD")
fmt.Printf("EURUSD: Bid=%.5f, Ask=%.5f\n", tick.Bid, tick.Ask)
fmt.Printf("Time: %s\n", tick.Time.Format("15:04:05"))
Code reduction: 60% (10 lines β 4 lines)
Example 2: Getting All Symbol ParametersΒΆ
// β BEFORE (MT5Account) - 10+ calls for different properties:
bidData, _ := account.SymbolInfoDouble(ctx, &pb.SymbolInfoDoubleRequest{
Symbol: "EURUSD",
Type: pb.SymbolInfoDoubleProperty_SYMBOL_BID,
})
askData, _ := account.SymbolInfoDouble(ctx, &pb.SymbolInfoDoubleRequest{
Symbol: "EURUSD",
Type: pb.SymbolInfoDoubleProperty_SYMBOL_ASK,
})
digitsData, _ := account.SymbolInfoInteger(ctx, &pb.SymbolInfoIntegerRequest{
Symbol: "EURUSD",
Type: pb.SymbolInfoIntegerProperty_SYMBOL_DIGITS,
})
// ... 7 more calls for other properties
// β
AFTER (MT5Service) - 1 GetSymbolParamsMany call:
symbolName := "EURUSD"
symbols, _, _ := service.GetSymbolParamsMany(ctx, &symbolName, nil, nil, nil)
if len(symbols) > 0 {
s := symbols[0]
fmt.Printf("Symbol: %s\n", s.Name)
fmt.Printf("Bid: %.5f, Ask: %.5f\n", s.Bid, s.Ask)
fmt.Printf("Digits: %d, Spread: %d\n", s.Digits, s.Spread)
fmt.Printf("Volume: %.2f - %.2f (step: %.2f)\n",
s.VolumeMin, s.VolumeMax, s.VolumeStep)
fmt.Printf("Swap Long: %.2f, Short: %.2f\n", s.SwapLong, s.SwapShort)
}
Code reduction: 70% (30+ lines β 9 lines)
Example 3: Getting List of All SymbolsΒΆ
// β
MT5Service - get all symbols in one call
symbols, total, err := service.GetSymbolParamsMany(ctx, nil, nil, nil, nil)
if err != nil {
return err
}
fmt.Printf("Total symbols: %d\n", total)
for i, s := range symbols {
fmt.Printf("%d. %s: Bid=%.5f, Ask=%.5f, Digits=%d\n",
i+1, s.Name, s.Bid, s.Ask, s.Digits)
}
Example 4: Filtering Symbols with High SpreadΒΆ
// β
MT5Service - filter symbols by spread
symbols, _, err := service.GetSymbolParamsMany(ctx, nil, nil, nil, nil)
if err != nil {
return err
}
fmt.Println("Symbols with spread > 10 points:")
for _, s := range symbols {
if s.Spread > 10 {
fmt.Printf("%s: Spread=%d points (%.5f)\n",
s.Name, s.Spread, float64(s.Spread)*s.Point)
}
}
Example 5: Checking Symbol Availability for TradingΒΆ
// β
MT5Service - comprehensive symbol check
func IsSymbolTradeable(service *mt5.MT5Service, symbol string) (bool, error) {
ctx := context.Background()
// 1. Check existence
exists, isCustom, err := service.SymbolExist(ctx, symbol)
if err != nil {
return false, err
}
if !exists {
fmt.Printf("β Symbol %s does not exist\n", symbol)
return false, nil
}
if isCustom {
fmt.Printf("β οΈ Symbol %s is custom\n", symbol)
}
// 2. Add to Market Watch (if needed)
success, err := service.SymbolSelect(ctx, symbol, true)
if err != nil || !success {
fmt.Printf("β Cannot add %s to Market Watch\n", symbol)
return false, err
}
// 3. Check synchronization
synced, err := service.IsSymbolSynchronized(ctx, symbol)
if err != nil || !synced {
fmt.Printf("β Symbol %s is not synchronized\n", symbol)
return false, err
}
// 4. Check trading parameters
symbolName := symbol
symbols, _, err := service.GetSymbolParamsMany(ctx, &symbolName, nil, nil, nil)
if err != nil || len(symbols) == 0 {
return false, err
}
s := symbols[0]
if s.VolumeMin <= 0 || s.VolumeMax <= 0 {
fmt.Printf("β Symbol %s has invalid volume limits\n", symbol)
return false, nil
}
fmt.Printf("β
Symbol %s is tradeable:\n", symbol)
fmt.Printf(" Bid=%.5f, Ask=%.5f\n", s.Bid, s.Ask)
fmt.Printf(" Volume: %.2f - %.2f (step: %.2f)\n",
s.VolumeMin, s.VolumeMax, s.VolumeStep)
fmt.Printf(" Spread: %d points\n", s.Spread)
return true, nil
}
Example 6: Calculating Pip ValueΒΆ
// β
MT5Service - calculate pip value
symbolName := "EURUSD"
symbols, _, _ := service.GetSymbolParamsMany(ctx, &symbolName, nil, nil, nil)
if len(symbols) == 0 {
return fmt.Errorf("symbol not found")
}
s := symbols[0]
volume := 1.0 // 1 lot
// Pip value = TradeTickValue * Volume
pipValue := s.TradeTickValue * volume
fmt.Printf("Symbol: %s\n", s.Name)
fmt.Printf("Point: %.5f\n", s.Point)
fmt.Printf("Pip value (1 lot): %.2f USD\n", pipValue)
fmt.Printf("Contract size: %.0f\n", s.TradeContractSize)
π§ When to UseΒΆ
β GetSymbolParamsMany (RECOMMENDED)ΒΆ
Use when:
- Need multiple parameters for one symbol
- Getting a list of symbols (all or filtered)
- Building a table/list of symbols
- Need pagination for large lists
Example:
symbols, total, _ := service.GetSymbolParamsMany(ctx, nil, nil, nil, nil)
fmt.Printf("Found %d symbols\n", total)
β GetSymbolTickΒΆ
Use when:
- Need current price (Bid/Ask)
- Need last tick with timestamp
- Checking quote freshness
Example:
tick, _ := service.GetSymbolTick(ctx, "EURUSD")
fmt.Printf("Current: Bid=%.5f, Ask=%.5f\n", tick.Bid, tick.Ask)
β GetSymbolDouble/Integer/StringΒΆ
Use when:
- Need one specific property
- Making a point check
- GetSymbolParamsMany is overkill
Example:
β SymbolExist / SymbolSelect / IsSymbolSynchronizedΒΆ
Use when:
- Checking symbol existence
- Adding symbol to Market Watch
- Checking data readiness for trading
π Performance ComparisonΒΆ
| Task | Low-Level (lines of code) | Mid-Level (lines of code) | Reduction |
|---|---|---|---|
| Get Bid/Ask | 6-8 lines | 2-3 lines | 60-70% |
| Get all symbol parameters | 30-40 lines | 5-10 lines | 70-80% |
| Get list of all symbols | 50+ lines | 5-10 lines | 80-90% |
| Check symbol | 10-15 lines | 3-5 lines | 60-70% |
π‘ RecommendationsΒΆ
- For multiple properties β use
GetSymbolParamsManyinstead of multipleGetSymbolDouble/Integercalls - For current price β use
GetSymbolTick(Bid/Ask + timestamp in one call) - Before trading β check
SymbolExist+IsSymbolSynchronized - For batch operations β use
GetSymbolParamsManywith pagination - For filtering β get all symbols via
GetSymbolParamsMany, then filter in code
"One Request Instead of Many" Pattern:
// β BAD - 10 calls for 10 parameters
bid, _ := service.GetSymbolDouble(ctx, "EURUSD", SYMBOL_BID)
ask, _ := service.GetSymbolDouble(ctx, "EURUSD", SYMBOL_ASK)
// ... 8 more calls
// β
GOOD - 1 call for all parameters
symbolName := "EURUSD"
symbols, _, _ := service.GetSymbolParamsMany(ctx, &symbolName, nil, nil, nil)
s := symbols[0] // Everything in one structure
π Related SectionsΒΆ
- MT5Service Overview - mid-level API overview
- Account Methods (Mid-Level) - account methods
- Account Information (Low-Level) - low-level account API
- Trading Methods (Mid-Level) - trading methods
- Trading Operations (Low-Level) - low-level trading API
- Streaming Methods (Mid-Level) - tick streaming
- Streaming Methods (Low-Level) - low-level streaming API
- MT5Account Master Overview - low-level API master reference
π― SummaryΒΆ
MT5Service Symbol methods solve the main task - eliminate multiple calls:
- β No need for 10+
SymbolInfo*calls for all parameters - β No need to call
.Valuefor each property - β No need to convert Unix timestamp to time.Time
- β
Get all symbol parameters in one
GetSymbolParamsManycall - β
SymbolTick and SessionTime with ready
time.Time - β Code reads like normal Go
- β Batch operations with pagination