✅ Getting Latest Tick Data for Symbol¶
Request: current market tick data for a specified symbol. Returns real-time bid/ask prices, last trade price, volume, and timestamp.
API Information:
- SDK wrapper:
MT5Account.symbolInfoTick(...)andMT5Account.quote(...)(from packageio.metarpc.mt5) - gRPC service:
mt5_term_api.MarketInfo - Proto definition:
SymbolInfoTick(defined inmt5-term-api-market-info.proto)
RPC¶
- Service:
mt5_term_api.MarketInfo - Method:
SymbolInfoTick(SymbolInfoTickRequest) → SymbolInfoTickRequestReply - Low‑level client (generated):
MarketInfoGrpc.MarketInfoBlockingStub.symbolInfoTick(request) - SDK wrapper (high-level):
package io.metarpc.mt5;
public class MT5Account {
/**
* Gets the latest tick data for a specified symbol.
* Returns real-time market information including current bid/ask prices, last trade price, volume, and timestamp.
* This is the primary method for retrieving current market prices for trading decisions.
*
* @param symbol Symbol name (e.g., "EURUSD", "GBPUSD")
* @return Latest tick data with bid/ask prices, last price, volume, and time
* @throws ApiExceptionMT5 if the call fails or connection is lost
*/
public Mt5TermApiMarketInfo.SymbolInfoTickRequestReply symbolInfoTick(String symbol) throws ApiExceptionMT5;
/**
* Gets the current market quote (Bid/Ask prices) for a trading symbol.
* This is a convenience method that internally calls symbolInfoTick().
*
* @param symbol Trading symbol name (e.g., "EURUSD", "GBPUSD")
* @return Current tick data including bid, ask, last price, and volume
* @throws ApiExceptionMT5 if the call fails or connection is lost
*/
public Mt5TermApiMarketInfo.SymbolInfoTickRequestReply quote(String symbol) throws ApiExceptionMT5;
}
Request message: SymbolInfoTickRequest { symbol: string }
Reply message: SymbolInfoTickRequestReply { data: MrpcMqlTick } or { error: Error }
🔽 Input¶
| Parameter | Type | Required | Description |
|---|---|---|---|
symbol |
String |
✅ | Symbol name (e.g., "EURUSD", "XAUUSD") |
⬆️ Output - MrpcMqlTick¶
| Field | Type | Description |
|---|---|---|
time |
long |
Time of the last prices update (Unix timestamp in seconds) |
bid |
double |
Current Bid price (sell price) |
ask |
double |
Current Ask price (buy price) |
last |
double |
Price of the last deal (Last) |
volume |
long |
Volume for the current Last price |
time_msc |
long |
Time of a price last update in milliseconds since 1970.01.01 |
flags |
int |
Tick flags (see MQL5 documentation) |
volume_real |
double |
Volume for the current Last price with greater accuracy |
Access the tick data using reply.getData().
💬 Just the essentials¶
- What it is. Single RPC returning current market prices and tick information for a symbol.
- Why you need it. Essential for getting real-time quotes before placing orders or analyzing market conditions.
- Performance. Lightweight call - ideal for frequent price checks.
- Spread calculation. Spread = Ask - Bid (in price units, not points).
- Alternative. Use
quoteMany()to fetch quotes for multiple symbols in batch.
🎯 Purpose¶
Use this method when you need to:
- Get current bid/ask prices before placing market orders.
- Calculate spread for trading decisions.
- Monitor real-time price changes.
- Verify market is active (check if prices are updating).
- Get last trade information (price and volume).
🧩 Notes & Tips¶
- The symbol must be selected in MarketWatch or the call may fail.
- Use
symbolSelect(symbol, true)first if you're unsure if the symbol is selected. - For Forex symbols, typically use
bidfor selling andaskfor buying. - The
time_mscfield provides millisecond precision for high-frequency trading. - The method uses automatic reconnection via
executeWithReconnect()to handle transient errors. - For monitoring multiple symbols, consider using
quoteMany()or tick subscriptions (onSymbolTick()).
🔗 Usage Examples¶
1) Get current bid/ask prices¶
import io.metarpc.mt5.MT5Account;
import io.metarpc.mt5.exceptions.ApiExceptionMT5;
import mt5_term_api.Mt5TermApiMarketInfo;
public class Example {
public static void main(String[] args) {
MT5Account account = new MT5Account(12345678, "password");
try {
account.connect("demo.mt5server.com", 443, "EURUSD");
// Get current tick
Mt5TermApiMarketInfo.SymbolInfoTickRequestReply reply =
account.symbolInfoTick("EURUSD");
Mt5TermApiMarketInfo.MrpcMqlTick tick = reply.getData();
System.out.printf("Symbol: EURUSD%n");
System.out.printf("Bid: %.5f%n", tick.getBid());
System.out.printf("Ask: %.5f%n", tick.getAsk());
System.out.printf("Spread: %.5f%n", tick.getAsk() - tick.getBid());
} catch (ApiExceptionMT5 e) {
System.err.println("Error: " + e.getMessage());
} finally {
account.close();
}
}
}
2) Using the quote() convenience method¶
// Simpler syntax using quote() wrapper
var reply = account.quote("GBPUSD");
var tick = reply.getData();
System.out.printf("GBPUSD Bid: %.5f | Ask: %.5f%n",
tick.getBid(), tick.getAsk());
3) Calculate spread in points¶
var reply = account.symbolInfoTick("EURUSD");
var tick = reply.getData();
// Get symbol point size (e.g., 0.00001 for EURUSD)
var symbolReply = account.symbolInfoDouble(
"EURUSD",
Mt5TermApiMarketInfo.SymbolInfoDoubleProperty.SYMBOL_POINT
);
double point = symbolReply.getData().getValue();
// Calculate spread
double spreadPrice = tick.getAsk() - tick.getBid();
double spreadPoints = spreadPrice / point;
System.out.printf("Spread: %.1f points (%.5f)%n", spreadPoints, spreadPrice);
4) Get tick with timestamp¶
var reply = account.symbolInfoTick("XAUUSD");
var tick = reply.getData();
// Convert Unix timestamp to Java Instant
java.time.Instant tickTime = java.time.Instant.ofEpochSecond(tick.getTime());
java.time.Instant tickTimeMsc = java.time.Instant.ofEpochMilli(tick.getTimeMsc());
System.out.printf("Gold price at %s:%n", tickTime);
System.out.printf("Bid: %.2f | Ask: %.2f%n", tick.getBid(), tick.getAsk());
System.out.printf("Millisecond precision: %s%n", tickTimeMsc);
5) Monitor price changes¶
import java.util.concurrent.TimeUnit;
public class PriceMonitor {
public static void monitorPrice(MT5Account account, String symbol) {
double lastBid = 0;
while (true) {
try {
var reply = account.quote(symbol);
var tick = reply.getData();
if (tick.getBid() != lastBid) {
System.out.printf("[%s] %s: %.5f / %.5f (Spread: %.5f)%n",
java.time.LocalTime.now(),
symbol,
tick.getBid(),
tick.getAsk(),
tick.getAsk() - tick.getBid()
);
lastBid = tick.getBid();
}
TimeUnit.SECONDS.sleep(1);
} catch (ApiExceptionMT5 e) {
System.err.println("API Error: " + e.getMessage());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ie) {
break;
}
} catch (InterruptedException e) {
break;
}
}
}
}
6) Get quotes for multiple symbols¶
// Get quotes for multiple symbols using quoteMany()
String[] symbols = {"EURUSD", "GBPUSD", "USDJPY", "XAUUSD"};
var quotes = account.quoteMany(symbols);
for (int i = 0; i < symbols.length; i++) {
var tick = quotes[i].getData();
System.out.printf("%s: Bid %.5f | Ask %.5f%n",
symbols[i],
tick.getBid(),
tick.getAsk()
);
}
7) Check if market is active¶
public class MarketChecker {
/**
* Check if market is actively trading by comparing tick timestamps
*/
public static boolean isMarketActive(MT5Account account, String symbol)
throws ApiExceptionMT5 {
var reply = account.symbolInfoTick(symbol);
var tick = reply.getData();
// Get current time
long currentTime = System.currentTimeMillis();
long tickTime = tick.getTimeMsc();
// Check if tick is fresh (within last 5 seconds)
long ageMillis = currentTime - tickTime;
boolean isActive = ageMillis < 5000;
System.out.printf("Symbol: %s%n", symbol);
System.out.printf("Tick age: %.1f seconds%n", ageMillis / 1000.0);
System.out.printf("Market active: %s%n", isActive);
return isActive;
}
}
8) Create a tick data record¶
/**
* Immutable record for tick data
*/
public record TickData(
String symbol,
double bid,
double ask,
double last,
double spread,
java.time.Instant time
) {
public static TickData fromProto(String symbol, Mt5TermApiMarketInfo.MrpcMqlTick tick) {
return new TickData(
symbol,
tick.getBid(),
tick.getAsk(),
tick.getLast(),
tick.getAsk() - tick.getBid(),
java.time.Instant.ofEpochMilli(tick.getTimeMsc())
);
}
@Override
public String toString() {
return String.format("%s @ %s: Bid=%.5f Ask=%.5f Spread=%.5f",
symbol, time, bid, ask, spread);
}
}
// Usage
var reply = account.quote("EURUSD");
var tickData = TickData.fromProto("EURUSD", reply.getData());
System.out.println(tickData);
9) Pre-trade price check¶
public class TradeHelper {
/**
* Get current price for order placement
*/
public static double getCurrentPrice(
MT5Account account,
String symbol,
boolean isBuy) throws ApiExceptionMT5 {
var reply = account.quote(symbol);
var tick = reply.getData();
// Buy at Ask, Sell at Bid
double price = isBuy ? tick.getAsk() : tick.getBid();
System.out.printf("%s %s at price: %.5f%n",
isBuy ? "Buying" : "Selling",
symbol,
price);
return price;
}
/**
* Check if spread is acceptable
*/
public static boolean isSpreadAcceptable(
MT5Account account,
String symbol,
double maxSpreadPoints) throws ApiExceptionMT5 {
var reply = account.quote(symbol);
var tick = reply.getData();
// Get point size
var pointReply = account.symbolInfoDouble(
symbol,
Mt5TermApiMarketInfo.SymbolInfoDoubleProperty.SYMBOL_POINT
);
double point = pointReply.getData().getValue();
// Calculate spread in points
double spreadPoints = (tick.getAsk() - tick.getBid()) / point;
boolean acceptable = spreadPoints <= maxSpreadPoints;
if (!acceptable) {
System.out.printf("⚠️ Spread too high: %.1f points (max: %.1f)%n",
spreadPoints, maxSpreadPoints);
}
return acceptable;
}
}
// Usage
if (TradeHelper.isSpreadAcceptable(account, "EURUSD", 3.0)) {
double buyPrice = TradeHelper.getCurrentPrice(account, "EURUSD", true);
// Place buy order at buyPrice
}
🔄 Low-level gRPC call (for reference)¶
import io.grpc.*;
import mt5_term_api.*;
// Create request
Mt5TermApiMarketInfo.SymbolInfoTickRequest request =
Mt5TermApiMarketInfo.SymbolInfoTickRequest.newBuilder()
.setSymbol("EURUSD")
.build();
// Add metadata headers
Metadata headers = new Metadata();
Metadata.Key<String> idKey = Metadata.Key.of("id", Metadata.ASCII_STRING_MARSHALLER);
headers.put(idKey, instanceId.toString());
// Call service
Mt5TermApiMarketInfo.SymbolInfoTickRequestReply reply = marketInfoClient
.withInterceptors(MetadataUtils.newAttachHeadersInterceptor(headers))
.symbolInfoTick(request);
// Check for errors
if (reply.hasError()) {
throw new ApiExceptionMT5(reply.getError());
}
// Use data
Mt5TermApiMarketInfo.MrpcMqlTick tick = reply.getData();
double bid = tick.getBid();
double ask = tick.getAsk();