I'm using Binance UMFutures testnet and want to build stream for user_data ( order updates).
Keys are ok. Other methods like klines work perfect as well. But .futures_user_socket() shows nothing when I place or cancel orders. Could you please advice what am I doing wrong?
`
from binance import AsyncClient , BinanceSocketManager
import asyncio
api_key_testnet = '<--->'
secret_key_testnet = '<--->'
async def user_data_listener(client):
bm = BinanceSocketManager(client)
async with bm.futures_user_socket() as stream:
while True:
res = await stream.recv()
print(res)
async def main():
client = await AsyncClient.create(api_key_testnet,secret_key_testnet,testnet=True)
await user_data_listener(client)
if __name__ == "__main__":
asyncio.run(main())
`
Related
I'm trying to post a dataframe to a Discord channel. However, I am having issue getting Discord.py to close the connection and move on the next task. I've tried using the event loop as suggested in this thread (How to run async function in Airflow?) as well as asyncio.run() function. Not really familiar with the async and hoping to get some pointers here. Below is my code in Python that I've tried importing in DAG and Task without success. Thanks in advance!
Airflow: 2.5.1
Python: 3.7
import discord
from tabulate import tabulate
import asyncio
import pandas as pd
async def post_to_discord(df, channel_id, bot_token, as_message=True, num_rows=5):
intents = discord.Intents.default()
intents.members = True
client = discord.Client(intents=intents)
try:
#client.event
async def on_ready():
channel = client.get_channel(channel_id)
if as_message:
# Post the dataframe as a message, num_rows rows at a time
for i in range(0, len(df), num_rows):
message = tabulate(df.iloc[i:i+num_rows,:], headers='keys', tablefmt='pipe', showindex=False)
await channel.send(message)
else:
# Send the dataframe as a CSV file
df.to_csv("dataframe.csv", index=False)
with open("dataframe.csv", "rb") as f:
await channel.send(file=discord.File(f))
# client.run(bot_token)
await client.start(bot_token)
await client.wait_until_ready()
finally:
await client.close()
async def main(df, channel_id, bot_token, as_message=True, num_rows=5):
# loop = asyncio.get_event_loop()
# result = loop.run_until_complete(post_to_discord(df, channel_id, bot_token, as_message, num_rows))
result = asyncio.run(post_to_discord(df, channel_id, bot_token, as_message, num_rows))
await result
return result
if __name__ =='__main__':
main()
It seems like your script works but the server is blocking the open socket (and kudos - the discord server is good at that). So we will work by creating a ping function (adopted from another answer).
def ping(ip, port):
try:
s = socket.socket() # TCP - standard values are `socket.AF_INET, socket.SOCK_STREAM` so you don't have to write them
s.settimeout(2)
print('[DEBUG] connect')
s.connect((ip, int(port)))
#result = s.connect_ex((ip, int(port)))
#print('result:', result)
return True
except socket.timeout as ex:
print('[DEBUG] timeout')
return True
except Exception as ex:
print('[Exception]', ex)
return False
finally:
print('[DEBUG] close')
s.close()
Feel free to test your ID
id = ...channel number...
print(id, type(id))
and you should see
<built-in function id> <class 'builtin_function_or_method'>
Then let us move on to improving your code:
import discord
import asyncio
import time # you are not using this module
import socket
import os
from tabulate import tabulate
import pandas as pd # as pd is not required
def ping(ip, port):
try:
s = socket.socket() # TCP - standard values are `socket.AF_INET, socket.SOCK_STREAM` so you don't have to write them
s.settimeout(2)
print('[DEBUG] connect')
s.connect((ip, int(port)))
#result = s.connect_ex((ip, int(port)))
#print('result:', result)
return True
except socket.timeout as ex:
print('[DEBUG] timeout')
return True
except Exception as ex:
print('[Exception]', ex)
return False
finally:
print('[DEBUG] close')
s.close()
TOKEN = os.getenv('DISCORD_TOKEN')
client = discord.Client()
async def post_to_discord(df, channel_id, bot_token, as_message=True, num_rows=5):
intents = discord.Intents.default()
intents.members = True
client = discord.Client(intents=intents)
try:
#client.event
async def on_ready():
channel = client.get_channel(channel_id)
if as_message:
# Post the dataframe as a message, num_rows rows at a time
for i in range(0, len(df), num_rows):
message = tabulate(df.iloc[i:i+num_rows,:], headers='keys', tablefmt='pipe', showindex=False)
await channel.send(message)
else:
# Send the dataframe as a CSV file
df.to_csv("dataframe.csv", index=False)
with open("dataframe.csv", "rb") as f:
await channel.send(file=discord.File(f))
# client.run(bot_token)
await client.start(bot_token)
await client.wait_until_ready()
while True:
online = ping("26.51.174.109", "25565") #modify it as you see fit
#online = ping("192.168.1.101", "8081") #same as above
if online:
print("server online")
#await channel.edit(name="Server Status - Online")
else:
print("server offline")
#await channel.edit(name="Server Status - Offline")
await asyncio.sleep(5)
# optional - client.run(TOKEN)
finally:
await client.close()
async def main(df, channel_id, bot_token, as_message=True, num_rows=5):
# loop = asyncio.get_event_loop()
# result = loop.run_until_complete(post_to_discord(df, channel_id, bot_token, as_message, num_rows))
result = asyncio.run(post_to_discord(df, channel_id, bot_token, as_message, num_rows))
await result
return result
if __name__ =='__main__':
main()
I have the below piece of code
async def get_data(uuid):
async with sema, httpx.AsyncClient(
base_url=udi_data_url, params=params
) as udi_client:
udi_result = udi_client.get(f"/{uuid}")
async with sema, httpx.AsyncClient(
base_url=manufacturer_data_url, params=params
) as client:
manufacturing_result = client.get(f"/{uuid}")
result1, result2 = await asyncio.gather(udi_result, manufacturing_result)
print(result1, result2)
async def main():
await get_data(uuid)
asyncio.run(main())
How do I keep the client connections open as i understand the moment i reach this line
result1, result2 = await asyncio.gather(udi_result, manufacturing_result)
I know that i can do something like
udi_result = await udi_client.get(f"/{uuid}")
and
manufacturing_result = await client.get(f"/{uuid}")
But that's not what I want to do.
I am out of the context and thus
I am getting an error.
I make API calls with asyncio but I have a limit of 300 calls per minutes. How can I pause or limit asyncio? I tried with "semaphore" with no success. How can I do this?
from asyncio.tasks import sleep
from aiohttp import ClientSession
import asyncio
import time
import aiohttp
semaphore = asyncio.Semaphore(2)
async def get_sites(sites):
tasks = [asyncio.create_task(fetch_site(s)) for s in sites]
return await asyncio.gather(*tasks)
NCAVStock = []
async def fetch_site(url):
async with ClientSession() as session:
async with session.get(url) as resp:
data = await resp.json()
data = data['symbol']
NCAVStock.append(data)
print(NCAVStock)
return data
if __name__ == '__main__':
List_Not_China = ['SRDX', 'AQB', 'CDTI', 'VRSN', 'MEC', 'NFG', 'KTOS', 'PRO', 'BEAT', 'HRB', 'JBLU', 'SRTS', 'PCRX', 'RVLV', 'CTSH', 'DHCNL', 'SYX', 'FARM', 'BAM', 'CALX', 'VTIQW', 'LKQ', 'ISR', 'GLDW', 'WORK', 'UTI', 'MXL', 'MTOR', 'CRWS', 'CHWY', 'GKOS', 'MDEX', 'AGI', 'LH', 'IDIV', 'CVEO', 'URI', 'FIX', 'RICK', 'ITW', 'STRT', 'SGLBW', 'EIX', 'AWX', 'ADSK', 'INS', 'MLHR', 'IIIV']
sites = [
f'http://financialmodelingprep.com/api/v3/financials/balance-sheet-statement/{company}?period=quarter&apikey=APIKEY'for company in List_Not_China
]
data = asyncio.run(get_sites(sites))
I have a code to receive data from binance, about current prices:
import asyncio
from binance import AsyncClient, BinanceSocketManager
import time
from datetime import datetime
def analyze(res):
kline = res['k']
if kline['x']: #candle is compleated
print('{} start_sleeping {} {}'.format(
datetime.now(),
kline['s'],
datetime.fromtimestamp(kline['t'] / 1000),
))
time.sleep(5)
print('{} finish_sleeping {}'.format(datetime.now(), kline['s']))
async def open_binance_stream(symbol):
client = await AsyncClient.create()
bm = BinanceSocketManager(client)
ts = bm.kline_socket(symbol)
async with ts as tscm:
while True:
res = await tscm.recv()
analyze(res)
await client.close_connection()
async def main():
t1 = asyncio.create_task(open_binance_stream('ETHBTC'))
t2 = asyncio.create_task(open_binance_stream('XRPBTC'))
await asyncio.gather(*[t1, t2])
if __name__ == "__main__":
asyncio.run(main())
How to make analyze function to be called concurently.
Binance sends info in the same time with both streams data (ETHBTC and XRPBTC)
But function analyze will be called only once previous analyze (sleep) is completed.
I wish function analyze is called immediately and independently.
Have you tried to put analyze in a thread. I think it will achieve what you want.
import asyncio
from binance import AsyncClient, BinanceSocketManager
import time
from datetime import datetime
from threading import Thread
def analyze(res):
kline = res['k']
if kline['x']: #candle is compleated
print('{} start_sleeping {} {}'.format(
datetime.now(),
kline['s'],
datetime.fromtimestamp(kline['t'] / 1000),
))
time.sleep(5)
print('{} finish_sleeping {}'.format(datetime.now(), kline['s']))
async def open_binance_stream(symbol):
client = await AsyncClient.create()
bm = BinanceSocketManager(client)
ts = bm.kline_socket(symbol)
async with ts as tscm:
while True:
res = await tscm.recv()
Thread(target= analyze, args = (res)).start()
await client.close_connection()
async def main():
t1 = asyncio.create_task(open_binance_stream('ETHBTC'))
t2 = asyncio.create_task(open_binance_stream('XRPBTC'))
await asyncio.gather(*[t1, t2])
if __name__ == "__main__":
asyncio.run(main())
This should work as expected.
I would like to use Telethon (Telegram bot) and aiopg (PostgreSQL) library.
Telethon example:
from telethon import TelegramClient
api_id = 12345
api_hash = '0123456789abcdef0123456789abcdef'
client = TelegramClient('anon', api_id, api_hash)
async def main():
# Getting information about yourself
me = await client.get_me()
print(me.stringify())
#client.on(events.NewMessage)
async def my_event_handler(event):
if 'hello' in event.raw_text:
await event.reply('hi!')
client.start()
client.run_until_disconnected()
aiopg example:
import aiopg
dsn = 'dbname=aiopg user=aiopg password=passwd host=127.0.0.1'
async def notify(conn):
async with conn.cursor() as cur:
for i in range(5):
msg = "message {}".format(i)
print('Send ->', msg)
await cur.execute("NOTIFY channel, %s", (msg,))
await cur.execute("NOTIFY channel, 'finish'")
async def listen(conn):
async with conn.cursor() as cur:
await cur.execute("LISTEN channel")
while True:
msg = await conn.notifies.get()
if msg.payload == 'finish':
return
else:
print('Receive <-', msg.payload)
async def main():
async with aiopg.create_pool(dsn) as pool:
async with pool.acquire() as conn1:
listener = listen(conn1)
async with pool.acquire() as conn2:
notifier = notify(conn2)
await asyncio.gather(listener, notifier)
print("ALL DONE")
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
I would like to use both in a same python script.
I tried to find the solution and it is maybe the asyncio.gather(...), but I don't know how can I combine these two library, how to start both loop.
Can you please help me?
create a new async function which creates a new client instance and add all the handlers you need, for the sake of this example I showed some example handlers of mine.
async def init_bot() -> TelegramClient:
client = TelegramClient(
session="trade-bot",
api_hash=Config.API_HASH,
api_id=Config.API_ID,
)
await client.start(bot_token=Config.BOT_TOKEN)
client.add_event_handler(
register_handler,
events.NewMessage(incoming=True, pattern=r"^[\/?!]register$"),
)
client.add_event_handler(
get_webhook_handler,
events.NewMessage(incoming=True, pattern=r"^[\/?!]webhook$"),
)
client.add_event_handler(
status_handler,
events.NewMessage(incoming=True, pattern=r"^[\/?!]status$"),
)
_LOG.info("Bot client started")
return client
then later on you main function
client = await init_bot()
await client.connect()
# the below code is non-blocking
asyncio.create_task(client.run_until_disconnected())