Работа с Binance через WebSockets

Андрей К…
Последнее изменение:
45
1
0

Введение

Большинство современных криптобирж отдают информацию через REST-запросы – клиент должен запросить через HTTP страницу с определенным адресом, отправить нужные параметры и получить некоторый ответ.

Сама по себе технология REST довольно интересна – незаметно для получателя запрос может путешествовать от одного сервера к другому, можно балансировать нагрузку, можно снизить кол-во отдаваемого трафика, но этого мало (с)

На крупных биржах счет пользователей идет на миллионы, а кол-во запросов к API намного выше, т.к. и команды пользователей идут через эти же интерфейсы, через них работают работы, через них другие сайты получают информацию для виджетов на свои сайты, брокеры выводят информацию своим клиентам, тысячи телеграм-каналов что-то там транслируют, анализируют, и многое-многое другое. А ведь каждый лишний байт трафика, помноженный на десятки миллионов запросов выливается в большие долларовые потери на оплату трафика, содержание серверов, сетевого оборудования, зарплаты техподдержки – поэтому REST становится накладным.

Для экономии трафика используется технология WebSocket -  с ней некоторое кол-во трафика тратится один раз на установление соединения, после чего клиент и сервер обмениваются непосредственно данными. Это как связаться с кем-то по телефону – вы позвонили, трубку снял автоответчик, теперь вы можете бесконечно висеть на трубке и слушать, что там происходит. Вообще вебсокеты подразумевают двустороннюю связь – вы можете что-то говорить в трубку, ваш абонент может, но в случае Binance (и большинства других криптобирж) есть ограничения.

Так, например, на бинансе нельзя слушать сокет непрерывно свыше 24 часов. Так же связь односторонняя – сервер время от времени (один раз в секунду, как правило) выдаёт один и тот же набор данных всем, кто его слушает. Это как прийти на вокзал и слушать объявления – «Поезд на Бердичев прибыл на второй путь», «Отправление поезда Саратов-Омск» в толпе таких же людей.


Реклама


Работа с сокетами Binance

Для работы вам потребуется установленный питон версии 3.6 и выше. Скачать его можно с официального сайта, при установке установив все флаги.

Технически, нет ничего сложного, чтобы реализовать протокол самому с нуля, для этого у вас всё есть, но не будем изобретать велосипеды и возьмем чужой готовый модуль питона websocket-client и посмотрим, что можно получить с binance. Для установки модуля выполните в командной строке

pip install websocket-client

Теперь давайте напишем простой скрипт для проверки работы, а потом пройдемся детальнее. Вот он:

import websocket

def on_message(ws, message):
    print(message)

def on_error(ws, error):
    print(error)

def on_close(ws):
    print("### closed ###")

def on_open(ws):
    print("### connected ###")

if __name__ == "__main__":
    #ws = websocket.WebSocketApp("wss://stream.binance.com:9443/stream?streams=ltcbtc@aggTrade/ethbtc@aggTrade",
    ws = websocket.WebSocketApp("wss://stream.binance.com:9443/ws/ltcbtc@aggTrade/ethbtc@aggTrade",
                              on_message = on_message,
                              on_error = on_error,
                              on_close = on_close)
    ws.on_open = on_open
    ws.run_forever()

После его запуска вы увидите нечто похожее:

Фактически, вы подключились к сокет-серверу и подписались на обновления сделок по парам LTCBTC и ETHBTC. Фактически синхронно с веб-интерфейсом у вас обновляются данные по последним сделкам. Теперь давайте рассмотрим подробнее, что и как можно и нужно делать. Начнем с режимов.


Реклама


Режимы raw и combined

В моем скрипте одна строка закомментирована – вы можете её раскомментировать и удалить строку под ней – тогда вам будет выдаваться чуть больше информации, вот так:

import websocket

def on_message(ws, message):
    print(message)

def on_error(ws, error):
    print(error)

def on_close(ws):
    print("### closed ###")

def on_open(ws):
    print("### connected ###")

