✅ Get Market Depth Data (MarketBookGetAsync)¶
Request: Get current Depth of Market (order book) snapshot for a subscribed symbol on MT5.
API Information:
- SDK wrapper:
MT5Account.MarketBookGetAsync(...)(from NuGet packageMetaRPC.MT5) - gRPC service:
mt5_term_api.MarketInfo - Proto definition:
MarketBookGet(defined inmt5-term-api-market-info.proto)
RPC¶
- Service:
mt5_term_api.MarketInfo - Method:
MarketBookGet(MarketBookGetRequest) → MarketBookGetReply - Low‑level client (generated):
MarketInfo.MarketInfoClient.MarketBookGet(request, headers, deadline, cancellationToken) - SDK wrapper (your class):
namespace mt5_term_api
{
public class MT5Account
{
public async Task<MarketBookGetData> MarketBookGetAsync(
string symbol,
DateTime? deadline = null,
CancellationToken cancellationToken = default);
}
}
Request message:
MarketBookGetRequest { symbol }
Reply message:
MarketBookGetReply { data: MarketBookGetData }
🔽 Input¶
| Parameter | Type | Description |
|---|---|---|
symbol |
string |
Symbol name (must be subscribed via MarketBookAddAsync) |
deadline |
DateTime? |
Absolute per‑call UTC deadline → converted to timeout |
cancellationToken |
CancellationToken |
Cooperative cancel for the call/retry loop |
⬆️ Output — MarketBookGetData¶
| Field | Type | Description |
|---|---|---|
MqlBookInfos |
List<MrpcMqlBookInfo> |
Array of DOM entries (price levels) |
MrpcMqlBookInfo — DOM entry structure¶
| Field | Type | Description |
|---|---|---|
Type |
BookType |
Order type (Sell, Buy, SellMarket, BuyMarket) |
Price |
double |
Price level |
Volume |
long |
Volume at this price (in contracts/lots) |
VolumeReal |
double |
Real volume at this price |
🧱 Related enums (from proto)¶
BookType¶
Sell(0) — Sell order (Offer/Ask side)Buy(1) — Buy order (Bid side)SellMarket(2) — Sell market orderBuyMarket(3) — Buy market order
💬 Just the essentials¶
- What it is. Returns current order book snapshot with bid/ask price levels and volumes.
- Why you need it. Analyze liquidity, identify support/resistance, implement DOM-based strategies.
- Sanity check. If
MqlBookInfos.Count > 0→ DOM data available. Empty list = no data or not subscribed.
🎯 Purpose¶
Use it to analyze order book:
- Get bid/ask price levels.
- Analyze liquidity distribution.
- Identify large orders (support/resistance).
- Implement order flow strategies.
🧩 Notes & Tips¶
- Subscription required: Must call
MarketBookAddAsyncfirst, otherwise get empty list. - Snapshot data: Returns current state at call time. For real-time updates use streaming (SubscribeToBookEvent).
- Price sorting: Entries typically sorted by price (best bid/ask first). Verify sorting in your code.
- Empty result: If
MqlBookInfosis empty, either not subscribed or broker doesn't provide DOM. - Broker limitations: Most Forex brokers don't provide DOM. Available mainly for futures, stocks, crypto.
🔗 Usage Examples¶
1) Basic DOM retrieval¶
// acc — connected MT5Account
// Symbol must be subscribed via MarketBookAddAsync first
var domData = await acc.MarketBookGetAsync("BTCUSD");
Console.WriteLine($"DOM entries: {domData.MqlBookInfos.Count}");
foreach (var entry in domData.MqlBookInfos.Take(10))
{
var side = entry.Type == BookType.BookTypeBuy ? "BID" : "ASK";
Console.WriteLine($"{side} | Price: {entry.Price:F2} | Volume: {entry.VolumeReal:F4}");
}
2) Analyze best bid/ask¶
var domData = await acc.MarketBookGetAsync("ETHUSD");
if (domData.MqlBookInfos.Count > 0)
{
var bids = domData.MqlBookInfos
.Where(e => e.Type == BookType.BookTypeBuy)
.OrderByDescending(e => e.Price);
var asks = domData.MqlBookInfos
.Where(e => e.Type == BookType.BookTypeSell)
.OrderBy(e => e.Price);
var bestBid = bids.FirstOrDefault();
var bestAsk = asks.FirstOrDefault();
if (bestBid != null && bestAsk != null)
{
var spread = bestAsk.Price - bestBid.Price;
Console.WriteLine($"Best Bid: {bestBid.Price} | Best Ask: {bestAsk.Price} | Spread: {spread}");
}
}
3) Find large orders (liquidity analysis)¶
var domData = await acc.MarketBookGetAsync("ES"); // E-mini S&P 500
// Find orders with volume > 100 contracts
var largeOrders = domData.MqlBookInfos
.Where(e => e.Volume > 100)
.OrderByDescending(e => e.Volume);
Console.WriteLine("Large orders (potential support/resistance):");
foreach (var order in largeOrders.Take(5))
{
var side = order.Type == BookType.BookTypeBuy ? "BID" : "ASK";
Console.WriteLine($"{side} | Price: {order.Price} | Volume: {order.Volume}");
}
4) Calculate total liquidity by side¶
var domData = await acc.MarketBookGetAsync("XAUUSD");
var totalBidVolume = domData.MqlBookInfos
.Where(e => e.Type == BookType.BookTypeBuy)
.Sum(e => e.VolumeReal);
var totalAskVolume = domData.MqlBookInfos
.Where(e => e.Type == BookType.BookTypeSell)
.Sum(e => e.VolumeReal);
var bidAskRatio = totalBidVolume / (totalAskVolume > 0 ? totalAskVolume : 1);
Console.WriteLine($"Total Bid Liquidity: {totalBidVolume:F2}");
Console.WriteLine($"Total Ask Liquidity: {totalAskVolume:F2}");
Console.WriteLine($"Bid/Ask Ratio: {bidAskRatio:F2}");
5) Continuous DOM monitoring (polling)¶
var symbol = "BTCUSD";
// Subscribe first
var subResult = await acc.MarketBookAddAsync(symbol);
if (!subResult.OpenedSuccessfully)
{
Console.WriteLine("DOM not available");
return;
}
// Poll DOM every second for 10 iterations
for (int i = 0; i < 10; i++)
{
var domData = await acc.MarketBookGetAsync(symbol);
if (domData.MqlBookInfos.Count > 0)
{
var bestBid = domData.MqlBookInfos
.Where(e => e.Type == BookType.BookTypeBuy)
.MaxBy(e => e.Price);
var bestAsk = domData.MqlBookInfos
.Where(e => e.Type == BookType.BookTypeSell)
.MinBy(e => e.Price);
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] Bid: {bestBid?.Price} | Ask: {bestAsk?.Price}");
}
await Task.Delay(1000); // Wait 1 second
}
// Unsubscribe when done
await acc.MarketBookReleaseAsync(symbol);
6) DOM-based entry strategy (example)¶
// Simple strategy: Enter when large order appears near current price
var domData = await acc.MarketBookGetAsync("ES");
var currentPrice = (await acc.SymbolInfoTickAsync("ES")).Bid;
var nearbyLargeOrders = domData.MqlBookInfos
.Where(e => Math.Abs(e.Price - currentPrice) < 5.0) // Within 5 points
.Where(e => e.Volume > 200) // Large order
.ToList();
if (nearbyLargeOrders.Any())
{
Console.WriteLine($"⚠ {nearbyLargeOrders.Count} large order(s) near price {currentPrice}");
foreach (var order in nearbyLargeOrders)
{
var side = order.Type == BookType.BookTypeBuy ? "Support" : "Resistance";
Console.WriteLine($"{side} at {order.Price} with volume {order.Volume}");
}
// Implement your entry logic here
}