MT5Service - Market Depth Methods (Mid-Level API)ΒΆ
3 methods for working with Depth of Market (DOM) / "order book"
π§© API Layer: MID-LEVEL - wrappers over MT5Account with clean Go types
π― Why These Methods ExistΒΆ
Problem: In MT5Account, working with DOM requires calls with protobuf structures:
// Low-level (MT5Account)
addData, err := account.MarketBookAdd(ctx, &pb.MarketBookAddRequest{Symbol: "EURUSD"})
success := addData.OpenedSuccessfully // β unpacking
bookData, err := account.MarketBookGet(ctx, &pb.MarketBookGetRequest{Symbol: "EURUSD"})
for _, b := range bookData.MqlBookInfos {
// working with protobuf MqlBookInfo
}
releaseData, err := account.MarketBookRelease(ctx, &pb.MarketBookReleaseRequest{Symbol: "EURUSD"})
closed := releaseData.ClosedSuccessfully // β unpacking
Solution: MT5Service simplifies the API and returns clean Go types:
// Mid-level (MT5Service)
success, err := service.SubscribeMarketDepth(ctx, "EURUSD") // β
bool directly
books, err := service.GetMarketDepth(ctx, "EURUSD") // β
[]BookInfo
for _, b := range books {
fmt.Printf("Type: %v, Price: %.5f, Volume: %.2f\n", b.Type, b.Price, b.VolumeReal)
}
success, err = service.UnsubscribeMarketDepth(ctx, "EURUSD") // β
bool directly
Advantages:
- β
Direct bool return instead of
.OpenedSuccessfully/.ClosedSuccessfully - β
Clean
[]BookInfoDTO instead of[]*pb.MqlBookInfo - β Clear method names (Subscribe/Unsubscribe)
- β Automatic request structure creation
π All 3 MethodsΒΆ
| Method | Returns | Low-Level Equivalent |
|---|---|---|
SubscribeMarketDepth(ctx, symbol) |
bool |
MarketBookAdd(ctx, req) + .OpenedSuccessfully |
GetMarketDepth(ctx, symbol) |
[]BookInfo |
MarketBookGet(ctx, req) + conversion to DTO |
UnsubscribeMarketDepth(ctx, symbol) |
bool |
MarketBookRelease(ctx, req) + .ClosedSuccessfully |
π¦ DTO StructureΒΆ
BookInfoΒΆ
type BookInfo struct {
Type pb.BookType // SELL (ask) or BUY (bid)
Price float64 // Price level
Volume int64 // Volume in lots (integer)
VolumeReal float64 // Volume with decimal precision
}
Advantage: Clean Go structure instead of protobuf MqlBookInfo.
Type Values:
pb.BookType_BOOK_TYPE_SELL- ask (sell offer)pb.BookType_BOOK_TYPE_BUY- bid (buy demand)
π Method SignaturesΒΆ
1) SubscribeMarketDepthΒΆ
Subscribes to Depth of Market (DOM) updates for a symbol.
IMPORTANT: Must be called before GetMarketDepth.
Parameters:
symbol- symbol name (e.g., "EURUSD")
Returns:
true- subscription successfulfalse- subscription failed (symbol doesn't support DOM)error- execution error
Example:
success, err := service.SubscribeMarketDepth(ctx, "EURUSD")
if err != nil {
return err
}
if !success {
return fmt.Errorf("failed to subscribe to DOM for EURUSD")
}
fmt.Println("β
Subscribed to EURUSD market depth")
2) GetMarketDepthΒΆ
Retrieves current Depth of Market (DOM) snapshot for a symbol.
IMPORTANT: Requires prior SubscribeMarketDepth call.
Parameters:
symbol- symbol name (e.g., "EURUSD")
Returns:
[]BookInfo- array of price levels (bid and ask)error- execution error
Example:
books, err := service.GetMarketDepth(ctx, "EURUSD")
if err != nil {
return err
}
fmt.Println("Market Depth for EURUSD:")
for i, b := range books {
typeStr := "BID"
if b.Type == pb.BookType_BOOK_TYPE_SELL {
typeStr = "ASK"
}
fmt.Printf(" %d. %s: Price=%.5f, Volume=%.2f\n",
i+1, typeStr, b.Price, b.VolumeReal)
}
3) UnsubscribeMarketDepthΒΆ
Unsubscribes from Depth of Market updates.
Call this to stop receiving DOM updates and free resources.
Parameters:
symbol- symbol name (e.g., "EURUSD")
Returns:
true- unsubscription successfulfalse- unsubscription failederror- execution error
Example:
success, err := service.UnsubscribeMarketDepth(ctx, "EURUSD")
if err != nil {
return err
}
if success {
fmt.Println("β
Unsubscribed from EURUSD market depth")
}
π‘ Usage ExamplesΒΆ
Example 1: Basic DOM OperationsΒΆ
// β
MT5Service - clean and concise
ctx := context.Background()
// 1. Subscribe to market depth
success, err := service.SubscribeMarketDepth(ctx, "EURUSD")
if err != nil || !success {
return fmt.Errorf("subscription failed")
}
defer service.UnsubscribeMarketDepth(ctx, "EURUSD")
// 2. Get current DOM snapshot
books, err := service.GetMarketDepth(ctx, "EURUSD")
if err != nil {
return err
}
// 3. Process DOM data
for _, b := range books {
fmt.Printf("Price: %.5f, Volume: %.2f\n", b.Price, b.VolumeReal)
}
Advantage: Returns clean []BookInfo DTO instead of protobuf []*pb.MqlBookInfo, with direct bool returns instead of unpacking .OpenedSuccessfully/.ClosedSuccessfully fields.
Example 2: Liquidity Analysis (Bid/Ask Volumes)ΒΆ
// β
MT5Service - analyze bid and ask liquidity
func AnalyzeLiquidity(service *mt5.MT5Service, symbol string) error {
ctx := context.Background()
// 1. Subscribe to DOM
success, err := service.SubscribeMarketDepth(ctx, symbol)
if err != nil || !success {
return fmt.Errorf("failed to subscribe to DOM: %w", err)
}
defer service.UnsubscribeMarketDepth(ctx, symbol)
// 2. Get DOM snapshot
books, err := service.GetMarketDepth(ctx, symbol)
if err != nil {
return err
}
// 3. Separate bid and ask levels
var bidVolume, askVolume float64
var bidLevels, askLevels []BookInfo
for _, b := range books {
if b.Type == pb.BookType_BOOK_TYPE_BUY {
bidLevels = append(bidLevels, b)
bidVolume += b.VolumeReal
} else {
askLevels = append(askLevels, b)
askVolume += b.VolumeReal
}
}
// 4. Display liquidity analysis
fmt.Printf("π Liquidity Analysis for %s\n", symbol)
fmt.Printf("Bid levels: %d, Total volume: %.2f\n", len(bidLevels), bidVolume)
fmt.Printf("Ask levels: %d, Total volume: %.2f\n", len(askLevels), askVolume)
// 5. Determine market pressure
if bidVolume > askVolume {
fmt.Println("β¬οΈ More buying pressure (bid volume > ask volume)")
} else {
fmt.Println("β¬οΈ More selling pressure (ask volume > bid volume)")
}
return nil
}
Example 3: Monitor Spread from DOMΒΆ
// β
MT5Service - calculate spread from DOM
func MonitorDOMSpread(service *mt5.MT5Service, symbol string, interval time.Duration) {
ctx := context.Background()
// 1. Subscribe to market depth
success, _ := service.SubscribeMarketDepth(ctx, symbol)
if !success {
fmt.Println("β Cannot subscribe to DOM")
return
}
defer service.UnsubscribeMarketDepth(ctx, symbol)
// 2. Setup periodic ticker
ticker := time.NewTicker(interval)
defer ticker.Stop()
for range ticker.C {
// 3. Get current DOM snapshot
books, err := service.GetMarketDepth(ctx, symbol)
if err != nil {
fmt.Printf("β Error: %v\n", err)
continue
}
// 4. Find best bid and ask prices
var bestBid, bestAsk float64
for _, b := range books {
if b.Type == pb.BookType_BOOK_TYPE_BUY && (bestBid == 0 || b.Price > bestBid) {
bestBid = b.Price
}
if b.Type == pb.BookType_BOOK_TYPE_SELL && (bestAsk == 0 || b.Price < bestAsk) {
bestAsk = b.Price
}
}
// 5. Calculate and display spread
if bestBid > 0 && bestAsk > 0 {
spread := bestAsk - bestBid
fmt.Printf("[%s] %s: Bid=%.5f, Ask=%.5f, Spread=%.5f\n",
time.Now().Format("15:04:05"), symbol, bestBid, bestAsk, spread)
}
}
}
Example 4: Visualize DOM (Order Book)ΒΆ
// β
MT5Service - beautiful DOM visualization
func PrintDOMBook(service *mt5.MT5Service, symbol string) error {
ctx := context.Background()
// 1. Subscribe to market depth
success, err := service.SubscribeMarketDepth(ctx, symbol)
if err != nil || !success {
return fmt.Errorf("failed to subscribe: %w", err)
}
defer service.UnsubscribeMarketDepth(ctx, symbol)
// 2. Get DOM snapshot
books, err := service.GetMarketDepth(ctx, symbol)
if err != nil {
return err
}
// 3. Separate bids and asks
var bids, asks []BookInfo
for _, b := range books {
if b.Type == pb.BookType_BOOK_TYPE_BUY {
bids = append(bids, b)
} else {
asks = append(asks, b)
}
}
// 4. Sort (asks ascending, bids descending)
sort.Slice(asks, func(i, j int) bool {
return asks[i].Price < asks[j].Price
})
sort.Slice(bids, func(i, j int) bool {
return bids[i].Price > bids[j].Price
})
// 5. Display formatted order book
fmt.Printf("\nπ Market Depth for %s\n", symbol)
fmt.Println("=" + strings.Repeat("=", 50))
fmt.Println("ASK (Sell Orders):")
for i := len(asks) - 1; i >= 0; i-- {
a := asks[i]
fmt.Printf(" %.5f | %8.2f\n", a.Price, a.VolumeReal)
}
fmt.Println(strings.Repeat("-", 50))
fmt.Println("BID (Buy Orders):")
for _, b := range bids {
fmt.Printf(" %.5f | %8.2f\n", b.Price, b.VolumeReal)
}
fmt.Println("=" + strings.Repeat("=", 50))
return nil
}
Output:
π Market Depth for EURUSD
==================================================
ASK (Sell Orders):
1.08905 | 150.00
1.08904 | 200.00
1.08903 | 300.00
--------------------------------------------------
BID (Buy Orders):
1.08902 | 250.00
1.08901 | 180.00
1.08900 | 120.00
==================================================
Example 5: Find Large Orders in DOM (Walls)ΒΆ
// β
MT5Service - find large orders in the book
func FindLargeOrders(service *mt5.MT5Service, symbol string, minVolume float64) error {
ctx := context.Background()
// 1. Subscribe to market depth
success, err := service.SubscribeMarketDepth(ctx, symbol)
if err != nil || !success {
return fmt.Errorf("failed to subscribe: %w", err)
}
defer service.UnsubscribeMarketDepth(ctx, symbol)
// 2. Get DOM snapshot
books, err := service.GetMarketDepth(ctx, symbol)
if err != nil {
return err
}
// 3. Find and display large orders
fmt.Printf("π Large orders (volume >= %.2f) in %s:\n", minVolume, symbol)
for _, b := range books {
if b.VolumeReal >= minVolume {
typeStr := "BID π’"
if b.Type == pb.BookType_BOOK_TYPE_SELL {
typeStr = "ASK π΄"
}
fmt.Printf(" %s: Price=%.5f, Volume=%.2f\n",
typeStr, b.Price, b.VolumeReal)
}
}
return nil
}
π§ When to UseΒΆ
β SubscribeMarketDepthΒΆ
Use when:
- Starting to work with DOM for a symbol
- Need real-time order book updates
- Analyzing market liquidity
IMPORTANT: Always call before GetMarketDepth.
β GetMarketDepthΒΆ
Use when:
- Getting current DOM snapshot
- Analyzing bid/ask levels
- Finding large orders (walls)
- Calculating average price by levels
IMPORTANT: Requires active subscription via SubscribeMarketDepth.
β UnsubscribeMarketDepthΒΆ
Use when:
- Finishing work with DOM
- Freeing resources
- Use
deferfor automatic unsubscription
π Performance ComparisonΒΆ
| Task | Low-Level (lines of code) | Mid-Level (lines of code) | Reduction |
|---|---|---|---|
| Subscribe to DOM | 3-4 lines | 1-2 lines | 40-50% |
| Get DOM | 2-3 lines | 1 line | 33-50% |
| Unsubscribe from DOM | 2-3 lines | 1 line | 33-50% |
| Full cycle (sub+get+unsub) | 8-10 lines | 4-5 lines | 40-50% |
π‘ RecommendationsΒΆ
-
Always use defer for UnsubscribeMarketDepth:
-
Check success when subscribing:
-
Not all symbols support DOM - verify subscription result
-
GetMarketDepth returns a snapshot - for real-time use polling or streaming
-
Handle errors - symbol may become unavailable during operation
"Subscribe-Defer-Get" Pattern:
func WorkWithDOM(service *mt5.MT5Service, symbol string) error {
ctx := context.Background()
// 1. Subscribe
success, err := service.SubscribeMarketDepth(ctx, symbol)
if err != nil || !success {
return fmt.Errorf("subscription failed")
}
// 2. Defer unsubscribe (automatic cleanup)
defer service.UnsubscribeMarketDepth(ctx, symbol)
// 3. Get data
books, err := service.GetMarketDepth(ctx, symbol)
if err != nil {
return err
}
// 4. Process
for _, b := range books {
// ...
}
return nil
}
π Related SectionsΒΆ
MT5Service (Mid-Level):
- MT5Service Overview - general mid-level API overview
- Account Methods - account information retrieval
- Symbol Methods - symbol parameters and quotes
- Position & Orders Methods - query positions and orders
- Trading Methods - place and manage orders
MT5Account (Low-Level):
- Market Depth Information - low-level DOM operations
- MT5Account Master Overview - complete low-level API reference
π― SummaryΒΆ
MT5Service Market Depth methods solve the main task - simplifying DOM operations:
- β No need to create requests manually (
MarketBookAddRequest, etc.) - β No need to extract
.OpenedSuccessfully/.ClosedSuccessfully - β No need to work with
[]*pb.MqlBookInfo - β Get bool directly (success/fail)
- β
Clean
[]BookInfoDTO instead of protobuf - β Clear names (Subscribe/Get/Unsubscribe)
- β Code reads like standard Go
Typical workflow: