🚀 Performance Notes (GoMT4)¶
Practical tips to keep GoMT4 fast, stable, and resource‑efficient. Focus is on your current codebase (examples/, pb API, MT4 terminal on Windows).
🎯 Goals¶
- Low latency for quotes/updates.
- Throughput for bulk reads (history, many symbols).
- Stability under loss/reconnects.
- Predictable CPU/RAM usage.
🔥 Hot paths to watch¶
- Streaming:
StreamQuotes,StreamOpenedOrderProfits,StreamTradeUpdates. - Batch RPCs:
ShowQuotesMany, paged/streamed Orders History (ShowOrdersHistory,StreamOrdersHistoryExample). - Symbol metadata:
ShowSymbolParams,ShowTickValuesused in loops.
Keep these tight: avoid heavy logging, allocations, and repeated RPCs.
📦 Batch, don’t loop RPCs¶
-
Prefer batch APIs over per‑symbol calls:
-
âś…
ShowQuotesManyinstead ofShowQuotein a loop. -
History: use paged/streaming endpoints rather than huge single responses.
Why: fewer round‑trips → lower latency and CPU per message.
📡 Streaming tuning¶
-
Backpressure: use the server’s knobs when available.
-
Example:
OpenedOrdersProfitStreamRequest{ buffer_size }— set buffer high enough to absorb short spikes, but not so high that consumer lags unnoticed. - Consumer loop: drain fast, do work in a goroutine pool if processing is heavy.
- Tick throttling: if you don’t need every tick, aggregate with a
time.Ticker(e.g., 100–200ms) before updating UI/logs. - Timeouts: long‑lived streams should use
WithCancel, not short timeouts; add an idle watchdog to reconnect when no data for X seconds.
ctx, cancel := context.WithCancel(parent)
defer cancel()
updates, errCh := svc.StreamQuotes(ctx, symbols)
for {
select {
case u := <-updates: /* cheap handling */
case err := <-errCh: /* reconnect + backoff */
case <-idle.C: /* no data → ping/refresh */
}
}
đź§µ Concurrency patterns (Go)¶
- One gRPC connection per MT4 instance; reuse
*grpc.ClientConn(creating many is expensive). - Worker pool for CPU‑bound post‑processing (e.g., statistics on history), not for issuing parallel trade RPCs to the same MT4 terminal.
- Channel fan‑out: if several consumers need the same stream, broadcast from one reader goroutine; don’t open multiple identical streams.
đź§° Symbol metadata cache¶
- Cache
ShowSymbolParamsandShowTickValuesin memory (map by symbol). These values change rarely; re‑fetch only on symbol list changes or once per session. - Use cached
digits/point/lot_stepfor rounding before any trade call (see Cookbook →RoundVolumePrice.md).
đź§® History I/O¶
- Request time windows in chunks (days/weeks) and merge client‑side.
- Prefer H1/H4/D1 where possible; M1 over long ranges is expensive.
- For analytics, stream and process as you go instead of storing everything first.
🗜️ Compression & payloads¶
- gRPC compression helps on large history responses; avoid compressing ultra‑short ticks.
- Avoid logging full payloads in hot paths; log only counts and latency metrics.
đź§ Allocations & GC¶
- Reuse buffers/slices for quote aggregation; pre‑allocate with
make(..., cap)when size is known. - Convert
time↔Timestampcarefully in tight loops; avoid repeated parsing/formatting. - Use
strings.Builderfor building CSV/TSV outputs.
⏱️ Timeouts & retries¶
- Unary calls:
context.WithTimeout(100ms–3s typical for local terminal). Add idempotency where safe and exponential backoff. - Streams: no short deadline; reconnect on error/idle with jittered backoff (see Cookbook →
HandleReconnect.md,UnaryRetries.md).
🖥️ Windows & MT4 specifics¶
- Keep MT4 responsive: exclude MT4 data directory from real‑time antivirus scanning if safe in your environment.
- Power plan: use High performance to avoid CPU sleep throttling for low‑latency streams.
- Symbol visibility: ensure symbols are visible before quote/history calls (Cookbook →
EnsureSymbolVisible.md). Pre‑subscribe to reduce first‑tick latency.
📊 Observability¶
- Add lightweight metrics: per‑RPC latency, stream message rate, reconnect counters.
- Sampled logs (1/N) for hot paths; full debug logs only on demand.
âś… Checklist (TL;DR)¶
- Use batch requests and paged/streamed history.
- Keep one gRPC conn; reuse clients.
- Cache SymbolParams / TickValues.
- Fast stream consumers; apply throttling/aggregation if UI‑facing.
- Timeouts for unary; cancel for streams; exponential backoff with jitter.
- Minimal logging in hot paths; metrics for rates/latency.
- Pre‑make symbols visible or subscribe early.
- Prefer higher‑TF history when possible; chunk long ranges.
🗺️ Code map → where each tip lives in your repo¶
1) Batch, don’t loop RPCs¶
- Batch quotes →
examples/mt4/MT4_service.go→func (s *MT4Service) ShowQuotesMany(ctx context.Context, symbols []string)Search:ShowQuotesMany( - Single quote (avoid loops) → same file →
ShowQuote(ctx, symbol string)Search:ShowQuote(ctx - History (paged/stream) →
examples/mt4/MT4_service.go→StreamOrdersHistoryExample,StreamQuoteHistoryExample
2) Streaming tuning & backpressure¶
- Quotes stream →
examples/mt4/MT4_service.go→StreamQuotes - Opened order profits → same file →
StreamOpenedOrderProfits(this is the method you pasted earlier withOnOpenedOrdersProfit(ctx, 1000)and the 30s timeout) - Trade updates → same file →
StreamTradeUpdates - Opened tickets → same file →
StreamOpenedOrderTickets
Tip → buffer_size: if you expose buffer_size for profits, it is wired at account layer:
examples/mt4/MT4Account.go→ look forOnOpenedOrdersProfit(ctx,
3) One gRPC connection, reuse clients¶
- Connection bootstrap →
examples/main.go→ creation of service & clients Search:NewMT4Service(/grpc.Dial( - Account/session holder →
examples/mt4/MT4Account.goSearch:type MT4Account struct/connect/login
4) Symbol metadata cache (params/tick-values)¶
- Fetch params →
examples/mt4/MT4_service.go→ShowSymbolParams - Fetch tick values → same file →
ShowTickValues - Used for rounding → see order helpers (e.g.,
ShowOrderSendExample) whereDigits,Point,LotStepare applied before send.
5) Rounding & validation before trades¶
- Volume/price rounding (from Cookbook) is backed by these call sites:
examples/mt4/MT4_service.go→ShowOrderSendExample,ShowOrderModifyExample - Ensure stops distance → check usage of
stops_level/freeze_levelfromShowSymbolParams.
6) Ensure symbol visible / pre‑subscribe¶
- Ensure visible →
examples/mt4/MT4Account.goSearch:EnsureSymbolVisible/SymbolSelect/SymbolsGet - Pre‑subscribe quotes (lower first‑tick latency) →
examples/mt4/MT4_service.go→StreamQuotes
7) History I/O in chunks¶
- Quote history (time windows) →
examples/mt4/MT4_service.go→ShowQuoteHistory - Orders history (paged) → same file →
StreamOrdersHistoryExample
8) Timeouts & retries¶
- Unary with timeout →
examples/mt4/MT4_service.go→ places that usecontext.WithTimeout(...)around quote/symbol calls. - Reconnect with backoff → reliability helpers you documented (Cookbook):
Cookbook/Reliability/HandleReconnect.mdandCookbook/Reliability/UnaryRetries.mdcorrespond to the code inexamples/mt4/MT4_service.go(stream loops) and in connection handling inMT4Account.go.
9) Observability (logs/metrics)¶
- Light logs around hot paths →
examples/mt4/MT4_service.gostream handlers printTick/Profit/Tradelines — replace with counters/rate meters in production.