📚 GetMultipleQuotes (GoMT4)¶
Goal: fetch quotes for many symbols efficiently.
Real code refs:
- Single quote:
examples/mt4/MT4Account.go(Quote)- Demo:
examples/mt4/MT4_service.go(seeShowQuotesManyflow)
✅ 1) Preconditions¶
- All symbols exist and are visible in MT4 (Market Watch → Show All).
config.jsonhas at least one known symbol to start with.
🚀 2) Fast path A — Batch RPC (if available in your build)¶
Some builds expose a batch RPC (e.g., QuotesMany(ctx, symbols)), mirroring the ShowQuotesMany example. If you have it, use it:
symbols := []string{"EURUSD", "GBPUSD", "USDJPY"}
qs, err := account.QuotesMany(ctx, symbols)
if err != nil { return err }
for _, q := range qs.GetQuotes() {
fmt.Printf("%s Bid=%.5f Ask=%.5f Spread=%.1f pips\n",
q.GetSymbol(), q.GetBid(), q.GetAsk(), (q.GetAsk()-q.GetBid())/q.GetPoint())
}
If your current API does not expose this convenience call, use fan‑out concurrency (next section).
🧵 3) Fast path B — Fan‑out with goroutines (always works)¶
Run Quote requests in parallel and collect results.
func GetQuotesParallel(ctx context.Context, a *MT4Account, syms []string) ([]*pb.Quote, error) {
type item struct { q *pb.Quote; err error }
out := make([]*pb.Quote, 0, len(syms))
ch := make(chan item, len(syms))
var wg sync.WaitGroup
// limit concurrency to avoid hammering the terminal
sem := make(chan struct{}, 8) // 8 concurrent calls
for _, s := range syms {
s := s
wg.Add(1)
go func() {
defer wg.Done()
sem <- struct{}{}
defer func(){ <-sem }()
q, err := a.Quote(ctx, s)
ch <- item{q, err}
}()
}
wg.Wait()
close(ch)
for it := range ch {
if it.err != nil { return nil, it.err }
out = append(out, it.q)
}
return out, nil
}
Usage:
qs, err := GetQuotesParallel(ctx, account, []string{"EURUSD","GBPUSD","USDJPY"})
if err != nil { log.Fatal(err) }
for _, q := range qs {
fmt.Printf("%s %.5f/%.5f @ %s\n", q.GetSymbol(), q.GetBid(), q.GetAsk(), q.GetTime().AsTime().Format(time.RFC3339))
}
🧪 4) Validation & fallbacks¶
- If a symbol fails (hidden or has a suffix), log it and continue.
- Optionally, map missing symbols to their broker‑specific names (
EURUSD→EURUSD.m).
for _, s := range syms {
q, err := a.Quote(ctx, s)
if err != nil {
log.Printf("skip %s: %v", s, err)
continue
}
// ...
}
⚠️ Pitfalls¶
- Storming MT4: keep concurrency reasonable (4–8) to avoid timeouts.
- Suffixes:
EURUSDvsEURUSD.m— normalize names or take from Market Watch. - Timeouts: wrap each call with a short timeout (2–3s) and retry only transport errors.
🔗 See also¶
GetQuote.md— single symbol quote.StreamQuotes.md— live stream for continuous updates.SymbolParams.md— getDigits,Point,LotStepfor rounding & display.