if __name__ == "__main__":
    ws = websocket.WebSocketApp("wss://stream.binance.com:9443/stream?streams=ltcbtc@aggTrade/ethbtc@aggTrade",
    #ws = websocket.WebSocketApp("wss://stream.binance.com:9443/ws/ltcbtc@aggTrade/ethbtc@aggTrade",
                              on_message = on_message,
                              on_error = on_error,
                              on_close = on_close)
    ws.on_open = on_open
    ws.run_forever()

 

Первый режим – это то, что Binance называет raw режимом – каждый набор данных отдается как есть, независимо от другого. Т.е. если в один момент времени произошли сделки И LTCBTC И ETHBTC, то вы получите две записи.

В случае combined режима, вы, скорее всего, получите одну запись, которая логически будет структурирована, и внутри которой будут сделки по каждой паре, каждая в своем разделе. Смотрите сами, как вам удобнее, мне удобнее raw.

Требования к подключениям

Каждое подключение должно идти на адрес

wss://stream.binance.com:9443

В конце адреса нужно подставить параметр, что бы указать, какая информация вам нужна. В случае raw укажите /ws/…, в случае combined - /stream?streams=, как у меня в примере.

Все пары маленькими буквами, и не забывайте пересоздавать коннект раз в 24 часа.

Непосредственно стримы

Стримы – streams (потоки) – это то, что «льется» из биржи – например, информация по свечам EOSBTC – это один стрим, по свечам ONTBTC – другой, тикер по всем парам – третий, и т.п.

Информация по сделкам (агрегированная)

То, что мы смотрели в примере выше – сделки по паре (или парам), объединенные в рамках одного ордера. Иными словами, если по одной цене одним человеком по одной паре в течении последних милисекунд было совершено несколько сделок, то вы увидите одну строку.

Пример запроса: ethbtc@aggTrade

wss://stream.binance.com:9443/ws/ethbtc@aggTrade

wss://stream.binance.com:9443/stream?streams=ethbtc@aggTrade

Структура ответа:{
  "e": "aggTrade",  // Тип события
  "E": 123456789,   // Время отправки события
  "s": "BNBBTC",    // Пара
  "a": 12345,       // ID возвращаемой записи
  "p": "0.001",     // Цена
  "q": "100",       // Кол-во
  "f": 100,         // ID первой сделки
  "l": 105,         // ID последней сделки
  "T": 123456785,   // Время сделки
  "m": true,        // Покупатель мейкер?
  "M": true         // Не актуально.
}

 

Информация по сделкам (подробная)

Выдается информация по сделкам, как есть.

Пример запроса: ethbtc@trade

wss://stream.binance.com:9443/ws/ethbtc@trade

wss://stream.binance.com:9443/stream?streams=ethbtc@trade

Структура ответа:

{
  "e": "trade",     // Тип события
  "E": 123456789,   // Время отправки
  "s": "BNBBTC",    // Пара
  "t": 12345,       // ID события
  "p": "0.001",     // Цена
  "q": "100",       // Объем
  "b": 88,          // Id заказа покупателя
  "a": 50,          // Id заказа продавца
  "T": 123456785,   // Время сделки
  "m": true,        // Покупатель мейкер?
  "M": true         // Не актуально.
}

Информация по свечам

Отдается каждую секунду. Нужно указать период, за который интересует информация.

Формируется так: параkline_период

Например

wss://stream.binance.com:9443/ws/ethbtc@kline_5m

wss://stream.binance.com:9443/stream?streams=ethbtc@kline_5m

Единицы измерения:

m -> минуты; h -> часы; d -> дни; w -> недели; M -> месяца

Возможные варианты:

  • 1m
  • 3m
  • 5m
  • 15m
  • 30m
  • 1h
  • 2h
  • 4h
  • 6h
  • 8h
  • 12h
  • 1d
  • 3d
  • 1w
  • 1M

 

Структура ответа:

