Binance websocket realtime plot without blocking code?
Asked Answered
L

1

7

I am trying to obtain and plot real-time data from Binance (ETHUSDT) using a WebSocket. Getting the data is no problem, but I cannot get a realtime plot to work when using matplotlib.

In the code, I update the close prices each time a message is received and try to plot this data in realtime. The plot is shown on the screen but blocks further code execution. I have to manually close the plot for the next message to be received.

My question is: how can I plot the data in realtime without blocking the code?

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()
Laundryman answered 10/1, 2021 at 17:22 Comment(0)
I
4

Matplotlib needs to run the GUI on the main thread.

You can setup the websocket connection on a background thread.

Imports

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

Realtime updates to data in background

Run the websocket data changes in a thread.

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()

Animated plot

Now, animate changes to the closes array.

Refer to documentation for matplotlib.animation.FuncAnimation.

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()
Isia answered 24/4, 2021 at 9:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.