Перейти к содержимому

Стриминг

Сделки, цены, стакан, счёт, раскладка и настройки в реальном времени через один WebSocket.

Стрим — это одно соединение WebSocket, которое несёт все живые обновления. Чтобы его открыть, нужно право market:read.

Подключиться и читать события

import asyncio
from spectre_terminal import Event, Gap, SubscriptionError, Terminal

async def main():
    terminal = Terminal.discover()
    async with terminal.stream() as stream:
        trades = await stream.subscribe("trades", "binance:futures:BTCUSDT")
        async for frame in stream:
            match frame:
                case Event(sub=trades.sub):
                    for trade in frame.data:
                        print(trade.side, trade.price, trade.qty)
                case Gap():
                    print("lost trades", frame.from_seq, frame.to_seq)
                case SubscriptionError():
                    print("subscription removed", frame.code)

asyncio.run(main())

Цикл отдаёт события, пропуски и ошибки подписок. Событие несёт sub, seq, ts и data. sub — идентификатор подписки, а форма data зависит от топика. Все кадры и поля есть в справочнике стрима.

Подписаться на топик

trades = await stream.subscribe("trades", "binance:futures:BTCUSDT")
book = await stream.subscribe("book.top", "binance:futures:BTCUSDT", depth=5, interval_ms=200)
fills = await stream.subscribe("account.fills", connection_id=12)
ТопикЧто несёт событиеЧто нужно
tradesНовые сделки, по порядкуИнструмент, market:read
tickerСуточный тикерИнструмент, market:read
mark_priceЦена маркировкиИнструмент, market:read
book.topВерх стаканаИнструмент, market:read
clustersБакет кластеров объёма, который изменилсяИнструмент, market:read
account.ordersЗаявки и триггерные заявки одного инструментаИдентификатор подключения, account:read
account.positionsПозиция по одному инструментуИдентификатор подключения, account:read
account.balancesБаланс одной валютыИдентификатор подключения, account:read
account.fillsОдно исполнениеИдентификатор подключения, account:read
workspaceВся раскладка оконworkspace:read
settingsОдна записанная строка настроекsettings:read

Отклонённый запрос выбрасывает StreamRequestError с кодом из раздела Ошибки. Данные Московской биржи (MOEX) не отдаются.

book.top принимает два необязательных параметра. depth — число уровней с каждой стороны: от 1 до 200, по умолчанию 50. interval_ms — наименьшее время между двумя кадрами: от 50, по умолчанию 100. Значения вне диапазона отклоняются с invalid_request.

workspace присылает текущую раскладку первым кадром. Топики счёта и settings присылают только изменения, поэтому сначала прочитайте текущее состояние. См. Счёт и Настройки.

Обработать пропуск

Когда ваша программа читает медленнее, чем приходят данные, терминал отбрасывает кадры, которые не помещаются.

ТопикПризнак потериЧто делать
tradesКадр пропуска перед следующим событиемПрочитать сделки ещё раз с since_ts
account.fillsseq пропускает номерПрочитать исполнения ещё раз с since_ts
settingsseq пропускает номерПрочитать настройки ещё раз
Все остальныеНетНичего. Следующий кадр — самое новое состояние, а пропущенные номера seq — это нормально

Передайте время последней сделки или последнего исполнения, которые у вас есть. Аргумент называется since_ts в Python и sinceTs в TypeScript.

Обработать снятую подписку

Терминал снимает подписку, когда биржа её отклоняет или когда её подключение выключают. Тогда цикл отдаёт ошибку подписки с sub, code и message. Подпишитесь снова, когда причина устранена.

Переподключиться

import asyncio
from spectre_terminal import StreamClosed, Terminal

async def main():
    terminal = Terminal.discover()
    while True:
        try:
            async with terminal.stream() as stream:
                await stream.subscribe("trades", "binance:futures:BTCUSDT")
                async for frame in stream:
                    print(frame)
        except StreamClosed as closed:
            print("stream closed", closed.code)
        await asyncio.sleep(1)

asyncio.run(main())

Когда терминал закрывает стрим, цикл выбрасывает StreamClosed в Python и StreamClosedError в TypeScript. Подписки не сохраняются, поэтому после переподключения подпишитесь заново.

Код закрытия говорит, почему стрим закрыт, см. Коды закрытия стрима.

Отписаться и закрыть

await stream.unsubscribe(trades)
await stream.close()

unsubscribe сразу снимает одну подписку. Закрытие стрима снимает все подписки и завершает цикл без ошибки.

Лимиты

Один токен может держать 8 соединений стрима, а одно соединение — 100 подписок. API может открыть 50 инструментов, которые не открыты в окне терминала, и не больше 5 новых в секунду.

Сверх лимита subscribe завершается ошибкой rate_limited. Немного подождите и попробуйте снова. См. Лимиты.

На этой странице