{
  "e": "kline",     // Тип события
  "E": 123456789,   // Время события
  "s": "BNBBTC",    // пара
  "k": {
    "t": 123400000, // Время открытия свечи (UNIXTIME)
    "T": 123460000, // Время закрытия свечи
    "s": "BNBBTC",  // Пара
    "i": "1m",      // Период
    "f": 100,       // ID первой сделки периода
    "L": 200,       // ID последней сделки периода
    "o": "0.0010",  // Цена открытия
    "c": "0.0020",  // Цена закрытия
    "h": "0.0025",  // High
    "l": "0.0015",  // Low
    "v": "1000",    // Объем базовой валюты
    "n": 100,       // Кол-во сделок
    "x": false,     // Закрыта ли свеча?
    "q": "1.0000",  // Объем квотируемой валюты
    "V": "500",     // Сколько базовой валюты куплено тейкерами
    "Q": "0.500",   // Сколько квотируемой валюты куплено тейкерами
    "B": "123456"   // Не актуально
  }
}

Статистика по паре за 24 часа

Отправляется с сервера раз в секунду.

Пример запроса: ethbtc@ticker

wss://stream.binance.com:9443/ws/ethbtc@ticker

wss://stream.binance.com:9443/stream?streams=ethbtc@ticker

Структура ответа:

{
  "e": "24hrTicker",  // Тип события
  "E": 123456789,     // Время события
  "s": "BNBBTC",      // Пара
  "p": "0.0015",      // Изменение цены
  "P": "250.00",      // Изменение цены в процентах
  "w": "0.0018",      // Средневзвешенная цена
  "x": "0.0009",      // Цена закрытия предыдущих суток
  "c": "0.0025",      // Цена закрытия текущих суток
  "Q": "10",          // Объем закрытия
  "b": "0.0024",      // Цена лучшего Bid (спроса/покупки) 
  "B": "10",          // Объем лучшего Bid
  "a": "0.0026",      // Цена лучшего ask (преложение/продажа)
  "A": "100",         // Объем лучшего ask
  "o": "0.0010",      // Цена открытия
  "h": "0.0025",      // High 
  "l": "0.0010",      // Low 
  "v": "10000",       // Общий объем торгов в базовой валюте
  "q": "18",          // Общий объем торгов в квотируемой валюте
  "O": 0,             // Время начала сбора статистики
  "C": 86400000,      // Время окончания сбора статистики
  "F": 0,             // ID первой сделки
  "L": 18150,         // Id последней сделки
  "n": 18151          // Общее кол-во сделок
}

Статистика по всем парам за 24 часа

Отправляется раз в секунду.

Пример запроса: /!ticker@arr

wss://stream.binance.com:9443/ws/!ticker@arr

wss://stream.binance.com:9443/stream?streams=!ticker@arr

Возвращает то же, что и статистика за 24 часа, но по всем парам сразу, вот в такой структуре:

[
  {
    // Отдельно взятая пара
  }
]

Часть книги ордеров

Лучшие предложения покупки и продажи. Допускается получать по 5, 10 или 20 предложений из каждого стакана. Обновляется раз в секунду

Пример запроса: ethbtc@depth5

wss://stream.binance.com:9443/ws/ethbtc@depth5

wss://stream.binance.com:9443/stream?streams=ethbtc@depth5

Структура ответа:

{
  "lastUpdateId": 160,  // ID события
  "bids": [             // Стакан покупок
    [
      "0.0024",         // Цена
      "10",             // Объем
      []                // Не актуально
    ]
  ],
  "asks": [             // Стакан продаж
    [
      "0.0026",         // Цена
      "100",            // Объем
      []                // Не актуально
    ]
  ]
}

Обновление книги ордеров

Обновляется раз в секунду. Метод нужен тем, кто локально собирает и анализирует копии стаканов.

Пример запроса: ethbtc@depth

wss://stream.binance.com:9443/ws/ethbtc@depth

wss://stream.binance.com:9443/stream?streams=ethbtc@depth

Структура ответа:

