График Binance websocket в реальном времени без блокирующего кода?

#python #matplotlib #websocket #real-time-updates #binance

#python #matplotlib #websocket #обновления в реальном времени #binance

Вопрос:

Я пытаюсь получить и отобразить данные в реальном времени из Binance (ETHUSDT) с помощью WebSocket. Получение данных не проблема, но я не могу заставить график в реальном времени работать при использовании matplotlib.

В коде я обновляю цены закрытия каждый раз при получении сообщения и пытаюсь отобразить эти данные в режиме реального времени. График отображается на экране, но блокирует дальнейшее выполнение кода. Я должен вручную закрыть график для получения следующего сообщения.

Мой вопрос: как я могу отображать данные в режиме реального времени, не блокируя код?

 import websocket, json
import matplotlib.pyplot as plt
import numpy as np

TRADE_SYMBOL = "ETHUSDT"
SOCKET = "wss://stream.binance.com:9443/ws/ethusdt@kline_1m"

closes = np.array([])    

#  CREATING AXIS
plt.axis([0, 1000, 0, 1])

def on_message(ws, message):
    global closes
    message = json.loads(message)

    candle = message['k']
    close = candle['c']
    closes = np.append(closes, float(close))

    # PLOTTING HERE
    plt.plot(closes)
    plt.show()


ws = websocket.WebSocketApp(SOCKET, on_message=on_message)
ws.run_forever()
 

Ответ №1:

Matplotlib должен запускать графический интерфейс в основном потоке.

Вы можете настроить подключение к websocket в фоновом потоке.

Импорт

 import json
import threading
import websocket
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
 

Данные обновляются в фоновом режиме в реальном времени

Запустите изменения данных websocket в потоке.

 TRADE_SYMBOL = "ETHUSDT"
SOCKET = "wss://stream.binance.com:9443/ws/ethusdt@kline_1m"
closes = np.array([])

def on_message(ws, message):
    global closes
    message = json.loads(message)
    candle = message['k']
    close = candle['c']
    closes = np.append(closes, float(close))

def wsthread(closes):
    ws = websocket.WebSocketApp(SOCKET, on_message=on_message)
    ws.run_forever()

t = threading.Thread(target=wsthread, args=(closes,))
t.start()
 

Анимированный сюжет

Теперь анимируйте изменения в closes массиве.

Обратитесь к документации для matplotlib.animation.Оживление.

 fig, ax = plt.subplots()
plt.axis([0, 100, 0, 3000])
x= np.arange(100)
y=[np.nan] * 100
line, = ax.plot(x, y)

def animate(i):
    global y
    # shift left to most recent 100 closing prices
    y[:len(closes)] = closes[-100:]
    line.set_ydata(y)
    return line,

def init():
    line.set_ydata([np.nan] * 100)
    return line,

anim = FuncAnimation(
    fig, animate, interval=20,
    init_func=init,
    blit=True
)

plt.show()