Бот опрашивал биржевой API раз в секунду и всё равно опаздывал. Знакомо? Так было, пока я не перешёл на WebSocket: вместо того чтобы выпрашивать цену, получаешь поток данных, который сам приходит в момент сделки. Разница — как между скриншотом вчерашнего графика и живой лентой котировок.
Почему polling проигрывает
Когда код дёргает REST API каждую секунду, он видит мир с опозданием. Для обычного приложения — мелочь. Для арбитража или скальпинга — вечность: узкое окно между ценами закрывается раньше, чем приходит ответ.
И это не единственная проблема.
- Каждый запрос сжигает rate-limit кредиты. Начнёте опрашивать чаще — упрётесь в блокировку.
- Цена в ответе уже устарела к моменту обработки.
- Нет механизма восстановления: если запрос упал, цикл просто продолжается вслепую.
Симптомы знакомы любому, кто писал торгового бота на коленке. Раньше это казалось нормой, пока не узнаёшь про WebSocket.
WebSocket — это постоянное соединение: сервер сам отправляет сообщение, когда в стакане или ленте сделок что-то меняется.
Сравнение: REST polling vs WebSocket
| Критерий | REST polling | WebSocket |
|---|---|---|
| Соединение | Новый HTTP-запрос каждую секунду | Одно постоянное соединение |
| Задержка данных | Цена устаревает на секунду и больше | Миллисекунды после события |
| Расход лимитов | Каждый запрос тратит лимит | Один коннект без повторных рукопожатий |
| Отказоустойчивость | Встроенной обработки сбоев нет | Нужно самому ловить ConnectionClosed и переподключаться |
Как это выглядит в коде
В Python достаточно библиотеки websockets. Подключаетесь к combined stream Binance: wss://stream.binance.com:9443/stream?streams=btcusdt@ticker/btcusdt@trade — и в цикле читаете сообщения.
Формат простой: каждая порция данных оборачивается объектом с полем stream (например, btcusdt@ticker) и data (сам payload). В ticker приходят лучшие bid/ask — поля b и a. В trade — цена p и объём q.
Дальше логика тривиальная: если stream заканчивается на @ticker, печатаем цену; если на @trade — печатаем сделку. Вся магия — в async with websockets.connect(...), а не в цикле опроса.
Три грабли, о которые спотыкаются
- Игнорирование ping/pong. Некоторые биржи ждут ответа на ping-фрейм, иначе отключают. Библиотеки обычно делают это сами, но если пишете свой клиент — не забудьте pong.
- Сообщения приходят не по порядку и могут дублироваться. Ориентируйтесь на event time или trade time, чтобы выстроить правильную последовательность.
- Тяжёлые вычисления внутри цикла. Обработка каждого сообщения должна быть лёгкой. Сложную логику выносите в asyncio.Queue или воркеры, иначе не успеете за потоком.
Ещё важный момент — backpressure. Если сообщений слишком много, вы не сможете обработать всё. Надо либо буферизовать, либо осознанно отбрасывать. Молчаливое отставание хуже явного дропа.
Что это даёт на практике
Живой поток данных открывает то, что на polling выглядело фантастикой:
- Micro-скальпинг — ловить спреды, живущие меньше секунды.
- Детект дисбаланса стакана — реагировать на резкие сдвиги до движения цены.
- Автоматический хедж — подстраивать фьючерсную позицию в момент изменения спота.
Тот же код работает и для других бирж: Coinbase Pro, Kraken, Alpaca. Меняется только URL и форма payload, логика остаётся.
План перехода
- Выберите биржу с WebSocket API. Начните с Binance — документация внятная.
- Подключите один поток тикера и просто печатайте изменения.
- Добавьте обработку ConnectionClosed с повторным подключением через пару секунд.
- Вынесите обработку сообщений в отдельную очередь, чтобы цикл оставался лёгким.
- Прогоните на исторической записи, прежде чем включать в боевую стратегию.
WebSocket не делает стратегию прибыльной. Он убирает задержку, из-за которой хорошая идея не успевает сработать. Переход с polling на потоковые данные — это не апгрейд ради хайпа, а смена модели мышления: перестаёте спрашивать и начинаете слушать.
Комментарии (0)
Войдите, чтобы комментировать.
Пока нет комментариев. Будьте первым.