{
  "e": "depthUpdate", // Тип события
  "E": 123456789,     // Время события
  "s": "BNBBTC",      // Пара
  "U": 157,           // Первое ID события
  "u": 160,           // Последнее ID события
  "b": [              // Покупки
    [
      "0.0024",       // Цена
      "10",         // Объем
      []              // Не актуально
    ]
  ],
  "a": [              // Продажи
    [
      "0.0026",       // Цена
      "100",          // Объем
      []              // Не актуально
    ]
  ]
}

Как правильно собирать стаканы на своей стороне:

  1. Откройте подключение к Open a stream to wss://stream.binance.com:9443/ws/bnbbtc@depth
  2. Собирайте в буфер информацию, которую получите оттуда
  3. Получите текущую информацию (слепок) по стаканам с адреса https://www.binance.com/api/v1/depth?symbol=BNBBTC&limit=1000
  4. У себя в буфере удалите (и не принимайте) все события, у которых u <= lastUpdateId слепка и u > lastUpdateId+1
  5. Каждое новое событие стрима должно быть выше предыдущего u на единицу
  6. Данные в каждом событии – абсолютные значения текущей цены и объема
  7. Если объем 0, удалите у себя цену
  8. Получение данных с 0, которых нет у вас в книге, допускается, и не является какой-либо ошибкой.

Это статья из цикла "Популярно о бирже"

