Trades Channel
Real-time trade execution data
Overview
The trades channel provides real-time updates of trade executions for a specific trading product. Each message contains information about a completed trade, including price, size, side, and timestamp.
Channel: trades
Authentication: Not required (Public)
Products: BTC-VND, ETH-VND, SOL-VND, XRP-VND
Subscribe
Request:
{
"op": "sub",
"channel": "trades",
"product": "BTC-VND"
}Friendly format:
sub trades BTC-VNDParameters:
op(string, required) - Must be"sub"channel(string, required) - Must be"trades"product(string, required) - Trading pair (e.g.,"BTC-VND")
Responses
Subscription Confirmation
Upon successful subscription:
{
"channel": "trades",
"product": "BTC-VND",
"type": "subscribed"
}Trade Updates
Each trade execution generates an update message:
{
"channel": "trades",
"product": "BTC-VND",
"type": "update",
"data": {
"price": "3124660000",
"size": "0.003",
"maker_side": "buy",
"id": "0x0198aca869...",
"time": "1755243387119627000"
}
}Data Structure
interface TradeData {
price: string; // Execution price
size: string; // Trade size (in base currency)
maker_side: "buy" | "sell"; // Maker order side
id: string; // Unique trade identifier
time: string; // Execution time (nanoseconds since epoch)
}Field Descriptions:
- price - The price at which the trade was executed (in quote currency, VND)
- size - The quantity traded (in base currency, e.g., BTC)
- maker_side - The side of the maker order
"buy"- Maker was buying (taker was selling)"sell"- Maker was selling (taker was buying)
- id - Unique identifier for this trade (match ID)
- time - Unix timestamp in nanoseconds when the trade occurred
Understanding Maker Side
The maker_side field indicates which side placed the resting order (maker):
| maker_side | Maker Action | Taker Action | Market Direction |
|---|---|---|---|
buy | Placed buy order | Placed sell order | Price supported at bid |
sell | Placed sell order | Placed buy order | Price pushed at ask |
Example: Processing Trades
const WebSocket = require('ws');
const ws = new WebSocket('wss://ws.dev.mbhq.net/ws');
const trades = [];
ws.on('open', () => {
console.log('Connected to WebSocket');
// Subscribe to BTC-VND trades
ws.send(JSON.stringify({
op: 'sub',
channel: 'trades',
product: 'BTC-VND'
}));
});
ws.on('message', (data) => {
const message = JSON.parse(data);
if (message.channel === 'trades') {
if (message.type === 'subscribed') {
console.log('Subscribed to trades');
} else if (message.type === 'update') {
const trade = message.data;
// Convert nanosecond timestamp to Date
const timestamp = new Date(parseInt(trade.time) / 1000000);
console.log(`Trade: ${trade.size} BTC @ ${trade.price} VND`);
console.log(` Maker Side: ${trade.maker_side}`);
console.log(` Time: ${timestamp.toISOString()}`);
console.log(` ID: ${trade.id}`);
// Store trade for analysis
trades.push({
...trade,
timestamp: timestamp
});
// Calculate volume metrics
if (trades.length >= 10) {
const recentVolume = trades.slice(-10).reduce(
(sum, t) => sum + parseFloat(t.size),
0
);
console.log(`Last 10 trades volume: ${recentVolume.toFixed(4)} BTC`);
}
}
}
});Example: Building a Trade Ticker
class TradeTicker {
constructor(windowMs = 60000) { // 1 minute window
this.trades = [];
this.windowMs = windowMs;
}
addTrade(trade) {
const timestamp = parseInt(trade.time) / 1000000; // Convert to ms
this.trades.push({
price: parseFloat(trade.price),
size: parseFloat(trade.size),
timestamp: timestamp,
side: trade.maker_side
});
// Remove trades outside the time window
const cutoff = Date.now() - this.windowMs;
this.trades = this.trades.filter(t => t.timestamp >= cutoff);
}
getStats() {
if (this.trades.length === 0) return null;
const prices = this.trades.map(t => t.price);
const volumes = this.trades.map(t => t.size);
return {
count: this.trades.length,
volume: volumes.reduce((a, b) => a + b, 0),
high: Math.max(...prices),
low: Math.min(...prices),
last: prices[prices.length - 1],
vwap: this.trades.reduce((sum, t) => sum + t.price * t.size, 0) /
volumes.reduce((a, b) => a + b, 0),
buyVolume: this.trades
.filter(t => t.side === 'sell') // Taker bought
.reduce((sum, t) => sum + t.size, 0),
sellVolume: this.trades
.filter(t => t.side === 'buy') // Taker sold
.reduce((sum, t) => sum + t.size, 0)
};
}
}
// Usage
const ticker = new TradeTicker(60000); // 1 minute window
ws.on('message', (data) => {
const message = JSON.parse(data);
if (message.channel === 'trades' && message.type === 'update') {
ticker.addTrade(message.data);
const stats = ticker.getStats();
if (stats) {
console.log('1-Minute Stats:');
console.log(` Trades: ${stats.count}`);
console.log(` Volume: ${stats.volume.toFixed(4)} BTC`);
console.log(` High: ${stats.high.toFixed(0)} VND`);
console.log(` Low: ${stats.low.toFixed(0)} VND`);
console.log(` VWAP: ${stats.vwap.toFixed(0)} VND`);
console.log(` Buy/Sell Ratio: ${(stats.buyVolume / stats.sellVolume).toFixed(2)}`);
}
}
});Unsubscribe
To stop receiving trade updates:
Request:
{
"op": "unsub",
"channel": "trades",
"product": "BTC-VND"
}Friendly format:
unsub trades BTC-VNDResponse:
{
"type": "unsubscribed",
"channel": "trades",
"product": "BTC-VND"
}Use Cases
- Price Feeds - Display real-time trade prices in your application
- Volume Analysis - Monitor trading volume and market activity
- Trade History - Build a recent trades list
- Market Sentiment - Analyze buy/sell pressure using maker_side
- VWAP Calculation - Calculate volume-weighted average price
- Alerts - Trigger notifications on large trades or price movements
Best Practices
- Use Timestamps - Trade timestamps are in nanoseconds; convert appropriately
- Handle High Frequency - During volatile periods, trades can arrive rapidly
- Buffer Messages - Consider buffering and batching UI updates
- Track Volume - Monitor both price and volume for complete market picture
- Combine Channels - Use with orderbook channel for comprehensive market data
Time Conversion
Trade timestamps are in nanoseconds since Unix epoch:
// Convert nanosecond timestamp to milliseconds
const timestampMs = parseInt(trade.time) / 1000000;
// Create Date object
const date = new Date(timestampMs);
// Format for display
const formatted = date.toISOString(); // "2023-06-15T14:30:45.123Z"Related Channels
- Orderbook Channel - Current market depth
- Ticker Channel - Best bid/ask prices
- Orders Channel - Your own trade executions