Skip to main content

Account Stream

Subscribe to real-time account updates including positions, orders, margin, and comprehensive risk metrics.
No signature required - Account data is public. Anyone can subscribe to any account’s updates.

Subscribe

{
  "method": "subscribe",
  "subscription": [{
    "type": "account",
    "user": "FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7"
  }]
}
Parameters:
  • user (String): User’s public key (base58 format)

Initial Snapshot

On subscription, you receive a single unified accountSnapshot message with complete account state:
{
  "channel": "account",
  "data": {
    "type": "accountSnapshot",
    "margin": {
      "totalBalance": 100000.0,
      "availableBalance": 95000.0,
      "marginUsed": 5000.0,
      "notional": 50000.0,
      "realizedPnl": 1234.5,
      "unrealizedPnl": 567.8,
      "fees": 12.34,
      "funding": 5.67
    },
    "positions": [
      {
        "symbol": "BTC-USD",
        "size": 0.5,
        "price": 100000.0,
        "fairPrice": 101000.0,
        "notional": 50500.0,
        "realizedPnl": 500.0,
        "unrealizedPnl": 500.0,
        "leverage": 5.0,
        "liquidationPrice": 95000.0,
        "fees": 10.0,
        "funding": 2.5,
        "maintenanceMargin": 1000.0,
        "lambda": 0.05,
        "riskAllocation": 5000.0
      }
    ],
    "openOrders": [
      {
        "symbol": "BTC-USD",
        "orderId": "Fpa3oVuL3UzjNANAMZZdmrn6D1Zhk83GmBuJpuAWG51F",
        "price": 102000.0,
        "size": 0.1,
        "filledSize": 0.0,
        "isBuy": true,
        "timestamp": 1763316177219383423
      }
    ],
    "leverageSettings": [
      {
        "symbol": "BTC-USD",
        "leverage": 5.0
      },
      {
        "symbol": "ETH-USD",
        "leverage": 3.0
      }
    ]
  },
  "id": 0
}

Account Snapshot Fields

Margin:
  • totalBalance: Total margin balance
  • availableBalance: Available margin (total - maintenance margin)
  • marginUsed: Maintenance margin used
  • notional: Total notional value of all positions
  • realizedPnl: Realized profit/loss
  • unrealizedPnl: Unrealized profit/loss
  • fees: Total fees paid
  • funding: Total funding paid/received
Positions:
  • symbol: Market symbol
  • size: Position size (positive for long, negative for short)
  • price: Volume-weighted average price (entry price)
  • fairPrice: Current fair/mark price
  • notional: Notional value (size × fair_price)
  • realizedPnl: Realized profit/loss for this position
  • unrealizedPnl: Unrealized profit/loss for this position
  • leverage: Position leverage
  • liquidationPrice: Liquidation price
  • fees: Fees paid for this position
  • funding: Funding paid/received for this position
  • maintenanceMargin: Maintenance margin required for this position
  • lambda: Lambda value (risk parameter)
  • riskAllocation: Risk allocation (C_i)
Open Orders:
  • symbol: Market symbol
  • orderId: Order ID (base58, use for cancellation)
  • price: Order price
  • size: Current remaining size
  • filledSize: Filled size
  • isBuy: true for buy orders, false for sell orders
  • timestamp: Order placement time (nanoseconds)
Leverage Settings:
  • symbol: Market symbol
  • leverage: Maximum leverage setting for that symbol (1.0 to 50.0)

Real-time Delta Updates

After the initial snapshot, you receive delta updates for changes:

Margin Update

{
  "channel": "account",
  "data": {
    "type": "marginUpdate",
    "totalBalance": 100500.0,
    "availableBalance": 95500.0,
    "marginUsed": 5000.0,
    "notional": 50500.0,
    "realizedPnl": 1234.5,
    "unrealizedPnl": 567.8,
    "fees": 12.34,
    "funding": 5.67
  },
  "id": 0
}

Position Update

{
  "channel": "account",
  "data": {
    "type": "positionUpdate",
    "symbol": "BTC-USD",
    "size": 0.5,
    "price": 100000.0,
    "realizedPnl": 500.0,
    "unrealizedPnl": 500.0,
    "leverage": 5.0,
    "liquidationPrice": 95000.0,
    "fairPrice": 101000.0,
    "notional": 50500.0,
    "fees": 10.0,
    "funding": 2.5,
    "maintenanceMargin": 1000.0,
    "lambda": 0.05,
    "riskAllocation": 5000.0
  },
  "id": 0
}

Order Placed

{
  "channel": "account",
  "data": {
    "type": "order",
    "status": "placed",
    "symbol": "BTC-USD",
    "orderId": "Fpa3oVuL3UzjNANAMZZdmrn6D1Zhk83GmBuJpuAWG51F",
    "price": 102000.0,
    "size": 0.1,
    "isBuy": true,
    "timestamp": 1763316177219383423
  },
  "id": 0
}

Order Cancelled

{
  "channel": "account",
  "data": {
    "type": "order",
    "status": "cancelled",
    "orderId": "Fpa3oVuL3UzjNANAMZZdmrn6D1Zhk83GmBuJpuAWG51F",
    "symbol": "BTC-USD",
    "timestamp": 1763316177219383423
  },
  "id": 0
}

Fill (Trade Execution)

{
  "channel": "account",
  "data": {
    "type": "fill",
    "symbol": "BTC-USD",
    "orderId": "Fpa3oVuL3UzjNANAMZZdmrn6D1Zhk83GmBuJpuAWG51F",
    "price": 102000.0,
    "size": 0.05,
    "isBuy": true,
    "timestamp": 1763316177219383423,
    "maker": false
  },
  "id": 0
}

Leverage Update

{
  "channel": "account",
  "data": {
    "type": "leverageUpdate",
    "leverage": [
      {
        "symbol": "BTC-USD",
        "leverage": 5.0
      }
    ]
  },
  "id": 0
}

Update Frequency

  • Initial Snapshot: Sent immediately on subscription (single unified message)
  • Periodic Updates: Every ~500 ticks (margin, positions, leverage settings)
  • Real-time Events: Immediately on order placement, cancellation, or fill execution

Example: Monitor Account

const WebSocket = require('ws');

const PUBLIC_KEY = 'FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7';
const ws = new WebSocket('wss://exchange-wss.bulk.trade');

ws.on('open', () => {
  console.log('Connected');
  
  // Subscribe to account updates
  ws.send(JSON.stringify({
    method: 'subscribe',
    subscription: [{
      type: 'account',
      user: PUBLIC_KEY
    }]
  }));
});

ws.on('message', (data) => {
  const message = JSON.parse(data);
  
  if (message.channel === 'account') {
    const { type, ...details } = message.data;
    
    switch(type) {
      case 'accountSnapshot':
        console.log('Account snapshot:', details);
        console.log('Positions:', details.positions);
        console.log('Open orders:', details.openOrders);
        break;
      case 'marginUpdate':
        console.log('Margin update:', details);
        break;
      case 'positionUpdate':
        console.log('Position update:', details);
        break;
      case 'order':
        if (details.status === 'placed') {
          console.log('Order placed:', details);
        } else if (details.status === 'cancelled') {
          console.log('Order cancelled:', details);
        }
        break;
      case 'fill':
        console.log('Order filled:', details);
        break;
      case 'leverageUpdate':
        console.log('Leverage updated:', details);
        break;
    }
  }
});