I can't make the websocket for COIN-M on Binance returns any data.
I managed to get it to work with the SPOT endpoint, but in the Futures it is a null response.
import websocket
import _thread
import time
import json
WEBSOCKET_URL_FUTURES = "wss://dstream.binance.com/ws"
WEBSOCKET_URL_SPOT = "wss://stream.binance.com:9443/ws"
def on_message(ws, message):
print(f'ONMESSAGE######: {message}')
with open ('./data.json', 'a') as f:
f.write(f'{message}\n')
def on_error(ws, error):
print(f'ONERROR####: {error}')
def on_close(ws, close_status_code, close_msg):
print("### closed ###")
def on_open(ws):
print("### opened ###")
subscribe_message = {
"method": "SUBSCRIBE",
"params":
[
"ethusd_perpetual#aggTrade"
],
"id": 1
}
list_message = {
"method": "LIST_SUBSCRIPTIONS",
"id": 3
}
ws.send(json.dumps(subscribe_message))
ws.send(json.dumps(list_message))
if __name__ == "__main__":
websocket.enableTrace(True)
ws = websocket.WebSocketApp(WEBSOCKET_URL_SPOT,
on_open=on_open,
on_message=on_message,
on_error=on_error,
on_close=on_close)
ws.run_forever()
I'm trying differents parameters in the SUSBCRIBE method but neither of them returns anything.
Also, I can't find any list with all the possible symbol pairs that could be used.
Any ideas?
There might be a typo in your stream URL.
The code uses wss://dstream..., while this should be wss://fstream...
Related
I'm using Alpaca's API with websocket to get stock price data. I want to use the variable position outside the function on_message but message is not previously defined so I get an error when I run the code name message is not defined
def on_message(ws, message):
global position
json.loads(message)
position = (message[0]['bp'])
import websocket, json
def on_open(ws):
print("opened")
auth_data = {
"action": "auth", "key": <API_KEY>, "secret": <API_SECRET>
}
ws.send(json.dumps(auth_data))
listen_message = {"action":"subscribe","quotes":["AAPL"]}
ws.send(json.dumps(listen_message))
def on_message(ws, message):
global position
json.loads(message)
position = (message[0]['bp'])
socket = "wss://stream.data.alpaca.markets/v2/iex"
ws = websocket.WebSocketApp(socket, on_open=on_open, on_message=on_message)
ws.run_forever()
sorry if this is a badly worded question it's about 1 am and im tired.
This is a simple program to retrieve candlestick data from Binance exchange for several pairs. I found out that it could be done with asyncio package.
import websockets
import asyncio
import json
import pprint
async def candle_stick_data():
url = "wss://stream.binance.com:9443/ws/" #steam address
first_pair = 'xlmbusd#kline_1m' #first pair
async with websockets.connect(url+first_pair) as sock:
pairs = '{"method": "SUBSCRIBE", "params": ["xlmbnb#kline_1m","bnbbusd#kline_1m" ], "id": 1}' #other pairs
await sock.send(pairs)
print(f"> {pairs}")
while True:
resp = await sock.recv()
resp=json.loads(resp)
pprint.pprint(resp)
candle = resp['k']
asyncio.get_event_loop().run_until_complete(candle_stick_data())
I am getting messages and changing type to dict with json.loads(resp). My question is how can I access dict values because candle = resp['k'] causes "Key error 'k'". I am new to asyncio maybe I don't need it at all to retrieve data for several pairs.
updated message screenshot
Your first incoming message really does not have 'k' key in dictionary.
I just added if else block to your code and it works well:
import websockets
import asyncio
import json
import pprint
async def candle_stick_data():
url = "wss://stream.binance.com:9443/ws/" #steam address
first_pair = 'xlmbusd#kline_1m' #first pair
async with websockets.connect(url+first_pair) as sock:
pairs = '{"method": "SUBSCRIBE", "params": ["xlmbnb#kline_1m","bnbbusd#kline_1m" ], "id": 1}' #other pairs
await sock.send(pairs)
print(f"> {pairs}")
while True:
resp = await sock.recv()
resp = json.loads(resp)
# get 'k' key value if it exits, otherwise None
k_key_val = resp.get('k', None)
# easy if else block
if not k_key_val:
print(f"No k key found: {resp}")
else:
pprint.pprint(k_key_val)
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(candle_stick_data())
from http.client import HTTPSConnection
from sys import stderr
from json import dumps
from time import sleep
header_data = {
"content-type": "application/json",
"user-agent": "discordapp.com",
"authorization": "IPlaceTokenHere",
"host": "discordapp.com",
"referer": "TheChannelUrlhere"
}
def get_connection():
return HTTPSConnection("discordapp.com", 443)
def send_message(conn, channel_id, message_data):
try:
conn.request("POST", f"/api/v6/channels/{channel_id}/messages", message_data, header_data)
resp = conn.getresponse()
if 199 < resp.status < 300:
print("Message sent...")
pass
else:
stderr.write(f"Received HTTP {resp.status}: {resp.reason}\n")
pass
except:
stderr.write("Failed to send_message\n")
def main():
message_data = {
"content": "Hello, world!",
"tts": "false",
}
send_message(get_connection(), "ChannelIDhere", dumps(message_data))
if __name__ == '__main__':
while True: # Infinite loop
main() # Send the message
sleep(3600) # Wait an hour to repeat
I am doing this to send messages like 'Good morning' etc (hosted on my webserver). The thing is I want to add many channels(Since I own a lot of servers) with different messages. I am unable to figure out how.
You can simply pass multiple channel IDs to the send_message function, loop through them and send a message
def send_message(conn, message_data, *channel_ids):
for channel_id in channel_ids:
try:
conn.request("POST", f"/api/v6/channels/{channel_id}/messages", message_data, header_data)
resp = conn.getresponse()
if 199 < resp.status < 300:
print("Message sent...")
else:
stderr.write(f"Received HTTP {resp.status}: {resp.reason}\n")
except:
stderr.write("Failed to send_message\n")
def main():
message_data = {
"content": "Hello, world!",
"tts": "false",
}
send_message(
get_connection(),
dumps(message_data),
"CHANNEL ID 1",
"CHANNEL ID 2",
"CHANNEL ID 3"
)
Note that now the channel ID's must be entered as the last arguments. Also I removed the unnecessary pass keyword in the if and else part as they're useless there. If you'd like to send the messages in different timestamps you should look at asyncio to functions things concurrently.
EDIT:
If you also want to send different messages per channel you can simply map the channel ID to a message in a dict
def send_message(conn, channels): # You can also use kwargs
for channel_id, message_data in channels.items():
try:
conn.request("POST", f"/api/v6/channels/{channel_id}/messages", message_data, header_data)
resp = conn.getresponse()
if 199 < resp.status < 300:
print("Message sent...")
else:
stderr.write(f"Received HTTP {resp.status}: {resp.reason}\n")
except:
stderr.write("Failed to send_message\n")
def main():
data = {
"CHANNEL ID 1": json.dumps({"content": "message for channel 1", "tts": "false"}),
"CHANNEL ID 2": json.dumps({"content": "message for channel 2", "tts": "false"}),
"CHANNEL ID 3": json.dumps({"content": "message for channel 3", "tts": "false"})
}
send_message(get_connection(), data)
This can be improved a lot, I'll leave that to you.
I'm writing a Python program that does some trading automation. The API I work with is from Deribit, whose preferred transport mechanism is Websocket. I'm a complete newbie to Python's websockets and asyncio modules.
Here's the code I first wrote for authenticating my client and then sending a separate private message to get an order position from the account, written only with functions and no classes:
import asyncio
import websockets
import json
CL_ID = 'qxv0EeAu'
CL_SECRET = 't24F49ocH1_qFawiKnEyqlWF5D-haABb31O8xCQhySg'
REQ_URL = 'wss://test.deribit.com/ws/api/v2'
acc_token = ''
msg = {
"jsonrpc": "2.0",
"id": 1,
"params": {}
}
async def auth_api():
global msg
global acc_token
msg["method"] = "public/auth"
msg["params"] = {
"grant_type": "client_credentials",
"client_id": CL_ID,
"client_secret": CL_SECRET,
"scope": "session:test"
}
async with websockets.connect(REQ_URL) as websocket:
await websocket.send(json.dumps(msg))
while websocket.open:
response = await websocket.recv()
response_json = json.loads(response)
acc_token = response_json["result"]["access_token"]
return
async def get_position(websocket, instrument):
global msg
global acc_token
msg["id"] += 1
msg["method"] = "private/get_position"
msg["params"] = {
"access_token": acc_token,
"instrument_name": instrument
}
await websocket.send(json.dumps(msg))
while websocket.open:
response = await websocket.recv()
return response
async def main():
global msg
await auth_api()
async with websockets.connect(REQ_URL) as websocket:
response = await get_position(websocket, "BTC-PERPETUAL")
print(response)
asyncio.get_event_loop().run_until_complete(main())
It works perfectly fine. Here's my result:
{"jsonrpc":"2.0","id":2,"result":{"total_profit_loss":0.000209124,"size_currency":-0.017402402,"size":-150.0,"settlement_price":8649.9,"realized_profit_loss":2.67e-7,"open_orders_margin":0.0,"mark_price":8619.5,"maintenance_margin":0.000100079,"leverage":100,"kind":"future","instrument_name":"BTC-PERPETUAL","initial_margin":0.000174039,"index_price":8619.45,"floating_profit_loss":0.000061161,"estimated_liquidation_price":-14.95,"direction":"sell","delta":-0.017402402,"average_price":8724.34},"usIn":1573756522511975,"usOut":1573756522512240,"usDiff":265,"testnet":true}
I decided to rewrite it the OOP way, and here's the class I created (the file is named "Call_Deribit"):
import asyncio, websockets, json
class WSClient():
def __init__(self, key=None, secret=None, url=None):
self.api_key = key
self.api_secret = secret
self.msg = {
"jsonrpc": "2.0",
"id": 0
}
if url:
self.host = url
else:
self.host = 'wss://test.deribit.com/ws/api/v2'
async def call_api(self, msg):
async with websockets.connect(self.host) as websocket:
print("Connected to URL:", self.host)
try:
await websocket.send(msg)
while websocket.open:
response = await websocket.recv()
response_json = json.loads(response)
return response_json
except Exception as e:
return e
def request(self, method, params, session=None):
msg = self.msg
msg["id"] += 1
msg["method"] = method
msg["params"] = params
if session != None:
msg["params"]["scope": "session:{}".format(session)]
return asyncio.get_event_loop().run_until_complete(self.call_api(json.dumps(msg)))
def get_order_book(self, instrument):
method = "public/get_order_book"
params = {
"instrument_name": instrument
}
return self.request(method, params)
And here's the main file I'm accessing the class from and where I make all the requests:
import json, asyncio, websockets
from Call_Deribit import WSClient
CL_ID = 'qxv0EeAu'
CL_SECRET = 't24F49ocH1_qFawiKnEyqlWF5D-haABb31O8xCQhySg'
REQ_URL = 'wss://test.deribit.com/ws/api/v2'
method_auth = "public/auth"
params_auth = {
"grant_type": "client_credentials",
"client_id": CL_ID,
"client_secret": CL_SECRET
}
main_client = WSClient(key=CL_ID, secret=CL_SECRET, url=REQ_URL)
auth_response = main_client.request(method_auth, params_auth)
acc_token = auth_response["result"]["access_token"]
method_pos = "private/get_position"
params_pos = {
"access_token": acc_token,
"instrument_name": "BTC-PERPETUAL"
}
position = main_client.request(method_pos, params_pos)
print(position)
The first request for authentication is working this time, and I'm able to extract the access token as well, but the second private/get_position message is, for whatever reason, returning an unauthorized error.
{'jsonrpc': '2.0', 'id': 1, 'error': {'message': 'unauthorized', 'code': 13009}, 'testnet': True, 'usIn': 1573756936534405, 'usOut': 1573756936534629, 'usDiff': 224}
I've spent hours on it, and I seem to be doing exactly the same thing in the OOP version as I did on the original one. My familiarity with OOP and its concepts (such as inheritance) is limited, so I'd like to know what I'm missing here, and why my code isn't working in the OOP version, despite following the same exact workflow as in the original version.
Here's the documentation for the Deribit API: https://docs.deribit.com/v2/?python#json-rpc
Any help would be greatly appreciated.
Adding the scope under params_auth in the main file works:
params_auth = {
"grant_type": "client_credentials",
"client_id": CL_ID,
"client_secret": CL_SECRET,
"scope": "session:test"
}
I am trying this :
import websocket
import json
def on_open(ws):
json_data = json.dumps({'ticks':'R_100'})
ws.send(json_data)
def on_message(ws, message):
print('ticks update: %s' % message)
if __name__ == "__main__":
apiUrl = "wss://ws.binaryws.com/websockets/v3?app_id=1089"
ws = websocket.WebSocketApp(apiUrl, on_message = on_message, on_open = on_open)
ws.run_forever()
This is working fine. But the issue is when I want to have a history using the payload:
{
"ticks_history": "R_50",
"end": "latest",
"start": 1,
"style": "ticks",
"adjust_start_time": 1,
"count": 10
}
I am not understanding what exactly I needed to do to get the information as the app is running and it won't serve the request to me.
Please help me get through this.