best way to RELIABLEY use of Websocket with python kline

OK and hello. First post, hopefully of many

I am after advice from a Newbie to python, so silly questions to follow…

i am reasonably advanced in php & SQL, but am learning python (read a few books and webpages, etc over the past few months)
At the confusion setting in stage, as to what is the best method (or a good one!) to do what i want. I am probably reading too much which is causing the confusion…

My code/application will have 3 main aspects

  1. get multiple stream data and insert into mySQL
  2. analyse the data from the database
  3. make trades

I should be OK with item 2 and 3. but item 1 needs to be RELIABLE!
So What i want:
Connect to the websocket kline stream.
Now i can do this easy enough (seen in lots of tutorials - basic code below), BUT… running it procedural does not seem to make for good coding (in php i would use methods within objects).
My main concern is: i need to check has the connection been closed, and if so re-open it OR take “emergency trading action”

So the very basic code below works fine but it does not sit easy with me. i need it to run separately
I have tried making it into a simple module or adding it as a class file (but when called this blocks the following code, as the stream never completes of course)

I have also been trying a few other methods, but below i am including the most basic, that i am sure you are all aware of…

I would like maybe pointing in the right direction (or any libraries) (as i am probably reading too much and getting confused what direction to be heading in)
i need to write it into an app/function/class/etc that will run indefinitely, be RELIABLE, reconnect if the connection is closed/lost (and message my other aspects if connection is not re-opened, so action can be taken) (i also read that the stream will be closed in 24 hours too…)

def on_message(ws, message):

closes = []
print('received message')
json_message = json.loads(message)

candle = json_message['k']
is_candle_closed = candle['x']
close = candle['c']

if is_candle_closed:
    print("candle closed at {}".format(close))
    closes.append(float(close))
    print("closes")
    print(closes)
    insert_data(json_message)

def insert_data(json_message):

try:
    Blah, Blah....
except Exception as e:
    print("Something went wrong:", e)    

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

def on_open(ws):
print(f"opened connection")

def on_close(ws):
print(‘connection closed’)

stream = “wss://stream.binance.com:9443/ws/ethusdt@kline_1m”
ws = websocket.WebSocketApp(stream, on_open=on_open, on_close=on_close, on_message=on_message, on_error=on_error)

ws.run_forever()

I hope this is not too confusing and you can see what it is i am badly asking

Thanks
Jon

In my opinion, what you are doing is completely fine. You just need to ensure that proper reconnection is done so that you do not lose any market data during disconnection (using of on_error and on_close functions).
Likewise, you can make use of the restful endpoint (Binance API Documentation) to retrieve lost data in cases where reconnection is not done and data is lost.

1 Like

Hello Chai

Thank you so much for your advice.
i am doing just as you suggest to try and expand on what i posted. hopefully to ensure 100% accuracy of constant data!
i am getting there, but keep finding “what ifs” that i need to work out how to code.
It it proving a good way to crash course learn python :slight_smile:
Thank you

Once i have the code “less messy” and fully functional, would this be the place to post it so that others can make suggestions (or spot any pitfalls that i have not realised)?

Once quick question if i may?

When i use the following code, i get an error returned simply of ‘k’
This does not seem to effect anything and the code runs fine, but is bugging me as i can not figure out why this is happening…

code extract -
stream = “wss://stream.binance.com:9443/ws/ethusdt@kline_1m”
ws = websocket.WebSocketApp(stream, on_open=on_open, on_close=on_close, on_message=on_message, on_error=on_error)
ws.run_forever()

code extract -
def on_open(ws):
print(“opened connection”)
json_subscribe = ‘{“method”: “SUBSCRIBE”, “params”: [“shibusdt@kline_1m”,“maticusdt@kline_1m”,“solusdt@kline_1m”,“btcusdt@kline_1m”,“bnbusdt@kline_1m”,“dogeusdt@kline_1m”], “id”: 1}’ #other pairs
ws.send(json_subscribe)

On another note
I would also prefer to initially connect to an empty websocket and then use the send() function to subscribe to all the streams i want, as it just seems silly to connect to an initial one. is this possible.
Not an issue if not, it just annoys my OCD a little :slight_smile:

First open the websocket using only the base endpoint ‘wss://stream.binance.com’ Second create a method to subscribe to multiple streams via the send method of the websocket using the following https://binance-docs.github.io/ apidocs/spot/en/#live-subscribing-unsubscribing-to-streams so you can open multiple streams using the same websocket

1 Like

Hello Saratoga

Thank you so much for taking the time to reply

I have tried what you advise (and different end point combinations)
However all give me an error usually of “Handshake status 400 Bad Request”

this is the simplified code i am using -

    stream = "wss://stream.binance.com"    
    ws = websocket.WebSocketApp(stream, on_open=on_open, on_close=on_close, on_message=on_message, on_error=on_error)
    ws.run_forever()
    json_subscribe = '{"method": "SUBSCRIBE", "params": ["shibusdt@kline_1m","maticusdt@kline_1m","solusdt@kline_1m","btcusdt@kline_1m","bnbusdt@kline_1m","dogeusdt@kline_1m"],  "id": 1}' #other pairs
    ws.send(json_subscribe)

The only way i seem to be able to get a connection is to include an initial stream.
If i add the end pint at the below, all works (apart from the pesky error message of simply ‘k’)

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

I am new to python, so it is going to be something i am missing/not understanding, but as of yet i don’t know what :slight_smile:

Thank you again!

First you are not checking if the connection to the websocket has already been opened I don’t know if it is that run_forever method but I don’t think from the name, the socket takes a few seconds longer to open than your code takes to execute, Second I don’t know phyton I use javascript so the json method that I use to pass the data in the send method is json.stringify and I don’t know if json_subcribre is its pyton summary, I leave you the part of my code that I use to subscribe a stream or streams

subscribe(...args){
        return new Promise(async resolve => {
            if(this.ws){
                if(args.length){
                    while(this.ws.readyState === WebSocket.CONNECTING)  {
                        await sleep(1000)
                    }
                    this.ws.send(JSON.stringify({
                        "method": "SUBSCRIBE",
                        "params": args,
                        "id": 1
                    }))
                }
            }
            resolve()
        })
    }
1 Like

Hello

That is brilliant, thank you!
Checking if there is already a connection is something i need to work out in Python (also is it still connected).
I am also a little better with JS than python (although php is more my thing), so am learning python as i go, kind of a crash course :slight_smile:

1 Like