Stop polling: your trading bot is acting on stale prices

Stop polling. How to stream tickers, order books, trades, and your own orders over WebSockets with CCXT — and what the library does for you under the hood.

By CCXT Team

The first version of every bot polls: call fetchTicker in a loop, sleep, repeat. It works — until you want more than one symbol, or faster reactions, or you hit the exchange's rate limit. Polling gives you a snapshot per request; markets move between your requests.

Exchanges solve this with WebSocket streams: you subscribe once and the exchange pushes every update to you. CCXT ships WebSocket support in the same package you already have, in all six languages, behind an API that mirrors the REST one: where REST has fetchOrderBook, WebSockets have watchOrderBook.

The watch loop

A watch* method resolves every time a new update arrives, so real-time code is just a loop:

import ccxt from 'ccxt';

const exchange = new ccxt.pro.binance();

while (true) {
    const orderbook = await exchange.watchOrderBook('BTC/USDT');
    console.log(orderbook.bids[0], orderbook.asks[0]);
}

The first call opens the connection and subscribes; every following call just waits for the next update. The same pattern works for watchTicker, watchTrades, watchOHLCV, and — with API keys — watchBalance, watchOrders, and watchMyTrades for your own fills.

What CCXT does for you under the hood

Raw exchange WebSocket APIs are messy, and this is where most hand-rolled integrations go wrong. When you call watchOrderBook, CCXT:

  • Maintains the book from deltas. Most exchanges send an initial snapshot and then incremental updates. CCXT applies them in order, checks sequence numbers, and hands you a complete, sorted order book every time — not a raw diff message.
  • Manages connections. One WebSocket per stream group, shared across your subscriptions. Subscribe to fifty symbols and CCXT multiplexes them properly for that exchange.
  • Reconnects and resubscribes. Exchanges drop connections routinely (Binance, for example, cuts every connection after 24 hours). CCXT reconnects, re-authenticates, and re-subscribes automatically; your loop just keeps receiving updates.
  • Handles keepalives — ping/pong frames, heartbeat messages, and the exchange-specific quirks you'd otherwise discover at 3 a.m.

Many symbols, many exchanges

For dashboards, scanners, and market making you rarely want a single stream. watchTickers subscribes to a list of symbols in one shot and returns a structure keyed by symbol, updated as events arrive:

const symbols = ['BTC/USDT', 'ETH/USDT', 'SOL/USDT'];
while (true) {
    const tickers = await exchange.watchTickers(symbols);
    console.log(tickers['BTC/USDT'].last);
}

There are ...ForSymbols variants (watchTradesForSymbols, watchOrderBookForSymbols, watchOHLCVForSymbols) when you need one loop over many markets, and running several exchanges concurrently is just multiple loops — one async task per exchange in JavaScript/Python/PHP/C#/Java, one goroutine per exchange in Go.

Watching your own orders

The same mechanism covers private data, which is how bots track fills without polling fetchOrder:

const exchange = new ccxt.pro.binance({ apiKey: KEY, secret: SECRET });
while (true) {
    const orders = await exchange.watchOrders();
    for (const order of orders) {
        console.log(order.id, order.status, order.filled);
    }
}

Practical notes

  • Check support first. Not every exchange implements every stream. Capability flags tell you at runtime: exchange.has['watchOrderBook'], exchange.has['watchOrders'], and so on.
  • Always close() on shutdown. WebSocket connections hold sockets and background tasks; call await exchange.close() when your program exits.
  • REST still has a job. Placing and canceling orders, fetching history, and one-shot queries are REST's territory. The standard architecture is: WebSockets for state you watch (prices, books, fills), REST for actions you take.
  • Throughput beats latency for most people. The realistic win of WebSockets is not microseconds — it's watching hundreds of markets simultaneously without touching a rate limit, which is simply impossible with polling.

If you're building toward strategies that need this — scanners, market making — the follow-up posts pick up exactly here: arbitrage strategies and market making.