Текущая статья
Комментарии: (45)
23.08.2018 08:59
Добрый день, можете подсказать, что означает эта ошибка при выполнении:
"wss://stream.binance.com:9443/ws/ethbtc@kline_5m"
### connected ###
{"e":"kline","E":1535014904715,"s":"ETHBTC","k":{"t":1535014800000,"T":1535015099999,"s":"ETHBTC","i":"5m","f":78705608,"L":78705736,"o":"0.04261000","c":"0.04259300","h":"0.04262500","l":"0.04259200","v":"47.97100000","n":129,"x":false,"q":"2.04394491","V":"24.24100000","Q":"1.03311231","B":"0"}}
'>' not supported between instances of 'float' and 'NoneType'
### closed ###
23.08.2018 11:36
Добрый день.
Это значит, что сравниваете два каких-то значения, из которых одно является числом с плавающей точкой, а другое неопределено.
Больше ничего сказать нельзя, не видя кода.
Проверьте, где у вас используется конструкция вида
переменная1 > переменная2
23.08.2018 12:12
Андрей, спасибо за быстрый ответ. 
Мне понятно, что означает это сообщение (его перевод), но непонятно как оно вообще может возникнуть при выполнении скрипта с этой страницы, где нет никаких сравнений переменных и т.п.
Возможно ошибка возникает при отработке WebSocketApp, причем вначале 1 раз возникает событие on_message (все ок), а затем on_error (с этой ошибкой)
23.08.2018 12:51
Судя по исходному коду, on_message изначально пустой, там нечему ломаться
Я скопировал скрипт со страницы, запустил, ошибок не вижу - может быть, у вас скопировались какие-то html-теги или вроде того?
29.08.2018 10:25
Андрей добрый день. Подтверждаю. Действительно с кодом с данной страницы возникает данная ошибка.
03.11.2018 14:53
Версия websocket-client 0.54.0 решила проблему, на 0.51.0 была та же ошибка
30.08.2018 12:21
Аналогично, только что всплыла данная проблема.
Решил данную проблему откатом библиотеки websocket-client
версии выше 0.45.0 не работали откатился к версии 0.21.0 всё заработало
02.09.2018 19:24
До этого устанавливался 0.51.0, удалил потом и установил pip install websocket-client==0.21.0
и всё равно Пишит:
Traceback (most recent call last):
  File "websocket.py", line 17, in <module>
    ws = websocket.WebSocketApp("wss://stream.binance.com:9443/ws/ltcbtc@aggTrade/ethbtc@aggTrade",
AttributeError: module 'websocket' has no attribute 'WebSocketApp'
>>> 
первый код</module>
11.09.2018 00:26
Доброго времени суток... Скажите пожалуйста, в одной из статей Вы упомянули что биржа Бинансе каждому зарегистрированному пользователю присваевает свой ID-номер. Можно ли в через websocket или  api получать связку данных по торгам ввиде ID-user+order(параметры ордера такие как размер ордера, тип ордера) для анализа ситуации по стакану? Или для отслеживания торгового поведения пользователя (например крупного игрока)?
11.09.2018 06:36
Доброго.
Для того, что бы отслеживать конкретного человека, нужно знать его API ключи, ну или хотя бы публичный.
Получать информацию по стаканам можно без авторизации, но там не будет видно, кто именно какие ставит, только суммарные данные, такие же, как вы видите на сайте в стакане.
23.09.2018 07:58
Добрый день!
А это все стримы? Если нет, то где можно посмотреть список всех?
Конкретно интересует "recent market activity", как на сайте, может есть такой.
17.10.2018 12:00
Да, взято с официального описания. Может быть, в источнике что-то добавится, но пока тенденции к этому не было
https://github.com/binance-exchange/binance-official-api-docs/blob/master/web-socket-streams.md
Еще есть полузакрытые источники - https://github.com/binance-exchange/binance-official-api-docs/blob/master/user-data-stream.md
Там можно отслеживать состояние своего баланса и получать информацию по своим ордерам.
Что бы эмулировать активность, наверное нужно подписаться на все trades и делать выводы самостоятельно
01.10.2018 08:06
Добрый день!
Не могу разобраться в сборе локального ордербука.
После того как вытаскивается текущий стакан с https://www.binance.com/api/v1/depth?symbol=BNBBTC&limit=1000 мы обновляем его данными накопленными со стрима. 
Паралельно с поступлением обновленией ордербука происходит торговля, т.е. некоторые ордера уже реализованы.
Возможно есть примеры реализации локальных стаканов?.
Заранее благодарен!
17.10.2018 12:03
Насчет примера - да, можете расковырять код из статьи https://bablofil.ru/inner-arbitrage/
Там как раз формируются стаканы по всем парам и поддерживаются в актуальном состоянии.
Технически, как только вы совершаете куплю/продажу, прилетает сообщение из сокета, так что прям уж рассинхрона быть не должно
06.12.2018 12:56
скажите, если возможность подписаться сразу на все пары альтернативным способом чес этот ? 
"wss://stream.binance.com:9443/ws/ethbtc@kline_1m/ltcbtc@kline_1m/bnbbtc@kline_1m/neobtc@kline_1m/qtumeth@kline_1m.................." etc...

А то получается очень длинная строка если подписаться сразу на все ~400 пар. Это мне нужно для создания базы истории торгов.
08.12.2018 12:41
Другого способа, насколько мне известно, нет (
08.12.2018 13:09
Спасибо за ответ. 
Еще я заметила странность, если запросить цены '/api/v3/ticker/price' то я получаю 412 уникальных пар, а вот если добавить их в /ws/ethbtc@kline_1m/все_412_пар/   то биржа выдает в стрим 382 свечи со статусом "x":true. Причем всегда  одинаково 382.
Интересно куда деваются 30 свечей как думаете ?
08.12.2018 13:54
Там вроде бы свечи обновляются по событию, если не было изменения цены, то всю минуту может ничего не происходить, придет в начале следующей.
Нужно запустить, и дать поработать какое-то время, постепенно кол-во пар дойдет до максимального, вроде бы так.
08.12.2018 14:02
Забыл сказать, берите только те пары из exchangeInfo, у которых
"status":"TRADING"
08.12.2018 13:58
А зачем вы вручную пары указываете? Я беру при старте exchangeInfo через rest, оттуда беру каждую пару 
ws = websocket.WebSocketApp("wss://stream.binance.com:9443/ws/" +
                                        '/'.join([symbol['symbol'].lower() + '@kline_1m' for symbol in limits['symbols'] ....
08.12.2018 17:52
А они бывают то TRADING то NONE причем за сутки может поменяться это состояние. А я базу собираю для технического анализа.
08.12.2018 19:34
Выяснила )) Как раз эти недостающие пары в статусе "BREAK". Я просто пары брала не с exchangeInfo, а с /api/v3/ticker/price
08.12.2018 17:57
Вручную разумеется не указываю, это я для примера написала. Я вообще с Python не знакома, но не плохо пишу на С++ и ваши статьи мне сильно помогли в написании своей собственной библиотеки.
09.12.2018 10:20
Вы так же можете рассмотреть вариант получения не минутных свечей, а сбор истории сделок.
Такая информация позволит самостоятельно строить свечи любой размерности, включая секундные, и так же даст некоторую дополнительную информацию для анализа. Разумеется, объем данных будет больше и потребуется больше времени и ресурсов для обработки и хранения.
09.12.2018 11:32
Спасибо за совет. Как раз для этого решила перейти на Couchbase Server.
15.01.2019 11:13
Доделываю этот скриптик, но проблема. Состояние позиции и работа моего цикла  асинхронны.  В цикле через слишком быстрый while получаю цены, из за чего отправленные заявки дублируются. Замедление решит проблему, но это слишком просто).  В двух словах подскажите как избежать дублирование заявок?
17.01.2019 10:32
Смотря какая логика..
Как вариант можно завести глобальный словарь, где ключом будет пара, и перед созданием ордера проверять, что значение не выставлено, а после создания проставлять.
19.03.2019 05:38
Андрей, здравствуйте! Подскажите по Binance API... Я подписался на стримы Trade и aggTrade  - как мне понять где Buy или Sell, цель отслеживать крупные сделки по парам....
{ e: 'trade',
  E: 1552973882978,
  s: 'BTCUSDT',
  t: 107095642,
  p: '3980.42000000',
  q: '0.00293000',
  b: 291269640,
  a: 291269650,
  T: 1552973882973,
  m: true,
  M: true }
19.03.2019 08:29
Интересует поле

"m": true,        // Is the buyer the market maker?

Тут на самом деле вопрос с подвохом, т.к. если один купил а другой продал, то это покупка или продажа?
В истории торгов на самой бирже зеленым подсвечиваются сделки, у которых isBuyerMaker == false, и маджентой - у кого true
Соответственно, если у вас поле m == true, то оно на бирже подсветилось бы красным, а если false, то зеленым
19.03.2019 13:29
Спасибо! Думал что "m" это флаг сделки по рынку.. Про подвох .. не знаю.. Ведь важно кто "первый начал" :)... подорвать либо покупать, а если б был бы флаг что покупал подорвал по рынку ... вообще цены не было б этой информации..
19.03.2019 13:48
... чтоб понять по рынку сделка или нет... смотреть верхнюю цену по бид\аск в стакане и сравнивать с ценой сделки .... опять же.. смотреть как спред себя ведет...
20.03.2019 11:23
Один выставил сделку по своей цене (сформировал рынок), другой купил/продал по этой цене (по рынку)
30.10.2019 05:50
Подскажите, как из этого потока выводить только пару и цену "s" и "p"?
10.11.2019 10:04
import json
import websocket

def on_message(ws, message):
    obj = json.loads(message)
    print(obj['s'], obj['p'])

def on_error(ws, error):
    print(error)

def on_close(ws):
    print("### closed ###")

def on_open(ws):
    print("### connected ###")

if __name__ == "__main__":
    ws = websocket.WebSocketApp("wss://stream.binance.com:9443/ws/ltcbtc@aggTrade/ethbtc@aggTrade",
                              on_message = on_message,
                              on_error = on_error,
                              on_close = on_close)
    ws.on_open = on_open
    ws.run_forever()
29.11.2019 22:22
привет. подскажите, можно на примере кода выше, как сделать рестарт вебсокетов при их закрытии со стороны биржи (например по истечении суток) ?
25.01.2020 23:22
Добавьте, плиз:
    #print( message )
    print( json.dumps( json.loads(message), indent=3, separators=(',',': ') ) )

Замучался искать, по инетам, у Вас же и нашел в "Чего бы с биржи стянуть? Изучаем API и способы работы с ним."
31.01.2020 15:13
Пускай будет в комментариях, как дополнение к статье)
28.01.2020 15:11
Подскажите, как сделать несколько подключений?
30.01.2020 14:42
Спасибо за статью "Многопоточность в Питоне" сомбинировал - заработало!
04.05.2020 05:03
Огромное спасибо за статью!
Благодаря Вам наконец-то сделал "криптотикер", который не останавливается из-за превышения ограничений по REST запросам
может кому нужно..выкладываю код , работает на старом нетбуке 2009 года выпуска.
import websocket
import json
from turtle import *
import time

