API WebSocket 16 мая 2026 · 8 мин

WebSocket vs REST: что выбрать для подключения к бирже

Когда достаточно обычных HTTP-запросов, а когда нужен постоянный канал — разбираем с числами и примерами.

Откуда вообще возник вопрос

Почти все криптобиржи поддерживают и REST, и WebSocket. Начинающие разработчики, как правило, стартуют с REST: запрос — ответ, всё понятно. Но при первом же тесте на реальном рынке обнаруживают задержки в 150–300 мс на получение тикера и ограничение в 1200 запросов в минуту (Binance). Тогда и появляется вопрос: а стоит ли переходить на WebSocket?

Как работает REST в контексте торговли

REST (Representational State Transfer) использует стандартный HTTP: клиент отправляет запрос, сервер отвечает, соединение закрывается. Каждый раз — новое TCP-рукопожатие, TLS-хендшейк, DNS-резолв (если нет постоянного соединения).

Для получения цены это выглядит так:

import requests

def get_price(symbol: str) -> float:
    url = f"https://api.binance.com/api/v3/ticker/price?symbol={symbol}"
    resp = requests.get(url, timeout=3)
    resp.raise_for_status()
    return float(resp.json()["price"])

# Каждый вызов — новый HTTP-запрос
price = get_price("BTCUSDT")

Суммарная задержка складывается из RTT до сервера + время обработки + накладные расходы HTTP. На колокейшне рядом с серверами биржи это может быть 3–8 мс, из любой точки России — 50–200 мс.

Rate limits: главное ограничение REST

Биржи жёстко ограничивают количество запросов. Binance даёт 1200 запросов/мин по весу (каждый endpoint имеет вес от 1 до 50). При превышении лимита приходит HTTP 429, а при систематических нарушениях — бан IP на несколько часов.

Если вы хотите обновлять цену каждую секунду для 20 символов — это уже 1200 запросов в минуту. Лимит исчерпан полностью, и остальная логика бота (размещение ордеров, проверка баланса) просто не поместится.

Как работает WebSocket

WebSocket — это постоянное двунаправленное соединение поверх TCP. После одного HTTP-хендшейка (Upgrade) сервер сам толкает данные клиенту при каждом изменении. Никаких повторных соединений, никакого опроса.

import asyncio
import websockets
import json

async def stream_price():
    url = "wss://stream.binance.com:9443/ws/btcusdt@trade"
    async with websockets.connect(url) as ws:
        while True:
            msg = await ws.recv()
            data = json.loads(msg)
            # data["p"] — цена каждой сделки в реальном времени
            print(data["p"])

asyncio.run(stream_price())

Задержка между изменением цены на бирже и получением сообщения — единицы миллисекунд (плюс сетевой RTT). Rate limits на стриминг существенно мягче или вовсе не применяются к входящим сообщениям.

Прямое сравнение

Критерий REST WebSocket
Задержка получения данных50–300 мс (polling)1–10 мс (push)
Нагрузка на сетьВысокая (заголовки HTTP на каждый запрос)Минимальная (только payload)
Rate limitsЖёсткие (1200 req/min)Мягкие / не применяются
Сложность реализацииНизкаяСредняя (реконнект, ping/pong)
Подходит для рыночных данных✗ при высокой частоте
Подходит для ордеров✓ (POST /order)✓ (Binance WS API v3)
Stateful соединение✓ (надо обрабатывать разрыв)

Когда достаточно REST

Когда необходим WebSocket

Практический вывод: используйте WebSocket для входящих рыночных данных и REST для исполняющих действий (ордера, баланс). Гибридный подход — стандарт для production-ботов.

Особенности работы с WebSocket в production

Реконнект при разрыве

Биржи разрывают соединение каждые 24 часа (Binance) или при длительном отсутствии активности. Ваш код должен автоматически переподключаться и восстанавливать подписки.

import asyncio
import websockets

async def connect_with_retry(url: str, handler):
    while True:
        try:
            async with websockets.connect(url, ping_interval=20) as ws:
                await handler(ws)
        except (websockets.ConnectionClosed, OSError):
            await asyncio.sleep(5)  # пауза перед реконнектом

Ping/Pong

Многие биржи требуют периодически отправлять ping-сообщения, иначе соединение признаётся неактивным. Библиотека websockets делает это автоматически через параметр ping_interval.

Множественные потоки

Binance позволяет объединять несколько стримов в одно соединение через /stream?streams=. Это снижает число соединений и упрощает управление:

url = "wss://stream.binance.com:9443/stream?streams=btcusdt@trade/ethusdt@trade"

Итог

Нет «лучшего» протокола — есть подходящий для задачи. Большинство production-систем используют оба: WebSocket для рыночных данных и REST для управления ордерами и аккаунтом. Если вы строите бота впервые — начните с REST, убедитесь в логике стратегии, потом переходите на стриминг.

Нужна готовая торговая система с оптимальной архитектурой? Опишите задачу — обсудим и оценим.

Все статьи Обсудить проект