t = Turtle()
t.screen.setup(800,550)
t.screen.bgcolor("#002137")
t.color('yellow')
b=1
def on_message(ws, message):
    obj = json.loads(message)
    print(obj["s"], obj["p"])
    price=float(obj["p"])
    print(price)
    t.clear()
    t.color('yellow')
    t.goto(-400,130)
    t.write((price),font=("Arial", 100, "bold"))
    t.color('yellow')
    t.goto(-400,20)
    t.write(('BINANCE BTC USDT'),font=("Arial", 50, "bold"))
    time.sleep(1)
    
def on_error(ws, error):
    print(error)

def on_close(ws):
    print("### closed ###")

def on_open(ws):
    print("### connected ###")

if __name__ == "__main__":
    #ws = websocket.WebSocketApp("wss://stream.binance.com:9443/stream?streams=ltcbtc@aggTrade/ethbtc@aggTrade",
    ws = websocket.WebSocketApp("wss://stream.binance.com:9443/ws/btcusdt@aggTrade",
                              on_message = on_message,
                              on_error = on_error,
                              on_close = on_close)
"""
    t.clear()
    t.color('yellow')
    t.goto(-400,130)
    t.write((price),font=("Arial", 100, "bold"))
    t.color('yellow')
    t.goto(-400,20)
    t.write(('BINANCE SPOT Account'),font=("Arial", 50, "bold"))
"""
ws.on_open = on_open
ws.run_forever()
04.05.2020 21:02
Я правильно понял, что klines тут возвращает только текущую свечу? Нельзя, как тут https://api.binance.com/api/v1/klines?symbol=LTCBTC&interval=5m, получать, скажем 100 последних свечей?
28.06.2020 13:26
Да, тут как в телевизоре, что вещают то и получаете, по запросу ничего не дадут. Биржа просто транслирует текущие актуальные данные
14.07.2020 20:14
Здравствуйте! Спасибо за ваши статьи!
Может вы знаете как обработать одновременно данные со спот и срочного рынков?

import multiprocessing.dummy as multiprocessing
import websocket
def on_message(ws, message):
    print(message)

def on_error(ws, error):
    print(error)

def on_close(ws):
    print("Отключен")

def on_open(ws):
    print("Подключен")


def a():
    ws = websocket.WebSocketApp("wss://stream.binance.com:9443/ws/ethusdt@aggTrade",
                              on_message = on_message,
                              on_error = on_error,
                              on_close = on_close)
    ws.on_open = on_open
    ws.run_forever()
def b():
    ws = websocket.WebSocketApp("wss://fstream.binance.com:9443/ws/ethusdt@aggTrade",
                              on_message = on_message,
                              on_error = on_error,
                              on_close = on_close)
    ws.on_open = on_open
    ws.run_forever()

p1 = multiprocessing.Process(target=a) 
p2 = multiprocessing.Process(target=b) 

p1.start() 
p2.start() 

p1.join() 
p2.join() 

Почему-то выводит только первый вебсокет. Что я делаю не так?
28.07.2020 14:28
Потому то первый уходит в бесконечный цикл, так задумано, а второй  ждет когда он закончит.
Запускайте в разных потоках, посмотрите эту статью https://bablofil.com/python-multithreading/
20.10.2020 17:55
Подскажите почему от бинанса прилетают не все данные?
я получаю одним WebSocket все пары @trade но когда сравниваю с сайтом не все данные приходят?
Может есть ограничения? или надо отдельно под каждую торговую пару получать данные?
Пожалуйста, Авторизуйтесь что бы оставить свой комментарий